On Wed, 2004-09-29 at 13:57 +0200, Duncan Sands wrote: > this races with modem_run: since the firmware loading is done in a separate > kernel thread, it is possible to do: > > (1) probe completes > (2) hotplug call - modem_run tries to grab the interface and fails > (3) firmware loading code fails to load the firmware - releases the interface > but too late.
<...> > By the way, do revision 0 modems really have no altsetting 2 for interface 1? Incremental patch... we don't claim interface #2 until we actually _have_ the first stage of the firmware loaded now, and I dropped the duplicate (and wrong) usb_set_interface() for interface #1, leaving only the one in udsl_got_firmware(). --- speedtch.c.firmware 2004-09-29 13:30:20.306991256 +0100 +++ speedtch.c 2004-09-29 13:40:42.485405760 +0100 @@ -1294,21 +1294,30 @@ return; /* deep doggy do */ } - if (!(intf = usb_ifnum_to_if (instance->usb_dev, 2))) { - dbg ("udsl_firmware_stage1: interface not found!"); + if (!fw) { + dbg ("udsl_firmware_stage1: no firmware!"); goto finish; } if (!(buffer = kmalloc (0x1000, GFP_KERNEL))) { dbg ("udsl_firmware_stage1: no memory for buffer!"); - goto fail; + goto finish; } - if (!fw) { - dbg ("udsl_firmware_stage1: no firmware!"); - goto fail; + if (!(intf = usb_ifnum_to_if (instance->usb_dev, 2))) { + dbg ("udsl_firmware_stage1: interface not found!"); + goto fail_buf; + } + + /* OK, we have the firmware. So try to claim interface #2 and actually + try uploading it. There's a slight possibility that the userspace + modem_run could be running too, and may have beaten us to it */ + if ((ret = usb_driver_claim_interface (&udsl_usb_driver, intf, NULL)) < 0) { + dbg ("udsl_firmware_start: interface in use (%d)!", ret); + goto fail_buf; } + /* URB 7 */ if (dl_512_first) { /* some modems need a read before writing the firmware */ ret = usb_bulk_msg (instance->usb_dev, @@ -1376,11 +1385,12 @@ kfree (buffer); return; -fail: - kfree (buffer); + fail: usb_driver_release_interface (&udsl_usb_driver, intf); -finish: - udsl_got_firmware (instance, (ret < 0) ? 0 : 1); + fail_buf: + kfree (buffer); + finish: + udsl_got_firmware (instance, 0); udsl_put_instance (instance); } @@ -1389,7 +1399,6 @@ static void udsl_firmware_start (struct udsl_instance_data *instance) { #ifdef CONFIG_FW_LOADER - struct usb_interface *intf; int ret; #endif @@ -1408,16 +1417,6 @@ udsl_get_instance (instance); #ifdef CONFIG_FW_LOADER - if (!(intf = usb_ifnum_to_if (instance->usb_dev, 2))) { - dbg ("udsl_firmware_start: interface not found!"); - goto finish; - } - - if ((ret = usb_driver_claim_interface (&udsl_usb_driver, intf, NULL)) < 0) { - dbg ("udsl_firmware_start: interface in use (%d)!", ret); - goto finish; - } - ret = request_firmware_nowait (THIS_MODULE, "speedtch_fw1", &instance->usb_dev->dev, @@ -1426,14 +1425,9 @@ if (ret < 0) { dbg ("udsl_firmware_start: request_firmware_nowait failed (%d)!", ret); - goto fail; } - return; - -fail: - usb_driver_release_interface (&udsl_usb_driver, intf); -finish: + /* Just pretend it never happened... hope modem_run happens */ #endif /* CONFIG_FW_LOADER */ udsl_got_firmware (instance, 0); udsl_put_instance (instance); @@ -1751,9 +1745,6 @@ if ((err = usb_set_interface (dev, 0, 0)) < 0) return err; - if ((err = usb_set_interface (dev, 1, instance->revision?2:1)) < 0) - return err; - if ((err = usb_set_interface (dev, 2, 0)) < 0) return err; -- dwmw2 ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel