diff options
| -rw-r--r-- | drivers/bluetooth/ath3k.c | 75 |
1 files changed, 20 insertions, 55 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 949ed09c6361..a126e614601f 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
| @@ -47,46 +47,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | |||
| 47 | #define USB_REQ_DFU_DNLOAD 1 | 47 | #define USB_REQ_DFU_DNLOAD 1 |
| 48 | #define BULK_SIZE 4096 | 48 | #define BULK_SIZE 4096 |
| 49 | 49 | ||
| 50 | struct ath3k_data { | 50 | static int ath3k_load_firmware(struct usb_device *udev, |
| 51 | struct usb_device *udev; | 51 | const struct firmware *firmware) |
| 52 | u8 *fw_data; | ||
| 53 | u32 fw_size; | ||
| 54 | u32 fw_sent; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int ath3k_load_firmware(struct ath3k_data *data, | ||
| 58 | unsigned char *firmware, | ||
| 59 | int count) | ||
| 60 | { | 52 | { |
| 61 | u8 *send_buf; | 53 | u8 *send_buf; |
| 62 | int err, pipe, len, size, sent = 0; | 54 | int err, pipe, len, size, sent = 0; |
| 55 | int count = firmware->size; | ||
| 63 | 56 | ||
| 64 | BT_DBG("ath3k %p udev %p", data, data->udev); | 57 | BT_DBG("udev %p", udev); |
| 65 | 58 | ||
| 66 | pipe = usb_sndctrlpipe(data->udev, 0); | 59 | pipe = usb_sndctrlpipe(udev, 0); |
| 67 | 60 | ||
| 68 | if ((usb_control_msg(data->udev, pipe, | 61 | send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); |
| 62 | if (!send_buf) { | ||
| 63 | BT_ERR("Can't allocate memory chunk for firmware"); | ||
| 64 | return -ENOMEM; | ||
| 65 | } | ||
| 66 | |||
| 67 | memcpy(send_buf, firmware->data, 20); | ||
| 68 | if ((err = usb_control_msg(udev, pipe, | ||
| 69 | USB_REQ_DFU_DNLOAD, | 69 | USB_REQ_DFU_DNLOAD, |
| 70 | USB_TYPE_VENDOR, 0, 0, | 70 | USB_TYPE_VENDOR, 0, 0, |
| 71 | firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { | 71 | send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { |
| 72 | BT_ERR("Can't change to loading configuration err"); | 72 | BT_ERR("Can't change to loading configuration err"); |
| 73 | return -EBUSY; | 73 | goto error; |
| 74 | } | 74 | } |
| 75 | sent += 20; | 75 | sent += 20; |
| 76 | count -= 20; | 76 | count -= 20; |
| 77 | 77 | ||
| 78 | send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); | ||
| 79 | if (!send_buf) { | ||
| 80 | BT_ERR("Can't allocate memory chunk for firmware"); | ||
| 81 | return -ENOMEM; | ||
| 82 | } | ||
| 83 | |||
| 84 | while (count) { | 78 | while (count) { |
| 85 | size = min_t(uint, count, BULK_SIZE); | 79 | size = min_t(uint, count, BULK_SIZE); |
| 86 | pipe = usb_sndbulkpipe(data->udev, 0x02); | 80 | pipe = usb_sndbulkpipe(udev, 0x02); |
| 87 | memcpy(send_buf, firmware + sent, size); | 81 | memcpy(send_buf, firmware->data + sent, size); |
| 88 | 82 | ||
| 89 | err = usb_bulk_msg(data->udev, pipe, send_buf, size, | 83 | err = usb_bulk_msg(udev, pipe, send_buf, size, |
| 90 | &len, 3000); | 84 | &len, 3000); |
| 91 | 85 | ||
| 92 | if (err || (len != size)) { | 86 | if (err || (len != size)) { |
| @@ -112,57 +106,28 @@ static int ath3k_probe(struct usb_interface *intf, | |||
| 112 | { | 106 | { |
| 113 | const struct firmware *firmware; | 107 | const struct firmware *firmware; |
| 114 | struct usb_device *udev = interface_to_usbdev(intf); | 108 | struct usb_device *udev = interface_to_usbdev(intf); |
| 115 | struct ath3k_data *data; | ||
| 116 | int size; | ||
| 117 | 109 | ||
| 118 | BT_DBG("intf %p id %p", intf, id); | 110 | BT_DBG("intf %p id %p", intf, id); |
| 119 | 111 | ||
| 120 | if (intf->cur_altsetting->desc.bInterfaceNumber != 0) | 112 | if (intf->cur_altsetting->desc.bInterfaceNumber != 0) |
| 121 | return -ENODEV; | 113 | return -ENODEV; |
| 122 | 114 | ||
| 123 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 124 | if (!data) | ||
| 125 | return -ENOMEM; | ||
| 126 | |||
| 127 | data->udev = udev; | ||
| 128 | |||
| 129 | if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { | 115 | if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { |
| 130 | kfree(data); | ||
| 131 | return -EIO; | 116 | return -EIO; |
| 132 | } | 117 | } |
| 133 | 118 | ||
| 134 | size = max_t(uint, firmware->size, 4096); | 119 | if (ath3k_load_firmware(udev, firmware)) { |
| 135 | data->fw_data = kmalloc(size, GFP_KERNEL); | ||
| 136 | if (!data->fw_data) { | ||
| 137 | release_firmware(firmware); | 120 | release_firmware(firmware); |
| 138 | kfree(data); | ||
| 139 | return -ENOMEM; | ||
| 140 | } | ||
| 141 | |||
| 142 | memcpy(data->fw_data, firmware->data, firmware->size); | ||
| 143 | data->fw_size = firmware->size; | ||
| 144 | data->fw_sent = 0; | ||
| 145 | release_firmware(firmware); | ||
| 146 | |||
| 147 | usb_set_intfdata(intf, data); | ||
| 148 | if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { | ||
| 149 | usb_set_intfdata(intf, NULL); | ||
| 150 | kfree(data->fw_data); | ||
| 151 | kfree(data); | ||
| 152 | return -EIO; | 121 | return -EIO; |
| 153 | } | 122 | } |
| 123 | release_firmware(firmware); | ||
| 154 | 124 | ||
| 155 | return 0; | 125 | return 0; |
| 156 | } | 126 | } |
| 157 | 127 | ||
| 158 | static void ath3k_disconnect(struct usb_interface *intf) | 128 | static void ath3k_disconnect(struct usb_interface *intf) |
| 159 | { | 129 | { |
| 160 | struct ath3k_data *data = usb_get_intfdata(intf); | ||
| 161 | |||
| 162 | BT_DBG("ath3k_disconnect intf %p", intf); | 130 | BT_DBG("ath3k_disconnect intf %p", intf); |
| 163 | |||
| 164 | kfree(data->fw_data); | ||
| 165 | kfree(data); | ||
| 166 | } | 131 | } |
| 167 | 132 | ||
| 168 | static struct usb_driver ath3k_driver = { | 133 | static struct usb_driver ath3k_driver = { |
