Some em28xx devices with tuner-xc2028, drx-k and drx-d need firmware, in order to be probed. Defer device probe on those devices, if userspace mode is disabled. Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> --- drivers/media/video/em28xx/em28xx-cards.c | 42 +++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 43 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 12bc54a..9229cd2 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -776,6 +776,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy A Hybrid XS", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, @@ -800,6 +801,7 @@ struct em28xx_board em28xx_boards[] = { .name = "KWorld PVRTV 300U", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -880,6 +882,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy T XS", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, }, [EM2870_BOARD_TERRATEC_XS_MT2060] = { @@ -891,6 +894,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld 350 U DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, }, [EM2870_BOARD_KWORLD_355U] = { @@ -919,6 +923,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Hybrid XS Secam", .has_msp34xx = 1, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, @@ -970,6 +975,7 @@ struct em28xx_board em28xx_boards[] = { .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, + .needs_firmware = true, }, [EM2884_BOARD_CINERGY_HTC_STICK] = { .name = "Terratec Cinergy HTC Stick", @@ -979,11 +985,13 @@ struct em28xx_board em28xx_boards[] = { .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, + .needs_firmware = true, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1011,6 +1019,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV HVR 900 (R2)", .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1037,6 +1046,7 @@ struct em28xx_board em28xx_boards[] = { [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = { .name = "Hauppauge WinTV HVR 850", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1063,6 +1073,7 @@ struct em28xx_board em28xx_boards[] = { [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1089,6 +1100,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { .name = "Pinnacle PCTV HD Pro Stick", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1115,6 +1127,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { .name = "AMD ATI TV Wonder HD 600", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1141,6 +1154,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, @@ -1170,6 +1184,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { .name = "Terratec Prodigy XS", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -1412,6 +1427,7 @@ struct em28xx_board em28xx_boards[] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -1435,6 +1451,7 @@ struct em28xx_board em28xx_boards[] = { .name = "MSI DigiVox A/D II", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -1457,6 +1474,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_KWORLD_DVB_305U] = { .name = "KWorld DVB-T 305U", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -1476,6 +1494,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_KWORLD_DVB_310U] = { .name = "KWorld DVB-T 310U", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .has_dvb = 1, .dvb_gpio = default_digital, @@ -1534,6 +1553,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_EMPIRE_DUAL_TV] = { .name = "Empire dual TV", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .has_dvb = 1, .dvb_gpio = default_digital, @@ -1560,6 +1580,7 @@ struct em28xx_board em28xx_boards[] = { .name = "DNT DA2 Hybrid", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { @@ -1582,6 +1603,7 @@ struct em28xx_board em28xx_boards[] = { [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { .name = "Pinnacle Hybrid Pro", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, @@ -1606,6 +1628,7 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = { .name = "Pinnacle Hybrid Pro (330e)", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, @@ -1632,6 +1655,7 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_KWORLD_VS_DVBT] = { .name = "Kworld VS-DVB-T 323UR", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .mts_firmware = 1, @@ -1656,6 +1680,7 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .decoder = EM28XX_TVP5150, @@ -1683,6 +1708,7 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_DIKOM_DK300] = { .name = "Dikom DK300", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .mts_firmware = 1, @@ -1698,6 +1724,7 @@ struct em28xx_board em28xx_boards[] = { [EM2883_BOARD_KWORLD_HYBRID_330U] = { .name = "Kworld PlusTV HD Hybrid 330", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .mts_firmware = 1, @@ -1750,6 +1777,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kaiomy TVnPC U2", .vchannels = 3, .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_addr = 0x61, .mts_firmware = 1, .decoder = EM28XX_TVP5150, @@ -1864,6 +1892,7 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_EVGA_INDTUBE] = { .name = "Evga inDtube", .tuner_type = TUNER_XC2028, + .needs_firmware = true, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ @@ -3133,6 +3162,19 @@ static int em28xx_usb_probe(struct usb_interface *interface, const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; char *speed; + /* + * If the device requires firmware, probe() may need to be + * postponed, as udev may not be ready yet to honour firmware + * load requests. + */ + if (em28xx_boards[id->driver_info].needs_firmware && + is_usermodehelp_disabled()) { + printk_once(KERN_DEBUG DRIVER_NAME + ": probe deferred for board %d.\n", + (unsigned)id->driver_info); + return -EPROBE_DEFER; + } + udev = usb_get_dev(interface_to_usbdev(interface)); /* Check to see next free device and mark as used */ diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 8757523..ed8dc65 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -402,6 +402,7 @@ struct em28xx_board { unsigned int is_webcam:1; unsigned int valid:1; unsigned int has_ir_i2c:1; + unsigned int needs_firmware:1; unsigned char xclk, i2c_speed; unsigned char radio_addr; -- 1.7.10.2 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html