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

Reply via email to