diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-01 02:34:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-01 02:34:58 -0500 |
commit | 1e98cadb0d2b9f945f35beee4a0ce667f3c6dbe4 (patch) | |
tree | 0b5940be30331d461cd4421abe7829b392ab6e62 | |
parent | 71cc1fa9f2d71eb2eba9b8e71e27cff9863e55f3 (diff) | |
parent | 6bf8268f9a91f1065c99503161ebd061492bebe3 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
-rw-r--r-- | drivers/bluetooth/Kconfig | 13 | ||||
-rw-r--r-- | drivers/bluetooth/Makefile | 1 | ||||
-rw-r--r-- | drivers/bluetooth/ath3k.c | 187 | ||||
-rw-r--r-- | drivers/bluetooth/bluecard_cs.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/bt3c_cs.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/btuart_cs.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/dtl1_cs.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 70 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 14 |
9 files changed, 254 insertions, 47 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 652367aa6546..058fbccf2f52 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig | |||
@@ -195,5 +195,16 @@ config BT_MRVL_SDIO | |||
195 | Say Y here to compile support for Marvell BT-over-SDIO driver | 195 | Say Y here to compile support for Marvell BT-over-SDIO driver |
196 | into the kernel or say M to compile it as module. | 196 | into the kernel or say M to compile it as module. |
197 | 197 | ||
198 | endmenu | 198 | config BT_ATH3K |
199 | tristate "Atheros firmware download driver" | ||
200 | depends on BT_HCIBTUSB | ||
201 | select FW_LOADER | ||
202 | help | ||
203 | Bluetooth firmware download driver. | ||
204 | This driver loads the firmware into the Atheros Bluetooth | ||
205 | chipset. | ||
199 | 206 | ||
207 | Say Y here to compile support for "Atheros firmware download driver" | ||
208 | into the kernel or say M to compile it as module (ath3k). | ||
209 | |||
210 | endmenu | ||
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index b3f57d2d4eb0..7e5aed598121 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o | |||
15 | obj-$(CONFIG_BT_HCIBTUSB) += btusb.o | 15 | obj-$(CONFIG_BT_HCIBTUSB) += btusb.o |
16 | obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o | 16 | obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o |
17 | 17 | ||
18 | obj-$(CONFIG_BT_ATH3K) += ath3k.o | ||
18 | obj-$(CONFIG_BT_MRVL) += btmrvl.o | 19 | obj-$(CONFIG_BT_MRVL) += btmrvl.o |
19 | obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o | 20 | obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o |
20 | 21 | ||
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c new file mode 100644 index 000000000000..add9485ca5b6 --- /dev/null +++ b/drivers/bluetooth/ath3k.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <net/bluetooth/bluetooth.h> | ||
31 | |||
32 | #define VERSION "1.0" | ||
33 | |||
34 | |||
35 | static struct usb_device_id ath3k_table[] = { | ||
36 | /* Atheros AR3011 */ | ||
37 | { USB_DEVICE(0x0CF3, 0x3000) }, | ||
38 | { } /* Terminating entry */ | ||
39 | }; | ||
40 | |||
41 | MODULE_DEVICE_TABLE(usb, ath3k_table); | ||
42 | |||
43 | #define USB_REQ_DFU_DNLOAD 1 | ||
44 | #define BULK_SIZE 4096 | ||
45 | |||
46 | struct ath3k_data { | ||
47 | struct usb_device *udev; | ||
48 | u8 *fw_data; | ||
49 | u32 fw_size; | ||
50 | u32 fw_sent; | ||
51 | }; | ||
52 | |||
53 | static int ath3k_load_firmware(struct ath3k_data *data, | ||
54 | unsigned char *firmware, | ||
55 | int count) | ||
56 | { | ||
57 | u8 *send_buf; | ||
58 | int err, pipe, len, size, sent = 0; | ||
59 | |||
60 | BT_DBG("ath3k %p udev %p", data, data->udev); | ||
61 | |||
62 | pipe = usb_sndctrlpipe(data->udev, 0); | ||
63 | |||
64 | if ((usb_control_msg(data->udev, pipe, | ||
65 | USB_REQ_DFU_DNLOAD, | ||
66 | USB_TYPE_VENDOR, 0, 0, | ||
67 | firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { | ||
68 | BT_ERR("Can't change to loading configuration err"); | ||
69 | return -EBUSY; | ||
70 | } | ||
71 | sent += 20; | ||
72 | count -= 20; | ||
73 | |||
74 | send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); | ||
75 | if (!send_buf) { | ||
76 | BT_ERR("Can't allocate memory chunk for firmware"); | ||
77 | return -ENOMEM; | ||
78 | } | ||
79 | |||
80 | while (count) { | ||
81 | size = min_t(uint, count, BULK_SIZE); | ||
82 | pipe = usb_sndbulkpipe(data->udev, 0x02); | ||
83 | memcpy(send_buf, firmware + sent, size); | ||
84 | |||
85 | err = usb_bulk_msg(data->udev, pipe, send_buf, size, | ||
86 | &len, 3000); | ||
87 | |||
88 | if (err || (len != size)) { | ||
89 | BT_ERR("Error in firmware loading err = %d," | ||
90 | "len = %d, size = %d", err, len, size); | ||
91 | goto error; | ||
92 | } | ||
93 | |||
94 | sent += size; | ||
95 | count -= size; | ||
96 | } | ||
97 | |||
98 | kfree(send_buf); | ||
99 | return 0; | ||
100 | |||
101 | error: | ||
102 | kfree(send_buf); | ||
103 | return err; | ||
104 | } | ||
105 | |||
106 | static int ath3k_probe(struct usb_interface *intf, | ||
107 | const struct usb_device_id *id) | ||
108 | { | ||
109 | const struct firmware *firmware; | ||
110 | struct usb_device *udev = interface_to_usbdev(intf); | ||
111 | struct ath3k_data *data; | ||
112 | int size; | ||
113 | |||
114 | BT_DBG("intf %p id %p", intf, id); | ||
115 | |||
116 | if (intf->cur_altsetting->desc.bInterfaceNumber != 0) | ||
117 | return -ENODEV; | ||
118 | |||
119 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
120 | if (!data) | ||
121 | return -ENOMEM; | ||
122 | |||
123 | data->udev = udev; | ||
124 | |||
125 | if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { | ||
126 | kfree(data); | ||
127 | return -EIO; | ||
128 | } | ||
129 | |||
130 | size = max_t(uint, firmware->size, 4096); | ||
131 | data->fw_data = kmalloc(size, GFP_KERNEL); | ||
132 | if (!data->fw_data) { | ||
133 | release_firmware(firmware); | ||
134 | kfree(data); | ||
135 | return -ENOMEM; | ||
136 | } | ||
137 | |||
138 | memcpy(data->fw_data, firmware->data, firmware->size); | ||
139 | data->fw_size = firmware->size; | ||
140 | data->fw_sent = 0; | ||
141 | release_firmware(firmware); | ||
142 | |||
143 | usb_set_intfdata(intf, data); | ||
144 | if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { | ||
145 | usb_set_intfdata(intf, NULL); | ||
146 | return -EIO; | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void ath3k_disconnect(struct usb_interface *intf) | ||
153 | { | ||
154 | struct ath3k_data *data = usb_get_intfdata(intf); | ||
155 | |||
156 | BT_DBG("ath3k_disconnect intf %p", intf); | ||
157 | |||
158 | kfree(data->fw_data); | ||
159 | kfree(data); | ||
160 | } | ||
161 | |||
162 | static struct usb_driver ath3k_driver = { | ||
163 | .name = "ath3k", | ||
164 | .probe = ath3k_probe, | ||
165 | .disconnect = ath3k_disconnect, | ||
166 | .id_table = ath3k_table, | ||
167 | }; | ||
168 | |||
169 | static int __init ath3k_init(void) | ||
170 | { | ||
171 | BT_INFO("Atheros AR30xx firmware driver ver %s", VERSION); | ||
172 | return usb_register(&ath3k_driver); | ||
173 | } | ||
174 | |||
175 | static void __exit ath3k_exit(void) | ||
176 | { | ||
177 | usb_deregister(&ath3k_driver); | ||
178 | } | ||
179 | |||
180 | module_init(ath3k_init); | ||
181 | module_exit(ath3k_exit); | ||
182 | |||
183 | MODULE_AUTHOR("Atheros Communications"); | ||
184 | MODULE_DESCRIPTION("Atheros AR30xx firmware driver"); | ||
185 | MODULE_VERSION(VERSION); | ||
186 | MODULE_LICENSE("GPL"); | ||
187 | MODULE_FIRMWARE("ath3k-1.fw"); | ||
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 2acdc605cb4b..c2cf81144715 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -503,7 +503,9 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst) | |||
503 | unsigned int iobase; | 503 | unsigned int iobase; |
504 | unsigned char reg; | 504 | unsigned char reg; |
505 | 505 | ||
506 | BUG_ON(!info->hdev); | 506 | if (!info || !info->hdev) |
507 | /* our irq handler is shared */ | ||
508 | return IRQ_NONE; | ||
507 | 509 | ||
508 | if (!test_bit(CARD_READY, &(info->hw_state))) | 510 | if (!test_bit(CARD_READY, &(info->hw_state))) |
509 | return IRQ_HANDLED; | 511 | return IRQ_HANDLED; |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d814a2755ccb..9f5926aaf57f 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -345,7 +345,9 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst) | |||
345 | int iir; | 345 | int iir; |
346 | irqreturn_t r = IRQ_NONE; | 346 | irqreturn_t r = IRQ_NONE; |
347 | 347 | ||
348 | BUG_ON(!info->hdev); | 348 | if (!info || !info->hdev) |
349 | /* our irq handler is shared */ | ||
350 | return IRQ_NONE; | ||
349 | 351 | ||
350 | iobase = info->p_dev->io.BasePort1; | 352 | iobase = info->p_dev->io.BasePort1; |
351 | 353 | ||
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index d339464dc15e..91c523099804 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -295,7 +295,9 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst) | |||
295 | int iir, lsr; | 295 | int iir, lsr; |
296 | irqreturn_t r = IRQ_NONE; | 296 | irqreturn_t r = IRQ_NONE; |
297 | 297 | ||
298 | BUG_ON(!info->hdev); | 298 | if (!info || !info->hdev) |
299 | /* our irq handler is shared */ | ||
300 | return IRQ_NONE; | ||
299 | 301 | ||
300 | iobase = info->p_dev->io.BasePort1; | 302 | iobase = info->p_dev->io.BasePort1; |
301 | 303 | ||
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 4f02a6f3c980..697591941e17 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -299,7 +299,9 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) | |||
299 | int iir, lsr; | 299 | int iir, lsr; |
300 | irqreturn_t r = IRQ_NONE; | 300 | irqreturn_t r = IRQ_NONE; |
301 | 301 | ||
302 | BUG_ON(!info->hdev); | 302 | if (!info || !info->hdev) |
303 | /* our irq handler is shared */ | ||
304 | return IRQ_NONE; | ||
303 | 305 | ||
304 | iobase = info->p_dev->io.BasePort1; | 306 | iobase = info->p_dev->io.BasePort1; |
305 | 307 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 18e7f5a43dc4..6cf526d06e21 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -243,6 +243,39 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) | |||
243 | input_sync(dev); | 243 | input_sync(dev); |
244 | } | 244 | } |
245 | 245 | ||
246 | static int __hidp_send_ctrl_message(struct hidp_session *session, | ||
247 | unsigned char hdr, unsigned char *data, int size) | ||
248 | { | ||
249 | struct sk_buff *skb; | ||
250 | |||
251 | BT_DBG("session %p data %p size %d", session, data, size); | ||
252 | |||
253 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { | ||
254 | BT_ERR("Can't allocate memory for new frame"); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | *skb_put(skb, 1) = hdr; | ||
259 | if (data && size > 0) | ||
260 | memcpy(skb_put(skb, size), data, size); | ||
261 | |||
262 | skb_queue_tail(&session->ctrl_transmit, skb); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static inline int hidp_send_ctrl_message(struct hidp_session *session, | ||
268 | unsigned char hdr, unsigned char *data, int size) | ||
269 | { | ||
270 | int err; | ||
271 | |||
272 | err = __hidp_send_ctrl_message(session, hdr, data, size); | ||
273 | |||
274 | hidp_schedule(session); | ||
275 | |||
276 | return err; | ||
277 | } | ||
278 | |||
246 | static int hidp_queue_report(struct hidp_session *session, | 279 | static int hidp_queue_report(struct hidp_session *session, |
247 | unsigned char *data, int size) | 280 | unsigned char *data, int size) |
248 | { | 281 | { |
@@ -282,7 +315,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep | |||
282 | 315 | ||
283 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count) | 316 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count) |
284 | { | 317 | { |
285 | if (hidp_queue_report(hid->driver_data, data, count)) | 318 | if (hidp_send_ctrl_message(hid->driver_data, |
319 | HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE, | ||
320 | data, count)) | ||
286 | return -ENOMEM; | 321 | return -ENOMEM; |
287 | return count; | 322 | return count; |
288 | } | 323 | } |
@@ -307,39 +342,6 @@ static inline void hidp_del_timer(struct hidp_session *session) | |||
307 | del_timer(&session->timer); | 342 | del_timer(&session->timer); |
308 | } | 343 | } |
309 | 344 | ||
310 | static int __hidp_send_ctrl_message(struct hidp_session *session, | ||
311 | unsigned char hdr, unsigned char *data, int size) | ||
312 | { | ||
313 | struct sk_buff *skb; | ||
314 | |||
315 | BT_DBG("session %p data %p size %d", session, data, size); | ||
316 | |||
317 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { | ||
318 | BT_ERR("Can't allocate memory for new frame"); | ||
319 | return -ENOMEM; | ||
320 | } | ||
321 | |||
322 | *skb_put(skb, 1) = hdr; | ||
323 | if (data && size > 0) | ||
324 | memcpy(skb_put(skb, size), data, size); | ||
325 | |||
326 | skb_queue_tail(&session->ctrl_transmit, skb); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static inline int hidp_send_ctrl_message(struct hidp_session *session, | ||
332 | unsigned char hdr, unsigned char *data, int size) | ||
333 | { | ||
334 | int err; | ||
335 | |||
336 | err = __hidp_send_ctrl_message(session, hdr, data, size); | ||
337 | |||
338 | hidp_schedule(session); | ||
339 | |||
340 | return err; | ||
341 | } | ||
342 | |||
343 | static void hidp_process_handshake(struct hidp_session *session, | 345 | static void hidp_process_handshake(struct hidp_session *session, |
344 | unsigned char param) | 346 | unsigned char param) |
345 | { | 347 | { |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 1120cf14a548..400efa26ddba 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -1368,7 +1368,6 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1368 | 1368 | ||
1369 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && | 1369 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && |
1370 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { | 1370 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { |
1371 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1372 | 1371 | ||
1373 | if (pi->remote_max_tx && | 1372 | if (pi->remote_max_tx && |
1374 | bt_cb(skb)->retries == pi->remote_max_tx) { | 1373 | bt_cb(skb)->retries == pi->remote_max_tx) { |
@@ -1376,6 +1375,8 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1376 | break; | 1375 | break; |
1377 | } | 1376 | } |
1378 | 1377 | ||
1378 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1379 | |||
1379 | bt_cb(skb)->retries++; | 1380 | bt_cb(skb)->retries++; |
1380 | 1381 | ||
1381 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | 1382 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); |
@@ -3518,7 +3519,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3518 | struct l2cap_pinfo *pi; | 3519 | struct l2cap_pinfo *pi; |
3519 | u16 control, len; | 3520 | u16 control, len; |
3520 | u8 tx_seq; | 3521 | u8 tx_seq; |
3521 | int err; | ||
3522 | 3522 | ||
3523 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3523 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
3524 | if (!sk) { | 3524 | if (!sk) { |
@@ -3570,13 +3570,11 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3570 | goto drop; | 3570 | goto drop; |
3571 | 3571 | ||
3572 | if (__is_iframe(control)) | 3572 | if (__is_iframe(control)) |
3573 | err = l2cap_data_channel_iframe(sk, control, skb); | 3573 | l2cap_data_channel_iframe(sk, control, skb); |
3574 | else | 3574 | else |
3575 | err = l2cap_data_channel_sframe(sk, control, skb); | 3575 | l2cap_data_channel_sframe(sk, control, skb); |
3576 | 3576 | ||
3577 | if (!err) | 3577 | goto done; |
3578 | goto done; | ||
3579 | break; | ||
3580 | 3578 | ||
3581 | case L2CAP_MODE_STREAMING: | 3579 | case L2CAP_MODE_STREAMING: |
3582 | control = get_unaligned_le16(skb->data); | 3580 | control = get_unaligned_le16(skb->data); |
@@ -3602,7 +3600,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3602 | else | 3600 | else |
3603 | pi->expected_tx_seq = tx_seq + 1; | 3601 | pi->expected_tx_seq = tx_seq + 1; |
3604 | 3602 | ||
3605 | err = l2cap_sar_reassembly_sdu(sk, skb, control); | 3603 | l2cap_sar_reassembly_sdu(sk, skb, control); |
3606 | 3604 | ||
3607 | goto done; | 3605 | goto done; |
3608 | 3606 | ||