I wrote:
> Concerns:
> - The locking is perhaps too complex?

Ok, to highlight the benefits of this series, I expect that patches such as
[1] and the one inlined below can follow up to clean up ad-hoc i2c locking
in drivers. Putting this locking in one place instead of having it spread
out in random drivers is a good thing.

PS. the inlined patch has not been tested as I have no hw, it's a proof of
concept. Maybe the simplifications can be extended into rtl2832_sdr.c as well?
Anyway, please do test this patch on top of the v4 series if you have the hw.

Cheers,
Peter

[1] https://lkml.org/lkml/2016/3/3/932

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 775444898599..fd1f05e9e79a 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -158,36 +158,24 @@ static int rtl2832_bulk_write(struct i2c_client *client, 
unsigned int reg,
                              const void *val, size_t val_count)
 {
        struct rtl2832_dev *dev = i2c_get_clientdata(client);
-       int ret;
 
-       i2c_lock_adapter(client->adapter);
-       ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-       i2c_unlock_adapter(client->adapter);
-       return ret;
+       return regmap_bulk_write(dev->regmap, reg, val, val_count);
 }
 
 static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
                               unsigned int mask, unsigned int val)
 {
        struct rtl2832_dev *dev = i2c_get_clientdata(client);
-       int ret;
 
-       i2c_lock_adapter(client->adapter);
-       ret = regmap_update_bits(dev->regmap, reg, mask, val);
-       i2c_unlock_adapter(client->adapter);
-       return ret;
+       return regmap_update_bits(dev->regmap, reg, mask, val);
 }
 
 static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
                             void *val, size_t val_count)
 {
        struct rtl2832_dev *dev = i2c_get_clientdata(client);
-       int ret;
 
-       i2c_lock_adapter(client->adapter);
-       ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-       i2c_unlock_adapter(client->adapter);
-       return ret;
+       return regmap_bulk_read(dev->regmap, reg, val, val_count);
 }
 
 static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
@@ -204,7 +192,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 *val)
        len = (msb >> 3) + 1;
        mask = REG_MASK(msb - lsb);
 
-       ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+       ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
        if (ret)
                goto err;
 
@@ -234,7 +222,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
        len = (msb >> 3) + 1;
        mask = REG_MASK(msb - lsb);
 
-       ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+       ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
        if (ret)
                goto err;
 
@@ -248,7 +236,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
        for (i = 0; i < len; i++)
                writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-       ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
+       ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
        if (ret)
                goto err;
 
@@ -492,7 +480,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
                fe->ops.tuner_ops.set_params(fe);
 
        /* PIP mode related */
-       ret = rtl2832_bulk_write(client, 0x192, "\x00\x0f\xff", 3);
+       ret = regmap_bulk_write(dev->regmap, 0x192, "\x00\x0f\xff", 3);
        if (ret)
                goto err;
 
@@ -530,7 +518,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
        }
 
        for (j = 0; j < sizeof(bw_params[0]); j++) {
-               ret = rtl2832_bulk_write(client, 0x11c + j, &bw_params[i][j], 
1);
+               ret = regmap_bulk_write(dev->regmap, 0x11c + j, 
&bw_params[i][j], 1);
                if (ret)
                        goto err;
        }
@@ -586,11 +574,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe)
        if (dev->sleeping)
                return 0;
 
-       ret = rtl2832_bulk_read(client, 0x33c, buf, 2);
+       ret = regmap_bulk_read(dev->regmap, 0x33c, buf, 2);
        if (ret)
                goto err;
 
-       ret = rtl2832_bulk_read(client, 0x351, &buf[2], 1);
+       ret = regmap_bulk_read(dev->regmap, 0x351, &buf[2], 1);
        if (ret)
                goto err;
 
@@ -757,7 +745,7 @@ static void rtl2832_stat_work(struct work_struct *work)
        /* signal strength */
        if (dev->fe_status & FE_HAS_SIGNAL) {
                /* read digital AGC */
-               ret = rtl2832_bulk_read(client, 0x305, &u8tmp, 1);
+               ret = regmap_bulk_read(dev->regmap, 0x305, &u8tmp, 1);
                if (ret)
                        goto err;
 
@@ -783,7 +771,7 @@ static void rtl2832_stat_work(struct work_struct *work)
                        {87659938, 87659938, 87885178, 88241743},
                };
 
-               ret = rtl2832_bulk_read(client, 0x33c, &u8tmp, 1);
+               ret = regmap_bulk_read(dev->regmap, 0x33c, &u8tmp, 1);
                if (ret)
                        goto err;
 
@@ -795,7 +783,7 @@ static void rtl2832_stat_work(struct work_struct *work)
                if (hierarchy > HIERARCHY_NUM - 1)
                        goto err_schedule_delayed_work;
 
-               ret = rtl2832_bulk_read(client, 0x40c, buf, 2);
+               ret = regmap_bulk_read(dev->regmap, 0x40c, buf, 2);
                if (ret)
                        goto err;
 
