diff options
author | Luis R. Rodriguez | 2011-03-30 13:22:29 -0500 |
---|---|---|
committer | Luis R. Rodriguez | 2011-03-30 13:22:29 -0500 |
commit | 11d2d7cb3e750eae6b39f2166cb2e26edd653919 (patch) | |
tree | 5ad98601f3a7e7ac5dd2551026df877b9efd648b /crap | |
parent | 65723483c251ca3523b2dad47842388a5408d00c (diff) | |
download | compat-wireless-11d2d7cb3e750eae6b39f2166cb2e26edd653919.tar.gz compat-wireless-11d2d7cb3e750eae6b39f2166cb2e26edd653919.tar.xz compat-wireless-11d2d7cb3e750eae6b39f2166cb2e26edd653919.zip |
compat-wireless: remove ath3k bt workaround
This should be addressed now upstream properly through this
patch:
commit d9f51b51db2064c9049bf7924318fd8c6ed852cb
Author: Bala Shanmugam <sbalashanmugam@atheros.com>
Date: Fri Feb 11 15:38:53 2011 +0530
Bluetooth: Add firmware support for Atheros 3012
Blacklisted AR3012 PID in btusb and added the same
in ath3k to load patch and sysconfig files.
Signed-off-by: Bala Shanmugam <sbalashanmugam@atheros.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Diffstat (limited to 'crap')
-rw-r--r-- | crap/0003-btusb-Add-fw-load-support.patch | 416 |
1 files changed, 0 insertions, 416 deletions
diff --git a/crap/0003-btusb-Add-fw-load-support.patch b/crap/0003-btusb-Add-fw-load-support.patch deleted file mode 100644 index 513f995..0000000 --- a/crap/0003-btusb-Add-fw-load-support.patch +++ /dev/null | |||
@@ -1,416 +0,0 @@ | |||
1 | Reason for this not being merged upstream: | ||
2 | |||
3 | It was first rejected without any alternatives suggested. Then | ||
4 | an alternative was finally suggested but too late for integration | ||
5 | upstream. | ||
6 | |||
7 | This is a work around until a new firmware and patch is being worked | ||
8 | on which is acceptable upstream. | ||
9 | |||
10 | For details refer to: | ||
11 | |||
12 | http://lkml.org/lkml/2010/10/5/195 | ||
13 | |||
14 | From 4ac276c14578b380d0c6a27658eeaa364efe6432 Mon Sep 17 00:00:00 2001 | ||
15 | From: Bala Shanmugam <sbalashanmugam@atheros.com> | ||
16 | Date: Fri, 1 Oct 2010 15:18:02 +0530 | ||
17 | Subject: [PATCH] Added support to load firmware to target RAM from btusb transport driver. | ||
18 | Each BT device vendor can add their product ID, firmware file, load and unload function | ||
19 | to btusb_fwcbs array. When the device is inserted btusb will call appropriate | ||
20 | firmware load function. This support will significantly reduce cost of | ||
21 | BT chip because of RAM based firmware. | ||
22 | Signed-off-by: Bala Shanmugam <sbalashanmugam@atheros.com> | ||
23 | |||
24 | --- | ||
25 | drivers/bluetooth/Makefile | 1 + | ||
26 | drivers/bluetooth/btusb.c | 67 +++++++++++++++ | ||
27 | drivers/bluetooth/fwload.c | 199 ++++++++++++++++++++++++++++++++++++++++++++ | ||
28 | drivers/bluetooth/fwload.h | 39 +++++++++ | ||
29 | 4 files changed, 306 insertions(+), 0 deletions(-) | ||
30 | create mode 100644 drivers/bluetooth/fwload.c | ||
31 | create mode 100644 drivers/bluetooth/fwload.h | ||
32 | |||
33 | --- a/drivers/bluetooth/Makefile | ||
34 | +++ b/drivers/bluetooth/Makefile | ||
35 | @@ -13,6 +13,7 @@ obj-$(CONFIG_BT_HCIBLUECARD) += bluecard | ||
36 | obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o | ||
37 | |||
38 | obj-$(CONFIG_BT_HCIBTUSB) += btusb.o | ||
39 | +obj-$(CONFIG_BT_HCIBTUSB) += fwload.o | ||
40 | obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o | ||
41 | |||
42 | obj-$(CONFIG_BT_ATH3K) += ath3k.o | ||
43 | --- a/drivers/bluetooth/btusb.c | ||
44 | +++ b/drivers/bluetooth/btusb.c | ||
45 | @@ -34,6 +34,7 @@ | ||
46 | |||
47 | #include <net/bluetooth/bluetooth.h> | ||
48 | #include <net/bluetooth/hci_core.h> | ||
49 | +#include "fwload.h" | ||
50 | |||
51 | #define VERSION "0.6" | ||
52 | |||
53 | @@ -55,6 +56,26 @@ static struct usb_driver btusb_driver; | ||
54 | #define BTUSB_BROKEN_ISOC 0x20 | ||
55 | #define BTUSB_WRONG_SCO_MTU 0x40 | ||
56 | |||
57 | +static struct usb_device_id ath_table[] = { | ||
58 | + /* Atheros AR3011 */ | ||
59 | + { USB_DEVICE(0x0CF3, 0x3002) }, | ||
60 | + { USB_DEVICE(0x13D3, 0x3304) }, | ||
61 | + { } /* Terminating entry */ | ||
62 | +}; | ||
63 | + | ||
64 | +/* Add firmware file, load and unload function | ||
65 | + * to download the firmware to target RAM | ||
66 | + */ | ||
67 | +static struct fw_cb_config btusb_fwcbs[] = { | ||
68 | + { | ||
69 | + .fwfile = "ath3k-1.fw", | ||
70 | + .usb_id_table = ath_table, | ||
71 | + .fwload = ath_fw_load, | ||
72 | + .fwunload = ath_fw_unload | ||
73 | + }, | ||
74 | + {} | ||
75 | +}; | ||
76 | + | ||
77 | static struct usb_device_id btusb_table[] = { | ||
78 | /* Generic Bluetooth USB device */ | ||
79 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, | ||
80 | @@ -887,6 +908,7 @@ static int btusb_probe(struct usb_interf | ||
81 | struct btusb_data *data; | ||
82 | struct hci_dev *hdev; | ||
83 | int i, err; | ||
84 | + const struct usb_device_id *match; | ||
85 | |||
86 | BT_DBG("intf %p id %p", intf, id); | ||
87 | |||
88 | @@ -946,6 +968,19 @@ static int btusb_probe(struct usb_interf | ||
89 | data->udev = interface_to_usbdev(intf); | ||
90 | data->intf = intf; | ||
91 | |||
92 | + for (i = 0; btusb_fwcbs[i].fwfile; i++) { | ||
93 | + match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); | ||
94 | + if (match) { | ||
95 | + if (btusb_fwcbs[i].fwload) { | ||
96 | + btusb_fwcbs[i].data = | ||
97 | + btusb_fwcbs[i].fwload(intf, | ||
98 | + btusb_fwcbs[i].fwfile, | ||
99 | + &btusb_fwcbs[i].bsuspend); | ||
100 | + } | ||
101 | + break; | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
105 | spin_lock_init(&data->lock); | ||
106 | |||
107 | INIT_WORK(&data->work, btusb_work); | ||
108 | @@ -1054,12 +1089,26 @@ static void btusb_disconnect(struct usb_ | ||
109 | { | ||
110 | struct btusb_data *data = usb_get_intfdata(intf); | ||
111 | struct hci_dev *hdev; | ||
112 | + const struct usb_device_id *match; | ||
113 | + int i; | ||
114 | |||
115 | BT_DBG("intf %p", intf); | ||
116 | |||
117 | if (!data) | ||
118 | return; | ||
119 | |||
120 | + for (i = 0; btusb_fwcbs[i].fwfile; i++) { | ||
121 | + match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); | ||
122 | + if (match) { | ||
123 | + if (btusb_fwcbs[i].fwunload) { | ||
124 | + btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, | ||
125 | + btusb_fwcbs[i].bsuspend); | ||
126 | + btusb_fwcbs[i].data = NULL; | ||
127 | + } | ||
128 | + break; | ||
129 | + } | ||
130 | + } | ||
131 | + | ||
132 | hdev = data->hdev; | ||
133 | |||
134 | __hci_dev_hold(hdev); | ||
135 | @@ -1085,12 +1134,22 @@ static void btusb_disconnect(struct usb_ | ||
136 | static int btusb_suspend(struct usb_interface *intf, pm_message_t message) | ||
137 | { | ||
138 | struct btusb_data *data = usb_get_intfdata(intf); | ||
139 | + const struct usb_device_id *match; | ||
140 | + int i; | ||
141 | |||
142 | BT_DBG("intf %p", intf); | ||
143 | |||
144 | if (data->suspend_count++) | ||
145 | return 0; | ||
146 | |||
147 | + for (i = 0; btusb_fwcbs[i].fwfile; i++) { | ||
148 | + match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); | ||
149 | + if (match) { | ||
150 | + btusb_fwcbs[i].bsuspend = 1; | ||
151 | + break; | ||
152 | + } | ||
153 | + } | ||
154 | + | ||
155 | spin_lock_irq(&data->txlock); | ||
156 | if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { | ||
157 | set_bit(BTUSB_SUSPENDING, &data->flags); | ||
158 | @@ -1203,6 +1262,14 @@ static int __init btusb_init(void) | ||
159 | |||
160 | static void __exit btusb_exit(void) | ||
161 | { | ||
162 | + int i; | ||
163 | + for (i = 0; btusb_fwcbs[i].fwfile; i++) { | ||
164 | + if (btusb_fwcbs[i].fwunload && btusb_fwcbs[i].data) { | ||
165 | + btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, | ||
166 | + btusb_fwcbs[i].bsuspend); | ||
167 | + btusb_fwcbs[i].data = NULL; | ||
168 | + } | ||
169 | + } | ||
170 | usb_deregister(&btusb_driver); | ||
171 | } | ||
172 | |||
173 | --- /dev/null | ||
174 | +++ b/drivers/bluetooth/fwload.c | ||
175 | @@ -0,0 +1,199 @@ | ||
176 | +/* | ||
177 | + * | ||
178 | + * Generic Bluetooth USB DFU driver to download firmware to target RAM | ||
179 | + * | ||
180 | + * Copyright (c) 2009-2010 Atheros Communications Inc. | ||
181 | + * | ||
182 | + * This program is free software; you can redistribute it and/or modify | ||
183 | + * it under the terms of the GNU General Public License as published by | ||
184 | + * the Free Software Foundation; either version 2 of the License, or | ||
185 | + * (at your option) any later version. | ||
186 | + * | ||
187 | + * This program is distributed in the hope that it will be useful, | ||
188 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
189 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
190 | + * GNU General Public License for more details. | ||
191 | + * | ||
192 | + * You should have received a copy of the GNU General Public License | ||
193 | + * along with this program; if not, write to the Free Software | ||
194 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
195 | + * | ||
196 | + */ | ||
197 | + | ||
198 | +#include <linux/module.h> | ||
199 | +#include <linux/kernel.h> | ||
200 | +#include <linux/init.h> | ||
201 | +#include <linux/slab.h> | ||
202 | +#include <linux/types.h> | ||
203 | +#include <linux/device.h> | ||
204 | +#include <linux/firmware.h> | ||
205 | +#include <linux/usb.h> | ||
206 | +#include <net/bluetooth/bluetooth.h> | ||
207 | + | ||
208 | +#define USB_REQ_DFU_DNLOAD 1 | ||
209 | +#define USB_REQ_GET_STATE 5 | ||
210 | +#define USB_FIRMWARE_RAM_MODE 11 | ||
211 | +#define USB_FIRMWARE_FLASH_MODE 12 | ||
212 | +#define BULK_SIZE 4096 | ||
213 | +#define VERSION "1.0" | ||
214 | + | ||
215 | +struct firmware_data { | ||
216 | + struct usb_device *udev; | ||
217 | + u8 *fw_data; | ||
218 | + u32 fw_size; | ||
219 | + u32 fw_sent; | ||
220 | +}; | ||
221 | + | ||
222 | +static int load_firmware(struct firmware_data *data, | ||
223 | + unsigned char *firmware, | ||
224 | + int count) | ||
225 | +{ | ||
226 | + u8 *send_buf; | ||
227 | + int err, pipe, len, size, sent = 0; | ||
228 | + char ucFirmware = 0; | ||
229 | + | ||
230 | + BT_DBG("ath3k %p udev %p", data, data->udev); | ||
231 | + | ||
232 | + if ((usb_control_msg(data->udev, usb_rcvctrlpipe(data->udev, 0), | ||
233 | + USB_REQ_GET_STATE, | ||
234 | + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
235 | + &ucFirmware, 1, USB_CTRL_SET_TIMEOUT)) < 0) { | ||
236 | + BT_ERR("Can't change to loading configuration err"); | ||
237 | + return -EBUSY; | ||
238 | + } | ||
239 | + | ||
240 | + if (ucFirmware == USB_FIRMWARE_RAM_MODE) { | ||
241 | + /* RAM based firmware is available in the target. | ||
242 | + * No need to load the firmware to RAM */ | ||
243 | + BT_DBG("RAM based firmware is available"); | ||
244 | + return 0; | ||
245 | + } | ||
246 | + | ||
247 | + pipe = usb_sndctrlpipe(data->udev, 0); | ||
248 | + if ((usb_control_msg(data->udev, pipe, | ||
249 | + USB_REQ_DFU_DNLOAD, | ||
250 | + USB_TYPE_VENDOR, 0, 0, | ||
251 | + firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { | ||
252 | + BT_ERR("Can't change to loading configuration err"); | ||
253 | + return -EBUSY; | ||
254 | + } | ||
255 | + sent += 20; | ||
256 | + count -= 20; | ||
257 | + | ||
258 | + send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); | ||
259 | + if (!send_buf) { | ||
260 | + BT_ERR("Can't allocate memory chunk for firmware"); | ||
261 | + return -ENOMEM; | ||
262 | + } | ||
263 | + | ||
264 | + while (count) { | ||
265 | + size = min_t(uint, count, BULK_SIZE); | ||
266 | + pipe = usb_sndbulkpipe(data->udev, 0x02); | ||
267 | + memcpy(send_buf, firmware + sent, size); | ||
268 | + | ||
269 | + err = usb_bulk_msg(data->udev, pipe, send_buf, size, | ||
270 | + &len, 3000); | ||
271 | + | ||
272 | + if (err || (len != size)) { | ||
273 | + BT_ERR("Error in firmware loading err = %d," | ||
274 | + "len = %d, size = %d", err, len, size); | ||
275 | + goto error; | ||
276 | + } | ||
277 | + | ||
278 | + sent += size; | ||
279 | + count -= size; | ||
280 | + } | ||
281 | + | ||
282 | + kfree(send_buf); | ||
283 | + return 0; | ||
284 | + | ||
285 | +error: | ||
286 | + kfree(send_buf); | ||
287 | + return err; | ||
288 | +} | ||
289 | + | ||
290 | +void *ath_fw_load(struct usb_interface *intf, | ||
291 | + const char *fwfile, bool *suspend) | ||
292 | +{ | ||
293 | + const struct firmware *firmware; | ||
294 | + struct usb_device *udev = interface_to_usbdev(intf); | ||
295 | + static struct firmware_data *data; | ||
296 | + int size; | ||
297 | + | ||
298 | + BT_DBG("\nintf %p suspend %d\n", intf, *suspend); | ||
299 | + | ||
300 | + if (*suspend) { | ||
301 | + load_firmware(data, data->fw_data, data->fw_size); | ||
302 | + *suspend = 0; | ||
303 | + return data; | ||
304 | + } | ||
305 | + | ||
306 | + if (intf->cur_altsetting->desc.bInterfaceNumber != 0) | ||
307 | + return NULL; | ||
308 | + | ||
309 | + data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
310 | + if (!data) | ||
311 | + return NULL; | ||
312 | + data->udev = udev; | ||
313 | + | ||
314 | + if (request_firmware(&firmware, fwfile, &udev->dev) < 0) { | ||
315 | + kfree(data); | ||
316 | + return NULL; | ||
317 | + } | ||
318 | + | ||
319 | + size = max_t(uint, firmware->size, 4096); | ||
320 | + data->fw_data = kmalloc(size, GFP_KERNEL); | ||
321 | + if (!data->fw_data) { | ||
322 | + release_firmware(firmware); | ||
323 | + kfree(data); | ||
324 | + return NULL; | ||
325 | + } | ||
326 | + | ||
327 | + memcpy(data->fw_data, firmware->data, firmware->size); | ||
328 | + data->fw_size = firmware->size; | ||
329 | + data->fw_sent = 0; | ||
330 | + release_firmware(firmware); | ||
331 | + | ||
332 | + if (load_firmware(data, data->fw_data, data->fw_size)) { | ||
333 | + kfree(data->fw_data); | ||
334 | + kfree(data); | ||
335 | + return NULL; | ||
336 | + } | ||
337 | + return data; | ||
338 | +} | ||
339 | +EXPORT_SYMBOL(ath_fw_load); | ||
340 | + | ||
341 | +void ath_fw_unload(void *pdata, bool bsuspend) | ||
342 | +{ | ||
343 | + struct firmware_data *data = (struct firmware_data *)pdata; | ||
344 | + | ||
345 | + if (data == NULL) | ||
346 | + return; | ||
347 | + | ||
348 | + /* do not free the data on suspend as we will | ||
349 | + * use it on resume */ | ||
350 | + if (!bsuspend) { | ||
351 | + kfree(data->fw_data); | ||
352 | + kfree(data); | ||
353 | + } | ||
354 | +} | ||
355 | +EXPORT_SYMBOL(ath_fw_unload); | ||
356 | + | ||
357 | +static int __init fwload_init(void) | ||
358 | +{ | ||
359 | + BT_INFO("Firmware load driver init. Version:%s", VERSION); | ||
360 | + return 0; | ||
361 | +} | ||
362 | + | ||
363 | +static void __exit fwload_deinit(void) | ||
364 | +{ | ||
365 | + BT_INFO("Firmware load driver deinit"); | ||
366 | +} | ||
367 | + | ||
368 | +module_init(fwload_init); | ||
369 | +module_exit(fwload_deinit); | ||
370 | + | ||
371 | +MODULE_AUTHOR("Atheros Communications"); | ||
372 | +MODULE_DESCRIPTION("Firmware load driver"); | ||
373 | +MODULE_VERSION(VERSION); | ||
374 | +MODULE_LICENSE("GPL"); | ||
375 | --- /dev/null | ||
376 | +++ b/drivers/bluetooth/fwload.h | ||
377 | @@ -0,0 +1,39 @@ | ||
378 | +/* | ||
379 | + * | ||
380 | + * Generic Bluetooth USB DFU driver to download firmware to target RAM | ||
381 | + * | ||
382 | + * Copyright (c) 2009-2010 Atheros Communications Inc. | ||
383 | + * | ||
384 | + * This program is free software; you can redistribute it and/or modify | ||
385 | + * it under the terms of the GNU General Public License as published by | ||
386 | + * the Free Software Foundation; either version 2 of the License, or | ||
387 | + * (at your option) any later version. | ||
388 | + * | ||
389 | + * This program is distributed in the hope that it will be useful, | ||
390 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
391 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
392 | + * GNU General Public License for more details. | ||
393 | + * | ||
394 | + * You should have received a copy of the GNU General Public License | ||
395 | + * along with this program; if not, write to the Free Software | ||
396 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
397 | + * | ||
398 | + */ | ||
399 | +#ifndef _FWLOAD_H_ | ||
400 | +#define _FWLOAD_H_ | ||
401 | + | ||
402 | +/* callbacks to load firmware to BT device RAM | ||
403 | + * when it is inserted */ | ||
404 | +struct fw_cb_config { | ||
405 | + const char *fwfile; | ||
406 | + void * (*fwload)(struct usb_interface *intf, const char *fwfile, | ||
407 | + bool *bsuspend); | ||
408 | + void (*fwunload)(void *, bool); | ||
409 | + const struct usb_device_id *usb_id_table; | ||
410 | + void *data; | ||
411 | + bool bsuspend; | ||
412 | +}; | ||
413 | +void *ath_fw_load(struct usb_interface *intf, const char *, bool *); | ||
414 | +void ath_fw_unload(void *pdata, bool bsuspend); | ||
415 | + | ||
416 | +#endif /* _FWLOAD_H_ */ | ||