summaryrefslogtreecommitdiff
path: root/drivers/media/usb/em28xx/em28xx-i2c.c
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-03-03 22:37:42 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-04 23:23:27 +0400
commita217968f919b0574ef59054430d8908aebcf0a35 (patch)
tree4675b3228a1a783ba686f5c9bc64b303c10f805f /drivers/media/usb/em28xx/em28xx-i2c.c
parentd832c5b28aff3c9aadfbde3002b640058eee6294 (diff)
downloadlinux-a217968f919b0574ef59054430d8908aebcf0a35.tar.xz
[media] em28xx: do not store eeprom content permanently
We currently reserve an array of 256 bytes for the eeprom content in the device struct. For eeproms with 16 bit address width it might even be necessary to increase the buffer size further. Having such a big chunk of memory reserved even if the device has no eeprom and keeping it after it has already been processed seems to be a waste of memory. Change the code to allocate + free the eeprom memory dynamically. This also makes it possible to handle different dataset sizes depending on what is stored/found in the eeprom. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-i2c.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 438cfbcb9bf5..8d4817747bf2 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -409,27 +409,33 @@ static int em28xx_i2c_read_block(struct em28xx *dev, u16 addr, bool addr_w16,
return len;
}
-static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char **eedata, int len)
{
- unsigned char buf, *p = eedata;
- struct em28xx_eeprom *em_eeprom = (void *)eedata;
+ u8 buf, *data;
+ struct em28xx_eeprom *em_eeprom;
int i, err;
+ *eedata = NULL;
+
dev->i2c_client.addr = 0xa0 >> 1;
/* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) {
em28xx_info("board has no eeprom\n");
- memset(eedata, 0, len);
return -ENODEV;
}
+ data = kzalloc(len, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
/* Read EEPROM content */
err = em28xx_i2c_read_block(dev, 0x0000, dev->eeprom_addrwidth_16bit,
- len, p);
+ len, data);
if (err != len) {
em28xx_errdev("failed to read eeprom (err=%d)\n", err);
+ kfree(data);
return err;
}
@@ -441,19 +447,19 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
else
em28xx_info("i2c eeprom %02x:", i);
}
- printk(" %02x", eedata[i]);
+ printk(" %02x", data[i]);
if (15 == (i % 16))
printk("\n");
}
if (dev->eeprom_addrwidth_16bit &&
- eedata[0] == 0x26 && eedata[3] == 0x00) {
+ data[0] == 0x26 && data[3] == 0x00) {
/* new eeprom format; size 4-64kb */
- dev->hash = em28xx_hash_mem(eedata, len, 32);
+ dev->hash = em28xx_hash_mem(data, len, 32);
em28xx_info("EEPROM hash = 0x%08lx\n", dev->hash);
em28xx_info("EEPROM info: boot page address = 0x%02x04, "
"boot configuration = 0x%02x\n",
- eedata[1], eedata[2]);
+ data[1], data[2]);
/* boot configuration (address 0x0002):
* [0] microcode download speed: 1 = 400 kHz; 0 = 100 kHz
* [1] always selects 12 kb RAM
@@ -471,13 +477,16 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
*/
return 0;
- } else if (em_eeprom->id[0] != 0x1a || em_eeprom->id[1] != 0xeb ||
- em_eeprom->id[2] != 0x67 || em_eeprom->id[3] != 0x95) {
+ } else if (data[0] != 0x1a || data[1] != 0xeb ||
+ data[2] != 0x67 || data[3] != 0x95) {
em28xx_info("unknown eeprom format or eeprom corrupted !\n");
return -ENODEV;
}
- dev->hash = em28xx_hash_mem(eedata, len, 32);
+ *eedata = data;
+ em_eeprom = (void *)eedata;
+
+ dev->hash = em28xx_hash_mem(data, len, 32);
em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
em_eeprom->id[0], em_eeprom->id[1],
@@ -635,7 +644,7 @@ int em28xx_i2c_register(struct em28xx *dev)
dev->i2c_client = em28xx_client_template;
dev->i2c_client.adapter = &dev->i2c_adap;
- retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+ retval = em28xx_i2c_eeprom(dev, &dev->eedata, 256);
if ((retval < 0) && (retval != -ENODEV)) {
em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
__func__, retval);