diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_usb.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 98 |
1 files changed, 71 insertions, 27 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ca24299a26c6..28d41a29d7b1 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -71,6 +71,7 @@ static struct usb_device_id usb_ids[] = { | |||
71 | { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, | 71 | { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, |
72 | { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, | 72 | { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, |
73 | { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, | 73 | { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, |
74 | { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, | ||
74 | /* "Driverless" devices that need ejecting */ | 75 | /* "Driverless" devices that need ejecting */ |
75 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, | 76 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, |
76 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, | 77 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, |
@@ -195,26 +196,27 @@ static u16 get_word(const void *data, u16 offset) | |||
195 | return le16_to_cpu(p[offset]); | 196 | return le16_to_cpu(p[offset]); |
196 | } | 197 | } |
197 | 198 | ||
198 | static char *get_fw_name(char *buffer, size_t size, u8 device_type, | 199 | static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size, |
199 | const char* postfix) | 200 | const char* postfix) |
200 | { | 201 | { |
201 | scnprintf(buffer, size, "%s%s", | 202 | scnprintf(buffer, size, "%s%s", |
202 | device_type == DEVICE_ZD1211B ? | 203 | usb->is_zd1211b ? |
203 | FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, | 204 | FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, |
204 | postfix); | 205 | postfix); |
205 | return buffer; | 206 | return buffer; |
206 | } | 207 | } |
207 | 208 | ||
208 | static int handle_version_mismatch(struct usb_device *udev, u8 device_type, | 209 | static int handle_version_mismatch(struct zd_usb *usb, |
209 | const struct firmware *ub_fw) | 210 | const struct firmware *ub_fw) |
210 | { | 211 | { |
212 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
211 | const struct firmware *ur_fw = NULL; | 213 | const struct firmware *ur_fw = NULL; |
212 | int offset; | 214 | int offset; |
213 | int r = 0; | 215 | int r = 0; |
214 | char fw_name[128]; | 216 | char fw_name[128]; |
215 | 217 | ||
216 | r = request_fw_file(&ur_fw, | 218 | r = request_fw_file(&ur_fw, |
217 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"), | 219 | get_fw_name(usb, fw_name, sizeof(fw_name), "ur"), |
218 | &udev->dev); | 220 | &udev->dev); |
219 | if (r) | 221 | if (r) |
220 | goto error; | 222 | goto error; |
@@ -237,11 +239,12 @@ error: | |||
237 | return r; | 239 | return r; |
238 | } | 240 | } |
239 | 241 | ||
240 | static int upload_firmware(struct usb_device *udev, u8 device_type) | 242 | static int upload_firmware(struct zd_usb *usb) |
241 | { | 243 | { |
242 | int r; | 244 | int r; |
243 | u16 fw_bcdDevice; | 245 | u16 fw_bcdDevice; |
244 | u16 bcdDevice; | 246 | u16 bcdDevice; |
247 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
245 | const struct firmware *ub_fw = NULL; | 248 | const struct firmware *ub_fw = NULL; |
246 | const struct firmware *uph_fw = NULL; | 249 | const struct firmware *uph_fw = NULL; |
247 | char fw_name[128]; | 250 | char fw_name[128]; |
@@ -249,7 +252,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) | |||
249 | bcdDevice = get_bcdDevice(udev); | 252 | bcdDevice = get_bcdDevice(udev); |
250 | 253 | ||
251 | r = request_fw_file(&ub_fw, | 254 | r = request_fw_file(&ub_fw, |
252 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), | 255 | get_fw_name(usb, fw_name, sizeof(fw_name), "ub"), |
253 | &udev->dev); | 256 | &udev->dev); |
254 | if (r) | 257 | if (r) |
255 | goto error; | 258 | goto error; |
@@ -264,7 +267,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) | |||
264 | dev_warn(&udev->dev, "device has old bootcode, please " | 267 | dev_warn(&udev->dev, "device has old bootcode, please " |
265 | "report success or failure\n"); | 268 | "report success or failure\n"); |
266 | 269 | ||
267 | r = handle_version_mismatch(udev, device_type, ub_fw); | 270 | r = handle_version_mismatch(usb, ub_fw); |
268 | if (r) | 271 | if (r) |
269 | goto error; | 272 | goto error; |
270 | } else { | 273 | } else { |
@@ -275,7 +278,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) | |||
275 | 278 | ||
276 | 279 | ||
277 | r = request_fw_file(&uph_fw, | 280 | r = request_fw_file(&uph_fw, |
278 | get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), | 281 | get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"), |
279 | &udev->dev); | 282 | &udev->dev); |
280 | if (r) | 283 | if (r) |
281 | goto error; | 284 | goto error; |
@@ -294,6 +297,30 @@ error: | |||
294 | return r; | 297 | return r; |
295 | } | 298 | } |
296 | 299 | ||
300 | /* Read data from device address space using "firmware interface" which does | ||
301 | * not require firmware to be loaded. */ | ||
302 | int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len) | ||
303 | { | ||
304 | int r; | ||
305 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
306 | |||
307 | r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
308 | USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0, | ||
309 | data, len, 5000); | ||
310 | if (r < 0) { | ||
311 | dev_err(&udev->dev, | ||
312 | "read over firmware interface failed: %d\n", r); | ||
313 | return r; | ||
314 | } else if (r != len) { | ||
315 | dev_err(&udev->dev, | ||
316 | "incomplete read over firmware interface: %d/%d\n", | ||
317 | r, len); | ||
318 | return -EIO; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
297 | #define urb_dev(urb) (&(urb)->dev->dev) | 324 | #define urb_dev(urb) (&(urb)->dev->dev) |
298 | 325 | ||
299 | static inline void handle_regs_int(struct urb *urb) | 326 | static inline void handle_regs_int(struct urb *urb) |
@@ -920,9 +947,42 @@ static int eject_installer(struct usb_interface *intf) | |||
920 | return 0; | 947 | return 0; |
921 | } | 948 | } |
922 | 949 | ||
950 | int zd_usb_init_hw(struct zd_usb *usb) | ||
951 | { | ||
952 | int r; | ||
953 | struct zd_mac *mac = zd_usb_to_mac(usb); | ||
954 | |||
955 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
956 | |||
957 | r = upload_firmware(usb); | ||
958 | if (r) { | ||
959 | dev_err(zd_usb_dev(usb), | ||
960 | "couldn't load firmware. Error number %d\n", r); | ||
961 | return r; | ||
962 | } | ||
963 | |||
964 | r = usb_reset_configuration(zd_usb_to_usbdev(usb)); | ||
965 | if (r) { | ||
966 | dev_dbg_f(zd_usb_dev(usb), | ||
967 | "couldn't reset configuration. Error number %d\n", r); | ||
968 | return r; | ||
969 | } | ||
970 | |||
971 | r = zd_mac_init_hw(mac); | ||
972 | if (r) { | ||
973 | dev_dbg_f(zd_usb_dev(usb), | ||
974 | "couldn't initialize mac. Error number %d\n", r); | ||
975 | return r; | ||
976 | } | ||
977 | |||
978 | usb->initialized = 1; | ||
979 | return 0; | ||
980 | } | ||
981 | |||
923 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | 982 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) |
924 | { | 983 | { |
925 | int r; | 984 | int r; |
985 | struct zd_usb *usb; | ||
926 | struct usb_device *udev = interface_to_usbdev(intf); | 986 | struct usb_device *udev = interface_to_usbdev(intf); |
927 | struct net_device *netdev = NULL; | 987 | struct net_device *netdev = NULL; |
928 | 988 | ||
@@ -950,26 +1010,10 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
950 | goto error; | 1010 | goto error; |
951 | } | 1011 | } |
952 | 1012 | ||
953 | r = upload_firmware(udev, id->driver_info); | 1013 | usb = &zd_netdev_mac(netdev)->chip.usb; |
954 | if (r) { | 1014 | usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0; |
955 | dev_err(&intf->dev, | ||
956 | "couldn't load firmware. Error number %d\n", r); | ||
957 | goto error; | ||
958 | } | ||
959 | 1015 | ||
960 | r = usb_reset_configuration(udev); | 1016 | r = zd_mac_preinit_hw(zd_netdev_mac(netdev)); |
961 | if (r) { | ||
962 | dev_dbg_f(&intf->dev, | ||
963 | "couldn't reset configuration. Error number %d\n", r); | ||
964 | goto error; | ||
965 | } | ||
966 | |||
967 | /* At this point the interrupt endpoint is not generally enabled. We | ||
968 | * save the USB bandwidth until the network device is opened. But | ||
969 | * notify that the initialization of the MAC will require the | ||
970 | * interrupts to be temporary enabled. | ||
971 | */ | ||
972 | r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); | ||
973 | if (r) { | 1017 | if (r) { |
974 | dev_dbg_f(&intf->dev, | 1018 | dev_dbg_f(&intf->dev, |
975 | "couldn't initialize mac. Error number %d\n", r); | 1019 | "couldn't initialize mac. Error number %d\n", r); |