@@ -816,7 +804,7 @@ static void rtl2832_stat_work(struct work_struct *work)
 
        /* BER */
        if (dev->fe_status & FE_HAS_LOCK) {
-               ret = rtl2832_bulk_read(client, 0x34e, buf, 2);
+               ret = regmap_bulk_read(dev->regmap, 0x34e, buf, 2);
                if (ret)
                        goto err;
 
@@ -844,8 +832,6 @@ err:
 
 /*
  * I2C gate/mux/repeater logic
- * We must use unlocked __i2c_transfer() here (through regmap) because of I2C
- * adapter lock is already taken by tuner driver.
  * There is delay mechanism to avoid unneeded I2C gate open / close. Gate close
  * is delayed here a little bit in order to see if there is sequence of I2C
  * messages sent to same I2C bus.
@@ -857,7 +843,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work)
        int ret;
 
        /* close gate */
-       ret = rtl2832_update_bits(dev->client, 0x101, 0x08, 0x00);
+       ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x00);
        if (ret)
                goto err;
 
@@ -875,10 +861,7 @@ static int rtl2832_select(struct i2c_mux_core *muxc, u32 
chan_id)
        /* terminate possible gate closing */
        cancel_delayed_work(&dev->i2c_gate_work);
 
-       /*
-        * I2C adapter lock is already taken and due to that we will use
-        * regmap_update_bits() which does not lock again I2C adapter.
-        */
+       /* open gate */
        ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
        if (ret)
                goto err;
@@ -950,120 +933,6 @@ static bool rtl2832_volatile_reg(struct device *dev, 
unsigned int reg)
        return false;
 }
 
