11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
266bb42fdSDaniel Drake /* ZD1211 USB-WLAN driver for Linux
366bb42fdSDaniel Drake *
466bb42fdSDaniel Drake * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
566bb42fdSDaniel Drake * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
666bb42fdSDaniel Drake * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
7e85d0918SDaniel Drake */
8e85d0918SDaniel Drake
9d066c219SDaniel Drake #include <linux/kernel.h>
10e85d0918SDaniel Drake #include <linux/init.h>
11e85d0918SDaniel Drake #include <linux/firmware.h>
12e85d0918SDaniel Drake #include <linux/device.h>
13e85d0918SDaniel Drake #include <linux/errno.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
15e85d0918SDaniel Drake #include <linux/skbuff.h>
16e85d0918SDaniel Drake #include <linux/usb.h>
17bc5f06a8SUlrich Kunitz #include <linux/workqueue.h>
189d9779e7SPaul Gortmaker #include <linux/module.h>
19459c51adSDaniel Drake #include <net/mac80211.h>
205f60d5f6SAl Viro #include <linux/unaligned.h>
21e85d0918SDaniel Drake
22e85d0918SDaniel Drake #include "zd_def.h"
23e85d0918SDaniel Drake #include "zd_mac.h"
24e85d0918SDaniel Drake #include "zd_usb.h"
25e85d0918SDaniel Drake
26ecf23a78SArvind Yadav static const struct usb_device_id usb_ids[] = {
27e85d0918SDaniel Drake /* ZD1211 */
283bfbe80eSHin-Tak Leung { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
293bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
303bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
313bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
323bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
333bfbe80eSHin-Tak Leung { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
343bfbe80eSHin-Tak Leung { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
35e85d0918SDaniel Drake { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
3614990c69SHin-Tak Leung { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
373bfbe80eSHin-Tak Leung { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
383bfbe80eSHin-Tak Leung { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
393bfbe80eSHin-Tak Leung { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
40e85d0918SDaniel Drake { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
41aa1d3a18SMatthew Davidson { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
423bfbe80eSHin-Tak Leung { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
43ababda03SUlrich Kunitz { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
443bfbe80eSHin-Tak Leung { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
453bfbe80eSHin-Tak Leung { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 },
468cecc90eSmaximilian attems { USB_DEVICE(0x14ea, 0xab10), .driver_info = DEVICE_ZD1211 },
473bfbe80eSHin-Tak Leung { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
48269fca0eSDaniel Drake { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
493bfbe80eSHin-Tak Leung { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
503bfbe80eSHin-Tak Leung { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
519011cd25STõnu Samuel { USB_DEVICE(0x157e, 0x3207), .driver_info = DEVICE_ZD1211 },
523bfbe80eSHin-Tak Leung { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
533bfbe80eSHin-Tak Leung { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
54e85d0918SDaniel Drake /* ZD1211B */
55019a6755SUlrich Kunitz { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
56ad580db5SHin-Tak Leung { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B },
5793f510bbSDaniel Drake { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
583bfbe80eSHin-Tak Leung { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
5961ef6062SDaniel Drake { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
603bfbe80eSHin-Tak Leung { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
613bfbe80eSHin-Tak Leung { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B },
623bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
633bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
643bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
653bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
663bfbe80eSHin-Tak Leung { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
673bfbe80eSHin-Tak Leung { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
683bfbe80eSHin-Tak Leung { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
693bfbe80eSHin-Tak Leung { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
708f75e07aSHin-Tak Leung { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B },
713bfbe80eSHin-Tak Leung { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B },
723bfbe80eSHin-Tak Leung { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
733bfbe80eSHin-Tak Leung { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
743bfbe80eSHin-Tak Leung { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
753bfbe80eSHin-Tak Leung { USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
763bfbe80eSHin-Tak Leung { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
773bfbe80eSHin-Tak Leung { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
783bfbe80eSHin-Tak Leung { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
793bfbe80eSHin-Tak Leung { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B },
803bfbe80eSHin-Tak Leung { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
813bfbe80eSHin-Tak Leung { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
823bfbe80eSHin-Tak Leung { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
833bfbe80eSHin-Tak Leung { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B },
848cecc90eSmaximilian attems { USB_DEVICE(0x2019, 0xed01), .driver_info = DEVICE_ZD1211B },
85a1030e92SDaniel Drake /* "Driverless" devices that need ejecting */
86a1030e92SDaniel Drake { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
87aa1d3a18SMatthew Davidson { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
88e85d0918SDaniel Drake {}
89e85d0918SDaniel Drake };
90e85d0918SDaniel Drake
91e85d0918SDaniel Drake MODULE_LICENSE("GPL");
92e85d0918SDaniel Drake MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip.");
93e85d0918SDaniel Drake MODULE_AUTHOR("Ulrich Kunitz");
94e85d0918SDaniel Drake MODULE_AUTHOR("Daniel Drake");
95e85d0918SDaniel Drake MODULE_VERSION("1.0");
96e85d0918SDaniel Drake MODULE_DEVICE_TABLE(usb, usb_ids);
97e85d0918SDaniel Drake
98e85d0918SDaniel Drake #define FW_ZD1211_PREFIX "zd1211/zd1211_"
99e85d0918SDaniel Drake #define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
100e85d0918SDaniel Drake
101c900eff3SJussi Kivilinna static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
102c900eff3SJussi Kivilinna unsigned int count);
103c900eff3SJussi Kivilinna
104e85d0918SDaniel Drake /* USB device initialization */
10572e77a8aSLuis Carlos Cobo static void int_urb_complete(struct urb *urb);
106e85d0918SDaniel Drake
request_fw_file(const struct firmware ** fw,const char * name,struct device * device)107e85d0918SDaniel Drake static int request_fw_file(
108e85d0918SDaniel Drake const struct firmware **fw, const char *name, struct device *device)
109e85d0918SDaniel Drake {
110e85d0918SDaniel Drake int r;
111e85d0918SDaniel Drake
112e85d0918SDaniel Drake dev_dbg_f(device, "fw name %s\n", name);
113e85d0918SDaniel Drake
114e85d0918SDaniel Drake r = request_firmware(fw, name, device);
115e85d0918SDaniel Drake if (r)
116e85d0918SDaniel Drake dev_err(device,
117e85d0918SDaniel Drake "Could not load firmware file %s. Error number %d\n",
118e85d0918SDaniel Drake name, r);
119e85d0918SDaniel Drake return r;
120e85d0918SDaniel Drake }
121e85d0918SDaniel Drake
get_bcdDevice(const struct usb_device * udev)122e85d0918SDaniel Drake static inline u16 get_bcdDevice(const struct usb_device *udev)
123e85d0918SDaniel Drake {
124e85d0918SDaniel Drake return le16_to_cpu(udev->descriptor.bcdDevice);
125e85d0918SDaniel Drake }
126e85d0918SDaniel Drake
127e85d0918SDaniel Drake enum upload_code_flags {
128e85d0918SDaniel Drake REBOOT = 1,
129e85d0918SDaniel Drake };
130e85d0918SDaniel Drake
131e85d0918SDaniel Drake /* Ensures that MAX_TRANSFER_SIZE is even. */
132e85d0918SDaniel Drake #define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1)
133e85d0918SDaniel Drake
upload_code(struct usb_device * udev,const u8 * data,size_t size,u16 code_offset,int flags)134e85d0918SDaniel Drake static int upload_code(struct usb_device *udev,
135e85d0918SDaniel Drake const u8 *data, size_t size, u16 code_offset, int flags)
136e85d0918SDaniel Drake {
137e85d0918SDaniel Drake u8 *p;
138e85d0918SDaniel Drake int r;
139e85d0918SDaniel Drake
140e85d0918SDaniel Drake /* USB request blocks need "kmalloced" buffers.
141e85d0918SDaniel Drake */
142e85d0918SDaniel Drake p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL);
143e85d0918SDaniel Drake if (!p) {
144e85d0918SDaniel Drake r = -ENOMEM;
145e85d0918SDaniel Drake goto error;
146e85d0918SDaniel Drake }
147e85d0918SDaniel Drake
148e85d0918SDaniel Drake size &= ~1;
149e85d0918SDaniel Drake while (size > 0) {
150e85d0918SDaniel Drake size_t transfer_size = size <= MAX_TRANSFER_SIZE ?
151e85d0918SDaniel Drake size : MAX_TRANSFER_SIZE;
152e85d0918SDaniel Drake
153e85d0918SDaniel Drake dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size);
154e85d0918SDaniel Drake
155e85d0918SDaniel Drake memcpy(p, data, transfer_size);
156e85d0918SDaniel Drake r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
157e85d0918SDaniel Drake USB_REQ_FIRMWARE_DOWNLOAD,
158e85d0918SDaniel Drake USB_DIR_OUT | USB_TYPE_VENDOR,
159e85d0918SDaniel Drake code_offset, 0, p, transfer_size, 1000 /* ms */);
160e85d0918SDaniel Drake if (r < 0) {
161e85d0918SDaniel Drake dev_err(&udev->dev,
162e85d0918SDaniel Drake "USB control request for firmware upload"
163e85d0918SDaniel Drake " failed. Error number %d\n", r);
164e85d0918SDaniel Drake goto error;
165e85d0918SDaniel Drake }
166e85d0918SDaniel Drake transfer_size = r & ~1;
167e85d0918SDaniel Drake
168e85d0918SDaniel Drake size -= transfer_size;
169e85d0918SDaniel Drake data += transfer_size;
170e85d0918SDaniel Drake code_offset += transfer_size/sizeof(u16);
171e85d0918SDaniel Drake }
172e85d0918SDaniel Drake
173e85d0918SDaniel Drake if (flags & REBOOT) {
174e85d0918SDaniel Drake u8 ret;
175e85d0918SDaniel Drake
176a8c4ea7aSAtsushi Nemoto /* Use "DMA-aware" buffer. */
177e85d0918SDaniel Drake r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
178e85d0918SDaniel Drake USB_REQ_FIRMWARE_CONFIRM,
179e85d0918SDaniel Drake USB_DIR_IN | USB_TYPE_VENDOR,
180a8c4ea7aSAtsushi Nemoto 0, 0, p, sizeof(ret), 5000 /* ms */);
181e85d0918SDaniel Drake if (r != sizeof(ret)) {
182e85d0918SDaniel Drake dev_err(&udev->dev,
183b46b5993SColin Ian King "control request firmware confirmation failed."
184e85d0918SDaniel Drake " Return value %d\n", r);
185e85d0918SDaniel Drake if (r >= 0)
186e85d0918SDaniel Drake r = -ENODEV;
187e85d0918SDaniel Drake goto error;
188e85d0918SDaniel Drake }
189a8c4ea7aSAtsushi Nemoto ret = p[0];
190e85d0918SDaniel Drake if (ret & 0x80) {
191e85d0918SDaniel Drake dev_err(&udev->dev,
192e85d0918SDaniel Drake "Internal error while downloading."
193e85d0918SDaniel Drake " Firmware confirm return value %#04x\n",
194e85d0918SDaniel Drake (unsigned int)ret);
195e85d0918SDaniel Drake r = -ENODEV;
196e85d0918SDaniel Drake goto error;
197e85d0918SDaniel Drake }
198e85d0918SDaniel Drake dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n",
199e85d0918SDaniel Drake (unsigned int)ret);
200e85d0918SDaniel Drake }
201e85d0918SDaniel Drake
202e85d0918SDaniel Drake r = 0;
203e85d0918SDaniel Drake error:
204e85d0918SDaniel Drake kfree(p);
205e85d0918SDaniel Drake return r;
206e85d0918SDaniel Drake }
207e85d0918SDaniel Drake
get_word(const void * data,u16 offset)208e85d0918SDaniel Drake static u16 get_word(const void *data, u16 offset)
209e85d0918SDaniel Drake {
210e85d0918SDaniel Drake const __le16 *p = data;
211e85d0918SDaniel Drake return le16_to_cpu(p[offset]);
212e85d0918SDaniel Drake }
213e85d0918SDaniel Drake
get_fw_name(struct zd_usb * usb,char * buffer,size_t size,const char * postfix)21474553aedSDaniel Drake static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
215e85d0918SDaniel Drake const char* postfix)
216e85d0918SDaniel Drake {
217e85d0918SDaniel Drake scnprintf(buffer, size, "%s%s",
21874553aedSDaniel Drake usb->is_zd1211b ?
219e85d0918SDaniel Drake FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
220e85d0918SDaniel Drake postfix);
221e85d0918SDaniel Drake return buffer;
222e85d0918SDaniel Drake }
223e85d0918SDaniel Drake
handle_version_mismatch(struct zd_usb * usb,const struct firmware * ub_fw)22474553aedSDaniel Drake static int handle_version_mismatch(struct zd_usb *usb,
225d066c219SDaniel Drake const struct firmware *ub_fw)
226d066c219SDaniel Drake {
22774553aedSDaniel Drake struct usb_device *udev = zd_usb_to_usbdev(usb);
228d066c219SDaniel Drake const struct firmware *ur_fw = NULL;
229d066c219SDaniel Drake int offset;
230d066c219SDaniel Drake int r = 0;
231d066c219SDaniel Drake char fw_name[128];
232d066c219SDaniel Drake
233d066c219SDaniel Drake r = request_fw_file(&ur_fw,
23474553aedSDaniel Drake get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
235d066c219SDaniel Drake &udev->dev);
236d066c219SDaniel Drake if (r)
237d066c219SDaniel Drake goto error;
238d066c219SDaniel Drake
239ee302767SDaniel Drake r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT);
240d066c219SDaniel Drake if (r)
241d066c219SDaniel Drake goto error;
242d066c219SDaniel Drake
243ee302767SDaniel Drake offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16));
244d066c219SDaniel Drake r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
245ee302767SDaniel Drake E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT);
246d066c219SDaniel Drake
247d066c219SDaniel Drake /* At this point, the vendor driver downloads the whole firmware
248d066c219SDaniel Drake * image, hacks around with version IDs, and uploads it again,
249d066c219SDaniel Drake * completely overwriting the boot code. We do not do this here as
250d066c219SDaniel Drake * it is not required on any tested devices, and it is suspected to
251d066c219SDaniel Drake * cause problems. */
252d066c219SDaniel Drake error:
253d066c219SDaniel Drake release_firmware(ur_fw);
254d066c219SDaniel Drake return r;
255d066c219SDaniel Drake }
256d066c219SDaniel Drake
upload_firmware(struct zd_usb * usb)25774553aedSDaniel Drake static int upload_firmware(struct zd_usb *usb)
258e85d0918SDaniel Drake {
259e85d0918SDaniel Drake int r;
260e85d0918SDaniel Drake u16 fw_bcdDevice;
261e85d0918SDaniel Drake u16 bcdDevice;
26274553aedSDaniel Drake struct usb_device *udev = zd_usb_to_usbdev(usb);
263e85d0918SDaniel Drake const struct firmware *ub_fw = NULL;
264e85d0918SDaniel Drake const struct firmware *uph_fw = NULL;
265e85d0918SDaniel Drake char fw_name[128];
266e85d0918SDaniel Drake
267e85d0918SDaniel Drake bcdDevice = get_bcdDevice(udev);
268e85d0918SDaniel Drake
269e85d0918SDaniel Drake r = request_fw_file(&ub_fw,
27074553aedSDaniel Drake get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
271e85d0918SDaniel Drake &udev->dev);
272e85d0918SDaniel Drake if (r)
273e85d0918SDaniel Drake goto error;
274e85d0918SDaniel Drake
275ee302767SDaniel Drake fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET);
276e85d0918SDaniel Drake
277e85d0918SDaniel Drake if (fw_bcdDevice != bcdDevice) {
278e85d0918SDaniel Drake dev_info(&udev->dev,
279d066c219SDaniel Drake "firmware version %#06x and device bootcode version "
280d066c219SDaniel Drake "%#06x differ\n", fw_bcdDevice, bcdDevice);
281d066c219SDaniel Drake if (bcdDevice <= 0x4313)
282d066c219SDaniel Drake dev_warn(&udev->dev, "device has old bootcode, please "
283d066c219SDaniel Drake "report success or failure\n");
284d066c219SDaniel Drake
28574553aedSDaniel Drake r = handle_version_mismatch(usb, ub_fw);
286d066c219SDaniel Drake if (r)
287d066c219SDaniel Drake goto error;
288e85d0918SDaniel Drake } else {
289e85d0918SDaniel Drake dev_dbg_f(&udev->dev,
290e85d0918SDaniel Drake "firmware device id %#06x is equal to the "
291e85d0918SDaniel Drake "actual device id\n", fw_bcdDevice);
292e85d0918SDaniel Drake }
293e85d0918SDaniel Drake
294e85d0918SDaniel Drake
295e85d0918SDaniel Drake r = request_fw_file(&uph_fw,
29674553aedSDaniel Drake get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
297e85d0918SDaniel Drake &udev->dev);
298e85d0918SDaniel Drake if (r)
299e85d0918SDaniel Drake goto error;
300e85d0918SDaniel Drake
301ee302767SDaniel Drake r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT);
302e85d0918SDaniel Drake if (r) {
303e85d0918SDaniel Drake dev_err(&udev->dev,
304e85d0918SDaniel Drake "Could not upload firmware code uph. Error number %d\n",
305e85d0918SDaniel Drake r);
306e85d0918SDaniel Drake }
307e85d0918SDaniel Drake
308e85d0918SDaniel Drake /* FALL-THROUGH */
309e85d0918SDaniel Drake error:
310e85d0918SDaniel Drake release_firmware(ub_fw);
311e85d0918SDaniel Drake release_firmware(uph_fw);
312e85d0918SDaniel Drake return r;
313e85d0918SDaniel Drake }
314e85d0918SDaniel Drake
3153e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ur");
3163e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211_PREFIX "ur");
3173e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ub");
3183e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211_PREFIX "ub");
3193e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211B_PREFIX "uphr");
3203e8b4d00SBen Hutchings MODULE_FIRMWARE(FW_ZD1211_PREFIX "uphr");
3213e8b4d00SBen Hutchings
32274553aedSDaniel Drake /* Read data from device address space using "firmware interface" which does
32374553aedSDaniel Drake * not require firmware to be loaded. */
zd_usb_read_fw(struct zd_usb * usb,zd_addr_t addr,u8 * data,u16 len)32474553aedSDaniel Drake int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
32574553aedSDaniel Drake {
32674553aedSDaniel Drake int r;
32774553aedSDaniel Drake struct usb_device *udev = zd_usb_to_usbdev(usb);
328a8c4ea7aSAtsushi Nemoto u8 *buf;
32974553aedSDaniel Drake
330a8c4ea7aSAtsushi Nemoto /* Use "DMA-aware" buffer. */
331a8c4ea7aSAtsushi Nemoto buf = kmalloc(len, GFP_KERNEL);
332a8c4ea7aSAtsushi Nemoto if (!buf)
333a8c4ea7aSAtsushi Nemoto return -ENOMEM;
33474553aedSDaniel Drake r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
33574553aedSDaniel Drake USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
336a8c4ea7aSAtsushi Nemoto buf, len, 5000);
33774553aedSDaniel Drake if (r < 0) {
33874553aedSDaniel Drake dev_err(&udev->dev,
33974553aedSDaniel Drake "read over firmware interface failed: %d\n", r);
340a8c4ea7aSAtsushi Nemoto goto exit;
34174553aedSDaniel Drake } else if (r != len) {
34274553aedSDaniel Drake dev_err(&udev->dev,
34374553aedSDaniel Drake "incomplete read over firmware interface: %d/%d\n",
34474553aedSDaniel Drake r, len);
345a8c4ea7aSAtsushi Nemoto r = -EIO;
346a8c4ea7aSAtsushi Nemoto goto exit;
34774553aedSDaniel Drake }
348a8c4ea7aSAtsushi Nemoto r = 0;
349a8c4ea7aSAtsushi Nemoto memcpy(data, buf, len);
350a8c4ea7aSAtsushi Nemoto exit:
351a8c4ea7aSAtsushi Nemoto kfree(buf);
352a8c4ea7aSAtsushi Nemoto return r;
35374553aedSDaniel Drake }
35474553aedSDaniel Drake
355e85d0918SDaniel Drake #define urb_dev(urb) (&(urb)->dev->dev)
356e85d0918SDaniel Drake
handle_regs_int_override(struct urb * urb)357c900eff3SJussi Kivilinna static inline void handle_regs_int_override(struct urb *urb)
358c900eff3SJussi Kivilinna {
359c900eff3SJussi Kivilinna struct zd_usb *usb = urb->context;
360c900eff3SJussi Kivilinna struct zd_usb_interrupt *intr = &usb->intr;
36181454b84SSebastian Andrzej Siewior unsigned long flags;
362c900eff3SJussi Kivilinna
36381454b84SSebastian Andrzej Siewior spin_lock_irqsave(&intr->lock, flags);
364c900eff3SJussi Kivilinna if (atomic_read(&intr->read_regs_enabled)) {
365c900eff3SJussi Kivilinna atomic_set(&intr->read_regs_enabled, 0);
366c900eff3SJussi Kivilinna intr->read_regs_int_overridden = 1;
367c900eff3SJussi Kivilinna complete(&intr->read_regs.completion);
368c900eff3SJussi Kivilinna }
36981454b84SSebastian Andrzej Siewior spin_unlock_irqrestore(&intr->lock, flags);
370c900eff3SJussi Kivilinna }
371c900eff3SJussi Kivilinna
handle_regs_int(struct urb * urb)372e85d0918SDaniel Drake static inline void handle_regs_int(struct urb *urb)
373e85d0918SDaniel Drake {
374e85d0918SDaniel Drake struct zd_usb *usb = urb->context;
375e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
37681454b84SSebastian Andrzej Siewior unsigned long flags;
377e85d0918SDaniel Drake int len;
37872e77a8aSLuis Carlos Cobo u16 int_num;
379e85d0918SDaniel Drake
38081454b84SSebastian Andrzej Siewior spin_lock_irqsave(&intr->lock, flags);
381e85d0918SDaniel Drake
382d63ddcecSAl Viro int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
3835a391813SJohannes Berg if (int_num == (u16)CR_INTERRUPT) {
38472e77a8aSLuis Carlos Cobo struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
3858b17f75cSJussi Kivilinna spin_lock(&mac->lock);
38672e77a8aSLuis Carlos Cobo memcpy(&mac->intr_buffer, urb->transfer_buffer,
38772e77a8aSLuis Carlos Cobo USB_MAX_EP_INT_BUFFER);
3888b17f75cSJussi Kivilinna spin_unlock(&mac->lock);
38972e77a8aSLuis Carlos Cobo schedule_work(&mac->process_intr);
390c900eff3SJussi Kivilinna } else if (atomic_read(&intr->read_regs_enabled)) {
391c900eff3SJussi Kivilinna len = urb->actual_length;
392c900eff3SJussi Kivilinna intr->read_regs.length = urb->actual_length;
393e85d0918SDaniel Drake if (len > sizeof(intr->read_regs.buffer))
394e85d0918SDaniel Drake len = sizeof(intr->read_regs.buffer);
395c900eff3SJussi Kivilinna
396e85d0918SDaniel Drake memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
397c900eff3SJussi Kivilinna
398c900eff3SJussi Kivilinna /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
399c900eff3SJussi Kivilinna * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
400c900eff3SJussi Kivilinna * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
401c900eff3SJussi Kivilinna * retry unhandled. Next read-reg command then might catch
402c900eff3SJussi Kivilinna * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
403c900eff3SJussi Kivilinna */
404c900eff3SJussi Kivilinna if (!check_read_regs(usb, intr->read_regs.req,
405c900eff3SJussi Kivilinna intr->read_regs.req_count))
406c900eff3SJussi Kivilinna goto out;
407c900eff3SJussi Kivilinna
408c900eff3SJussi Kivilinna atomic_set(&intr->read_regs_enabled, 0);
409c900eff3SJussi Kivilinna intr->read_regs_int_overridden = 0;
410e85d0918SDaniel Drake complete(&intr->read_regs.completion);
411c900eff3SJussi Kivilinna
412e85d0918SDaniel Drake goto out;
413e85d0918SDaniel Drake }
414e85d0918SDaniel Drake
415e85d0918SDaniel Drake out:
41681454b84SSebastian Andrzej Siewior spin_unlock_irqrestore(&intr->lock, flags);
417c900eff3SJussi Kivilinna
418c900eff3SJussi Kivilinna /* CR_INTERRUPT might override read_reg too. */
4195a391813SJohannes Berg if (int_num == (u16)CR_INTERRUPT &&
4205a391813SJohannes Berg atomic_read(&intr->read_regs_enabled))
421c900eff3SJussi Kivilinna handle_regs_int_override(urb);
422e85d0918SDaniel Drake }
423e85d0918SDaniel Drake
int_urb_complete(struct urb * urb)4247d12e780SDavid Howells static void int_urb_complete(struct urb *urb)
425e85d0918SDaniel Drake {
426e85d0918SDaniel Drake int r;
427e85d0918SDaniel Drake struct usb_int_header *hdr;
428c900eff3SJussi Kivilinna struct zd_usb *usb;
429c900eff3SJussi Kivilinna struct zd_usb_interrupt *intr;
430e85d0918SDaniel Drake
431e85d0918SDaniel Drake switch (urb->status) {
432e85d0918SDaniel Drake case 0:
433e85d0918SDaniel Drake break;
434e85d0918SDaniel Drake case -ESHUTDOWN:
435e85d0918SDaniel Drake case -EINVAL:
436e85d0918SDaniel Drake case -ENODEV:
437e85d0918SDaniel Drake case -ENOENT:
438e85d0918SDaniel Drake case -ECONNRESET:
439e85d0918SDaniel Drake case -EPIPE:
44024d24c62SJussi Kivilinna dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
4414a3b0874SJussi Kivilinna return;
442e85d0918SDaniel Drake default:
44324d24c62SJussi Kivilinna dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
444e85d0918SDaniel Drake goto resubmit;
445e85d0918SDaniel Drake }
446e85d0918SDaniel Drake
447e85d0918SDaniel Drake if (urb->actual_length < sizeof(hdr)) {
448*41469ff9SBjorn Helgaas dev_dbg_f(urb_dev(urb), "error: urb %p too small\n", urb);
449e85d0918SDaniel Drake goto resubmit;
450e85d0918SDaniel Drake }
451e85d0918SDaniel Drake
452e85d0918SDaniel Drake hdr = urb->transfer_buffer;
453e85d0918SDaniel Drake if (hdr->type != USB_INT_TYPE) {
454e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb);
455e85d0918SDaniel Drake goto resubmit;
456e85d0918SDaniel Drake }
457e85d0918SDaniel Drake
458c900eff3SJussi Kivilinna /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
459c900eff3SJussi Kivilinna * pending USB_INT_ID_REGS causing read command timeout.
460c900eff3SJussi Kivilinna */
461c900eff3SJussi Kivilinna usb = urb->context;
462c900eff3SJussi Kivilinna intr = &usb->intr;
463c900eff3SJussi Kivilinna if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
464c900eff3SJussi Kivilinna handle_regs_int_override(urb);
465c900eff3SJussi Kivilinna
466e85d0918SDaniel Drake switch (hdr->id) {
467e85d0918SDaniel Drake case USB_INT_ID_REGS:
468e85d0918SDaniel Drake handle_regs_int(urb);
469e85d0918SDaniel Drake break;
470e85d0918SDaniel Drake case USB_INT_ID_RETRY_FAILED:
4717f4013f0SBenoit PAPILLAULT zd_mac_tx_failed(urb);
472e85d0918SDaniel Drake break;
473e85d0918SDaniel Drake default:
474e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb,
475e85d0918SDaniel Drake (unsigned int)hdr->id);
476e85d0918SDaniel Drake goto resubmit;
477e85d0918SDaniel Drake }
478e85d0918SDaniel Drake
479e85d0918SDaniel Drake resubmit:
480e85d0918SDaniel Drake r = usb_submit_urb(urb, GFP_ATOMIC);
481e85d0918SDaniel Drake if (r) {
4824a3b0874SJussi Kivilinna dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n",
4834a3b0874SJussi Kivilinna urb, r);
4844a3b0874SJussi Kivilinna /* TODO: add worker to reset intr->urb */
485e85d0918SDaniel Drake }
486e85d0918SDaniel Drake return;
487e85d0918SDaniel Drake }
488e85d0918SDaniel Drake
int_urb_interval(struct usb_device * udev)489e85d0918SDaniel Drake static inline int int_urb_interval(struct usb_device *udev)
490e85d0918SDaniel Drake {
491e85d0918SDaniel Drake switch (udev->speed) {
492e85d0918SDaniel Drake case USB_SPEED_HIGH:
493e85d0918SDaniel Drake return 4;
494e85d0918SDaniel Drake case USB_SPEED_LOW:
495e85d0918SDaniel Drake return 10;
496e85d0918SDaniel Drake case USB_SPEED_FULL:
497e85d0918SDaniel Drake default:
498e85d0918SDaniel Drake return 1;
499e85d0918SDaniel Drake }
500e85d0918SDaniel Drake }
501e85d0918SDaniel Drake
usb_int_enabled(struct zd_usb * usb)502e85d0918SDaniel Drake static inline int usb_int_enabled(struct zd_usb *usb)
503e85d0918SDaniel Drake {
504e85d0918SDaniel Drake unsigned long flags;
505e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
506e85d0918SDaniel Drake struct urb *urb;
507e85d0918SDaniel Drake
508e85d0918SDaniel Drake spin_lock_irqsave(&intr->lock, flags);
509e85d0918SDaniel Drake urb = intr->urb;
510e85d0918SDaniel Drake spin_unlock_irqrestore(&intr->lock, flags);
511e85d0918SDaniel Drake return urb != NULL;
512e85d0918SDaniel Drake }
513e85d0918SDaniel Drake
zd_usb_enable_int(struct zd_usb * usb)514e85d0918SDaniel Drake int zd_usb_enable_int(struct zd_usb *usb)
515e85d0918SDaniel Drake {
516e85d0918SDaniel Drake int r;
5174a3b0874SJussi Kivilinna struct usb_device *udev = zd_usb_to_usbdev(usb);
518e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
519e85d0918SDaniel Drake struct urb *urb;
520e85d0918SDaniel Drake
521e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "\n");
522e85d0918SDaniel Drake
52335c3404eSUlrich Kunitz urb = usb_alloc_urb(0, GFP_KERNEL);
524e85d0918SDaniel Drake if (!urb) {
525e85d0918SDaniel Drake r = -ENOMEM;
526e85d0918SDaniel Drake goto out;
527e85d0918SDaniel Drake }
528e85d0918SDaniel Drake
529e85d0918SDaniel Drake ZD_ASSERT(!irqs_disabled());
530e85d0918SDaniel Drake spin_lock_irq(&intr->lock);
531e85d0918SDaniel Drake if (intr->urb) {
532e85d0918SDaniel Drake spin_unlock_irq(&intr->lock);
533e85d0918SDaniel Drake r = 0;
534e85d0918SDaniel Drake goto error_free_urb;
535e85d0918SDaniel Drake }
536e85d0918SDaniel Drake intr->urb = urb;
537e85d0918SDaniel Drake spin_unlock_irq(&intr->lock);
538e85d0918SDaniel Drake
539e85d0918SDaniel Drake r = -ENOMEM;
5404a3b0874SJussi Kivilinna intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER,
5414a3b0874SJussi Kivilinna GFP_KERNEL, &intr->buffer_dma);
5424a3b0874SJussi Kivilinna if (!intr->buffer) {
543e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
544e85d0918SDaniel Drake "couldn't allocate transfer_buffer\n");
545e85d0918SDaniel Drake goto error_set_urb_null;
546e85d0918SDaniel Drake }
547e85d0918SDaniel Drake
548e85d0918SDaniel Drake usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
5494a3b0874SJussi Kivilinna intr->buffer, USB_MAX_EP_INT_BUFFER,
550e85d0918SDaniel Drake int_urb_complete, usb,
551e85d0918SDaniel Drake intr->interval);
5524a3b0874SJussi Kivilinna urb->transfer_dma = intr->buffer_dma;
5534a3b0874SJussi Kivilinna urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
554e85d0918SDaniel Drake
555e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
55635c3404eSUlrich Kunitz r = usb_submit_urb(urb, GFP_KERNEL);
557e85d0918SDaniel Drake if (r) {
558e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
559e85d0918SDaniel Drake "Couldn't submit urb. Error number %d\n", r);
560e85d0918SDaniel Drake goto error;
561e85d0918SDaniel Drake }
562e85d0918SDaniel Drake
563e85d0918SDaniel Drake return 0;
564e85d0918SDaniel Drake error:
5654a3b0874SJussi Kivilinna usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
5664a3b0874SJussi Kivilinna intr->buffer, intr->buffer_dma);
567e85d0918SDaniel Drake error_set_urb_null:
568e85d0918SDaniel Drake spin_lock_irq(&intr->lock);
569e85d0918SDaniel Drake intr->urb = NULL;
570e85d0918SDaniel Drake spin_unlock_irq(&intr->lock);
571e85d0918SDaniel Drake error_free_urb:
572e85d0918SDaniel Drake usb_free_urb(urb);
573e85d0918SDaniel Drake out:
574e85d0918SDaniel Drake return r;
575e85d0918SDaniel Drake }
576e85d0918SDaniel Drake
zd_usb_disable_int(struct zd_usb * usb)577e85d0918SDaniel Drake void zd_usb_disable_int(struct zd_usb *usb)
578e85d0918SDaniel Drake {
579e85d0918SDaniel Drake unsigned long flags;
5804a3b0874SJussi Kivilinna struct usb_device *udev = zd_usb_to_usbdev(usb);
581e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
582e85d0918SDaniel Drake struct urb *urb;
5834a3b0874SJussi Kivilinna void *buffer;
5844a3b0874SJussi Kivilinna dma_addr_t buffer_dma;
585e85d0918SDaniel Drake
586e85d0918SDaniel Drake spin_lock_irqsave(&intr->lock, flags);
587e85d0918SDaniel Drake urb = intr->urb;
588e85d0918SDaniel Drake if (!urb) {
589e85d0918SDaniel Drake spin_unlock_irqrestore(&intr->lock, flags);
590e85d0918SDaniel Drake return;
591e85d0918SDaniel Drake }
592e85d0918SDaniel Drake intr->urb = NULL;
5934a3b0874SJussi Kivilinna buffer = intr->buffer;
5944a3b0874SJussi Kivilinna buffer_dma = intr->buffer_dma;
5954a3b0874SJussi Kivilinna intr->buffer = NULL;
596e85d0918SDaniel Drake spin_unlock_irqrestore(&intr->lock, flags);
597e85d0918SDaniel Drake
598e85d0918SDaniel Drake usb_kill_urb(urb);
599e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
600e85d0918SDaniel Drake usb_free_urb(urb);
6014a3b0874SJussi Kivilinna
6024f3ebd6fSXu Wang usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, buffer, buffer_dma);
603e85d0918SDaniel Drake }
604e85d0918SDaniel Drake
handle_rx_packet(struct zd_usb * usb,const u8 * buffer,unsigned int length)605e85d0918SDaniel Drake static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
606e85d0918SDaniel Drake unsigned int length)
607e85d0918SDaniel Drake {
608e85d0918SDaniel Drake int i;
609e85d0918SDaniel Drake const struct rx_length_info *length_info;
610e85d0918SDaniel Drake
611e85d0918SDaniel Drake if (length < sizeof(struct rx_length_info)) {
612e85d0918SDaniel Drake /* It's not a complete packet anyhow. */
613b405e1b8SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
614b405e1b8SJussi Kivilinna length);
615e85d0918SDaniel Drake return;
616e85d0918SDaniel Drake }
617e85d0918SDaniel Drake length_info = (struct rx_length_info *)
618e85d0918SDaniel Drake (buffer + length - sizeof(struct rx_length_info));
619e85d0918SDaniel Drake
620e85d0918SDaniel Drake /* It might be that three frames are merged into a single URB
621e85d0918SDaniel Drake * transaction. We have to check for the length info tag.
622e85d0918SDaniel Drake *
623e85d0918SDaniel Drake * While testing we discovered that length_info might be unaligned,
624e85d0918SDaniel Drake * because if USB transactions are merged, the last packet will not
625e85d0918SDaniel Drake * be padded. Unaligned access might also happen if the length_info
626e85d0918SDaniel Drake * structure is not present.
627e85d0918SDaniel Drake */
628533dd1b0SHarvey Harrison if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
629b269825bSUlrich Kunitz {
630e85d0918SDaniel Drake unsigned int l, k, n;
631e85d0918SDaniel Drake for (i = 0, l = 0;; i++) {
632533dd1b0SHarvey Harrison k = get_unaligned_le16(&length_info->length[i]);
633850c211cSUlrich Kunitz if (k == 0)
634850c211cSUlrich Kunitz return;
635e85d0918SDaniel Drake n = l+k;
636e85d0918SDaniel Drake if (n > length)
637e85d0918SDaniel Drake return;
638459c51adSDaniel Drake zd_mac_rx(zd_usb_to_hw(usb), buffer+l, k);
639e85d0918SDaniel Drake if (i >= 2)
640e85d0918SDaniel Drake return;
641e85d0918SDaniel Drake l = (n+3) & ~3;
642e85d0918SDaniel Drake }
643e85d0918SDaniel Drake } else {
644459c51adSDaniel Drake zd_mac_rx(zd_usb_to_hw(usb), buffer, length);
645e85d0918SDaniel Drake }
646e85d0918SDaniel Drake }
647e85d0918SDaniel Drake
rx_urb_complete(struct urb * urb)6487d12e780SDavid Howells static void rx_urb_complete(struct urb *urb)
649e85d0918SDaniel Drake {
65024d24c62SJussi Kivilinna int r;
651e85d0918SDaniel Drake struct zd_usb *usb;
652e85d0918SDaniel Drake struct zd_usb_rx *rx;
653e85d0918SDaniel Drake const u8 *buffer;
654e85d0918SDaniel Drake unsigned int length;
65581454b84SSebastian Andrzej Siewior unsigned long flags;
656e85d0918SDaniel Drake
657e85d0918SDaniel Drake switch (urb->status) {
658e85d0918SDaniel Drake case 0:
659e85d0918SDaniel Drake break;
660e85d0918SDaniel Drake case -ESHUTDOWN:
661e85d0918SDaniel Drake case -EINVAL:
662e85d0918SDaniel Drake case -ENODEV:
663e85d0918SDaniel Drake case -ENOENT:
664e85d0918SDaniel Drake case -ECONNRESET:
665e85d0918SDaniel Drake case -EPIPE:
66624d24c62SJussi Kivilinna dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
667b312d799SDaniel Drake return;
668e85d0918SDaniel Drake default:
669e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
670e85d0918SDaniel Drake goto resubmit;
671e85d0918SDaniel Drake }
672e85d0918SDaniel Drake
673e85d0918SDaniel Drake buffer = urb->transfer_buffer;
674e85d0918SDaniel Drake length = urb->actual_length;
675e85d0918SDaniel Drake usb = urb->context;
676e85d0918SDaniel Drake rx = &usb->rx;
677e85d0918SDaniel Drake
67802353573SJussi Kivilinna tasklet_schedule(&rx->reset_timer_tasklet);
6791f6cccccSJussi Kivilinna
680e85d0918SDaniel Drake if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
681e85d0918SDaniel Drake /* If there is an old first fragment, we don't care. */
682e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
683e85d0918SDaniel Drake ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment));
68481454b84SSebastian Andrzej Siewior spin_lock_irqsave(&rx->lock, flags);
685e85d0918SDaniel Drake memcpy(rx->fragment, buffer, length);
686e85d0918SDaniel Drake rx->fragment_length = length;
68781454b84SSebastian Andrzej Siewior spin_unlock_irqrestore(&rx->lock, flags);
688e85d0918SDaniel Drake goto resubmit;
689e85d0918SDaniel Drake }
690e85d0918SDaniel Drake
69181454b84SSebastian Andrzej Siewior spin_lock_irqsave(&rx->lock, flags);
692e85d0918SDaniel Drake if (rx->fragment_length > 0) {
693e85d0918SDaniel Drake /* We are on a second fragment, we believe */
694e85d0918SDaniel Drake ZD_ASSERT(length + rx->fragment_length <=
695e85d0918SDaniel Drake ARRAY_SIZE(rx->fragment));
696e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "*** second fragment ***\n");
697e85d0918SDaniel Drake memcpy(rx->fragment+rx->fragment_length, buffer, length);
698e85d0918SDaniel Drake handle_rx_packet(usb, rx->fragment,
699e85d0918SDaniel Drake rx->fragment_length + length);
700e85d0918SDaniel Drake rx->fragment_length = 0;
70181454b84SSebastian Andrzej Siewior spin_unlock_irqrestore(&rx->lock, flags);
702e85d0918SDaniel Drake } else {
70381454b84SSebastian Andrzej Siewior spin_unlock_irqrestore(&rx->lock, flags);
704e85d0918SDaniel Drake handle_rx_packet(usb, buffer, length);
705e85d0918SDaniel Drake }
706e85d0918SDaniel Drake
707e85d0918SDaniel Drake resubmit:
70824d24c62SJussi Kivilinna r = usb_submit_urb(urb, GFP_ATOMIC);
70924d24c62SJussi Kivilinna if (r)
71024d24c62SJussi Kivilinna dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r);
711e85d0918SDaniel Drake }
712e85d0918SDaniel Drake
alloc_rx_urb(struct zd_usb * usb)713459c51adSDaniel Drake static struct urb *alloc_rx_urb(struct zd_usb *usb)
714e85d0918SDaniel Drake {
715e85d0918SDaniel Drake struct usb_device *udev = zd_usb_to_usbdev(usb);
716e85d0918SDaniel Drake struct urb *urb;
717e85d0918SDaniel Drake void *buffer;
718e85d0918SDaniel Drake
71935c3404eSUlrich Kunitz urb = usb_alloc_urb(0, GFP_KERNEL);
720e85d0918SDaniel Drake if (!urb)
721e85d0918SDaniel Drake return NULL;
722997ea58eSDaniel Mack buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
723e85d0918SDaniel Drake &urb->transfer_dma);
724e85d0918SDaniel Drake if (!buffer) {
725e85d0918SDaniel Drake usb_free_urb(urb);
726e85d0918SDaniel Drake return NULL;
727e85d0918SDaniel Drake }
728e85d0918SDaniel Drake
729e85d0918SDaniel Drake usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
730e85d0918SDaniel Drake buffer, USB_MAX_RX_SIZE,
731e85d0918SDaniel Drake rx_urb_complete, usb);
732e85d0918SDaniel Drake urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
733e85d0918SDaniel Drake
734e85d0918SDaniel Drake return urb;
735e85d0918SDaniel Drake }
736e85d0918SDaniel Drake
free_rx_urb(struct urb * urb)737459c51adSDaniel Drake static void free_rx_urb(struct urb *urb)
738e85d0918SDaniel Drake {
739e85d0918SDaniel Drake if (!urb)
740e85d0918SDaniel Drake return;
741997ea58eSDaniel Mack usb_free_coherent(urb->dev, urb->transfer_buffer_length,
742e85d0918SDaniel Drake urb->transfer_buffer, urb->transfer_dma);
743e85d0918SDaniel Drake usb_free_urb(urb);
744e85d0918SDaniel Drake }
745e85d0918SDaniel Drake
__zd_usb_enable_rx(struct zd_usb * usb)7461f6cccccSJussi Kivilinna static int __zd_usb_enable_rx(struct zd_usb *usb)
747e85d0918SDaniel Drake {
748e85d0918SDaniel Drake int i, r;
749e85d0918SDaniel Drake struct zd_usb_rx *rx = &usb->rx;
750e85d0918SDaniel Drake struct urb **urbs;
751e85d0918SDaniel Drake
752e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "\n");
753e85d0918SDaniel Drake
754e85d0918SDaniel Drake r = -ENOMEM;
755459c51adSDaniel Drake urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
756e85d0918SDaniel Drake if (!urbs)
757e85d0918SDaniel Drake goto error;
758459c51adSDaniel Drake for (i = 0; i < RX_URBS_COUNT; i++) {
759459c51adSDaniel Drake urbs[i] = alloc_rx_urb(usb);
760e85d0918SDaniel Drake if (!urbs[i])
761e85d0918SDaniel Drake goto error;
762e85d0918SDaniel Drake }
763e85d0918SDaniel Drake
764e85d0918SDaniel Drake ZD_ASSERT(!irqs_disabled());
765e85d0918SDaniel Drake spin_lock_irq(&rx->lock);
766e85d0918SDaniel Drake if (rx->urbs) {
767e85d0918SDaniel Drake spin_unlock_irq(&rx->lock);
768e85d0918SDaniel Drake r = 0;
769e85d0918SDaniel Drake goto error;
770e85d0918SDaniel Drake }
771e85d0918SDaniel Drake rx->urbs = urbs;
772459c51adSDaniel Drake rx->urbs_count = RX_URBS_COUNT;
773e85d0918SDaniel Drake spin_unlock_irq(&rx->lock);
774e85d0918SDaniel Drake
775459c51adSDaniel Drake for (i = 0; i < RX_URBS_COUNT; i++) {
77635c3404eSUlrich Kunitz r = usb_submit_urb(urbs[i], GFP_KERNEL);
777e85d0918SDaniel Drake if (r)
778e85d0918SDaniel Drake goto error_submit;
779e85d0918SDaniel Drake }
780e85d0918SDaniel Drake
781e85d0918SDaniel Drake return 0;
782e85d0918SDaniel Drake error_submit:
783459c51adSDaniel Drake for (i = 0; i < RX_URBS_COUNT; i++) {
784e85d0918SDaniel Drake usb_kill_urb(urbs[i]);
785e85d0918SDaniel Drake }
786e85d0918SDaniel Drake spin_lock_irq(&rx->lock);
787e85d0918SDaniel Drake rx->urbs = NULL;
788e85d0918SDaniel Drake rx->urbs_count = 0;
789e85d0918SDaniel Drake spin_unlock_irq(&rx->lock);
790e85d0918SDaniel Drake error:
791e85d0918SDaniel Drake if (urbs) {
792459c51adSDaniel Drake for (i = 0; i < RX_URBS_COUNT; i++)
793459c51adSDaniel Drake free_rx_urb(urbs[i]);
794e85d0918SDaniel Drake }
795e85d0918SDaniel Drake return r;
796e85d0918SDaniel Drake }
797e85d0918SDaniel Drake
zd_usb_enable_rx(struct zd_usb * usb)7981f6cccccSJussi Kivilinna int zd_usb_enable_rx(struct zd_usb *usb)
7991f6cccccSJussi Kivilinna {
8001f6cccccSJussi Kivilinna int r;
8011f6cccccSJussi Kivilinna struct zd_usb_rx *rx = &usb->rx;
8021f6cccccSJussi Kivilinna
8031f6cccccSJussi Kivilinna mutex_lock(&rx->setup_mutex);
8041f6cccccSJussi Kivilinna r = __zd_usb_enable_rx(usb);
8051f6cccccSJussi Kivilinna mutex_unlock(&rx->setup_mutex);
8061f6cccccSJussi Kivilinna
8071f6cccccSJussi Kivilinna zd_usb_reset_rx_idle_timer(usb);
8081f6cccccSJussi Kivilinna
8091f6cccccSJussi Kivilinna return r;
8101f6cccccSJussi Kivilinna }
8111f6cccccSJussi Kivilinna
__zd_usb_disable_rx(struct zd_usb * usb)8121f6cccccSJussi Kivilinna static void __zd_usb_disable_rx(struct zd_usb *usb)
813e85d0918SDaniel Drake {
814e85d0918SDaniel Drake int i;
815e85d0918SDaniel Drake unsigned long flags;
816e85d0918SDaniel Drake struct urb **urbs;
817e85d0918SDaniel Drake unsigned int count;
818e85d0918SDaniel Drake struct zd_usb_rx *rx = &usb->rx;
819e85d0918SDaniel Drake
820e85d0918SDaniel Drake spin_lock_irqsave(&rx->lock, flags);
821e85d0918SDaniel Drake urbs = rx->urbs;
822e85d0918SDaniel Drake count = rx->urbs_count;
823e85d0918SDaniel Drake spin_unlock_irqrestore(&rx->lock, flags);
824e85d0918SDaniel Drake if (!urbs)
825e85d0918SDaniel Drake return;
826e85d0918SDaniel Drake
827e85d0918SDaniel Drake for (i = 0; i < count; i++) {
828e85d0918SDaniel Drake usb_kill_urb(urbs[i]);
829459c51adSDaniel Drake free_rx_urb(urbs[i]);
830e85d0918SDaniel Drake }
831e85d0918SDaniel Drake kfree(urbs);
832e85d0918SDaniel Drake
833e85d0918SDaniel Drake spin_lock_irqsave(&rx->lock, flags);
834e85d0918SDaniel Drake rx->urbs = NULL;
835e85d0918SDaniel Drake rx->urbs_count = 0;
836e85d0918SDaniel Drake spin_unlock_irqrestore(&rx->lock, flags);
837e85d0918SDaniel Drake }
838e85d0918SDaniel Drake
zd_usb_disable_rx(struct zd_usb * usb)8391f6cccccSJussi Kivilinna void zd_usb_disable_rx(struct zd_usb *usb)
8401f6cccccSJussi Kivilinna {
8411f6cccccSJussi Kivilinna struct zd_usb_rx *rx = &usb->rx;
8421f6cccccSJussi Kivilinna
8431f6cccccSJussi Kivilinna mutex_lock(&rx->setup_mutex);
8441f6cccccSJussi Kivilinna __zd_usb_disable_rx(usb);
8451f6cccccSJussi Kivilinna mutex_unlock(&rx->setup_mutex);
8461f6cccccSJussi Kivilinna
84702353573SJussi Kivilinna tasklet_kill(&rx->reset_timer_tasklet);
8481f6cccccSJussi Kivilinna cancel_delayed_work_sync(&rx->idle_work);
8491f6cccccSJussi Kivilinna }
8501f6cccccSJussi Kivilinna
zd_usb_reset_rx(struct zd_usb * usb)8511f6cccccSJussi Kivilinna static void zd_usb_reset_rx(struct zd_usb *usb)
8521f6cccccSJussi Kivilinna {
8531f6cccccSJussi Kivilinna bool do_reset;
8541f6cccccSJussi Kivilinna struct zd_usb_rx *rx = &usb->rx;
8551f6cccccSJussi Kivilinna unsigned long flags;
8561f6cccccSJussi Kivilinna
8571f6cccccSJussi Kivilinna mutex_lock(&rx->setup_mutex);
8581f6cccccSJussi Kivilinna
8591f6cccccSJussi Kivilinna spin_lock_irqsave(&rx->lock, flags);
8601f6cccccSJussi Kivilinna do_reset = rx->urbs != NULL;
8611f6cccccSJussi Kivilinna spin_unlock_irqrestore(&rx->lock, flags);
8621f6cccccSJussi Kivilinna
8631f6cccccSJussi Kivilinna if (do_reset) {
8641f6cccccSJussi Kivilinna __zd_usb_disable_rx(usb);
8651f6cccccSJussi Kivilinna __zd_usb_enable_rx(usb);
8661f6cccccSJussi Kivilinna }
8671f6cccccSJussi Kivilinna
8681f6cccccSJussi Kivilinna mutex_unlock(&rx->setup_mutex);
8691f6cccccSJussi Kivilinna
8701f6cccccSJussi Kivilinna if (do_reset)
8711f6cccccSJussi Kivilinna zd_usb_reset_rx_idle_timer(usb);
8721f6cccccSJussi Kivilinna }
8731f6cccccSJussi Kivilinna
874459c51adSDaniel Drake /**
875459c51adSDaniel Drake * zd_usb_disable_tx - disable transmission
876459c51adSDaniel Drake * @usb: the zd1211rw-private USB structure
877459c51adSDaniel Drake *
878459c51adSDaniel Drake * Frees all URBs in the free list and marks the transmission as disabled.
879459c51adSDaniel Drake */
zd_usb_disable_tx(struct zd_usb * usb)880459c51adSDaniel Drake void zd_usb_disable_tx(struct zd_usb *usb)
881459c51adSDaniel Drake {
882459c51adSDaniel Drake struct zd_usb_tx *tx = &usb->tx;
883459c51adSDaniel Drake unsigned long flags;
88478fc800fSJussi Kivilinna
88578fc800fSJussi Kivilinna atomic_set(&tx->enabled, 0);
88678fc800fSJussi Kivilinna
88778fc800fSJussi Kivilinna /* kill all submitted tx-urbs */
88878fc800fSJussi Kivilinna usb_kill_anchored_urbs(&tx->submitted);
889459c51adSDaniel Drake
890459c51adSDaniel Drake spin_lock_irqsave(&tx->lock, flags);
891a0fd751fSJussi Kivilinna WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
89278fc800fSJussi Kivilinna WARN_ON(tx->submitted_urbs != 0);
893459c51adSDaniel Drake tx->submitted_urbs = 0;
89478fc800fSJussi Kivilinna spin_unlock_irqrestore(&tx->lock, flags);
89578fc800fSJussi Kivilinna
896459c51adSDaniel Drake /* The stopped state is ignored, relying on ieee80211_wake_queues()
897459c51adSDaniel Drake * in a potentionally following zd_usb_enable_tx().
898459c51adSDaniel Drake */
899459c51adSDaniel Drake }
900459c51adSDaniel Drake
901459c51adSDaniel Drake /**
902459c51adSDaniel Drake * zd_usb_enable_tx - enables transmission
903459c51adSDaniel Drake * @usb: a &struct zd_usb pointer
904459c51adSDaniel Drake *
905459c51adSDaniel Drake * This function enables transmission and prepares the &zd_usb_tx data
906459c51adSDaniel Drake * structure.
907459c51adSDaniel Drake */
zd_usb_enable_tx(struct zd_usb * usb)908459c51adSDaniel Drake void zd_usb_enable_tx(struct zd_usb *usb)
909459c51adSDaniel Drake {
910459c51adSDaniel Drake unsigned long flags;
911459c51adSDaniel Drake struct zd_usb_tx *tx = &usb->tx;
912459c51adSDaniel Drake
913459c51adSDaniel Drake spin_lock_irqsave(&tx->lock, flags);
91478fc800fSJussi Kivilinna atomic_set(&tx->enabled, 1);
915459c51adSDaniel Drake tx->submitted_urbs = 0;
916459c51adSDaniel Drake ieee80211_wake_queues(zd_usb_to_hw(usb));
917459c51adSDaniel Drake tx->stopped = 0;
918459c51adSDaniel Drake spin_unlock_irqrestore(&tx->lock, flags);
919459c51adSDaniel Drake }
920459c51adSDaniel Drake
tx_dec_submitted_urbs(struct zd_usb * usb)921459c51adSDaniel Drake static void tx_dec_submitted_urbs(struct zd_usb *usb)
922459c51adSDaniel Drake {
923459c51adSDaniel Drake struct zd_usb_tx *tx = &usb->tx;
924459c51adSDaniel Drake unsigned long flags;
925459c51adSDaniel Drake
926459c51adSDaniel Drake spin_lock_irqsave(&tx->lock, flags);
927459c51adSDaniel Drake --tx->submitted_urbs;
928459c51adSDaniel Drake if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) {
929459c51adSDaniel Drake ieee80211_wake_queues(zd_usb_to_hw(usb));
930459c51adSDaniel Drake tx->stopped = 0;
931459c51adSDaniel Drake }
932459c51adSDaniel Drake spin_unlock_irqrestore(&tx->lock, flags);
933459c51adSDaniel Drake }
934459c51adSDaniel Drake
tx_inc_submitted_urbs(struct zd_usb * usb)935459c51adSDaniel Drake static void tx_inc_submitted_urbs(struct zd_usb *usb)
936459c51adSDaniel Drake {
937459c51adSDaniel Drake struct zd_usb_tx *tx = &usb->tx;
938459c51adSDaniel Drake unsigned long flags;
939459c51adSDaniel Drake
940459c51adSDaniel Drake spin_lock_irqsave(&tx->lock, flags);
941459c51adSDaniel Drake ++tx->submitted_urbs;
942459c51adSDaniel Drake if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) {
943459c51adSDaniel Drake ieee80211_stop_queues(zd_usb_to_hw(usb));
944459c51adSDaniel Drake tx->stopped = 1;
945459c51adSDaniel Drake }
946459c51adSDaniel Drake spin_unlock_irqrestore(&tx->lock, flags);
947459c51adSDaniel Drake }
948459c51adSDaniel Drake
949459c51adSDaniel Drake /**
950459c51adSDaniel Drake * tx_urb_complete - completes the execution of an URB
951459c51adSDaniel Drake * @urb: a URB
952459c51adSDaniel Drake *
953459c51adSDaniel Drake * This function is called if the URB has been transferred to a device or an
954459c51adSDaniel Drake * error has happened.
955459c51adSDaniel Drake */
tx_urb_complete(struct urb * urb)9567d12e780SDavid Howells static void tx_urb_complete(struct urb *urb)
957e85d0918SDaniel Drake {
958e85d0918SDaniel Drake int r;
959459c51adSDaniel Drake struct sk_buff *skb;
960e039fa4aSJohannes Berg struct ieee80211_tx_info *info;
961459c51adSDaniel Drake struct zd_usb *usb;
96278fc800fSJussi Kivilinna struct zd_usb_tx *tx;
96378fc800fSJussi Kivilinna
96478fc800fSJussi Kivilinna skb = (struct sk_buff *)urb->context;
96578fc800fSJussi Kivilinna info = IEEE80211_SKB_CB(skb);
96678fc800fSJussi Kivilinna /*
96778fc800fSJussi Kivilinna * grab 'usb' pointer before handing off the skb (since
96878fc800fSJussi Kivilinna * it might be freed by zd_mac_tx_to_dev or mac80211)
96978fc800fSJussi Kivilinna */
97078fc800fSJussi Kivilinna usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
97178fc800fSJussi Kivilinna tx = &usb->tx;
972e85d0918SDaniel Drake
973e85d0918SDaniel Drake switch (urb->status) {
974e85d0918SDaniel Drake case 0:
975e85d0918SDaniel Drake break;
976e85d0918SDaniel Drake case -ESHUTDOWN:
977e85d0918SDaniel Drake case -EINVAL:
978e85d0918SDaniel Drake case -ENODEV:
979e85d0918SDaniel Drake case -ENOENT:
980e85d0918SDaniel Drake case -ECONNRESET:
981b312d799SDaniel Drake case -EPIPE:
982e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
983e85d0918SDaniel Drake break;
984e85d0918SDaniel Drake default:
985e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
986e85d0918SDaniel Drake goto resubmit;
987e85d0918SDaniel Drake }
988e85d0918SDaniel Drake free_urb:
989a0fd751fSJussi Kivilinna skb_unlink(skb, &usb->tx.submitted_skbs);
990dbabad0cSJohannes Berg zd_mac_tx_to_dev(skb, urb->status);
99178fc800fSJussi Kivilinna usb_free_urb(urb);
992459c51adSDaniel Drake tx_dec_submitted_urbs(usb);
993e85d0918SDaniel Drake return;
994e85d0918SDaniel Drake resubmit:
99578fc800fSJussi Kivilinna usb_anchor_urb(urb, &tx->submitted);
996e85d0918SDaniel Drake r = usb_submit_urb(urb, GFP_ATOMIC);
997e85d0918SDaniel Drake if (r) {
99878fc800fSJussi Kivilinna usb_unanchor_urb(urb);
999e85d0918SDaniel Drake dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
1000e85d0918SDaniel Drake goto free_urb;
1001e85d0918SDaniel Drake }
1002e85d0918SDaniel Drake }
1003e85d0918SDaniel Drake
1004459c51adSDaniel Drake /**
1005459c51adSDaniel Drake * zd_usb_tx: initiates transfer of a frame of the device
1006459c51adSDaniel Drake *
1007459c51adSDaniel Drake * @usb: the zd1211rw-private USB structure
1008459c51adSDaniel Drake * @skb: a &struct sk_buff pointer
1009459c51adSDaniel Drake *
10102d594783SYueh-Shun Li * This function transmits a frame to the device. It doesn't wait for
1011459c51adSDaniel Drake * completion. The frame must contain the control set and have all the
1012459c51adSDaniel Drake * control set information available.
1013459c51adSDaniel Drake *
1014459c51adSDaniel Drake * The function returns 0 if the transfer has been successfully initiated.
1015e85d0918SDaniel Drake */
zd_usb_tx(struct zd_usb * usb,struct sk_buff * skb)1016459c51adSDaniel Drake int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
1017e85d0918SDaniel Drake {
1018e85d0918SDaniel Drake int r;
1019a0fd751fSJussi Kivilinna struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1020e85d0918SDaniel Drake struct usb_device *udev = zd_usb_to_usbdev(usb);
1021e85d0918SDaniel Drake struct urb *urb;
102278fc800fSJussi Kivilinna struct zd_usb_tx *tx = &usb->tx;
1023e85d0918SDaniel Drake
102478fc800fSJussi Kivilinna if (!atomic_read(&tx->enabled)) {
102578fc800fSJussi Kivilinna r = -ENOENT;
102678fc800fSJussi Kivilinna goto out;
102778fc800fSJussi Kivilinna }
102878fc800fSJussi Kivilinna
102978fc800fSJussi Kivilinna urb = usb_alloc_urb(0, GFP_ATOMIC);
1030e85d0918SDaniel Drake if (!urb) {
1031e85d0918SDaniel Drake r = -ENOMEM;
1032e85d0918SDaniel Drake goto out;
1033e85d0918SDaniel Drake }
1034e85d0918SDaniel Drake
1035e85d0918SDaniel Drake usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
1036459c51adSDaniel Drake skb->data, skb->len, tx_urb_complete, skb);
1037e85d0918SDaniel Drake
1038a0fd751fSJussi Kivilinna info->rate_driver_data[1] = (void *)jiffies;
1039a0fd751fSJussi Kivilinna skb_queue_tail(&tx->submitted_skbs, skb);
104078fc800fSJussi Kivilinna usb_anchor_urb(urb, &tx->submitted);
1041a0fd751fSJussi Kivilinna
1042e85d0918SDaniel Drake r = usb_submit_urb(urb, GFP_ATOMIC);
104378fc800fSJussi Kivilinna if (r) {
104424d24c62SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r);
104578fc800fSJussi Kivilinna usb_unanchor_urb(urb);
1046a0fd751fSJussi Kivilinna skb_unlink(skb, &tx->submitted_skbs);
1047e85d0918SDaniel Drake goto error;
104878fc800fSJussi Kivilinna }
1049459c51adSDaniel Drake tx_inc_submitted_urbs(usb);
1050e85d0918SDaniel Drake return 0;
1051e85d0918SDaniel Drake error:
105278fc800fSJussi Kivilinna usb_free_urb(urb);
1053e85d0918SDaniel Drake out:
1054e85d0918SDaniel Drake return r;
1055e85d0918SDaniel Drake }
1056e85d0918SDaniel Drake
zd_tx_timeout(struct zd_usb * usb)1057a0fd751fSJussi Kivilinna static bool zd_tx_timeout(struct zd_usb *usb)
1058a0fd751fSJussi Kivilinna {
1059a0fd751fSJussi Kivilinna struct zd_usb_tx *tx = &usb->tx;
1060a0fd751fSJussi Kivilinna struct sk_buff_head *q = &tx->submitted_skbs;
1061a0fd751fSJussi Kivilinna struct sk_buff *skb, *skbnext;
1062a0fd751fSJussi Kivilinna struct ieee80211_tx_info *info;
1063a0fd751fSJussi Kivilinna unsigned long flags, trans_start;
1064a0fd751fSJussi Kivilinna bool have_timedout = false;
1065a0fd751fSJussi Kivilinna
1066a0fd751fSJussi Kivilinna spin_lock_irqsave(&q->lock, flags);
1067a0fd751fSJussi Kivilinna skb_queue_walk_safe(q, skb, skbnext) {
1068a0fd751fSJussi Kivilinna info = IEEE80211_SKB_CB(skb);
1069a0fd751fSJussi Kivilinna trans_start = (unsigned long)info->rate_driver_data[1];
1070a0fd751fSJussi Kivilinna
1071a0fd751fSJussi Kivilinna if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
1072a0fd751fSJussi Kivilinna have_timedout = true;
1073a0fd751fSJussi Kivilinna break;
1074a0fd751fSJussi Kivilinna }
1075a0fd751fSJussi Kivilinna }
1076a0fd751fSJussi Kivilinna spin_unlock_irqrestore(&q->lock, flags);
1077a0fd751fSJussi Kivilinna
1078a0fd751fSJussi Kivilinna return have_timedout;
1079a0fd751fSJussi Kivilinna }
1080a0fd751fSJussi Kivilinna
zd_tx_watchdog_handler(struct work_struct * work)1081a0fd751fSJussi Kivilinna static void zd_tx_watchdog_handler(struct work_struct *work)
1082a0fd751fSJussi Kivilinna {
1083a0fd751fSJussi Kivilinna struct zd_usb *usb =
1084a0fd751fSJussi Kivilinna container_of(work, struct zd_usb, tx.watchdog_work.work);
1085a0fd751fSJussi Kivilinna struct zd_usb_tx *tx = &usb->tx;
1086a0fd751fSJussi Kivilinna
1087a0fd751fSJussi Kivilinna if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
1088a0fd751fSJussi Kivilinna goto out;
1089a0fd751fSJussi Kivilinna if (!zd_tx_timeout(usb))
1090a0fd751fSJussi Kivilinna goto out;
1091a0fd751fSJussi Kivilinna
1092a0fd751fSJussi Kivilinna /* TX halted, try reset */
109350db7fa3SMasanari Iida dev_warn(zd_usb_dev(usb), "TX-stall detected, resetting device...");
1094a0fd751fSJussi Kivilinna
1095a0fd751fSJussi Kivilinna usb_queue_reset_device(usb->intf);
1096a0fd751fSJussi Kivilinna
1097a0fd751fSJussi Kivilinna /* reset will stop this worker, don't rearm */
1098a0fd751fSJussi Kivilinna return;
1099a0fd751fSJussi Kivilinna out:
1100a0fd751fSJussi Kivilinna queue_delayed_work(zd_workqueue, &tx->watchdog_work,
1101a0fd751fSJussi Kivilinna ZD_TX_WATCHDOG_INTERVAL);
1102a0fd751fSJussi Kivilinna }
1103a0fd751fSJussi Kivilinna
zd_tx_watchdog_enable(struct zd_usb * usb)1104a0fd751fSJussi Kivilinna void zd_tx_watchdog_enable(struct zd_usb *usb)
1105a0fd751fSJussi Kivilinna {
1106a0fd751fSJussi Kivilinna struct zd_usb_tx *tx = &usb->tx;
1107a0fd751fSJussi Kivilinna
1108a0fd751fSJussi Kivilinna if (!tx->watchdog_enabled) {
1109a0fd751fSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "\n");
1110a0fd751fSJussi Kivilinna queue_delayed_work(zd_workqueue, &tx->watchdog_work,
1111a0fd751fSJussi Kivilinna ZD_TX_WATCHDOG_INTERVAL);
1112a0fd751fSJussi Kivilinna tx->watchdog_enabled = 1;
1113a0fd751fSJussi Kivilinna }
1114a0fd751fSJussi Kivilinna }
1115a0fd751fSJussi Kivilinna
zd_tx_watchdog_disable(struct zd_usb * usb)1116a0fd751fSJussi Kivilinna void zd_tx_watchdog_disable(struct zd_usb *usb)
1117a0fd751fSJussi Kivilinna {
1118a0fd751fSJussi Kivilinna struct zd_usb_tx *tx = &usb->tx;
1119a0fd751fSJussi Kivilinna
1120a0fd751fSJussi Kivilinna if (tx->watchdog_enabled) {
1121a0fd751fSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "\n");
1122a0fd751fSJussi Kivilinna tx->watchdog_enabled = 0;
1123a0fd751fSJussi Kivilinna cancel_delayed_work_sync(&tx->watchdog_work);
1124a0fd751fSJussi Kivilinna }
1125a0fd751fSJussi Kivilinna }
1126a0fd751fSJussi Kivilinna
zd_rx_idle_timer_handler(struct work_struct * work)11271f6cccccSJussi Kivilinna static void zd_rx_idle_timer_handler(struct work_struct *work)
11281f6cccccSJussi Kivilinna {
11291f6cccccSJussi Kivilinna struct zd_usb *usb =
11301f6cccccSJussi Kivilinna container_of(work, struct zd_usb, rx.idle_work.work);
11311f6cccccSJussi Kivilinna struct zd_mac *mac = zd_usb_to_mac(usb);
11321f6cccccSJussi Kivilinna
11331f6cccccSJussi Kivilinna if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
11341f6cccccSJussi Kivilinna return;
11351f6cccccSJussi Kivilinna
11361f6cccccSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "\n");
11371f6cccccSJussi Kivilinna
11381f6cccccSJussi Kivilinna /* 30 seconds since last rx, reset rx */
11391f6cccccSJussi Kivilinna zd_usb_reset_rx(usb);
11401f6cccccSJussi Kivilinna }
11411f6cccccSJussi Kivilinna
zd_usb_reset_rx_idle_timer_tasklet(struct tasklet_struct * t)114226721b02SAllen Pais static void zd_usb_reset_rx_idle_timer_tasklet(struct tasklet_struct *t)
114302353573SJussi Kivilinna {
114426721b02SAllen Pais struct zd_usb *usb = from_tasklet(usb, t, rx.reset_timer_tasklet);
114502353573SJussi Kivilinna
114602353573SJussi Kivilinna zd_usb_reset_rx_idle_timer(usb);
114702353573SJussi Kivilinna }
114802353573SJussi Kivilinna
zd_usb_reset_rx_idle_timer(struct zd_usb * usb)11491f6cccccSJussi Kivilinna void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
11501f6cccccSJussi Kivilinna {
11511f6cccccSJussi Kivilinna struct zd_usb_rx *rx = &usb->rx;
11521f6cccccSJussi Kivilinna
115341f63c53STejun Heo mod_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
11541f6cccccSJussi Kivilinna }
11551f6cccccSJussi Kivilinna
init_usb_interrupt(struct zd_usb * usb)1156e85d0918SDaniel Drake static inline void init_usb_interrupt(struct zd_usb *usb)
1157e85d0918SDaniel Drake {
1158e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
1159e85d0918SDaniel Drake
1160e85d0918SDaniel Drake spin_lock_init(&intr->lock);
1161e85d0918SDaniel Drake intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
1162e85d0918SDaniel Drake init_completion(&intr->read_regs.completion);
1163c900eff3SJussi Kivilinna atomic_set(&intr->read_regs_enabled, 0);
11640ce34bc8SDaniel Drake intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
1165e85d0918SDaniel Drake }
1166e85d0918SDaniel Drake
init_usb_rx(struct zd_usb * usb)1167e85d0918SDaniel Drake static inline void init_usb_rx(struct zd_usb *usb)
1168e85d0918SDaniel Drake {
1169e85d0918SDaniel Drake struct zd_usb_rx *rx = &usb->rx;
117002353573SJussi Kivilinna
1171e85d0918SDaniel Drake spin_lock_init(&rx->lock);
11721f6cccccSJussi Kivilinna mutex_init(&rx->setup_mutex);
1173e85d0918SDaniel Drake if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
1174e85d0918SDaniel Drake rx->usb_packet_size = 512;
1175e85d0918SDaniel Drake } else {
1176e85d0918SDaniel Drake rx->usb_packet_size = 64;
1177e85d0918SDaniel Drake }
1178e85d0918SDaniel Drake ZD_ASSERT(rx->fragment_length == 0);
11791f6cccccSJussi Kivilinna INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
11805d4650aeSAllen Pais rx->reset_timer_tasklet.func = (void (*))
118126721b02SAllen Pais zd_usb_reset_rx_idle_timer_tasklet;
11825d4650aeSAllen Pais rx->reset_timer_tasklet.data = (unsigned long)&rx->reset_timer_tasklet;
1183e85d0918SDaniel Drake }
1184e85d0918SDaniel Drake
init_usb_tx(struct zd_usb * usb)1185e85d0918SDaniel Drake static inline void init_usb_tx(struct zd_usb *usb)
1186e85d0918SDaniel Drake {
1187459c51adSDaniel Drake struct zd_usb_tx *tx = &usb->tx;
118802353573SJussi Kivilinna
1189459c51adSDaniel Drake spin_lock_init(&tx->lock);
119078fc800fSJussi Kivilinna atomic_set(&tx->enabled, 0);
1191459c51adSDaniel Drake tx->stopped = 0;
1192a0fd751fSJussi Kivilinna skb_queue_head_init(&tx->submitted_skbs);
119378fc800fSJussi Kivilinna init_usb_anchor(&tx->submitted);
1194459c51adSDaniel Drake tx->submitted_urbs = 0;
1195a0fd751fSJussi Kivilinna tx->watchdog_enabled = 0;
1196a0fd751fSJussi Kivilinna INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
1197e85d0918SDaniel Drake }
1198e85d0918SDaniel Drake
zd_usb_init(struct zd_usb * usb,struct ieee80211_hw * hw,struct usb_interface * intf)1199459c51adSDaniel Drake void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
1200e85d0918SDaniel Drake struct usb_interface *intf)
1201e85d0918SDaniel Drake {
1202e85d0918SDaniel Drake memset(usb, 0, sizeof(*usb));
1203e85d0918SDaniel Drake usb->intf = usb_get_intf(intf);
1204459c51adSDaniel Drake usb_set_intfdata(usb->intf, hw);
1205eefdbec1SJussi Kivilinna init_usb_anchor(&usb->submitted_cmds);
1206e85d0918SDaniel Drake init_usb_interrupt(usb);
1207e85d0918SDaniel Drake init_usb_tx(usb);
1208e85d0918SDaniel Drake init_usb_rx(usb);
1209e85d0918SDaniel Drake }
1210e85d0918SDaniel Drake
zd_usb_clear(struct zd_usb * usb)1211e85d0918SDaniel Drake void zd_usb_clear(struct zd_usb *usb)
1212e85d0918SDaniel Drake {
1213e85d0918SDaniel Drake usb_set_intfdata(usb->intf, NULL);
1214e85d0918SDaniel Drake usb_put_intf(usb->intf);
1215c48cf125SUlrich Kunitz ZD_MEMCLEAR(usb, sizeof(*usb));
1216e85d0918SDaniel Drake /* FIXME: usb_interrupt, usb_tx, usb_rx? */
1217e85d0918SDaniel Drake }
1218e85d0918SDaniel Drake
speed(enum usb_device_speed speed)1219e85d0918SDaniel Drake static const char *speed(enum usb_device_speed speed)
1220e85d0918SDaniel Drake {
1221e85d0918SDaniel Drake switch (speed) {
1222e85d0918SDaniel Drake case USB_SPEED_LOW:
1223e85d0918SDaniel Drake return "low";
1224e85d0918SDaniel Drake case USB_SPEED_FULL:
1225e85d0918SDaniel Drake return "full";
1226e85d0918SDaniel Drake case USB_SPEED_HIGH:
1227e85d0918SDaniel Drake return "high";
1228e85d0918SDaniel Drake default:
1229e85d0918SDaniel Drake return "unknown speed";
1230e85d0918SDaniel Drake }
1231e85d0918SDaniel Drake }
1232e85d0918SDaniel Drake
scnprint_id(struct usb_device * udev,char * buffer,size_t size)1233e85d0918SDaniel Drake static int scnprint_id(struct usb_device *udev, char *buffer, size_t size)
1234e85d0918SDaniel Drake {
1235e85d0918SDaniel Drake return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s",
1236e85d0918SDaniel Drake le16_to_cpu(udev->descriptor.idVendor),
1237e85d0918SDaniel Drake le16_to_cpu(udev->descriptor.idProduct),
1238e85d0918SDaniel Drake get_bcdDevice(udev),
1239e85d0918SDaniel Drake speed(udev->speed));
1240e85d0918SDaniel Drake }
1241e85d0918SDaniel Drake
zd_usb_scnprint_id(struct zd_usb * usb,char * buffer,size_t size)1242e85d0918SDaniel Drake int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size)
1243e85d0918SDaniel Drake {
1244e85d0918SDaniel Drake struct usb_device *udev = interface_to_usbdev(usb->intf);
1245e85d0918SDaniel Drake return scnprint_id(udev, buffer, size);
1246e85d0918SDaniel Drake }
1247e85d0918SDaniel Drake
1248e85d0918SDaniel Drake #ifdef DEBUG
print_id(struct usb_device * udev)1249e85d0918SDaniel Drake static void print_id(struct usb_device *udev)
1250e85d0918SDaniel Drake {
1251e85d0918SDaniel Drake char buffer[40];
1252e85d0918SDaniel Drake
1253e85d0918SDaniel Drake scnprint_id(udev, buffer, sizeof(buffer));
1254e85d0918SDaniel Drake buffer[sizeof(buffer)-1] = 0;
1255e85d0918SDaniel Drake dev_dbg_f(&udev->dev, "%s\n", buffer);
1256e85d0918SDaniel Drake }
1257e85d0918SDaniel Drake #else
1258e85d0918SDaniel Drake #define print_id(udev) do { } while (0)
1259e85d0918SDaniel Drake #endif
1260e85d0918SDaniel Drake
eject_installer(struct usb_interface * intf)1261a1030e92SDaniel Drake static int eject_installer(struct usb_interface *intf)
1262a1030e92SDaniel Drake {
1263a1030e92SDaniel Drake struct usb_device *udev = interface_to_usbdev(intf);
12642d68bb26SJohan Hovold struct usb_host_interface *iface_desc = intf->cur_altsetting;
1265a1030e92SDaniel Drake struct usb_endpoint_descriptor *endpoint;
1266a1030e92SDaniel Drake unsigned char *cmd;
1267a1030e92SDaniel Drake u8 bulk_out_ep;
1268a1030e92SDaniel Drake int r;
1269a1030e92SDaniel Drake
1270ca260eceSJohan Hovold if (iface_desc->desc.bNumEndpoints < 2)
1271ca260eceSJohan Hovold return -ENODEV;
1272ca260eceSJohan Hovold
1273a1030e92SDaniel Drake /* Find bulk out endpoint */
127411466f13SStefan Seyfried for (r = 1; r >= 0; r--) {
127511466f13SStefan Seyfried endpoint = &iface_desc->endpoint[r].desc;
127633e2fb2fSJulia Lawall if (usb_endpoint_dir_out(endpoint) &&
1277f201a8a4SJulia Lawall usb_endpoint_xfer_bulk(endpoint)) {
1278a1030e92SDaniel Drake bulk_out_ep = endpoint->bEndpointAddress;
127911466f13SStefan Seyfried break;
128011466f13SStefan Seyfried }
128111466f13SStefan Seyfried }
128211466f13SStefan Seyfried if (r == -1) {
1283a1030e92SDaniel Drake dev_err(&udev->dev,
1284a1030e92SDaniel Drake "zd1211rw: Could not find bulk out endpoint\n");
1285a1030e92SDaniel Drake return -ENODEV;
1286a1030e92SDaniel Drake }
1287a1030e92SDaniel Drake
1288a1030e92SDaniel Drake cmd = kzalloc(31, GFP_KERNEL);
1289a1030e92SDaniel Drake if (cmd == NULL)
1290a1030e92SDaniel Drake return -ENODEV;
1291a1030e92SDaniel Drake
1292a1030e92SDaniel Drake /* USB bulk command block */
1293a1030e92SDaniel Drake cmd[0] = 0x55; /* bulk command signature */
1294a1030e92SDaniel Drake cmd[1] = 0x53; /* bulk command signature */
1295a1030e92SDaniel Drake cmd[2] = 0x42; /* bulk command signature */
1296a1030e92SDaniel Drake cmd[3] = 0x43; /* bulk command signature */
1297a1030e92SDaniel Drake cmd[14] = 6; /* command length */
1298a1030e92SDaniel Drake
1299a1030e92SDaniel Drake cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
1300a1030e92SDaniel Drake cmd[19] = 0x2; /* eject disc */
1301a1030e92SDaniel Drake
1302a1030e92SDaniel Drake dev_info(&udev->dev, "Ejecting virtual installer media...\n");
1303a1030e92SDaniel Drake r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
1304a1030e92SDaniel Drake cmd, 31, NULL, 2000);
1305a1030e92SDaniel Drake kfree(cmd);
1306a1030e92SDaniel Drake if (r)
1307a1030e92SDaniel Drake return r;
1308a1030e92SDaniel Drake
1309a1030e92SDaniel Drake /* At this point, the device disconnects and reconnects with the real
1310a1030e92SDaniel Drake * ID numbers. */
1311a1030e92SDaniel Drake
1312a1030e92SDaniel Drake usb_set_intfdata(intf, NULL);
1313a1030e92SDaniel Drake return 0;
1314a1030e92SDaniel Drake }
1315a1030e92SDaniel Drake
zd_usb_init_hw(struct zd_usb * usb)131674553aedSDaniel Drake int zd_usb_init_hw(struct zd_usb *usb)
131774553aedSDaniel Drake {
131874553aedSDaniel Drake int r;
131974553aedSDaniel Drake struct zd_mac *mac = zd_usb_to_mac(usb);
132074553aedSDaniel Drake
132174553aedSDaniel Drake dev_dbg_f(zd_usb_dev(usb), "\n");
132274553aedSDaniel Drake
132374553aedSDaniel Drake r = upload_firmware(usb);
132474553aedSDaniel Drake if (r) {
132574553aedSDaniel Drake dev_err(zd_usb_dev(usb),
132674553aedSDaniel Drake "couldn't load firmware. Error number %d\n", r);
132774553aedSDaniel Drake return r;
132874553aedSDaniel Drake }
132974553aedSDaniel Drake
133074553aedSDaniel Drake r = usb_reset_configuration(zd_usb_to_usbdev(usb));
133174553aedSDaniel Drake if (r) {
133274553aedSDaniel Drake dev_dbg_f(zd_usb_dev(usb),
133374553aedSDaniel Drake "couldn't reset configuration. Error number %d\n", r);
133474553aedSDaniel Drake return r;
133574553aedSDaniel Drake }
133674553aedSDaniel Drake
1337459c51adSDaniel Drake r = zd_mac_init_hw(mac->hw);
133874553aedSDaniel Drake if (r) {
133974553aedSDaniel Drake dev_dbg_f(zd_usb_dev(usb),
134074553aedSDaniel Drake "couldn't initialize mac. Error number %d\n", r);
134174553aedSDaniel Drake return r;
134274553aedSDaniel Drake }
134374553aedSDaniel Drake
134474553aedSDaniel Drake usb->initialized = 1;
134574553aedSDaniel Drake return 0;
134674553aedSDaniel Drake }
134774553aedSDaniel Drake
probe(struct usb_interface * intf,const struct usb_device_id * id)1348e85d0918SDaniel Drake static int probe(struct usb_interface *intf, const struct usb_device_id *id)
1349e85d0918SDaniel Drake {
1350e85d0918SDaniel Drake int r;
1351e85d0918SDaniel Drake struct usb_device *udev = interface_to_usbdev(intf);
1352459c51adSDaniel Drake struct zd_usb *usb;
1353459c51adSDaniel Drake struct ieee80211_hw *hw = NULL;
1354e85d0918SDaniel Drake
1355e85d0918SDaniel Drake print_id(udev);
1356e85d0918SDaniel Drake
1357a1030e92SDaniel Drake if (id->driver_info & DEVICE_INSTALLER)
1358a1030e92SDaniel Drake return eject_installer(intf);
1359a1030e92SDaniel Drake
1360e85d0918SDaniel Drake switch (udev->speed) {
1361e85d0918SDaniel Drake case USB_SPEED_LOW:
1362e85d0918SDaniel Drake case USB_SPEED_FULL:
1363e85d0918SDaniel Drake case USB_SPEED_HIGH:
1364e85d0918SDaniel Drake break;
1365e85d0918SDaniel Drake default:
1366e85d0918SDaniel Drake dev_dbg_f(&intf->dev, "Unknown USB speed\n");
1367e85d0918SDaniel Drake r = -ENODEV;
1368e85d0918SDaniel Drake goto error;
1369e85d0918SDaniel Drake }
1370e85d0918SDaniel Drake
1371459c51adSDaniel Drake r = usb_reset_device(udev);
1372459c51adSDaniel Drake if (r) {
1373459c51adSDaniel Drake dev_err(&intf->dev,
1374459c51adSDaniel Drake "couldn't reset usb device. Error number %d\n", r);
1375459c51adSDaniel Drake goto error;
1376459c51adSDaniel Drake }
13776e3632f6SUlrich Kunitz
1378459c51adSDaniel Drake hw = zd_mac_alloc_hw(intf);
1379459c51adSDaniel Drake if (hw == NULL) {
1380e85d0918SDaniel Drake r = -ENOMEM;
1381e85d0918SDaniel Drake goto error;
1382e85d0918SDaniel Drake }
1383e85d0918SDaniel Drake
1384459c51adSDaniel Drake usb = &zd_hw_mac(hw)->chip.usb;
138574553aedSDaniel Drake usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
1386e85d0918SDaniel Drake
1387459c51adSDaniel Drake r = zd_mac_preinit_hw(hw);
1388e85d0918SDaniel Drake if (r) {
1389e85d0918SDaniel Drake dev_dbg_f(&intf->dev,
1390e85d0918SDaniel Drake "couldn't initialize mac. Error number %d\n", r);
1391e85d0918SDaniel Drake goto error;
1392e85d0918SDaniel Drake }
1393e85d0918SDaniel Drake
1394459c51adSDaniel Drake r = ieee80211_register_hw(hw);
1395e85d0918SDaniel Drake if (r) {
1396e85d0918SDaniel Drake dev_dbg_f(&intf->dev,
1397459c51adSDaniel Drake "couldn't register device. Error number %d\n", r);
1398e85d0918SDaniel Drake goto error;
1399e85d0918SDaniel Drake }
1400e85d0918SDaniel Drake
1401e85d0918SDaniel Drake dev_dbg_f(&intf->dev, "successful\n");
1402459c51adSDaniel Drake dev_info(&intf->dev, "%s\n", wiphy_name(hw->wiphy));
1403e85d0918SDaniel Drake return 0;
1404e85d0918SDaniel Drake error:
1405e85d0918SDaniel Drake usb_reset_device(interface_to_usbdev(intf));
1406459c51adSDaniel Drake if (hw) {
1407459c51adSDaniel Drake zd_mac_clear(zd_hw_mac(hw));
1408459c51adSDaniel Drake ieee80211_free_hw(hw);
1409459c51adSDaniel Drake }
1410e85d0918SDaniel Drake return r;
1411e85d0918SDaniel Drake }
1412e85d0918SDaniel Drake
disconnect(struct usb_interface * intf)1413e85d0918SDaniel Drake static void disconnect(struct usb_interface *intf)
1414e85d0918SDaniel Drake {
1415459c51adSDaniel Drake struct ieee80211_hw *hw = zd_intf_to_hw(intf);
1416e0579d57SMarc Pignat struct zd_mac *mac;
1417e0579d57SMarc Pignat struct zd_usb *usb;
1418e85d0918SDaniel Drake
1419a1030e92SDaniel Drake /* Either something really bad happened, or we're just dealing with
1420a1030e92SDaniel Drake * a DEVICE_INSTALLER. */
1421459c51adSDaniel Drake if (hw == NULL)
1422a1030e92SDaniel Drake return;
1423a1030e92SDaniel Drake
1424459c51adSDaniel Drake mac = zd_hw_mac(hw);
1425e0579d57SMarc Pignat usb = &mac->chip.usb;
1426e0579d57SMarc Pignat
1427e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "\n");
1428e85d0918SDaniel Drake
1429459c51adSDaniel Drake ieee80211_unregister_hw(hw);
1430e85d0918SDaniel Drake
1431e85d0918SDaniel Drake /* Just in case something has gone wrong! */
143278fc800fSJussi Kivilinna zd_usb_disable_tx(usb);
1433e85d0918SDaniel Drake zd_usb_disable_rx(usb);
1434e85d0918SDaniel Drake zd_usb_disable_int(usb);
1435e85d0918SDaniel Drake
1436e85d0918SDaniel Drake /* If the disconnect has been caused by a removal of the
1437e85d0918SDaniel Drake * driver module, the reset allows reloading of the driver. If the
1438e85d0918SDaniel Drake * reset will not be executed here, the upload of the firmware in the
1439e85d0918SDaniel Drake * probe function caused by the reloading of the driver will fail.
1440e85d0918SDaniel Drake */
1441e85d0918SDaniel Drake usb_reset_device(interface_to_usbdev(intf));
1442e85d0918SDaniel Drake
1443459c51adSDaniel Drake zd_mac_clear(mac);
1444459c51adSDaniel Drake ieee80211_free_hw(hw);
1445e85d0918SDaniel Drake dev_dbg(&intf->dev, "disconnected\n");
1446e85d0918SDaniel Drake }
1447e85d0918SDaniel Drake
zd_usb_resume(struct zd_usb * usb)1448a0fd751fSJussi Kivilinna static void zd_usb_resume(struct zd_usb *usb)
1449a0fd751fSJussi Kivilinna {
1450a0fd751fSJussi Kivilinna struct zd_mac *mac = zd_usb_to_mac(usb);
1451a0fd751fSJussi Kivilinna int r;
1452a0fd751fSJussi Kivilinna
1453a0fd751fSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "\n");
1454a0fd751fSJussi Kivilinna
1455a0fd751fSJussi Kivilinna r = zd_op_start(zd_usb_to_hw(usb));
1456a0fd751fSJussi Kivilinna if (r < 0) {
1457a0fd751fSJussi Kivilinna dev_warn(zd_usb_dev(usb), "Device resume failed "
1458a0fd751fSJussi Kivilinna "with error code %d. Retrying...\n", r);
1459a0fd751fSJussi Kivilinna if (usb->was_running)
1460a0fd751fSJussi Kivilinna set_bit(ZD_DEVICE_RUNNING, &mac->flags);
1461a0fd751fSJussi Kivilinna usb_queue_reset_device(usb->intf);
1462a0fd751fSJussi Kivilinna return;
1463a0fd751fSJussi Kivilinna }
1464a0fd751fSJussi Kivilinna
1465a0fd751fSJussi Kivilinna if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
1466a0fd751fSJussi Kivilinna r = zd_restore_settings(mac);
1467a0fd751fSJussi Kivilinna if (r < 0) {
1468a0fd751fSJussi Kivilinna dev_dbg(zd_usb_dev(usb),
1469a0fd751fSJussi Kivilinna "failed to restore settings, %d\n", r);
1470a0fd751fSJussi Kivilinna return;
1471a0fd751fSJussi Kivilinna }
1472a0fd751fSJussi Kivilinna }
1473a0fd751fSJussi Kivilinna }
1474a0fd751fSJussi Kivilinna
zd_usb_stop(struct zd_usb * usb)1475a0fd751fSJussi Kivilinna static void zd_usb_stop(struct zd_usb *usb)
1476a0fd751fSJussi Kivilinna {
1477a0fd751fSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "\n");
1478a0fd751fSJussi Kivilinna
14791decf05dSEmmanuel Grumbach zd_op_stop(zd_usb_to_hw(usb), false);
1480a0fd751fSJussi Kivilinna
1481a0fd751fSJussi Kivilinna zd_usb_disable_tx(usb);
1482a0fd751fSJussi Kivilinna zd_usb_disable_rx(usb);
1483a0fd751fSJussi Kivilinna zd_usb_disable_int(usb);
1484a0fd751fSJussi Kivilinna
1485a0fd751fSJussi Kivilinna usb->initialized = 0;
1486a0fd751fSJussi Kivilinna }
1487a0fd751fSJussi Kivilinna
pre_reset(struct usb_interface * intf)1488a0fd751fSJussi Kivilinna static int pre_reset(struct usb_interface *intf)
1489a0fd751fSJussi Kivilinna {
1490a0fd751fSJussi Kivilinna struct ieee80211_hw *hw = usb_get_intfdata(intf);
1491a0fd751fSJussi Kivilinna struct zd_mac *mac;
1492a0fd751fSJussi Kivilinna struct zd_usb *usb;
1493a0fd751fSJussi Kivilinna
1494a0fd751fSJussi Kivilinna if (!hw || intf->condition != USB_INTERFACE_BOUND)
1495a0fd751fSJussi Kivilinna return 0;
1496a0fd751fSJussi Kivilinna
1497a0fd751fSJussi Kivilinna mac = zd_hw_mac(hw);
1498a0fd751fSJussi Kivilinna usb = &mac->chip.usb;
1499a0fd751fSJussi Kivilinna
1500a0fd751fSJussi Kivilinna usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
1501a0fd751fSJussi Kivilinna
1502a0fd751fSJussi Kivilinna zd_usb_stop(usb);
1503a0fd751fSJussi Kivilinna
1504a0fd751fSJussi Kivilinna mutex_lock(&mac->chip.mutex);
1505a0fd751fSJussi Kivilinna return 0;
1506a0fd751fSJussi Kivilinna }
1507a0fd751fSJussi Kivilinna
post_reset(struct usb_interface * intf)1508a0fd751fSJussi Kivilinna static int post_reset(struct usb_interface *intf)
1509a0fd751fSJussi Kivilinna {
1510a0fd751fSJussi Kivilinna struct ieee80211_hw *hw = usb_get_intfdata(intf);
1511a0fd751fSJussi Kivilinna struct zd_mac *mac;
1512a0fd751fSJussi Kivilinna struct zd_usb *usb;
1513a0fd751fSJussi Kivilinna
1514a0fd751fSJussi Kivilinna if (!hw || intf->condition != USB_INTERFACE_BOUND)
1515a0fd751fSJussi Kivilinna return 0;
1516a0fd751fSJussi Kivilinna
1517a0fd751fSJussi Kivilinna mac = zd_hw_mac(hw);
1518a0fd751fSJussi Kivilinna usb = &mac->chip.usb;
1519a0fd751fSJussi Kivilinna
1520a0fd751fSJussi Kivilinna mutex_unlock(&mac->chip.mutex);
1521a0fd751fSJussi Kivilinna
1522a0fd751fSJussi Kivilinna if (usb->was_running)
1523a0fd751fSJussi Kivilinna zd_usb_resume(usb);
1524a0fd751fSJussi Kivilinna return 0;
1525a0fd751fSJussi Kivilinna }
1526a0fd751fSJussi Kivilinna
1527e85d0918SDaniel Drake static struct usb_driver driver = {
1528459c51adSDaniel Drake .name = KBUILD_MODNAME,
1529e85d0918SDaniel Drake .id_table = usb_ids,
1530e85d0918SDaniel Drake .probe = probe,
1531e85d0918SDaniel Drake .disconnect = disconnect,
1532a0fd751fSJussi Kivilinna .pre_reset = pre_reset,
1533a0fd751fSJussi Kivilinna .post_reset = post_reset,
1534e1f12eb6SSarah Sharp .disable_hub_initiated_lpm = 1,
1535e85d0918SDaniel Drake };
1536e85d0918SDaniel Drake
1537bc5f06a8SUlrich Kunitz struct workqueue_struct *zd_workqueue;
1538bc5f06a8SUlrich Kunitz
usb_init(void)1539e85d0918SDaniel Drake static int __init usb_init(void)
1540e85d0918SDaniel Drake {
1541e85d0918SDaniel Drake int r;
1542e85d0918SDaniel Drake
1543741fec53SUlrich Kunitz pr_debug("%s usb_init()\n", driver.name);
1544e85d0918SDaniel Drake
1545bc5f06a8SUlrich Kunitz zd_workqueue = create_singlethread_workqueue(driver.name);
1546bc5f06a8SUlrich Kunitz if (zd_workqueue == NULL) {
154729d97219SSaurav Girepunje pr_err("%s couldn't create workqueue\n", driver.name);
1548bc5f06a8SUlrich Kunitz return -ENOMEM;
1549bc5f06a8SUlrich Kunitz }
1550bc5f06a8SUlrich Kunitz
1551e85d0918SDaniel Drake r = usb_register(&driver);
1552e85d0918SDaniel Drake if (r) {
1553192b775cSMaxime Austruy destroy_workqueue(zd_workqueue);
155429d97219SSaurav Girepunje pr_err("%s usb_register() failed. Error number %d\n",
1555741fec53SUlrich Kunitz driver.name, r);
1556e85d0918SDaniel Drake return r;
1557e85d0918SDaniel Drake }
1558e85d0918SDaniel Drake
1559741fec53SUlrich Kunitz pr_debug("%s initialized\n", driver.name);
1560e85d0918SDaniel Drake return 0;
1561e85d0918SDaniel Drake }
1562e85d0918SDaniel Drake
usb_exit(void)1563e85d0918SDaniel Drake static void __exit usb_exit(void)
1564e85d0918SDaniel Drake {
1565741fec53SUlrich Kunitz pr_debug("%s usb_exit()\n", driver.name);
1566e85d0918SDaniel Drake usb_deregister(&driver);
1567bc5f06a8SUlrich Kunitz destroy_workqueue(zd_workqueue);
1568e85d0918SDaniel Drake }
1569e85d0918SDaniel Drake
1570e85d0918SDaniel Drake module_init(usb_init);
1571e85d0918SDaniel Drake module_exit(usb_exit);
1572e85d0918SDaniel Drake
zd_ep_regs_out_msg(struct usb_device * udev,void * data,int len,int * actual_length,int timeout)157359342f6aSJussi Kivilinna static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len,
157459342f6aSJussi Kivilinna int *actual_length, int timeout)
157559342f6aSJussi Kivilinna {
157659342f6aSJussi Kivilinna /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in
157759342f6aSJussi Kivilinna * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint
157859342f6aSJussi Kivilinna * descriptor.
157959342f6aSJussi Kivilinna */
158059342f6aSJussi Kivilinna struct usb_host_endpoint *ep;
158159342f6aSJussi Kivilinna unsigned int pipe;
158259342f6aSJussi Kivilinna
158359342f6aSJussi Kivilinna pipe = usb_sndintpipe(udev, EP_REGS_OUT);
158459342f6aSJussi Kivilinna ep = usb_pipe_endpoint(udev, pipe);
158559342f6aSJussi Kivilinna if (!ep)
158659342f6aSJussi Kivilinna return -EINVAL;
158759342f6aSJussi Kivilinna
158859342f6aSJussi Kivilinna if (usb_endpoint_xfer_int(&ep->desc)) {
158959342f6aSJussi Kivilinna return usb_interrupt_msg(udev, pipe, data, len,
159059342f6aSJussi Kivilinna actual_length, timeout);
159159342f6aSJussi Kivilinna } else {
159259342f6aSJussi Kivilinna pipe = usb_sndbulkpipe(udev, EP_REGS_OUT);
159359342f6aSJussi Kivilinna return usb_bulk_msg(udev, pipe, data, len, actual_length,
159459342f6aSJussi Kivilinna timeout);
159559342f6aSJussi Kivilinna }
159659342f6aSJussi Kivilinna }
159759342f6aSJussi Kivilinna
prepare_read_regs_int(struct zd_usb * usb,struct usb_req_read_regs * req,unsigned int count)1598c900eff3SJussi Kivilinna static void prepare_read_regs_int(struct zd_usb *usb,
1599c900eff3SJussi Kivilinna struct usb_req_read_regs *req,
1600c900eff3SJussi Kivilinna unsigned int count)
1601e85d0918SDaniel Drake {
1602e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
1603e85d0918SDaniel Drake
1604a68077deSUlrich Kunitz spin_lock_irq(&intr->lock);
1605c900eff3SJussi Kivilinna atomic_set(&intr->read_regs_enabled, 1);
1606c900eff3SJussi Kivilinna intr->read_regs.req = req;
1607c900eff3SJussi Kivilinna intr->read_regs.req_count = count;
160816735d02SWolfram Sang reinit_completion(&intr->read_regs.completion);
1609a68077deSUlrich Kunitz spin_unlock_irq(&intr->lock);
1610a68077deSUlrich Kunitz }
1611a68077deSUlrich Kunitz
disable_read_regs_int(struct zd_usb * usb)1612a68077deSUlrich Kunitz static void disable_read_regs_int(struct zd_usb *usb)
1613a68077deSUlrich Kunitz {
1614a68077deSUlrich Kunitz struct zd_usb_interrupt *intr = &usb->intr;
1615a68077deSUlrich Kunitz
1616a68077deSUlrich Kunitz spin_lock_irq(&intr->lock);
1617c900eff3SJussi Kivilinna atomic_set(&intr->read_regs_enabled, 0);
1618a68077deSUlrich Kunitz spin_unlock_irq(&intr->lock);
1619e85d0918SDaniel Drake }
1620e85d0918SDaniel Drake
check_read_regs(struct zd_usb * usb,struct usb_req_read_regs * req,unsigned int count)1621c900eff3SJussi Kivilinna static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
1622c900eff3SJussi Kivilinna unsigned int count)
1623c900eff3SJussi Kivilinna {
1624c900eff3SJussi Kivilinna int i;
1625c900eff3SJussi Kivilinna struct zd_usb_interrupt *intr = &usb->intr;
1626c900eff3SJussi Kivilinna struct read_regs_int *rr = &intr->read_regs;
1627c900eff3SJussi Kivilinna struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
1628c900eff3SJussi Kivilinna
1629c900eff3SJussi Kivilinna /* The created block size seems to be larger than expected.
1630c900eff3SJussi Kivilinna * However results appear to be correct.
1631c900eff3SJussi Kivilinna */
163284b0b663SGustavo A. R. Silva if (rr->length < struct_size(regs, regs, count)) {
1633c900eff3SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb),
16346355592eSGeert Uytterhoeven "error: actual length %d less than expected %zu\n",
163584b0b663SGustavo A. R. Silva rr->length, struct_size(regs, regs, count));
1636c900eff3SJussi Kivilinna return false;
1637c900eff3SJussi Kivilinna }
1638c900eff3SJussi Kivilinna
1639c900eff3SJussi Kivilinna if (rr->length > sizeof(rr->buffer)) {
1640c900eff3SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb),
1641c900eff3SJussi Kivilinna "error: actual length %d exceeds buffer size %zu\n",
1642c900eff3SJussi Kivilinna rr->length, sizeof(rr->buffer));
1643c900eff3SJussi Kivilinna return false;
1644c900eff3SJussi Kivilinna }
1645c900eff3SJussi Kivilinna
1646c900eff3SJussi Kivilinna for (i = 0; i < count; i++) {
1647c900eff3SJussi Kivilinna struct reg_data *rd = ®s->regs[i];
1648c900eff3SJussi Kivilinna if (rd->addr != req->addr[i]) {
1649c900eff3SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb),
1650c900eff3SJussi Kivilinna "rd[%d] addr %#06hx expected %#06hx\n", i,
1651c900eff3SJussi Kivilinna le16_to_cpu(rd->addr),
1652c900eff3SJussi Kivilinna le16_to_cpu(req->addr[i]));
1653c900eff3SJussi Kivilinna return false;
1654c900eff3SJussi Kivilinna }
1655c900eff3SJussi Kivilinna }
1656c900eff3SJussi Kivilinna
1657c900eff3SJussi Kivilinna return true;
1658c900eff3SJussi Kivilinna }
1659c900eff3SJussi Kivilinna
get_results(struct zd_usb * usb,u16 * values,struct usb_req_read_regs * req,unsigned int count,bool * retry)1660e85d0918SDaniel Drake static int get_results(struct zd_usb *usb, u16 *values,
1661c900eff3SJussi Kivilinna struct usb_req_read_regs *req, unsigned int count,
1662c900eff3SJussi Kivilinna bool *retry)
1663e85d0918SDaniel Drake {
1664e85d0918SDaniel Drake int r;
1665e85d0918SDaniel Drake int i;
1666e85d0918SDaniel Drake struct zd_usb_interrupt *intr = &usb->intr;
1667e85d0918SDaniel Drake struct read_regs_int *rr = &intr->read_regs;
1668e85d0918SDaniel Drake struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
1669e85d0918SDaniel Drake
1670a68077deSUlrich Kunitz spin_lock_irq(&intr->lock);
1671e85d0918SDaniel Drake
1672e85d0918SDaniel Drake r = -EIO;
1673c900eff3SJussi Kivilinna
1674c900eff3SJussi Kivilinna /* Read failed because firmware bug? */
1675c900eff3SJussi Kivilinna *retry = !!intr->read_regs_int_overridden;
1676c900eff3SJussi Kivilinna if (*retry)
1677e85d0918SDaniel Drake goto error_unlock;
1678c900eff3SJussi Kivilinna
1679c900eff3SJussi Kivilinna if (!check_read_regs(usb, req, count)) {
1680c900eff3SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
1681e85d0918SDaniel Drake goto error_unlock;
1682e85d0918SDaniel Drake }
1683e85d0918SDaniel Drake
1684e85d0918SDaniel Drake for (i = 0; i < count; i++) {
1685e85d0918SDaniel Drake struct reg_data *rd = ®s->regs[i];
1686e85d0918SDaniel Drake values[i] = le16_to_cpu(rd->value);
1687e85d0918SDaniel Drake }
1688e85d0918SDaniel Drake
1689e85d0918SDaniel Drake r = 0;
1690e85d0918SDaniel Drake error_unlock:
1691a68077deSUlrich Kunitz spin_unlock_irq(&intr->lock);
1692e85d0918SDaniel Drake return r;
1693e85d0918SDaniel Drake }
1694e85d0918SDaniel Drake
zd_usb_ioread16v(struct zd_usb * usb,u16 * values,const zd_addr_t * addresses,unsigned int count)1695e85d0918SDaniel Drake int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
1696e85d0918SDaniel Drake const zd_addr_t *addresses, unsigned int count)
1697e85d0918SDaniel Drake {
1698c900eff3SJussi Kivilinna int r, i, req_len, actual_req_len, try_count = 0;
1699e85d0918SDaniel Drake struct usb_device *udev;
1700e85d0918SDaniel Drake struct usb_req_read_regs *req = NULL;
1701a2ead344SWolfram Sang unsigned long time_left;
1702c900eff3SJussi Kivilinna bool retry = false;
1703e85d0918SDaniel Drake
1704e85d0918SDaniel Drake if (count < 1) {
1705e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
1706e85d0918SDaniel Drake return -EINVAL;
1707e85d0918SDaniel Drake }
1708e85d0918SDaniel Drake if (count > USB_MAX_IOREAD16_COUNT) {
1709e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1710e85d0918SDaniel Drake "error: count %u exceeds possible max %u\n",
1711e85d0918SDaniel Drake count, USB_MAX_IOREAD16_COUNT);
1712e85d0918SDaniel Drake return -EINVAL;
1713e85d0918SDaniel Drake }
1714e85d0918SDaniel Drake if (!usb_int_enabled(usb)) {
1715e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1716e85d0918SDaniel Drake "error: usb interrupt not enabled\n");
1717e85d0918SDaniel Drake return -EWOULDBLOCK;
1718e85d0918SDaniel Drake }
1719e85d0918SDaniel Drake
17209bca0c3bSJussi Kivilinna ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
17219bca0c3bSJussi Kivilinna BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT *
17229bca0c3bSJussi Kivilinna sizeof(__le16) > sizeof(usb->req_buf));
17239bca0c3bSJussi Kivilinna BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) >
17249bca0c3bSJussi Kivilinna sizeof(usb->req_buf));
17259bca0c3bSJussi Kivilinna
1726e85d0918SDaniel Drake req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
17279bca0c3bSJussi Kivilinna req = (void *)usb->req_buf;
17289bca0c3bSJussi Kivilinna
1729e85d0918SDaniel Drake req->id = cpu_to_le16(USB_REQ_READ_REGS);
1730e85d0918SDaniel Drake for (i = 0; i < count; i++)
17310ce34bc8SDaniel Drake req->addr[i] = cpu_to_le16((u16)addresses[i]);
1732e85d0918SDaniel Drake
1733c900eff3SJussi Kivilinna retry_read:
1734c900eff3SJussi Kivilinna try_count++;
1735e85d0918SDaniel Drake udev = zd_usb_to_usbdev(usb);
1736c900eff3SJussi Kivilinna prepare_read_regs_int(usb, req, count);
173759342f6aSJussi Kivilinna r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
1738e85d0918SDaniel Drake if (r) {
1739e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
174059342f6aSJussi Kivilinna "error in zd_ep_regs_out_msg(). Error number %d\n", r);
1741e85d0918SDaniel Drake goto error;
1742e85d0918SDaniel Drake }
1743e85d0918SDaniel Drake if (req_len != actual_req_len) {
174459342f6aSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"
1745e85d0918SDaniel Drake " req_len %d != actual_req_len %d\n",
1746e85d0918SDaniel Drake req_len, actual_req_len);
1747e85d0918SDaniel Drake r = -EIO;
1748e85d0918SDaniel Drake goto error;
1749e85d0918SDaniel Drake }
1750e85d0918SDaniel Drake
1751a2ead344SWolfram Sang time_left = wait_for_completion_timeout(&usb->intr.read_regs.completion,
17528f2d8f86SJussi Kivilinna msecs_to_jiffies(50));
1753a2ead344SWolfram Sang if (!time_left) {
1754e85d0918SDaniel Drake disable_read_regs_int(usb);
1755e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
1756e85d0918SDaniel Drake r = -ETIMEDOUT;
1757e85d0918SDaniel Drake goto error;
1758e85d0918SDaniel Drake }
1759e85d0918SDaniel Drake
1760c900eff3SJussi Kivilinna r = get_results(usb, values, req, count, &retry);
1761c900eff3SJussi Kivilinna if (retry && try_count < 20) {
1762c900eff3SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
1763c900eff3SJussi Kivilinna try_count);
1764c900eff3SJussi Kivilinna goto retry_read;
1765c900eff3SJussi Kivilinna }
1766e85d0918SDaniel Drake error:
1767e85d0918SDaniel Drake return r;
1768e85d0918SDaniel Drake }
1769e85d0918SDaniel Drake
iowrite16v_urb_complete(struct urb * urb)1770eefdbec1SJussi Kivilinna static void iowrite16v_urb_complete(struct urb *urb)
1771eefdbec1SJussi Kivilinna {
1772eefdbec1SJussi Kivilinna struct zd_usb *usb = urb->context;
1773eefdbec1SJussi Kivilinna
1774eefdbec1SJussi Kivilinna if (urb->status && !usb->cmd_error)
1775eefdbec1SJussi Kivilinna usb->cmd_error = urb->status;
17762fc713b2SJussi Kivilinna
17772fc713b2SJussi Kivilinna if (!usb->cmd_error &&
17782fc713b2SJussi Kivilinna urb->actual_length != urb->transfer_buffer_length)
17792fc713b2SJussi Kivilinna usb->cmd_error = -EIO;
1780eefdbec1SJussi Kivilinna }
1781eefdbec1SJussi Kivilinna
zd_submit_waiting_urb(struct zd_usb * usb,bool last)1782eefdbec1SJussi Kivilinna static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
1783eefdbec1SJussi Kivilinna {
17848662b251SJussi Kivilinna int r = 0;
1785eefdbec1SJussi Kivilinna struct urb *urb = usb->urb_async_waiting;
1786eefdbec1SJussi Kivilinna
1787eefdbec1SJussi Kivilinna if (!urb)
1788eefdbec1SJussi Kivilinna return 0;
1789eefdbec1SJussi Kivilinna
1790eefdbec1SJussi Kivilinna usb->urb_async_waiting = NULL;
1791eefdbec1SJussi Kivilinna
1792eefdbec1SJussi Kivilinna if (!last)
1793eefdbec1SJussi Kivilinna urb->transfer_flags |= URB_NO_INTERRUPT;
1794eefdbec1SJussi Kivilinna
1795eefdbec1SJussi Kivilinna usb_anchor_urb(urb, &usb->submitted_cmds);
1796eefdbec1SJussi Kivilinna r = usb_submit_urb(urb, GFP_KERNEL);
1797eefdbec1SJussi Kivilinna if (r) {
1798eefdbec1SJussi Kivilinna usb_unanchor_urb(urb);
1799eefdbec1SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb),
1800eefdbec1SJussi Kivilinna "error in usb_submit_urb(). Error number %d\n", r);
1801eefdbec1SJussi Kivilinna goto error;
1802eefdbec1SJussi Kivilinna }
1803eefdbec1SJussi Kivilinna
1804eefdbec1SJussi Kivilinna /* fall-through with r == 0 */
1805eefdbec1SJussi Kivilinna error:
1806eefdbec1SJussi Kivilinna usb_free_urb(urb);
1807eefdbec1SJussi Kivilinna return r;
1808eefdbec1SJussi Kivilinna }
1809eefdbec1SJussi Kivilinna
zd_usb_iowrite16v_async_start(struct zd_usb * usb)18108662b251SJussi Kivilinna void zd_usb_iowrite16v_async_start(struct zd_usb *usb)
1811eefdbec1SJussi Kivilinna {
1812eefdbec1SJussi Kivilinna ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds));
1813eefdbec1SJussi Kivilinna ZD_ASSERT(usb->urb_async_waiting == NULL);
1814eefdbec1SJussi Kivilinna ZD_ASSERT(!usb->in_async);
1815eefdbec1SJussi Kivilinna
1816eefdbec1SJussi Kivilinna ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
1817eefdbec1SJussi Kivilinna
1818eefdbec1SJussi Kivilinna usb->in_async = 1;
1819eefdbec1SJussi Kivilinna usb->cmd_error = 0;
1820eefdbec1SJussi Kivilinna usb->urb_async_waiting = NULL;
1821eefdbec1SJussi Kivilinna }
1822eefdbec1SJussi Kivilinna
zd_usb_iowrite16v_async_end(struct zd_usb * usb,unsigned int timeout)18238662b251SJussi Kivilinna int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout)
1824eefdbec1SJussi Kivilinna {
1825eefdbec1SJussi Kivilinna int r;
1826eefdbec1SJussi Kivilinna
1827eefdbec1SJussi Kivilinna ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
1828eefdbec1SJussi Kivilinna ZD_ASSERT(usb->in_async);
1829eefdbec1SJussi Kivilinna
1830eefdbec1SJussi Kivilinna /* Submit last iowrite16v URB */
1831eefdbec1SJussi Kivilinna r = zd_submit_waiting_urb(usb, true);
1832eefdbec1SJussi Kivilinna if (r) {
1833eefdbec1SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb),
1834eefdbec1SJussi Kivilinna "error in zd_submit_waiting_usb(). "
1835eefdbec1SJussi Kivilinna "Error number %d\n", r);
1836eefdbec1SJussi Kivilinna
1837eefdbec1SJussi Kivilinna usb_kill_anchored_urbs(&usb->submitted_cmds);
1838eefdbec1SJussi Kivilinna goto error;
1839eefdbec1SJussi Kivilinna }
1840eefdbec1SJussi Kivilinna
1841eefdbec1SJussi Kivilinna if (timeout)
1842eefdbec1SJussi Kivilinna timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds,
1843eefdbec1SJussi Kivilinna timeout);
1844eefdbec1SJussi Kivilinna if (!timeout) {
1845eefdbec1SJussi Kivilinna usb_kill_anchored_urbs(&usb->submitted_cmds);
1846eefdbec1SJussi Kivilinna if (usb->cmd_error == -ENOENT) {
1847eefdbec1SJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "timed out");
1848eefdbec1SJussi Kivilinna r = -ETIMEDOUT;
1849eefdbec1SJussi Kivilinna goto error;
1850eefdbec1SJussi Kivilinna }
1851eefdbec1SJussi Kivilinna }
1852eefdbec1SJussi Kivilinna
1853eefdbec1SJussi Kivilinna r = usb->cmd_error;
1854eefdbec1SJussi Kivilinna error:
1855eefdbec1SJussi Kivilinna usb->in_async = 0;
1856eefdbec1SJussi Kivilinna return r;
1857eefdbec1SJussi Kivilinna }
1858eefdbec1SJussi Kivilinna
zd_usb_iowrite16v_async(struct zd_usb * usb,const struct zd_ioreq16 * ioreqs,unsigned int count)18598662b251SJussi Kivilinna int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
1860e85d0918SDaniel Drake unsigned int count)
1861e85d0918SDaniel Drake {
1862e85d0918SDaniel Drake int r;
1863e85d0918SDaniel Drake struct usb_device *udev;
1864e85d0918SDaniel Drake struct usb_req_write_regs *req = NULL;
1865eefdbec1SJussi Kivilinna int i, req_len;
1866eefdbec1SJussi Kivilinna struct urb *urb;
1867eefdbec1SJussi Kivilinna struct usb_host_endpoint *ep;
1868eefdbec1SJussi Kivilinna
1869eefdbec1SJussi Kivilinna ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
1870eefdbec1SJussi Kivilinna ZD_ASSERT(usb->in_async);
1871e85d0918SDaniel Drake
1872e85d0918SDaniel Drake if (count == 0)
1873e85d0918SDaniel Drake return 0;
1874e85d0918SDaniel Drake if (count > USB_MAX_IOWRITE16_COUNT) {
1875e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1876e85d0918SDaniel Drake "error: count %u exceeds possible max %u\n",
1877e85d0918SDaniel Drake count, USB_MAX_IOWRITE16_COUNT);
1878e85d0918SDaniel Drake return -EINVAL;
1879e85d0918SDaniel Drake }
1880e85d0918SDaniel Drake
1881eefdbec1SJussi Kivilinna udev = zd_usb_to_usbdev(usb);
1882eefdbec1SJussi Kivilinna
1883eefdbec1SJussi Kivilinna ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
1884eefdbec1SJussi Kivilinna if (!ep)
1885eefdbec1SJussi Kivilinna return -ENOENT;
1886eefdbec1SJussi Kivilinna
1887eefdbec1SJussi Kivilinna urb = usb_alloc_urb(0, GFP_KERNEL);
1888eefdbec1SJussi Kivilinna if (!urb)
1889eefdbec1SJussi Kivilinna return -ENOMEM;
18909bca0c3bSJussi Kivilinna
18910c7beb2dSGustavo A. R. Silva req_len = struct_size(req, reg_writes, count);
1892eefdbec1SJussi Kivilinna req = kmalloc(req_len, GFP_KERNEL);
1893eefdbec1SJussi Kivilinna if (!req) {
1894eefdbec1SJussi Kivilinna r = -ENOMEM;
1895eefdbec1SJussi Kivilinna goto error;
1896eefdbec1SJussi Kivilinna }
1897e85d0918SDaniel Drake
1898e85d0918SDaniel Drake req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
1899e85d0918SDaniel Drake for (i = 0; i < count; i++) {
1900e85d0918SDaniel Drake struct reg_data *rw = &req->reg_writes[i];
19010ce34bc8SDaniel Drake rw->addr = cpu_to_le16((u16)ioreqs[i].addr);
1902e85d0918SDaniel Drake rw->value = cpu_to_le16(ioreqs[i].value);
1903e85d0918SDaniel Drake }
1904e85d0918SDaniel Drake
190559342f6aSJussi Kivilinna /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode
190659342f6aSJussi Kivilinna * endpoint is bulk. Select correct type URB by endpoint descriptor.
190759342f6aSJussi Kivilinna */
190859342f6aSJussi Kivilinna if (usb_endpoint_xfer_int(&ep->desc))
1909eefdbec1SJussi Kivilinna usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
1910eefdbec1SJussi Kivilinna req, req_len, iowrite16v_urb_complete, usb,
1911eefdbec1SJussi Kivilinna ep->desc.bInterval);
191259342f6aSJussi Kivilinna else
191359342f6aSJussi Kivilinna usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
191459342f6aSJussi Kivilinna req, req_len, iowrite16v_urb_complete, usb);
191559342f6aSJussi Kivilinna
19162fc713b2SJussi Kivilinna urb->transfer_flags |= URB_FREE_BUFFER;
1917eefdbec1SJussi Kivilinna
1918eefdbec1SJussi Kivilinna /* Submit previous URB */
1919eefdbec1SJussi Kivilinna r = zd_submit_waiting_urb(usb, false);
1920e85d0918SDaniel Drake if (r) {
1921e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1922eefdbec1SJussi Kivilinna "error in zd_submit_waiting_usb(). "
1923eefdbec1SJussi Kivilinna "Error number %d\n", r);
1924e85d0918SDaniel Drake goto error;
1925e85d0918SDaniel Drake }
1926e85d0918SDaniel Drake
1927eefdbec1SJussi Kivilinna /* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
1928eefdbec1SJussi Kivilinna * of currect batch except for very last.
1929eefdbec1SJussi Kivilinna */
1930eefdbec1SJussi Kivilinna usb->urb_async_waiting = urb;
1931eefdbec1SJussi Kivilinna return 0;
1932e85d0918SDaniel Drake error:
1933eefdbec1SJussi Kivilinna usb_free_urb(urb);
1934e85d0918SDaniel Drake return r;
1935e85d0918SDaniel Drake }
1936e85d0918SDaniel Drake
zd_usb_iowrite16v(struct zd_usb * usb,const struct zd_ioreq16 * ioreqs,unsigned int count)1937eefdbec1SJussi Kivilinna int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
1938eefdbec1SJussi Kivilinna unsigned int count)
1939eefdbec1SJussi Kivilinna {
1940eefdbec1SJussi Kivilinna int r;
1941eefdbec1SJussi Kivilinna
1942eefdbec1SJussi Kivilinna zd_usb_iowrite16v_async_start(usb);
1943eefdbec1SJussi Kivilinna r = zd_usb_iowrite16v_async(usb, ioreqs, count);
1944eefdbec1SJussi Kivilinna if (r) {
1945eefdbec1SJussi Kivilinna zd_usb_iowrite16v_async_end(usb, 0);
1946eefdbec1SJussi Kivilinna return r;
1947eefdbec1SJussi Kivilinna }
1948eefdbec1SJussi Kivilinna return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
1949eefdbec1SJussi Kivilinna }
1950eefdbec1SJussi Kivilinna
zd_usb_rfwrite(struct zd_usb * usb,u32 value,u8 bits)1951e85d0918SDaniel Drake int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
1952e85d0918SDaniel Drake {
1953e85d0918SDaniel Drake int r;
1954e85d0918SDaniel Drake struct usb_device *udev;
1955e85d0918SDaniel Drake struct usb_req_rfwrite *req = NULL;
1956e85d0918SDaniel Drake int i, req_len, actual_req_len;
1957e85d0918SDaniel Drake u16 bit_value_template;
1958e85d0918SDaniel Drake
1959e85d0918SDaniel Drake if (bits < USB_MIN_RFWRITE_BIT_COUNT) {
1960e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1961e85d0918SDaniel Drake "error: bits %d are smaller than"
1962e85d0918SDaniel Drake " USB_MIN_RFWRITE_BIT_COUNT %d\n",
1963e85d0918SDaniel Drake bits, USB_MIN_RFWRITE_BIT_COUNT);
1964e85d0918SDaniel Drake return -EINVAL;
1965e85d0918SDaniel Drake }
1966e85d0918SDaniel Drake if (bits > USB_MAX_RFWRITE_BIT_COUNT) {
1967e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1968e85d0918SDaniel Drake "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n",
1969e85d0918SDaniel Drake bits, USB_MAX_RFWRITE_BIT_COUNT);
1970e85d0918SDaniel Drake return -EINVAL;
1971e85d0918SDaniel Drake }
1972e85d0918SDaniel Drake #ifdef DEBUG
1973e85d0918SDaniel Drake if (value & (~0UL << bits)) {
1974e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1975e85d0918SDaniel Drake "error: value %#09x has bits >= %d set\n",
1976e85d0918SDaniel Drake value, bits);
1977e85d0918SDaniel Drake return -EINVAL;
1978e85d0918SDaniel Drake }
1979e85d0918SDaniel Drake #endif /* DEBUG */
1980e85d0918SDaniel Drake
1981e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits);
1982e85d0918SDaniel Drake
1983fbd5d17bSJussi Kivilinna r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203);
1984e85d0918SDaniel Drake if (r) {
1985e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
1986fbd5d17bSJussi Kivilinna "error %d: Couldn't read ZD_CR203\n", r);
19879bca0c3bSJussi Kivilinna return r;
1988e85d0918SDaniel Drake }
1989e85d0918SDaniel Drake bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
1990e85d0918SDaniel Drake
19919bca0c3bSJussi Kivilinna ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
19929bca0c3bSJussi Kivilinna BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) +
19939bca0c3bSJussi Kivilinna USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) >
19949bca0c3bSJussi Kivilinna sizeof(usb->req_buf));
19959bca0c3bSJussi Kivilinna BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) >
19969bca0c3bSJussi Kivilinna sizeof(usb->req_buf));
19979bca0c3bSJussi Kivilinna
1998e85d0918SDaniel Drake req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
19999bca0c3bSJussi Kivilinna req = (void *)usb->req_buf;
2000e85d0918SDaniel Drake
2001e85d0918SDaniel Drake req->id = cpu_to_le16(USB_REQ_WRITE_RF);
2002e85d0918SDaniel Drake /* 1: 3683a, but not used in ZYDAS driver */
2003e85d0918SDaniel Drake req->value = cpu_to_le16(2);
2004e85d0918SDaniel Drake req->bits = cpu_to_le16(bits);
2005e85d0918SDaniel Drake
2006e85d0918SDaniel Drake for (i = 0; i < bits; i++) {
2007e85d0918SDaniel Drake u16 bv = bit_value_template;
2008e85d0918SDaniel Drake if (value & (1 << (bits-1-i)))
2009e85d0918SDaniel Drake bv |= RF_DATA;
2010e85d0918SDaniel Drake req->bit_values[i] = cpu_to_le16(bv);
2011e85d0918SDaniel Drake }
2012e85d0918SDaniel Drake
2013e85d0918SDaniel Drake udev = zd_usb_to_usbdev(usb);
201459342f6aSJussi Kivilinna r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
2015e85d0918SDaniel Drake if (r) {
2016e85d0918SDaniel Drake dev_dbg_f(zd_usb_dev(usb),
201759342f6aSJussi Kivilinna "error in zd_ep_regs_out_msg(). Error number %d\n", r);
2018e85d0918SDaniel Drake goto out;
2019e85d0918SDaniel Drake }
2020e85d0918SDaniel Drake if (req_len != actual_req_len) {
202159342f6aSJussi Kivilinna dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"
2022e85d0918SDaniel Drake " req_len %d != actual_req_len %d\n",
2023e85d0918SDaniel Drake req_len, actual_req_len);
2024e85d0918SDaniel Drake r = -EIO;
2025e85d0918SDaniel Drake goto out;
2026e85d0918SDaniel Drake }
2027e85d0918SDaniel Drake
2028e85d0918SDaniel Drake /* FALL-THROUGH with r == 0 */
2029e85d0918SDaniel Drake out:
2030e85d0918SDaniel Drake return r;
2031e85d0918SDaniel Drake }
2032