Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Em Mon, 10 Apr 2017 20:06:03 +0200 Frank Schäferescreveu: > Am 26.03.2017 um 16:24 schrieb Frank Schäfer: > > > > > > Am 24.03.2017 um 20:16 schrieb Mauro Carvalho Chehab: > >> Em Thu, 23 Mar 2017 19:03:20 +0100 > >> Frank Schäfer escreveu: > >> > >>> Am 23.03.2017 um 13:56 schrieb Mauro Carvalho Chehab: > Em Thu, 23 Mar 2017 13:01:32 +0100 > Frank Schäfer escreveu: > > > Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: > >> Em Sun, 19 Feb 2017 19:29:18 +0100 > >> Frank Schäfer escreveu: > >> > >>> Use i2c_smbus_read_word_data() instead of i2c_master_send() and > >>> i2c_master_recv() for reading the ID of Micorn sensors. > >>> Bytes need to be swapped afterwards, because > >>> i2c_smbus_read_word_data() > >>> assumes that the received bytes are little-endian byte order (as > >>> specified > >>> by smbus), while Micron sensors with 16 bit register width use > >>> big endian > >>> byte order. > >>> > >>> Signed-off-by: Frank Schäfer > >>> --- > >>> drivers/media/usb/em28xx/em28xx-camera.c | 28 > >>> > >>> 1 file changed, 4 insertions(+), 24 deletions(-) > >>> > >>> diff --git a/drivers/media/usb/em28xx/em28xx-camera.c > >>> b/drivers/media/usb/em28xx/em28xx-camera.c > >>> index 7b4129ab1cf9..4839479624e7 100644 > >>> --- a/drivers/media/usb/em28xx/em28xx-camera.c > >>> +++ b/drivers/media/usb/em28xx/em28xx-camera.c > >>> @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct > >>> em28xx *dev) > >>> { > >>> int ret, i; > >>> char *name; > >>> -u8 reg; > >>> -__be16 id_be; > >>> u16 id; > >>> struct i2c_client *client = > >>> >i2c_client[dev->def_i2c_bus]; > >>> @@ -115,10 +113,8 @@ static int > >>> em28xx_probe_sensor_micron(struct em28xx *dev) > >>> dev->em28xx_sensor = EM28XX_NOSENSOR; > >>> for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; > >>> i++) { > >>> client->addr = micron_sensor_addrs[i]; > >>> -/* NOTE: i2c_smbus_read_word_data() doesn't work with > >>> BE data */ > >>> /* Read chip ID from register 0x00 */ > >>> -reg = 0x00; > >>> -ret = i2c_master_send(client, , 1); > >>> +ret = i2c_smbus_read_word_data(client, 0x00); /* > >>> assumes LE */ > >>> if (ret < 0) { > >>> if (ret != -ENXIO) > >>> dev_err(>intf->dev, > >>> @@ -126,24 +122,9 @@ static int > >>> em28xx_probe_sensor_micron(struct em28xx *dev) > >>>client->addr << 1, ret); > >>> continue; > >>> } > >>> -ret = i2c_master_recv(client, (u8 *)_be, 2); > >>> -if (ret < 0) { > >>> -dev_err(>intf->dev, > >>> -"couldn't read from i2c device 0x%02x: error > >>> %i\n", > >>> -client->addr << 1, ret); > >>> -continue; > >>> -} > >>> -id = be16_to_cpu(id_be); > >>> +id = swab16(ret); /* LE -> BE */ > >> That's wrong! You can't assume that CPU is BE, as some archs use LE. > >> > >> You should, instead, call le16_to_cpu(), to be sure that it will be > >> doing the right thing. > >> > >> Something like: > >> > >> id = le16_to_cpu((__le16)ret); > > SMBus read/write word transfers are always LE (see SMBus spec section > > 6.5.5), > > which is also what i2c_smbus_xfer_emulated() assumes: > > http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 > I got that part, but, if the CPU is also LE, doing swab16() is > wrong. It should swap it *only* if the CPU is BE. > >>> No, it should always be swapped, because the bytes are always > >>> transfered > >>> in the wrong order. > >>> The cpu endianess doesn't matter, (0x12 << 8) | 0x34 is always 0x1234. > >> You still didn't get it. > >> > >> Let's assume that the ID is 0x148c (MT9M112). > >> > >> This value, represented in low endian, is stored in memory as: > >> > >> unsigned char __id[2] = { 0x8c, 0x14 }; > >> > >> If we do: > >> u16 ret = *(u16 *)__id; > >> > >> What's stored at "ret" will depend if the sistem is LE or BE: > >> > >> on LE, ret == 0x148c > >> on BE, ret == 0x8c14 > >> > >> If you do: > >> u16 id = swapb16(val) > >> > >> you'll get: > >> > >> on LE, id == 0x8c14 > >> on BE, id == 0x148c > >> > >> So, the value will be *wrong* at LE. > >> > >> However, if you do: > >> id = le16_to_cpu((__le16)ret); > >> > >> On LE, this will evaluate to id = ret, and on BE, to id =
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Am 26.03.2017 um 16:24 schrieb Frank Schäfer: > > > Am 24.03.2017 um 20:16 schrieb Mauro Carvalho Chehab: >> Em Thu, 23 Mar 2017 19:03:20 +0100 >> Frank Schäferescreveu: >> >>> Am 23.03.2017 um 13:56 schrieb Mauro Carvalho Chehab: Em Thu, 23 Mar 2017 13:01:32 +0100 Frank Schäfer escreveu: > Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: >> Em Sun, 19 Feb 2017 19:29:18 +0100 >> Frank Schäfer escreveu: >> >>> Use i2c_smbus_read_word_data() instead of i2c_master_send() and >>> i2c_master_recv() for reading the ID of Micorn sensors. >>> Bytes need to be swapped afterwards, because >>> i2c_smbus_read_word_data() >>> assumes that the received bytes are little-endian byte order (as >>> specified >>> by smbus), while Micron sensors with 16 bit register width use >>> big endian >>> byte order. >>> >>> Signed-off-by: Frank Schäfer >>> --- >>> drivers/media/usb/em28xx/em28xx-camera.c | 28 >>> >>> 1 file changed, 4 insertions(+), 24 deletions(-) >>> >>> diff --git a/drivers/media/usb/em28xx/em28xx-camera.c >>> b/drivers/media/usb/em28xx/em28xx-camera.c >>> index 7b4129ab1cf9..4839479624e7 100644 >>> --- a/drivers/media/usb/em28xx/em28xx-camera.c >>> +++ b/drivers/media/usb/em28xx/em28xx-camera.c >>> @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct >>> em28xx *dev) >>> { >>> int ret, i; >>> char *name; >>> -u8 reg; >>> -__be16 id_be; >>> u16 id; >>> struct i2c_client *client = >>> >i2c_client[dev->def_i2c_bus]; >>> @@ -115,10 +113,8 @@ static int >>> em28xx_probe_sensor_micron(struct em28xx *dev) >>> dev->em28xx_sensor = EM28XX_NOSENSOR; >>> for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; >>> i++) { >>> client->addr = micron_sensor_addrs[i]; >>> -/* NOTE: i2c_smbus_read_word_data() doesn't work with >>> BE data */ >>> /* Read chip ID from register 0x00 */ >>> -reg = 0x00; >>> -ret = i2c_master_send(client, , 1); >>> +ret = i2c_smbus_read_word_data(client, 0x00); /* >>> assumes LE */ >>> if (ret < 0) { >>> if (ret != -ENXIO) >>> dev_err(>intf->dev, >>> @@ -126,24 +122,9 @@ static int >>> em28xx_probe_sensor_micron(struct em28xx *dev) >>>client->addr << 1, ret); >>> continue; >>> } >>> -ret = i2c_master_recv(client, (u8 *)_be, 2); >>> -if (ret < 0) { >>> -dev_err(>intf->dev, >>> -"couldn't read from i2c device 0x%02x: error >>> %i\n", >>> -client->addr << 1, ret); >>> -continue; >>> -} >>> -id = be16_to_cpu(id_be); >>> +id = swab16(ret); /* LE -> BE */ >> That's wrong! You can't assume that CPU is BE, as some archs use LE. >> >> You should, instead, call le16_to_cpu(), to be sure that it will be >> doing the right thing. >> >> Something like: >> >> id = le16_to_cpu((__le16)ret); > SMBus read/write word transfers are always LE (see SMBus spec section > 6.5.5), > which is also what i2c_smbus_xfer_emulated() assumes: > http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 I got that part, but, if the CPU is also LE, doing swab16() is wrong. It should swap it *only* if the CPU is BE. >>> No, it should always be swapped, because the bytes are always >>> transfered >>> in the wrong order. >>> The cpu endianess doesn't matter, (0x12 << 8) | 0x34 is always 0x1234. >> You still didn't get it. >> >> Let's assume that the ID is 0x148c (MT9M112). >> >> This value, represented in low endian, is stored in memory as: >> >> unsigned char __id[2] = { 0x8c, 0x14 }; >> >> If we do: >> u16 ret = *(u16 *)__id; >> >> What's stored at "ret" will depend if the sistem is LE or BE: >> >> on LE, ret == 0x148c >> on BE, ret == 0x8c14 >> >> If you do: >> u16 id = swapb16(val) >> >> you'll get: >> >> on LE, id == 0x8c14 >> on BE, id == 0x148c >> >> So, the value will be *wrong* at LE. >> >> However, if you do: >> id = le16_to_cpu((__le16)ret); >> >> On LE, this will evaluate to id = ret, and on BE, to id = swab16(ret). >> So, on both, you'll have: >> id = 0x148c. > > Can you please show me the code line(s) that make the value of the > word returned by i2c_smbus_read_word_data() cpu endianess dependent ? :) > Ping !? Cheers, Frank
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Am 24.03.2017 um 20:16 schrieb Mauro Carvalho Chehab: Em Thu, 23 Mar 2017 19:03:20 +0100 Frank Schäferescreveu: Am 23.03.2017 um 13:56 schrieb Mauro Carvalho Chehab: Em Thu, 23 Mar 2017 13:01:32 +0100 Frank Schäfer escreveu: Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: Em Sun, 19 Feb 2017 19:29:18 +0100 Frank Schäfer escreveu: Use i2c_smbus_read_word_data() instead of i2c_master_send() and i2c_master_recv() for reading the ID of Micorn sensors. Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() assumes that the received bytes are little-endian byte order (as specified by smbus), while Micron sensors with 16 bit register width use big endian byte order. Signed-off-by: Frank Schäfer --- drivers/media/usb/em28xx/em28xx-camera.c | 28 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 7b4129ab1cf9..4839479624e7 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; - __be16 id_be; u16 id; struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client->addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(client, , 1); + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ if (ret < 0) { if (ret != -ENXIO) dev_err(>intf->dev, @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) client->addr << 1, ret); continue; } - ret = i2c_master_recv(client, (u8 *)_be, 2); - if (ret < 0) { - dev_err(>intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - id = be16_to_cpu(id_be); + id = swab16(ret); /* LE -> BE */ That's wrong! You can't assume that CPU is BE, as some archs use LE. You should, instead, call le16_to_cpu(), to be sure that it will be doing the right thing. Something like: id = le16_to_cpu((__le16)ret); SMBus read/write word transfers are always LE (see SMBus spec section 6.5.5), which is also what i2c_smbus_xfer_emulated() assumes: http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 I got that part, but, if the CPU is also LE, doing swab16() is wrong. It should swap it *only* if the CPU is BE. No, it should always be swapped, because the bytes are always transfered in the wrong order. The cpu endianess doesn't matter, (0x12 << 8) | 0x34 is always 0x1234. You still didn't get it. Let's assume that the ID is 0x148c (MT9M112). This value, represented in low endian, is stored in memory as: unsigned char __id[2] = { 0x8c, 0x14 }; If we do: u16 ret = *(u16 *)__id; What's stored at "ret" will depend if the sistem is LE or BE: on LE, ret == 0x148c on BE, ret == 0x8c14 If you do: u16 id = swapb16(val) you'll get: on LE, id == 0x8c14 on BE, id == 0x148c So, the value will be *wrong* at LE. However, if you do: id = le16_to_cpu((__le16)ret); On LE, this will evaluate to id = ret, and on BE, to id = swab16(ret). So, on both, you'll have: id = 0x148c. Can you please show me the code line(s) that make the value of the word returned by i2c_smbus_read_word_data() cpu endianess dependent ? :) Cheers, Frank Thanks, Mauro
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Em Thu, 23 Mar 2017 19:03:20 +0100 Frank Schäferescreveu: > Am 23.03.2017 um 13:56 schrieb Mauro Carvalho Chehab: > > Em Thu, 23 Mar 2017 13:01:32 +0100 > > Frank Schäfer escreveu: > > > >> Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: > >>> Em Sun, 19 Feb 2017 19:29:18 +0100 > >>> Frank Schäfer escreveu: > >>> > Use i2c_smbus_read_word_data() instead of i2c_master_send() and > i2c_master_recv() for reading the ID of Micorn sensors. > Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() > assumes that the received bytes are little-endian byte order (as > specified > by smbus), while Micron sensors with 16 bit register width use big endian > byte order. > > Signed-off-by: Frank Schäfer > --- > drivers/media/usb/em28xx/em28xx-camera.c | 28 > > 1 file changed, 4 insertions(+), 24 deletions(-) > > diff --git a/drivers/media/usb/em28xx/em28xx-camera.c > b/drivers/media/usb/em28xx/em28xx-camera.c > index 7b4129ab1cf9..4839479624e7 100644 > --- a/drivers/media/usb/em28xx/em28xx-camera.c > +++ b/drivers/media/usb/em28xx/em28xx-camera.c > @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx > *dev) > { > int ret, i; > char *name; > -u8 reg; > -__be16 id_be; > u16 id; > > struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; > @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx > *dev) > dev->em28xx_sensor = EM28XX_NOSENSOR; > for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { > client->addr = micron_sensor_addrs[i]; > -/* NOTE: i2c_smbus_read_word_data() doesn't work with > BE data */ > /* Read chip ID from register 0x00 */ > -reg = 0x00; > -ret = i2c_master_send(client, , 1); > +ret = i2c_smbus_read_word_data(client, 0x00); /* > assumes LE */ > if (ret < 0) { > if (ret != -ENXIO) > dev_err(>intf->dev, > @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx > *dev) > client->addr << 1, ret); > continue; > } > -ret = i2c_master_recv(client, (u8 *)_be, 2); > -if (ret < 0) { > -dev_err(>intf->dev, > -"couldn't read from i2c device 0x%02x: > error %i\n", > -client->addr << 1, ret); > -continue; > -} > -id = be16_to_cpu(id_be); > +id = swab16(ret); /* LE -> BE */ > >>> That's wrong! You can't assume that CPU is BE, as some archs use LE. > >>> > >>> You should, instead, call le16_to_cpu(), to be sure that it will be > >>> doing the right thing. > >>> > >>> Something like: > >>> > >>> id = le16_to_cpu((__le16)ret); > >> SMBus read/write word transfers are always LE (see SMBus spec section > >> 6.5.5), > >> which is also what i2c_smbus_xfer_emulated() assumes: > >> http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 > > I got that part, but, if the CPU is also LE, doing swab16() is > > wrong. It should swap it *only* if the CPU is BE. > No, it should always be swapped, because the bytes are always transfered > in the wrong order. > The cpu endianess doesn't matter, (0x12 << 8) | 0x34 is always 0x1234. You still didn't get it. Let's assume that the ID is 0x148c (MT9M112). This value, represented in low endian, is stored in memory as: unsigned char __id[2] = { 0x8c, 0x14 }; If we do: u16 ret = *(u16 *)__id; What's stored at "ret" will depend if the sistem is LE or BE: on LE, ret == 0x148c on BE, ret == 0x8c14 If you do: u16 id = swapb16(val) you'll get: on LE, id == 0x8c14 on BE, id == 0x148c So, the value will be *wrong* at LE. However, if you do: id = le16_to_cpu((__le16)ret); On LE, this will evaluate to id = ret, and on BE, to id = swab16(ret). So, on both, you'll have: id = 0x148c. Thanks, Mauro
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Am 23.03.2017 um 13:56 schrieb Mauro Carvalho Chehab: Em Thu, 23 Mar 2017 13:01:32 +0100 Frank Schäferescreveu: Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: Em Sun, 19 Feb 2017 19:29:18 +0100 Frank Schäfer escreveu: Use i2c_smbus_read_word_data() instead of i2c_master_send() and i2c_master_recv() for reading the ID of Micorn sensors. Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() assumes that the received bytes are little-endian byte order (as specified by smbus), while Micron sensors with 16 bit register width use big endian byte order. Signed-off-by: Frank Schäfer --- drivers/media/usb/em28xx/em28xx-camera.c | 28 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 7b4129ab1cf9..4839479624e7 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; - __be16 id_be; u16 id; struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client->addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(client, , 1); + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ if (ret < 0) { if (ret != -ENXIO) dev_err(>intf->dev, @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) client->addr << 1, ret); continue; } - ret = i2c_master_recv(client, (u8 *)_be, 2); - if (ret < 0) { - dev_err(>intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - id = be16_to_cpu(id_be); + id = swab16(ret); /* LE -> BE */ That's wrong! You can't assume that CPU is BE, as some archs use LE. You should, instead, call le16_to_cpu(), to be sure that it will be doing the right thing. Something like: id = le16_to_cpu((__le16)ret); SMBus read/write word transfers are always LE (see SMBus spec section 6.5.5), which is also what i2c_smbus_xfer_emulated() assumes: http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 I got that part, but, if the CPU is also LE, doing swab16() is wrong. It should swap it *only* if the CPU is BE. No, it should always be swapped, because the bytes are always transfered in the wrong order. The cpu endianess doesn't matter, (0x12 << 8) | 0x34 is always 0x1234. Regards, Frank le16_to_cpu() should do the right thing, e. g. swap for BE CPUs or not swap otherwise. Thanks, Mauro
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Em Thu, 23 Mar 2017 13:01:32 +0100 Frank Schäferescreveu: > Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: > > Em Sun, 19 Feb 2017 19:29:18 +0100 > > Frank Schäfer escreveu: > > > >> Use i2c_smbus_read_word_data() instead of i2c_master_send() and > >> i2c_master_recv() for reading the ID of Micorn sensors. > >> Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() > >> assumes that the received bytes are little-endian byte order (as specified > >> by smbus), while Micron sensors with 16 bit register width use big endian > >> byte order. > >> > >> Signed-off-by: Frank Schäfer > >> --- > >> drivers/media/usb/em28xx/em28xx-camera.c | 28 > >> > >> 1 file changed, 4 insertions(+), 24 deletions(-) > >> > >> diff --git a/drivers/media/usb/em28xx/em28xx-camera.c > >> b/drivers/media/usb/em28xx/em28xx-camera.c > >> index 7b4129ab1cf9..4839479624e7 100644 > >> --- a/drivers/media/usb/em28xx/em28xx-camera.c > >> +++ b/drivers/media/usb/em28xx/em28xx-camera.c > >> @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx > >> *dev) > >> { > >>int ret, i; > >>char *name; > >> - u8 reg; > >> - __be16 id_be; > >>u16 id; > >> > >>struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; > >> @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx > >> *dev) > >>dev->em28xx_sensor = EM28XX_NOSENSOR; > >>for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { > >>client->addr = micron_sensor_addrs[i]; > >> - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ > >>/* Read chip ID from register 0x00 */ > >> - reg = 0x00; > >> - ret = i2c_master_send(client, , 1); > >> + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ > >>if (ret < 0) { > >>if (ret != -ENXIO) > >>dev_err(>intf->dev, > >> @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx > >> *dev) > >> client->addr << 1, ret); > >>continue; > >>} > >> - ret = i2c_master_recv(client, (u8 *)_be, 2); > >> - if (ret < 0) { > >> - dev_err(>intf->dev, > >> - "couldn't read from i2c device 0x%02x: error > >> %i\n", > >> - client->addr << 1, ret); > >> - continue; > >> - } > >> - id = be16_to_cpu(id_be); > >> + id = swab16(ret); /* LE -> BE */ > > That's wrong! You can't assume that CPU is BE, as some archs use LE. > > > > You should, instead, call le16_to_cpu(), to be sure that it will be > > doing the right thing. > > > > Something like: > > > > id = le16_to_cpu((__le16)ret); > > SMBus read/write word transfers are always LE (see SMBus spec section > 6.5.5), > which is also what i2c_smbus_xfer_emulated() assumes: > http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 I got that part, but, if the CPU is also LE, doing swab16() is wrong. It should swap it *only* if the CPU is BE. le16_to_cpu() should do the right thing, e. g. swap for BE CPUs or not swap otherwise. Thanks, Mauro
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Am 22.03.2017 um 15:46 schrieb Mauro Carvalho Chehab: Em Sun, 19 Feb 2017 19:29:18 +0100 Frank Schäferescreveu: Use i2c_smbus_read_word_data() instead of i2c_master_send() and i2c_master_recv() for reading the ID of Micorn sensors. Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() assumes that the received bytes are little-endian byte order (as specified by smbus), while Micron sensors with 16 bit register width use big endian byte order. Signed-off-by: Frank Schäfer --- drivers/media/usb/em28xx/em28xx-camera.c | 28 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 7b4129ab1cf9..4839479624e7 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; - __be16 id_be; u16 id; struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client->addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(client, , 1); + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ if (ret < 0) { if (ret != -ENXIO) dev_err(>intf->dev, @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) client->addr << 1, ret); continue; } - ret = i2c_master_recv(client, (u8 *)_be, 2); - if (ret < 0) { - dev_err(>intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - id = be16_to_cpu(id_be); + id = swab16(ret); /* LE -> BE */ That's wrong! You can't assume that CPU is BE, as some archs use LE. You should, instead, call le16_to_cpu(), to be sure that it will be doing the right thing. Something like: id = le16_to_cpu((__le16)ret); SMBus read/write word transfers are always LE (see SMBus spec section 6.5.5), which is also what i2c_smbus_xfer_emulated() assumes: http://lxr.free-electrons.com/source/drivers/i2c/i2c-core.c#L3485 Regards, Frank Regards, Thanks, Mauro
Re: [PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Em Sun, 19 Feb 2017 19:29:18 +0100 Frank Schäferescreveu: > Use i2c_smbus_read_word_data() instead of i2c_master_send() and > i2c_master_recv() for reading the ID of Micorn sensors. > Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() > assumes that the received bytes are little-endian byte order (as specified > by smbus), while Micron sensors with 16 bit register width use big endian > byte order. > > Signed-off-by: Frank Schäfer > --- > drivers/media/usb/em28xx/em28xx-camera.c | 28 > 1 file changed, 4 insertions(+), 24 deletions(-) > > diff --git a/drivers/media/usb/em28xx/em28xx-camera.c > b/drivers/media/usb/em28xx/em28xx-camera.c > index 7b4129ab1cf9..4839479624e7 100644 > --- a/drivers/media/usb/em28xx/em28xx-camera.c > +++ b/drivers/media/usb/em28xx/em28xx-camera.c > @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > { > int ret, i; > char *name; > - u8 reg; > - __be16 id_be; > u16 id; > > struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; > @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > dev->em28xx_sensor = EM28XX_NOSENSOR; > for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { > client->addr = micron_sensor_addrs[i]; > - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ > /* Read chip ID from register 0x00 */ > - reg = 0x00; > - ret = i2c_master_send(client, , 1); > + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ > if (ret < 0) { > if (ret != -ENXIO) > dev_err(>intf->dev, > @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) > client->addr << 1, ret); > continue; > } > - ret = i2c_master_recv(client, (u8 *)_be, 2); > - if (ret < 0) { > - dev_err(>intf->dev, > - "couldn't read from i2c device 0x%02x: error > %i\n", > - client->addr << 1, ret); > - continue; > - } > - id = be16_to_cpu(id_be); > + id = swab16(ret); /* LE -> BE */ That's wrong! You can't assume that CPU is BE, as some archs use LE. You should, instead, call le16_to_cpu(), to be sure that it will be doing the right thing. Something like: id = le16_to_cpu((__le16)ret); Regards, Thanks, Mauro
[PATCH 2/2] em28xx: simplify ID-reading from Micron sensors
Use i2c_smbus_read_word_data() instead of i2c_master_send() and i2c_master_recv() for reading the ID of Micorn sensors. Bytes need to be swapped afterwards, because i2c_smbus_read_word_data() assumes that the received bytes are little-endian byte order (as specified by smbus), while Micron sensors with 16 bit register width use big endian byte order. Signed-off-by: Frank Schäfer--- drivers/media/usb/em28xx/em28xx-camera.c | 28 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 7b4129ab1cf9..4839479624e7 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -106,8 +106,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; - __be16 id_be; u16 id; struct i2c_client *client = >i2c_client[dev->def_i2c_bus]; @@ -115,10 +113,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client->addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(client, , 1); + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ if (ret < 0) { if (ret != -ENXIO) dev_err(>intf->dev, @@ -126,24 +122,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) client->addr << 1, ret); continue; } - ret = i2c_master_recv(client, (u8 *)_be, 2); - if (ret < 0) { - dev_err(>intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - id = be16_to_cpu(id_be); + id = swab16(ret); /* LE -> BE */ /* Read chip ID from register 0xff */ - reg = 0xff; - ret = i2c_master_send(client, , 1); - if (ret < 0) { - dev_err(>intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - ret = i2c_master_recv(client, (u8 *)_be, 2); + ret = i2c_smbus_read_word_data(client, 0xff); if (ret < 0) { dev_err(>intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", @@ -151,10 +132,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) continue; } /* Validate chip ID to be sure we have a Micron device */ - if (id != be16_to_cpu(id_be)) + if (id != swab16(ret)) continue; /* Check chip ID */ - id = be16_to_cpu(id_be); switch (id) { case 0x1222: name = "MT9V012"; /* MI370 */ /* 640x480 */ -- 2.11.0