-/*
- * We implement own I2C access routines for regmap in order to get manual 
access
- * to I2C adapter lock, which is needed for I2C mux adapter.
- */
-static int rtl2832_regmap_read(void *context, const void *reg_buf,
-                              size_t reg_size, void *val_buf, size_t val_size)
-{
-       struct i2c_client *client = context;
-       int ret;
-       struct i2c_msg msg[2] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = reg_size,
-                       .buf = (u8 *)reg_buf,
-               }, {
-                       .addr = client->addr,
-                       .flags = I2C_M_RD,
-                       .len = val_size,
-                       .buf = val_buf,
-               }
-       };
-
-       ret = __i2c_transfer(client->adapter, msg, 2);
-       if (ret != 2) {
-               dev_warn(&client->dev, "i2c reg read failed %d reg %02x\n",
-                        ret, *(u8 *)reg_buf);
-               if (ret >= 0)
-                       ret = -EREMOTEIO;
-               return ret;
-       }
-       return 0;
-}
-
-static int rtl2832_regmap_write(void *context, const void *data, size_t count)
-{
-       struct i2c_client *client = context;
-       int ret;
-       struct i2c_msg msg[1] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = count,
-                       .buf = (u8 *)data,
-               }
-       };
-
-       ret = __i2c_transfer(client->adapter, msg, 1);
-       if (ret != 1) {
-               dev_warn(&client->dev, "i2c reg write failed %d reg %02x\n",
-                        ret, *(u8 *)data);
-               if (ret >= 0)
-                       ret = -EREMOTEIO;
-               return ret;
-       }
-       return 0;
-}
-
-static int rtl2832_regmap_gather_write(void *context, const void *reg,
-                                      size_t reg_len, const void *val,
-                                      size_t val_len)
-{
-       struct i2c_client *client = context;
-       int ret;
-       u8 buf[256];
-       struct i2c_msg msg[1] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 1 + val_len,
-                       .buf = buf,
-               }
-       };
-
-       buf[0] = *(u8 const *)reg;
-       memcpy(&buf[1], val, val_len);
-
-       ret = __i2c_transfer(client->adapter, msg, 1);
-       if (ret != 1) {
-               dev_warn(&client->dev, "i2c reg write failed %d reg %02x\n",
-                        ret, *(u8 const *)reg);
-               if (ret >= 0)
-                       ret = -EREMOTEIO;
-               return ret;
-       }
-       return 0;
-}
-
-/*
- * FIXME: Hack. Implement own regmap locking in order to silence lockdep
- * recursive lock warning. That happens when regmap I2C client calls I2C mux
- * adapter, which leads demod I2C repeater enable via demod regmap. Operation
- * takes two regmap locks recursively - but those are different regmap 
instances
- * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
- * regmap aware of lockdep.
- */
-static void rtl2832_regmap_lock(void *__dev)
-{
-       struct rtl2832_dev *dev = __dev;
-       struct i2c_client *client = dev->client;
-
-       dev_dbg(&client->dev, "\n");
-       mutex_lock(&dev->regmap_mutex);
-}
-
-static void rtl2832_regmap_unlock(void *__dev)
-{
-       struct rtl2832_dev *dev = __dev;
-       struct i2c_client *client = dev->client;
-
-       dev_dbg(&client->dev, "\n");
-       mutex_unlock(&dev->regmap_mutex);
-}
-
 static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
 {
        struct rtl2832_dev *dev = i2c_get_clientdata(client);
@@ -1087,7 +956,7 @@ static int rtl2832_enable_slave_ts(struct i2c_client 
*client)
 
        dev_dbg(&client->dev, "\n");
 
-       ret = rtl2832_bulk_write(client, 0x10c, "\x5f\xff", 2);
+       ret = regmap_bulk_write(dev->regmap, 0x10c, "\x5f\xff", 2);
        if (ret)
                goto err;
 
@@ -1095,11 +964,11 @@ static int rtl2832_enable_slave_ts(struct i2c_client 
*client)
        if (ret)
                goto err;
 
-       ret = rtl2832_bulk_write(client, 0x0bc, "\x18", 1);
+       ret = regmap_bulk_write(dev->regmap, 0x0bc, "\x18", 1);
        if (ret)
                goto err;
 
-       ret = rtl2832_bulk_write(client, 0x192, "\x7f\xf7\xff", 3);
+       ret = regmap_bulk_write(dev->regmap, 0x192, "\x7f\xf7\xff", 3);
        if (ret)
                goto err;
 
@@ -1133,7 +1002,7 @@ static int rtl2832_pid_filter_ctrl(struct dvb_frontend 
*fe, int onoff)
        else
                u8tmp = 0x00;
 
-       ret = rtl2832_update_bits(client, 0x061, 0xc0, u8tmp);
+       ret = regmap_update_bits(dev->regmap, 0x061, 0xc0, u8tmp);
        if (ret)
                goto err;
 
@@ -1168,14 +1037,14 @@ static int rtl2832_pid_filter(struct dvb_frontend *fe, 
u8 index, u16 pid,
        buf[1] = (dev->filters >>  8) & 0xff;
        buf[2] = (dev->filters >> 16) & 0xff;
        buf[3] = (dev->filters >> 24) & 0xff;
-       ret = rtl2832_bulk_write(client, 0x062, buf, 4);
+       ret = regmap_bulk_write(dev->regmap, 0x062, buf, 4);
        if (ret)
                goto err;
 
        /* add PID */
        buf[0] = (pid >> 8) & 0xff;
        buf[1] = (pid >> 0) & 0xff;
-       ret = rtl2832_bulk_write(client, 0x066 + 2 * index, buf, 2);
+       ret = regmap_bulk_write(dev->regmap, 0x066 + 2 * index, buf, 2);
        if (ret)
                goto err;
 
@@ -1193,12 +1062,6 @@ static int rtl2832_probe(struct i2c_client *client,
        struct rtl2832_dev *dev;
        int ret;
        u8 tmp;
-       static const struct regmap_bus regmap_bus = {
-               .read = rtl2832_regmap_read,
-               .write = rtl2832_regmap_write,
-               .gather_write = rtl2832_regmap_gather_write,
-               .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-       };
        static const struct regmap_range_cfg regmap_range_cfg[] = {
                {
                        .selector_reg     = 0x00,
@@ -1231,15 +1094,12 @@ static int rtl2832_probe(struct i2c_client *client,
        mutex_init(&dev->regmap_mutex);
        dev->regmap_config.reg_bits =  8,
        dev->regmap_config.val_bits =  8,
-       dev->regmap_config.lock = rtl2832_regmap_lock,
-       dev->regmap_config.unlock = rtl2832_regmap_unlock,
-       dev->regmap_config.lock_arg = dev,
        dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
        dev->regmap_config.max_register = 5 * 0x100,
        dev->regmap_config.ranges = regmap_range_cfg,
        dev->regmap_config.num_ranges = ARRAY_SIZE(regmap_range_cfg),
        dev->regmap_config.cache_type = REGCACHE_NONE,
-       dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
+       dev->regmap = regmap_init(&client->dev, NULL, client,
                                  &dev->regmap_config);
        if (IS_ERR(dev->regmap)) {
                ret = PTR_ERR(dev->regmap);
@@ -1247,12 +1107,13 @@ static int rtl2832_probe(struct i2c_client *client,
        }
 
        /* check if the demod is there */
-       ret = rtl2832_bulk_read(client, 0x000, &tmp, 1);
+       ret = regmap_bulk_read(dev->regmap, 0x000, &tmp, 1);
        if (ret)
                goto err_regmap_exit;
 
        /* create muxed i2c adapter for demod tuner bus */
-       dev->muxc = i2c_mux_one_adapter(i2c, &i2c->dev, 0, 0, 0, 0, 0,
+       dev->muxc = i2c_mux_one_adapter(i2c, &i2c->dev, 0,
+                                       I2C_CONTROLLED_MUX, 0, 0, 0,
                                        rtl2832_select, rtl2832_deselect);
        if (IS_ERR(dev->muxc)) {
                ret = PTR_ERR(dev->muxc);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to