[PATCH RFC 2/4] em28xx: defer probe() if userspace mode is disabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux