This patch works fine here and solves the bug. Thanks.
Probably it should be tested if it works fine with other devices ( those which do not suffer from this bug ) as well and could then hopefully be added as a temporary solution at least. Best regards, Norman Am Sonntag, den 24.09.2006, 15:21 +0000 schrieb Matthieu CASTET: > Hi, > > Daniel Drake wrote: > > > Matthieu CASTET wrote: > > > >> Waiting for a clean solution I found a way to solve my problem : I read the > >> start of the firmware in order to see if it is already loaded. > > > > > > > > This approach looks acceptable (although the actual implementation needs > > cleaning a little) - thanks for investigating! > > Here a more clean patch. > There still a problem if a wrong firmware was loaded by another driver > (windows or vendor driver) : we won't reload the one supported by our driver. > > > > > Have you been able to tell why the vendor driver does not suffer the same > > problem? It would be good if we had more than one approach to choose from :) > > The vendor driver doesn't recover a rmmod of the rw driver. > > > Matthieu > > Signed-off-by: Matthieu CASTET <[EMAIL PROTECTED]> > > > > Index: zd1211_2006-09-20/zd_chip.h > =================================================================== > --- zd1211_2006-09-20.orig/zd_chip.h 2006-09-24 16:45:50.000000000 +0200 > +++ zd1211_2006-09-20/zd_chip.h 2006-09-24 16:48:30.000000000 +0200 > @@ -645,7 +645,9 @@ > FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d, > EEPROM_START_OFFSET = 0xf800, > EEPROM_SIZE = 0x800, /* words */ > + LOAD_CODE_START_OFFSET = 0xffe9, > LOAD_CODE_SIZE = 0xe, /* words */ > + LOAD_VECT_START_OFFSET = 0xfff7, > LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ > EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, > EEPROM_REGS_SIZE = 0x7e, /* words */ > Index: zd1211_2006-09-20/zd_usb.c > =================================================================== > --- zd1211_2006-09-20.orig/zd_usb.c 2006-09-24 16:48:52.000000000 +0200 > +++ zd1211_2006-09-20/zd_usb.c 2006-09-24 17:19:32.000000000 +0200 > @@ -366,6 +366,27 @@ > return r; > } > > +static int is_firmware_loaded(struct usb_device *udev) > +{ > + int r; > + u16 reset_vector; > + > + r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), > + USB_REQ_FIRMWARE_READ_DATA, > + USB_DIR_IN | USB_TYPE_VENDOR, > + LOAD_VECT_START_OFFSET, 0, &reset_vector, > sizeof(reset_vector), 5000 /* ms */); > + if (r != sizeof(reset_vector)) { > + dev_err(&udev->dev, > + "control request firmeware read." > + " Return value %d\n", r); > + if (r >= 0) > + return -ENODEV; > + } > + /* If a firware is loaded the reset_vector is the start of the > + * firmware */ > + return reset_vector == FW_START_OFFSET; > +} > + > static void disable_read_regs_int(struct zd_usb *usb) > { > struct zd_usb_interrupt *intr = &usb->intr; > @@ -1036,18 +1057,31 @@ > goto error; > } > > - r = upload_firmware(udev, id->driver_info); > - if (r) { > + r = is_firmware_loaded(udev); > + if (r < 0) { > dev_err(&intf->dev, > - "couldn't load firmware. Error number %d\n", r); > + "you should unplug/replug your device"); > goto error; > } > + /* TODO if the firmware was already loaded, upload new firmware here > + * hangs. We should reload the firmware in a latter stage after a > + * FW_SOFT_RESET because the current firmware could different from > + * the one we wanted. > + */ > + if (r == 0) { > + r = upload_firmware(udev, id->driver_info); > + if (r) { > + dev_err(&intf->dev, > + "couldn't load firmware. Error number > %d\n", r); > + goto error; > + } > > - r = usb_reset_configuration(udev); > - if (r) { > - dev_dbg_f(&intf->dev, > - "couldn't reset configuration. Error number %d\n", r); > - goto error; > + r = usb_reset_configuration(udev); > + if (r) { > + dev_dbg_f(&intf->dev, > + "couldn't reset configuration. Error > number %d\n", r); > + goto error; > + } > } > > /* At this point the interrupt endpoint is not generally enabled. We > @@ -1073,7 +1107,6 @@ > dev_info(&intf->dev,"%s\n", netdev->name); > return 0; > error: > - usb_reset_device(interface_to_usbdev(intf)); > zd_netdev_free(netdev); > return r; > } > @@ -1097,13 +1130,6 @@ > zd_usb_disable_rx(usb); > zd_usb_disable_int(usb); > > - /* If the disconnect has been caused by a removal of the > - * driver module, the reset allows reloading of the driver. If the > - * reset will not be executed here, the upload of the firmware in the > - * probe function caused by the reloading of the driver will fail. > - */ > - usb_reset_device(interface_to_usbdev(intf)); > - > zd_netdev_free(netdev); > dev_dbg(&intf->dev, "disconnected\n"); > } ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Zd1211-devs mailing list - http://zd1211.ath.cx/ Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs