From 11d2d7cb3e750eae6b39f2166cb2e26edd653919 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 30 Mar 2011 11:22:29 -0700 Subject: [PATCH] compat-wireless: remove ath3k bt workaround This should be addressed now upstream properly through this patch: commit d9f51b51db2064c9049bf7924318fd8c6ed852cb Author: Bala Shanmugam 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 Signed-off-by: Gustavo F. Padovan Signed-off-by: Luis R. Rodriguez --- crap/0003-btusb-Add-fw-load-support.patch | 416 ---------------------- 1 file changed, 416 deletions(-) delete mode 100644 crap/0003-btusb-Add-fw-load-support.patch 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 513f995ca90b..000000000000 --- a/crap/0003-btusb-Add-fw-load-support.patch +++ /dev/null @@ -1,416 +0,0 @@ -Reason for this not being merged upstream: - -It was first rejected without any alternatives suggested. Then -an alternative was finally suggested but too late for integration -upstream. - -This is a work around until a new firmware and patch is being worked -on which is acceptable upstream. - -For details refer to: - -http://lkml.org/lkml/2010/10/5/195 - -From 4ac276c14578b380d0c6a27658eeaa364efe6432 Mon Sep 17 00:00:00 2001 -From: Bala Shanmugam -Date: Fri, 1 Oct 2010 15:18:02 +0530 -Subject: [PATCH] Added support to load firmware to target RAM from btusb transport driver. - Each BT device vendor can add their product ID, firmware file, load and unload function - to btusb_fwcbs array. When the device is inserted btusb will call appropriate - firmware load function. This support will significantly reduce cost of - BT chip because of RAM based firmware. - Signed-off-by: Bala Shanmugam - ---- - drivers/bluetooth/Makefile | 1 + - drivers/bluetooth/btusb.c | 67 +++++++++++++++ - drivers/bluetooth/fwload.c | 199 ++++++++++++++++++++++++++++++++++++++++++++ - drivers/bluetooth/fwload.h | 39 +++++++++ - 4 files changed, 306 insertions(+), 0 deletions(-) - create mode 100644 drivers/bluetooth/fwload.c - create mode 100644 drivers/bluetooth/fwload.h - ---- a/drivers/bluetooth/Makefile -+++ b/drivers/bluetooth/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_BT_HCIBLUECARD) += bluecard - obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o - - obj-$(CONFIG_BT_HCIBTUSB) += btusb.o -+obj-$(CONFIG_BT_HCIBTUSB) += fwload.o - obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o - - obj-$(CONFIG_BT_ATH3K) += ath3k.o ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -34,6 +34,7 @@ - - #include - #include -+#include "fwload.h" - - #define VERSION "0.6" - -@@ -55,6 +56,26 @@ static struct usb_driver btusb_driver; - #define BTUSB_BROKEN_ISOC 0x20 - #define BTUSB_WRONG_SCO_MTU 0x40 - -+static struct usb_device_id ath_table[] = { -+ /* Atheros AR3011 */ -+ { USB_DEVICE(0x0CF3, 0x3002) }, -+ { USB_DEVICE(0x13D3, 0x3304) }, -+ { } /* Terminating entry */ -+}; -+ -+/* Add firmware file, load and unload function -+ * to download the firmware to target RAM -+ */ -+static struct fw_cb_config btusb_fwcbs[] = { -+ { -+ .fwfile = "ath3k-1.fw", -+ .usb_id_table = ath_table, -+ .fwload = ath_fw_load, -+ .fwunload = ath_fw_unload -+ }, -+ {} -+}; -+ - static struct usb_device_id btusb_table[] = { - /* Generic Bluetooth USB device */ - { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, -@@ -887,6 +908,7 @@ static int btusb_probe(struct usb_interf - struct btusb_data *data; - struct hci_dev *hdev; - int i, err; -+ const struct usb_device_id *match; - - BT_DBG("intf %p id %p", intf, id); - -@@ -946,6 +968,19 @@ static int btusb_probe(struct usb_interf - data->udev = interface_to_usbdev(intf); - data->intf = intf; - -+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { -+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); -+ if (match) { -+ if (btusb_fwcbs[i].fwload) { -+ btusb_fwcbs[i].data = -+ btusb_fwcbs[i].fwload(intf, -+ btusb_fwcbs[i].fwfile, -+ &btusb_fwcbs[i].bsuspend); -+ } -+ break; -+ } -+ } -+ - spin_lock_init(&data->lock); - - INIT_WORK(&data->work, btusb_work); -@@ -1054,12 +1089,26 @@ static void btusb_disconnect(struct usb_ - { - struct btusb_data *data = usb_get_intfdata(intf); - struct hci_dev *hdev; -+ const struct usb_device_id *match; -+ int i; - - BT_DBG("intf %p", intf); - - if (!data) - return; - -+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { -+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); -+ if (match) { -+ if (btusb_fwcbs[i].fwunload) { -+ btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, -+ btusb_fwcbs[i].bsuspend); -+ btusb_fwcbs[i].data = NULL; -+ } -+ break; -+ } -+ } -+ - hdev = data->hdev; - - __hci_dev_hold(hdev); -@@ -1085,12 +1134,22 @@ static void btusb_disconnect(struct usb_ - static int btusb_suspend(struct usb_interface *intf, pm_message_t message) - { - struct btusb_data *data = usb_get_intfdata(intf); -+ const struct usb_device_id *match; -+ int i; - - BT_DBG("intf %p", intf); - - if (data->suspend_count++) - return 0; - -+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { -+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); -+ if (match) { -+ btusb_fwcbs[i].bsuspend = 1; -+ break; -+ } -+ } -+ - spin_lock_irq(&data->txlock); - if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { - set_bit(BTUSB_SUSPENDING, &data->flags); -@@ -1203,6 +1262,14 @@ static int __init btusb_init(void) - - static void __exit btusb_exit(void) - { -+ int i; -+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { -+ if (btusb_fwcbs[i].fwunload && btusb_fwcbs[i].data) { -+ btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, -+ btusb_fwcbs[i].bsuspend); -+ btusb_fwcbs[i].data = NULL; -+ } -+ } - usb_deregister(&btusb_driver); - } - ---- /dev/null -+++ b/drivers/bluetooth/fwload.c -@@ -0,0 +1,199 @@ -+/* -+ * -+ * Generic Bluetooth USB DFU driver to download firmware to target RAM -+ * -+ * Copyright (c) 2009-2010 Atheros Communications Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define USB_REQ_DFU_DNLOAD 1 -+#define USB_REQ_GET_STATE 5 -+#define USB_FIRMWARE_RAM_MODE 11 -+#define USB_FIRMWARE_FLASH_MODE 12 -+#define BULK_SIZE 4096 -+#define VERSION "1.0" -+ -+struct firmware_data { -+ struct usb_device *udev; -+ u8 *fw_data; -+ u32 fw_size; -+ u32 fw_sent; -+}; -+ -+static int load_firmware(struct firmware_data *data, -+ unsigned char *firmware, -+ int count) -+{ -+ u8 *send_buf; -+ int err, pipe, len, size, sent = 0; -+ char ucFirmware = 0; -+ -+ BT_DBG("ath3k %p udev %p", data, data->udev); -+ -+ if ((usb_control_msg(data->udev, usb_rcvctrlpipe(data->udev, 0), -+ USB_REQ_GET_STATE, -+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -+ &ucFirmware, 1, USB_CTRL_SET_TIMEOUT)) < 0) { -+ BT_ERR("Can't change to loading configuration err"); -+ return -EBUSY; -+ } -+ -+ if (ucFirmware == USB_FIRMWARE_RAM_MODE) { -+ /* RAM based firmware is available in the target. -+ * No need to load the firmware to RAM */ -+ BT_DBG("RAM based firmware is available"); -+ return 0; -+ } -+ -+ pipe = usb_sndctrlpipe(data->udev, 0); -+ if ((usb_control_msg(data->udev, pipe, -+ USB_REQ_DFU_DNLOAD, -+ USB_TYPE_VENDOR, 0, 0, -+ firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { -+ BT_ERR("Can't change to loading configuration err"); -+ return -EBUSY; -+ } -+ sent += 20; -+ count -= 20; -+ -+ send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); -+ if (!send_buf) { -+ BT_ERR("Can't allocate memory chunk for firmware"); -+ return -ENOMEM; -+ } -+ -+ while (count) { -+ size = min_t(uint, count, BULK_SIZE); -+ pipe = usb_sndbulkpipe(data->udev, 0x02); -+ memcpy(send_buf, firmware + sent, size); -+ -+ err = usb_bulk_msg(data->udev, pipe, send_buf, size, -+ &len, 3000); -+ -+ if (err || (len != size)) { -+ BT_ERR("Error in firmware loading err = %d," -+ "len = %d, size = %d", err, len, size); -+ goto error; -+ } -+ -+ sent += size; -+ count -= size; -+ } -+ -+ kfree(send_buf); -+ return 0; -+ -+error: -+ kfree(send_buf); -+ return err; -+} -+ -+void *ath_fw_load(struct usb_interface *intf, -+ const char *fwfile, bool *suspend) -+{ -+ const struct firmware *firmware; -+ struct usb_device *udev = interface_to_usbdev(intf); -+ static struct firmware_data *data; -+ int size; -+ -+ BT_DBG("\nintf %p suspend %d\n", intf, *suspend); -+ -+ if (*suspend) { -+ load_firmware(data, data->fw_data, data->fw_size); -+ *suspend = 0; -+ return data; -+ } -+ -+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) -+ return NULL; -+ -+ data = kzalloc(sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return NULL; -+ data->udev = udev; -+ -+ if (request_firmware(&firmware, fwfile, &udev->dev) < 0) { -+ kfree(data); -+ return NULL; -+ } -+ -+ size = max_t(uint, firmware->size, 4096); -+ data->fw_data = kmalloc(size, GFP_KERNEL); -+ if (!data->fw_data) { -+ release_firmware(firmware); -+ kfree(data); -+ return NULL; -+ } -+ -+ memcpy(data->fw_data, firmware->data, firmware->size); -+ data->fw_size = firmware->size; -+ data->fw_sent = 0; -+ release_firmware(firmware); -+ -+ if (load_firmware(data, data->fw_data, data->fw_size)) { -+ kfree(data->fw_data); -+ kfree(data); -+ return NULL; -+ } -+ return data; -+} -+EXPORT_SYMBOL(ath_fw_load); -+ -+void ath_fw_unload(void *pdata, bool bsuspend) -+{ -+ struct firmware_data *data = (struct firmware_data *)pdata; -+ -+ if (data == NULL) -+ return; -+ -+ /* do not free the data on suspend as we will -+ * use it on resume */ -+ if (!bsuspend) { -+ kfree(data->fw_data); -+ kfree(data); -+ } -+} -+EXPORT_SYMBOL(ath_fw_unload); -+ -+static int __init fwload_init(void) -+{ -+ BT_INFO("Firmware load driver init. Version:%s", VERSION); -+ return 0; -+} -+ -+static void __exit fwload_deinit(void) -+{ -+ BT_INFO("Firmware load driver deinit"); -+} -+ -+module_init(fwload_init); -+module_exit(fwload_deinit); -+ -+MODULE_AUTHOR("Atheros Communications"); -+MODULE_DESCRIPTION("Firmware load driver"); -+MODULE_VERSION(VERSION); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/bluetooth/fwload.h -@@ -0,0 +1,39 @@ -+/* -+ * -+ * Generic Bluetooth USB DFU driver to download firmware to target RAM -+ * -+ * Copyright (c) 2009-2010 Atheros Communications Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+#ifndef _FWLOAD_H_ -+#define _FWLOAD_H_ -+ -+/* callbacks to load firmware to BT device RAM -+ * when it is inserted */ -+struct fw_cb_config { -+ const char *fwfile; -+ void * (*fwload)(struct usb_interface *intf, const char *fwfile, -+ bool *bsuspend); -+ void (*fwunload)(void *, bool); -+ const struct usb_device_id *usb_id_table; -+ void *data; -+ bool bsuspend; -+}; -+void *ath_fw_load(struct usb_interface *intf, const char *, bool *); -+void ath_fw_unload(void *pdata, bool bsuspend); -+ -+#endif /* _FWLOAD_H_ */ -- 2.30.2