Re: [PATCH 1/2] ir-core: centralize sysfs raw decoder enabling/disabling
On 06/13/2010 01:29 PM, David Härdeman wrote: diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index daf33c1..7ae5662 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -33,122 +33,178 @@ static struct class ir_input_class = { }; /** - * show_protocol() - shows the current IR protocol + * show_protocols() - shows the current IR protocol(s) * @d:the device descriptor * @mattr:the device attribute struct (unused) * @buf: a pointer to the output buffer * - * This routine is a callback routine for input read the IR protocol type. - * it is trigged by reading /sys/class/rc/rc?/current_protocol. - * It returns the protocol name, as understood by the driver. + * This routine is a callback routine for input read the IR protocol type(s). + * it is trigged by reading /sys/class/rc/rc?/protocols. + * It returns the protocol names of supported protocols. + * Enabled protocols are printed in brackets. */ -static ssize_t show_protocol(struct device *d, -struct device_attribute *mattr, char *buf) +static ssize_t show_protocols(struct device *d, + struct device_attribute *mattr, char *buf) { - char *s; struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 ir_type = ir_dev->rc_tab.ir_type; - - IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); - - /* FIXME: doesn't support multiple protocols at the same time */ - if (ir_type == IR_TYPE_UNKNOWN) - s = "Unknown"; - else if (ir_type == IR_TYPE_RC5) - s = "rc-5"; - else if (ir_type == IR_TYPE_NEC) - s = "nec"; - else if (ir_type == IR_TYPE_RC6) - s = "rc6"; - else if (ir_type == IR_TYPE_JVC) - s = "jvc"; - else if (ir_type == IR_TYPE_SONY) - s = "sony"; - else - s = "other"; + u64 allowed, enabled; + char *tmp = buf; + + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { This change introduced an oops for me. On my saa7134 MSI TV Anywhere Plus, ir_dev->props is null, so dereferencing it causes the following while attempting to read /sys/devices/virtual/rc/rc0/protocols: [ 601.632041] BUG: unable to handle kernel NULL pointer dereference at (null) [ 601.632061] IP: [] show_protocols+0x25/0x120 [ir_core] [ 601.632079] PGD 7b181067 PUD 7bafe067 PMD 0 [ 601.632093] Oops: [#1] SMP [ 601.632103] last sysfs file: /sys/devices/virtual/rc/rc0/protocols [ 601.632111] CPU 0 [ 601.632115] Modules linked in: binfmt_misc rfcomm parport_pc ppdev sco bnep l2cap saa7134_alsa arc4 rc_msi_tvanywhere_plus ir_kbd_i2c advantechwdt tda827x rt2500pci rt2x00pci rt2x00lib snd_intel8x0 tda8290 snd_ac97_codec led_class ac97_bus tuner snd_seq_midi snd_rawmidi ir_lirc_codec lirc_dev mac80211 cfg80211 snd_seq_midi_event ir_sony_decoder ir_jvc_decoder saa7134 v4l2_common videodev v4l1_compat v4l2_compat_ioctl32 psmouse serio_raw ir_rc6_decoder snd_pcm snd_seq lp shpchp eeprom_93cx6 btusb snd_timer snd_seq_device videobuf_dma_sg ir_rc5_decoder snd videobuf_core ir_nec_decoder ir_common ir_core tveeprom soundcore edac_core bluetooth snd_page_alloc parport i2c_nforce2 k8temp edac_mce_amd usbhid hid btrfs zlib_deflate crc32c libcrc32c sata_nv forcedeth pata_amd [ 601.632319] [ 601.632335] Pid: 2928, comm: cat Not tainted 2.6.36-rc3-00185-gd56557a #2 KN9 Series(NF-CK804)/Unknow [ 601.632368] RIP: 0010:[] [] show_protocols+0x25/0x120 [ir_core] [ 601.632404] RSP: 0018:88007bb93e38 EFLAGS: 00010282 [ 601.632423] RAX: 88007bb6e000 RBX: a00f5ee0 RCX: a00f4390 [ 601.632444] RDX: RSI: a00f5ee0 RDI: 88007bb6e000 [ 601.632465] RBP: 88007bb93e68 R08: 88007bb6e010 R09: 8164ab40 [ 601.632486] R10: R11: 0246 R12: 88007c928000 [ 601.632507] R13: 8000 R14: 0246d000 R15: 88007c8798a0 [ 601.632529] FS: 7fe7aa26c700() GS:880001e0() knlGS: [ 601.632561] CS: 0010 DS: ES: CR0: 80050033 [ 601.632580] CR2: CR3: 7b19f000 CR4: 06f0 [ 601.632601] DR0: DR1: DR2: [ 601.632623] DR3: DR6: 0ff0 DR7: 0400 [ 601.632644] Process cat (pid: 2928, threadinfo 88007bb92000, task 88007bcd2dc0) [ 601.632675] Stack: [ 601.632689] a00f5ee0 88007bb93f48 8000 [ 601.632713] <0> 0246d000 88007c8798a0 88007bb93e98 813816e7 [ 601.632750] <0> 88007bb93e88 8110681e 88007bb93e98 88007c8798c0 [ 601.632797] Call Trace: [ 601.632819] [] dev_attr_show+0x27/0x50 [ 601.632842] [] ? __get_free_pages+0xe/0x50 [ 601.632864] [] sysfs_read_f
[PATCH] ir-core: Fix null dereferences in the protocols sysfs interface
On 09/08/2010 07:16 AM, Jarod Wilson wrote: On Wed, Sep 08, 2010 at 07:04:03AM -0700, Brian Rogers wrote: ir_dev->raw is also null. If I check these pointers before using them, and bail out if both are null, then I get a working lircd, but of course the file /sys/devices/virtual/rc/rc0/protocols no longer does anything. On 2.6.35.4, the system never creates the /sys/class/rc/rc0/current_protocol file. Is it the case that the 'protocols' file should never appear, because my card can't support this feature? Hm... So protocols is indeed intended for hardware that handles raw IR, as its a list of raw IR decoders available/enabled/disabled for the receiver. But some devices that do onboard decoding and deal with scancodes still need to support changing protocols, as they can be told "decode rc5" or "decode nec", etc... My memory is currently foggy on how it was exactly that it was supposed to be donee though. :) (Yet another reason I really need to poke at the imon driver code again). How about the attached patch? Does this look like a reasonable solution for 2.6.36? Brian >From 7937051c5e2c8b5b0410172d48e62d54bd1906ee Mon Sep 17 00:00:00 2001 From: Brian Rogers Date: Wed, 8 Sep 2010 05:33:34 -0700 Subject: [PATCH] ir-core: Fix null dereferences in the protocols sysfs interface For some cards, ir_dev->props and ir_dev->raw are both NULL. These cards are using built-in IR decoding instead of raw, and can't easily be made to switch protocols. So upon reading /sys/class/rc/rc?/protocols on such a card, return 'builtin' as the supported and enabled protocol. Return -EINVAL on any attempts to change the protocol. And most important of all, don't crash. Signed-off-by: Brian Rogers --- drivers/media/IR/ir-sysfs.c | 17 +++-- 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 96dafc4..46d4246 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d, char *tmp = buf; int i; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { enabled = ir_dev->rc_tab.ir_type; allowed = ir_dev->props->allowed_protos; - } else { + } else if (ir_dev->raw) { enabled = ir_dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return sprintf(tmp, "[builtin]\n"); IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, @@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d, int rc, i, count = 0; unsigned long flags; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) type = ir_dev->rc_tab.ir_type; - else + else if (ir_dev->raw) type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } while ((tmp = strsep((char **) &data, " \n")) != NULL) { if (!*tmp) @@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d, } } - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); ir_dev->rc_tab.ir_type = type; spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); -- 1.7.1
[PATCH] ir-core: Fix null dereferences in the protocols sysfs interface
For some cards, ir_dev->props and ir_dev->raw are both NULL. These cards are using built-in IR decoding instead of raw, and can't easily be made to switch protocols. So upon reading /sys/class/rc/rc?/protocols on such a card, return 'builtin' as the supported and enabled protocol. Return -EINVAL on any attempts to change the protocol. And most important of all, don't crash. Signed-off-by: Brian Rogers Acked-by: Jarod Wilson --- drivers/media/IR/ir-sysfs.c | 17 +++-- 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 96dafc4..46d4246 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d, char *tmp = buf; int i; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { enabled = ir_dev->rc_tab.ir_type; allowed = ir_dev->props->allowed_protos; - } else { + } else if (ir_dev->raw) { enabled = ir_dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return sprintf(tmp, "[builtin]\n"); IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, @@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d, int rc, i, count = 0; unsigned long flags; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) type = ir_dev->rc_tab.ir_type; - else + else if (ir_dev->raw) type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } while ((tmp = strsep((char **) &data, " \n")) != NULL) { if (!*tmp) @@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d, } } - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); ir_dev->rc_tab.ir_type = type; spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); -- 1.7.1 -- 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
Re: [GIT PULL for 2.6.36] V4L/DVB fixes
On 09/27/2010 05:36 PM, Mauro Carvalho Chehab wrote: I'll clean up the mess and prepare a new pull request in the next days. Can you look at including "ir-core: Fix null dereferences in the protocols sysfs interface"? I never got a response to that, and it's a regression fix for 2.6.36. https://patchwork.kernel.org/patch/199002/ -- 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
Fix memory corruption during IR initialization for various tuner cards
Mauro, The attached git-formatted patch fixes a regression I just found that was introduced in 2.6.31-rc1. I hope it can make it into the release. Brian >From d238e150805a0710fa626f9a7f65816aa15b741c Mon Sep 17 00:00:00 2001 From: Brian Rogers Date: Fri, 4 Sep 2009 05:55:01 -0700 Subject: [PATCH] Fix memory corruption during IR initialization for various tuner cards In two different places the IR_i2c_init_data structure is used to store some data for particular cards that will later override the settings that would otherwise be used by the ir-kbd-i2c driver in ir_probe(). The way those settings get there is problematic: init_data is on the stack, and a pointer to it is stored to be used after the function that sets it up returns. Not good. init_data might be overwritten by the time ir_probe() runs. ir_probe() will then call ir_input_init(), which proceeds to fill out the dev->keybit bit array with a 1 in the appropriate slot for every key on the tuner's remote. But if the keymap pointer now points to random garbage, that will be used instead to determine where to write each 1. And since IR_KEYTAB_TYPE is u32, it can be write millions of bits past the end of dev->keybit. Essentially this bug writes a 1 to up to 128 random bits in memory, stopping early (and oopsing) if or when it hits an invalid page. To fix this, I define a static IR_i2c_init_data struct for each card that needs one rather than creating the data on the stack. This way, I can supply a pointer that will remain valid. Also I don't have to allocate memory just to store information that's already known at compile time and I don't have bother freeing it, either. This fixes a regression caused by commit 4d7a2d6721. Signed-off-by: Brian Rogers --- drivers/media/video/em28xx/em28xx-cards.c | 36 +- drivers/media/video/saa7134/saa7134-input.c | 71 ++- 2 files changed, 70 insertions(+), 37 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 1c2e544..be9a4e8 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2167,11 +2167,29 @@ static int em28xx_hint_board(struct em28xx *dev) return -1; } +static struct IR_i2c_init_data init_data_em28xx_terratec = { + .name = "i2c IR (EM28XX Terratec)", + .ir_codes = ir_codes_em_terratec, + .get_key = em28xx_get_key_terratec, +}; + +static struct IR_i2c_init_data init_data_em28xx_pinnacle = { + .name = "i2c IR (EM28XX Pinnacle PCTV)", + .ir_codes = ir_codes_pinnacle_grey, + .get_key = em28xx_get_key_pinnacle_usb_grey, +}; + +static struct IR_i2c_init_data init_data_em28xx_hauppauge = { + .name = "i2c IR (EM2840 Hauppauge)", + .ir_codes = ir_codes_hauppauge_new, + .get_key = em28xx_get_key_em_haup, +}; + /* --- */ void em28xx_register_i2c_ir(struct em28xx *dev) { struct i2c_board_info info; - struct IR_i2c_init_data init_data; + struct IR_i2c_init_data *init_data = NULL; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2180,7 +2198,6 @@ void em28xx_register_i2c_ir(struct em28xx *dev) return; memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); /* detect & configure */ @@ -2191,19 +2208,13 @@ void em28xx_register_i2c_ir(struct em28xx *dev) break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): - init_data.ir_codes = ir_codes_em_terratec; - init_data.get_key = em28xx_get_key_terratec; - init_data.name = "i2c IR (EM28XX Terratec)"; + init_data = &init_data_em28xx_terratec; break; case (EM2820_BOARD_PINNACLE_USB_2): - init_data.ir_codes = ir_codes_pinnacle_grey; - init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + init_data = &init_data_em28xx_pinnacle; break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): - init_data.ir_codes = ir_codes_hauppauge_new; - init_data.get_key = em28xx_get_key_em_haup; - init_data.name = "i2c IR (EM2840 Hauppauge)"; + init_data = &init_data_em28xx_hauppauge; break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -2215,8 +2226,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) break; } - if (init_data.name) - info.platform_data = &init_data; + info.platform_data = init_data; i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6e219c2..bb17bb9 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -682,10 +682,46 @@ void saa7134_input_fini(struct saa71
Re: [PULL] http://linuxtv.org/hg/~awalls/v4l-dvb
Mauro Carvalho Chehab wrote: Em Sat, 5 Sep 2009 20:46:12 +0200 Jean Delvare escreveu: As far as I can see, the em28xx and saa7134 drivers have the exact same problem. Is there anyone working on this? I tested it here with an em28xx device and I got the trouble. I've committed a patch fixing it with this driver, with a different strategy, using dynamic memory. I did a similar patch for saa7134, although I can't test it ATM. Tests with saa7134 devices with i2c keyboards are welcome. Works fine with the MSI t...@nywhere Plus that prompted my version of the patch. A couple comments. It looks like since the saa7134_dev is allocated with kzalloc, you shouldn't have to zero out dev->info and dev->init_data. Secondly, you misspelled my name in your commit messages. :) Are you going to send this in for 2.6.31, or is it likely to wait until 2.6.31.1? I filed a bug to track the regression: http://bugzilla.kernel.org/show_bug.cgi?id=14142 Brian -- 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
[PATCH 1/2] em28xx: ir-kbd-i2c init data needs a persistent object
commit d2ebd0f806fdb6104903365e355675934eec22b2 upstream. Original commit message: ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to rise this question. Before this patch, if ir-kbd-i2c were probed after em28xx, trash data were used. After the patch, no matter what order, it is properly reported as tested by me: input: i2c IR (i2c IR (EM2840 Hauppaug as /class/input/input10 ir-kbd-i2c: i2c IR (i2c IR (EM2840 Hauppaug detected at i2c-4/4-0030/ir0 [em28xx #0] Original-patch-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab [br...@xyzw.org: backported for 2.6.31] Signed-off-by: Brian Rogers --- drivers/media/video/em28xx/em28xx-cards.c | 32 +--- drivers/media/video/em28xx/em28xx.h |4 +++ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 1c2e544..ffe9306 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2170,8 +2170,6 @@ static int em28xx_hint_board(struct em28xx *dev) /* --- */ void em28xx_register_i2c_ir(struct em28xx *dev) { - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2179,9 +2177,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) if (disable_ir) return; - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(&dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); /* detect & configure */ switch (dev->model) { @@ -2191,19 +2189,19 @@ void em28xx_register_i2c_ir(struct em28xx *dev) break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): - init_data.ir_codes = ir_codes_em_terratec; - init_data.get_key = em28xx_get_key_terratec; - init_data.name = "i2c IR (EM28XX Terratec)"; + dev->init_data.ir_codes = ir_codes_em_terratec; + dev->init_data.get_key = em28xx_get_key_terratec; + dev->init_data.name = "i2c IR (EM28XX Terratec)"; break; case (EM2820_BOARD_PINNACLE_USB_2): - init_data.ir_codes = ir_codes_pinnacle_grey; - init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + dev->init_data.ir_codes = ir_codes_pinnacle_grey; + dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): - init_data.ir_codes = ir_codes_hauppauge_new; - init_data.get_key = em28xx_get_key_em_haup; - init_data.name = "i2c IR (EM2840 Hauppauge)"; + dev->init_data.ir_codes = ir_codes_hauppauge_new; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -2215,9 +2213,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) break; } - if (init_data.name) - info.platform_data = &init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); } void em28xx_card_setup(struct em28xx *dev) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index a2add61..cb2a70a 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -595,6 +595,10 @@ struct em28xx { struct delayed_work sbutton_query_work; struct em28xx_dvb *dvb; + + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; }; struct em28xx_ops { -- 1.6.3.3 -- 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
[PATCH 2/2] saa7134: ir-kbd-i2c init data needs a persistent object
commit 7aedd5ec87686c557d48584d69ad880c11a0984d upstream. Tested on MSI t...@nywhere Plus. Original commit message: ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to rise this question. Before this patch, if ir-kbd-i2c were probed after SAA7134, trash data were used. Compile tested only, but the patch is identical to em28xx one. So, it should work properly. Original-patch-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab [br...@xyzw.org: backported for 2.6.31] Signed-off-by: Brian Rogers --- drivers/media/video/saa7134/saa7134-input.c | 56 +-- drivers/media/video/saa7134/saa7134.h |4 ++ 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6e219c2..69e48ce 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -684,8 +684,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x7a, 0x47, 0x71, 0x2d, I2C_CLIENT_END @@ -705,32 +703,32 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) return; } - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: - init_data.name = "Pinnacle PCTV"; + dev->init_data.name = "Pinnacle PCTV"; if (pinnacle_remote == 0) { - init_data.get_key = get_key_pinnacle_color; - init_data.ir_codes = ir_codes_pinnacle_color; + dev->init_data.get_key = get_key_pinnacle_color; + dev->init_data.ir_codes = ir_codes_pinnacle_color; } else { - init_data.get_key = get_key_pinnacle_grey; - init_data.ir_codes = ir_codes_pinnacle_grey; + dev->init_data.get_key = get_key_pinnacle_grey; + dev->init_data.ir_codes = ir_codes_pinnacle_grey; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: - init_data.name = "Purple TV"; - init_data.get_key = get_key_purpletv; - init_data.ir_codes = ir_codes_purpletv; + dev->init_data.name = "Purple TV"; + dev->init_data.get_key = get_key_purpletv; + dev->init_data.ir_codes = ir_codes_purpletv; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: - init_data.name = "MSI t...@nywhere Plus"; - init_data.get_key = get_key_msi_tvanywhere_plus; - init_data.ir_codes = ir_codes_msi_tvanywhere_plus; - info.addr = 0x30; + dev->init_data.name = "MSI t...@nywhere Plus"; + dev->init_data.get_key = get_key_msi_tvanywhere_plus; + dev->init_data.ir_codes = ir_codes_msi_tvanywhere_plus; + dev->info.addr = 0x30; /* MSI t...@nywhere Plus controller doesn't seem to respond to probes unless we read something from an existing device. Weird... @@ -741,9 +739,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) (1 == rc) ? "yes" : "no"); break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - init_data.name = "HVR 1110"; - init_data.get_key = get_key_hvr1110; - init_data.ir_codes = ir_codes_hauppauge_new; + dev->init_data.name = "HVR 1110"; + dev->init_data.get_key = get_key_hvr1110; + dev->init_data.ir_codes = ir_codes_hauppauge_new; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: case SAA7134_BOARD_BEHOLD_607FM_MK5: @@ -757,26 +755,26 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) cas