diff options
Diffstat (limited to 'drivers/bluetooth/ath3k.c')
-rw-r--r-- | drivers/bluetooth/ath3k.c | 80 |
1 files changed, 25 insertions, 55 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 949ed09c6361..6dcd55a74c0a 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -39,6 +39,11 @@ static struct usb_device_id ath3k_table[] = { | |||
39 | /* Atheros AR3011 with sflash firmware*/ | 39 | /* Atheros AR3011 with sflash firmware*/ |
40 | { USB_DEVICE(0x0CF3, 0x3002) }, | 40 | { USB_DEVICE(0x0CF3, 0x3002) }, |
41 | 41 | ||
42 | /* Atheros AR9285 Malbec with sflash firmware */ | ||
43 | { USB_DEVICE(0x03F0, 0x311D) }, | ||
44 | |||
45 | /* Atheros AR5BBU12 with sflash firmware */ | ||
46 | { USB_DEVICE(0x0489, 0xE02C) }, | ||
42 | { } /* Terminating entry */ | 47 | { } /* Terminating entry */ |
43 | }; | 48 | }; |
44 | 49 | ||
@@ -47,46 +52,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | |||
47 | #define USB_REQ_DFU_DNLOAD 1 | 52 | #define USB_REQ_DFU_DNLOAD 1 |
48 | #define BULK_SIZE 4096 | 53 | #define BULK_SIZE 4096 |
49 | 54 | ||
50 | struct ath3k_data { | 55 | static int ath3k_load_firmware(struct usb_device *udev, |
51 | struct usb_device *udev; | 56 | 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 | { | 57 | { |
61 | u8 *send_buf; | 58 | u8 *send_buf; |
62 | int err, pipe, len, size, sent = 0; | 59 | int err, pipe, len, size, sent = 0; |
60 | int count = firmware->size; | ||
63 | 61 | ||
64 | BT_DBG("ath3k %p udev %p", data, data->udev); | 62 | BT_DBG("udev %p", udev); |
65 | 63 | ||
66 | pipe = usb_sndctrlpipe(data->udev, 0); | 64 | pipe = usb_sndctrlpipe(udev, 0); |
67 | 65 | ||
68 | if ((usb_control_msg(data->udev, pipe, | 66 | send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); |
67 | if (!send_buf) { | ||
68 | BT_ERR("Can't allocate memory chunk for firmware"); | ||
69 | return -ENOMEM; | ||
70 | } | ||
71 | |||
72 | memcpy(send_buf, firmware->data, 20); | ||
73 | if ((err = usb_control_msg(udev, pipe, | ||
69 | USB_REQ_DFU_DNLOAD, | 74 | USB_REQ_DFU_DNLOAD, |
70 | USB_TYPE_VENDOR, 0, 0, | 75 | USB_TYPE_VENDOR, 0, 0, |
71 | firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { | 76 | send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { |
72 | BT_ERR("Can't change to loading configuration err"); | 77 | BT_ERR("Can't change to loading configuration err"); |
73 | return -EBUSY; | 78 | goto error; |
74 | } | 79 | } |
75 | sent += 20; | 80 | sent += 20; |
76 | count -= 20; | 81 | count -= 20; |
77 | 82 | ||
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) { | 83 | while (count) { |
85 | size = min_t(uint, count, BULK_SIZE); | 84 | size = min_t(uint, count, BULK_SIZE); |
86 | pipe = usb_sndbulkpipe(data->udev, 0x02); | 85 | pipe = usb_sndbulkpipe(udev, 0x02); |
87 | memcpy(send_buf, firmware + sent, size); | 86 | memcpy(send_buf, firmware->data + sent, size); |
88 | 87 | ||
89 | err = usb_bulk_msg(data->udev, pipe, send_buf, size, | 88 | err = usb_bulk_msg(udev, pipe, send_buf, size, |
90 | &len, 3000); | 89 | &len, 3000); |
91 | 90 | ||
92 | if (err || (len != size)) { | 91 | if (err || (len != size)) { |
@@ -112,57 +111,28 @@ static int ath3k_probe(struct usb_interface *intf, | |||
112 | { | 111 | { |
113 | const struct firmware *firmware; | 112 | const struct firmware *firmware; |
114 | struct usb_device *udev = interface_to_usbdev(intf); | 113 | struct usb_device *udev = interface_to_usbdev(intf); |
115 | struct ath3k_data *data; | ||
116 | int size; | ||
117 | 114 | ||
118 | BT_DBG("intf %p id %p", intf, id); | 115 | BT_DBG("intf %p id %p", intf, id); |
119 | 116 | ||
120 | if (intf->cur_altsetting->desc.bInterfaceNumber != 0) | 117 | if (intf->cur_altsetting->desc.bInterfaceNumber != 0) |
121 | return -ENODEV; | 118 | return -ENODEV; |
122 | 119 | ||
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) { | 120 | if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { |
130 | kfree(data); | ||
131 | return -EIO; | 121 | return -EIO; |
132 | } | 122 | } |
133 | 123 | ||
134 | size = max_t(uint, firmware->size, 4096); | 124 | if (ath3k_load_firmware(udev, firmware)) { |
135 | data->fw_data = kmalloc(size, GFP_KERNEL); | ||
136 | if (!data->fw_data) { | ||
137 | release_firmware(firmware); | 125 | 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; | 126 | return -EIO; |
153 | } | 127 | } |
128 | release_firmware(firmware); | ||
154 | 129 | ||
155 | return 0; | 130 | return 0; |
156 | } | 131 | } |
157 | 132 | ||
158 | static void ath3k_disconnect(struct usb_interface *intf) | 133 | static void ath3k_disconnect(struct usb_interface *intf) |
159 | { | 134 | { |
160 | struct ath3k_data *data = usb_get_intfdata(intf); | ||
161 | |||
162 | BT_DBG("ath3k_disconnect intf %p", intf); | 135 | BT_DBG("ath3k_disconnect intf %p", intf); |
163 | |||
164 | kfree(data->fw_data); | ||
165 | kfree(data); | ||
166 | } | 136 | } |
167 | 137 | ||
168 | static struct usb_driver ath3k_driver = { | 138 | static struct usb_driver ath3k_driver = { |