diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bluetooth/Kconfig | 25 | ||||
-rw-r--r-- | drivers/bluetooth/Makefile | 6 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_debugfs.c | 432 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 139 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 624 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 1003 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.h | 108 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 198 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcsp.c | 3 |
9 files changed, 2514 insertions, 24 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 1164837bb781..652367aa6546 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig | |||
@@ -170,5 +170,30 @@ config BT_HCIVHCI | |||
170 | Say Y here to compile support for virtual HCI devices into the | 170 | Say Y here to compile support for virtual HCI devices into the |
171 | kernel or say M to compile it as module (hci_vhci). | 171 | kernel or say M to compile it as module (hci_vhci). |
172 | 172 | ||
173 | config BT_MRVL | ||
174 | tristate "Marvell Bluetooth driver support" | ||
175 | help | ||
176 | The core driver to support Marvell Bluetooth devices. | ||
177 | |||
178 | This driver is required if you want to support | ||
179 | Marvell Bluetooth devices, such as 8688. | ||
180 | |||
181 | Say Y here to compile Marvell Bluetooth driver | ||
182 | into the kernel or say M to compile it as module. | ||
183 | |||
184 | config BT_MRVL_SDIO | ||
185 | tristate "Marvell BT-over-SDIO driver" | ||
186 | depends on BT_MRVL && MMC | ||
187 | select FW_LOADER | ||
188 | help | ||
189 | The driver for Marvell Bluetooth chipsets with SDIO interface. | ||
190 | |||
191 | This driver is required if you want to use Marvell Bluetooth | ||
192 | devices with SDIO interface. Currently only SD8688 chipset is | ||
193 | supported. | ||
194 | |||
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. | ||
197 | |||
173 | endmenu | 198 | endmenu |
174 | 199 | ||
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 16930f93d1ca..b3f57d2d4eb0 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile | |||
@@ -15,6 +15,12 @@ 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_MRVL) += btmrvl.o | ||
19 | obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o | ||
20 | |||
21 | btmrvl-y := btmrvl_main.o | ||
22 | btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o | ||
23 | |||
18 | hci_uart-y := hci_ldisc.o | 24 | hci_uart-y := hci_ldisc.o |
19 | hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o | 25 | hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o |
20 | hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o | 26 | hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o |
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c new file mode 100644 index 000000000000..4617bd12f63b --- /dev/null +++ b/drivers/bluetooth/btmrvl_debugfs.c | |||
@@ -0,0 +1,432 @@ | |||
1 | /** | ||
2 | * Marvell Bluetooth driver: debugfs related functions | ||
3 | * | ||
4 | * Copyright (C) 2009, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | **/ | ||
20 | |||
21 | #include <linux/debugfs.h> | ||
22 | |||
23 | #include <net/bluetooth/bluetooth.h> | ||
24 | #include <net/bluetooth/hci_core.h> | ||
25 | |||
26 | #include "btmrvl_drv.h" | ||
27 | |||
28 | struct btmrvl_debugfs_data { | ||
29 | struct dentry *root_dir, *config_dir, *status_dir; | ||
30 | |||
31 | /* config */ | ||
32 | struct dentry *drvdbg; | ||
33 | struct dentry *psmode; | ||
34 | struct dentry *pscmd; | ||
35 | struct dentry *hsmode; | ||
36 | struct dentry *hscmd; | ||
37 | struct dentry *gpiogap; | ||
38 | struct dentry *hscfgcmd; | ||
39 | |||
40 | /* status */ | ||
41 | struct dentry *curpsmode; | ||
42 | struct dentry *hsstate; | ||
43 | struct dentry *psstate; | ||
44 | struct dentry *txdnldready; | ||
45 | }; | ||
46 | |||
47 | static int btmrvl_open_generic(struct inode *inode, struct file *file) | ||
48 | { | ||
49 | file->private_data = inode->i_private; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static ssize_t btmrvl_hscfgcmd_write(struct file *file, | ||
54 | const char __user *ubuf, size_t count, loff_t *ppos) | ||
55 | { | ||
56 | struct btmrvl_private *priv = file->private_data; | ||
57 | char buf[16]; | ||
58 | long result, ret; | ||
59 | |||
60 | memset(buf, 0, sizeof(buf)); | ||
61 | |||
62 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
63 | return -EFAULT; | ||
64 | |||
65 | ret = strict_strtol(buf, 10, &result); | ||
66 | |||
67 | priv->btmrvl_dev.hscfgcmd = result; | ||
68 | |||
69 | if (priv->btmrvl_dev.hscfgcmd) { | ||
70 | btmrvl_prepare_command(priv); | ||
71 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
72 | } | ||
73 | |||
74 | return count; | ||
75 | } | ||
76 | |||
77 | static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf, | ||
78 | size_t count, loff_t *ppos) | ||
79 | { | ||
80 | struct btmrvl_private *priv = file->private_data; | ||
81 | char buf[16]; | ||
82 | int ret; | ||
83 | |||
84 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", | ||
85 | priv->btmrvl_dev.hscfgcmd); | ||
86 | |||
87 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
88 | } | ||
89 | |||
90 | static const struct file_operations btmrvl_hscfgcmd_fops = { | ||
91 | .read = btmrvl_hscfgcmd_read, | ||
92 | .write = btmrvl_hscfgcmd_write, | ||
93 | .open = btmrvl_open_generic, | ||
94 | }; | ||
95 | |||
96 | static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf, | ||
97 | size_t count, loff_t *ppos) | ||
98 | { | ||
99 | struct btmrvl_private *priv = file->private_data; | ||
100 | char buf[16]; | ||
101 | long result, ret; | ||
102 | |||
103 | memset(buf, 0, sizeof(buf)); | ||
104 | |||
105 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
106 | return -EFAULT; | ||
107 | |||
108 | ret = strict_strtol(buf, 10, &result); | ||
109 | |||
110 | priv->btmrvl_dev.psmode = result; | ||
111 | |||
112 | return count; | ||
113 | } | ||
114 | |||
115 | static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf, | ||
116 | size_t count, loff_t *ppos) | ||
117 | { | ||
118 | struct btmrvl_private *priv = file->private_data; | ||
119 | char buf[16]; | ||
120 | int ret; | ||
121 | |||
122 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", | ||
123 | priv->btmrvl_dev.psmode); | ||
124 | |||
125 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
126 | } | ||
127 | |||
128 | static const struct file_operations btmrvl_psmode_fops = { | ||
129 | .read = btmrvl_psmode_read, | ||
130 | .write = btmrvl_psmode_write, | ||
131 | .open = btmrvl_open_generic, | ||
132 | }; | ||
133 | |||
134 | static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf, | ||
135 | size_t count, loff_t *ppos) | ||
136 | { | ||
137 | struct btmrvl_private *priv = file->private_data; | ||
138 | char buf[16]; | ||
139 | long result, ret; | ||
140 | |||
141 | memset(buf, 0, sizeof(buf)); | ||
142 | |||
143 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
144 | return -EFAULT; | ||
145 | |||
146 | ret = strict_strtol(buf, 10, &result); | ||
147 | |||
148 | priv->btmrvl_dev.pscmd = result; | ||
149 | |||
150 | if (priv->btmrvl_dev.pscmd) { | ||
151 | btmrvl_prepare_command(priv); | ||
152 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
153 | } | ||
154 | |||
155 | return count; | ||
156 | |||
157 | } | ||
158 | |||
159 | static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf, | ||
160 | size_t count, loff_t *ppos) | ||
161 | { | ||
162 | struct btmrvl_private *priv = file->private_data; | ||
163 | char buf[16]; | ||
164 | int ret; | ||
165 | |||
166 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd); | ||
167 | |||
168 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
169 | } | ||
170 | |||
171 | static const struct file_operations btmrvl_pscmd_fops = { | ||
172 | .read = btmrvl_pscmd_read, | ||
173 | .write = btmrvl_pscmd_write, | ||
174 | .open = btmrvl_open_generic, | ||
175 | }; | ||
176 | |||
177 | static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf, | ||
178 | size_t count, loff_t *ppos) | ||
179 | { | ||
180 | struct btmrvl_private *priv = file->private_data; | ||
181 | char buf[16]; | ||
182 | long result, ret; | ||
183 | |||
184 | memset(buf, 0, sizeof(buf)); | ||
185 | |||
186 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
187 | return -EFAULT; | ||
188 | |||
189 | ret = strict_strtol(buf, 16, &result); | ||
190 | |||
191 | priv->btmrvl_dev.gpio_gap = result; | ||
192 | |||
193 | return count; | ||
194 | } | ||
195 | |||
196 | static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf, | ||
197 | size_t count, loff_t *ppos) | ||
198 | { | ||
199 | struct btmrvl_private *priv = file->private_data; | ||
200 | char buf[16]; | ||
201 | int ret; | ||
202 | |||
203 | ret = snprintf(buf, sizeof(buf) - 1, "0x%x\n", | ||
204 | priv->btmrvl_dev.gpio_gap); | ||
205 | |||
206 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
207 | } | ||
208 | |||
209 | static const struct file_operations btmrvl_gpiogap_fops = { | ||
210 | .read = btmrvl_gpiogap_read, | ||
211 | .write = btmrvl_gpiogap_write, | ||
212 | .open = btmrvl_open_generic, | ||
213 | }; | ||
214 | |||
215 | static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf, | ||
216 | size_t count, loff_t *ppos) | ||
217 | { | ||
218 | struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data; | ||
219 | char buf[16]; | ||
220 | long result, ret; | ||
221 | |||
222 | memset(buf, 0, sizeof(buf)); | ||
223 | |||
224 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
225 | return -EFAULT; | ||
226 | |||
227 | ret = strict_strtol(buf, 10, &result); | ||
228 | |||
229 | priv->btmrvl_dev.hscmd = result; | ||
230 | if (priv->btmrvl_dev.hscmd) { | ||
231 | btmrvl_prepare_command(priv); | ||
232 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
233 | } | ||
234 | |||
235 | return count; | ||
236 | } | ||
237 | |||
238 | static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf, | ||
239 | size_t count, loff_t *ppos) | ||
240 | { | ||
241 | struct btmrvl_private *priv = file->private_data; | ||
242 | char buf[16]; | ||
243 | int ret; | ||
244 | |||
245 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd); | ||
246 | |||
247 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
248 | } | ||
249 | |||
250 | static const struct file_operations btmrvl_hscmd_fops = { | ||
251 | .read = btmrvl_hscmd_read, | ||
252 | .write = btmrvl_hscmd_write, | ||
253 | .open = btmrvl_open_generic, | ||
254 | }; | ||
255 | |||
256 | static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf, | ||
257 | size_t count, loff_t *ppos) | ||
258 | { | ||
259 | struct btmrvl_private *priv = file->private_data; | ||
260 | char buf[16]; | ||
261 | long result, ret; | ||
262 | |||
263 | memset(buf, 0, sizeof(buf)); | ||
264 | |||
265 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
266 | return -EFAULT; | ||
267 | |||
268 | ret = strict_strtol(buf, 10, &result); | ||
269 | |||
270 | priv->btmrvl_dev.hsmode = result; | ||
271 | |||
272 | return count; | ||
273 | } | ||
274 | |||
275 | static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf, | ||
276 | size_t count, loff_t *ppos) | ||
277 | { | ||
278 | struct btmrvl_private *priv = file->private_data; | ||
279 | char buf[16]; | ||
280 | int ret; | ||
281 | |||
282 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hsmode); | ||
283 | |||
284 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
285 | } | ||
286 | |||
287 | static const struct file_operations btmrvl_hsmode_fops = { | ||
288 | .read = btmrvl_hsmode_read, | ||
289 | .write = btmrvl_hsmode_write, | ||
290 | .open = btmrvl_open_generic, | ||
291 | }; | ||
292 | |||
293 | static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf, | ||
294 | size_t count, loff_t *ppos) | ||
295 | { | ||
296 | struct btmrvl_private *priv = file->private_data; | ||
297 | char buf[16]; | ||
298 | int ret; | ||
299 | |||
300 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->psmode); | ||
301 | |||
302 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
303 | } | ||
304 | |||
305 | static const struct file_operations btmrvl_curpsmode_fops = { | ||
306 | .read = btmrvl_curpsmode_read, | ||
307 | .open = btmrvl_open_generic, | ||
308 | }; | ||
309 | |||
310 | static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf, | ||
311 | size_t count, loff_t *ppos) | ||
312 | { | ||
313 | struct btmrvl_private *priv = file->private_data; | ||
314 | char buf[16]; | ||
315 | int ret; | ||
316 | |||
317 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->ps_state); | ||
318 | |||
319 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
320 | } | ||
321 | |||
322 | static const struct file_operations btmrvl_psstate_fops = { | ||
323 | .read = btmrvl_psstate_read, | ||
324 | .open = btmrvl_open_generic, | ||
325 | }; | ||
326 | |||
327 | static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf, | ||
328 | size_t count, loff_t *ppos) | ||
329 | { | ||
330 | struct btmrvl_private *priv = file->private_data; | ||
331 | char buf[16]; | ||
332 | int ret; | ||
333 | |||
334 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->hs_state); | ||
335 | |||
336 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
337 | } | ||
338 | |||
339 | static const struct file_operations btmrvl_hsstate_fops = { | ||
340 | .read = btmrvl_hsstate_read, | ||
341 | .open = btmrvl_open_generic, | ||
342 | }; | ||
343 | |||
344 | static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf, | ||
345 | size_t count, loff_t *ppos) | ||
346 | { | ||
347 | struct btmrvl_private *priv = file->private_data; | ||
348 | char buf[16]; | ||
349 | int ret; | ||
350 | |||
351 | ret = snprintf(buf, sizeof(buf) - 1, "%d\n", | ||
352 | priv->btmrvl_dev.tx_dnld_rdy); | ||
353 | |||
354 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
355 | } | ||
356 | |||
357 | static const struct file_operations btmrvl_txdnldready_fops = { | ||
358 | .read = btmrvl_txdnldready_read, | ||
359 | .open = btmrvl_open_generic, | ||
360 | }; | ||
361 | |||
362 | void btmrvl_debugfs_init(struct hci_dev *hdev) | ||
363 | { | ||
364 | struct btmrvl_private *priv = hdev->driver_data; | ||
365 | struct btmrvl_debugfs_data *dbg; | ||
366 | |||
367 | dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); | ||
368 | priv->debugfs_data = dbg; | ||
369 | |||
370 | if (!dbg) { | ||
371 | BT_ERR("Can not allocate memory for btmrvl_debugfs_data."); | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | dbg->root_dir = debugfs_create_dir("btmrvl", NULL); | ||
376 | |||
377 | dbg->config_dir = debugfs_create_dir("config", dbg->root_dir); | ||
378 | |||
379 | dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir, | ||
380 | hdev->driver_data, &btmrvl_psmode_fops); | ||
381 | dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir, | ||
382 | hdev->driver_data, &btmrvl_pscmd_fops); | ||
383 | dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir, | ||
384 | hdev->driver_data, &btmrvl_gpiogap_fops); | ||
385 | dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir, | ||
386 | hdev->driver_data, &btmrvl_hsmode_fops); | ||
387 | dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir, | ||
388 | hdev->driver_data, &btmrvl_hscmd_fops); | ||
389 | dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, | ||
390 | hdev->driver_data, &btmrvl_hscfgcmd_fops); | ||
391 | |||
392 | dbg->status_dir = debugfs_create_dir("status", dbg->root_dir); | ||
393 | dbg->curpsmode = debugfs_create_file("curpsmode", 0444, | ||
394 | dbg->status_dir, | ||
395 | hdev->driver_data, | ||
396 | &btmrvl_curpsmode_fops); | ||
397 | dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir, | ||
398 | hdev->driver_data, &btmrvl_psstate_fops); | ||
399 | dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir, | ||
400 | hdev->driver_data, &btmrvl_hsstate_fops); | ||
401 | dbg->txdnldready = debugfs_create_file("txdnldready", 0444, | ||
402 | dbg->status_dir, | ||
403 | hdev->driver_data, | ||
404 | &btmrvl_txdnldready_fops); | ||
405 | } | ||
406 | |||
407 | void btmrvl_debugfs_remove(struct hci_dev *hdev) | ||
408 | { | ||
409 | struct btmrvl_private *priv = hdev->driver_data; | ||
410 | struct btmrvl_debugfs_data *dbg = priv->debugfs_data; | ||
411 | |||
412 | if (!dbg) | ||
413 | return; | ||
414 | |||
415 | debugfs_remove(dbg->psmode); | ||
416 | debugfs_remove(dbg->pscmd); | ||
417 | debugfs_remove(dbg->gpiogap); | ||
418 | debugfs_remove(dbg->hsmode); | ||
419 | debugfs_remove(dbg->hscmd); | ||
420 | debugfs_remove(dbg->hscfgcmd); | ||
421 | debugfs_remove(dbg->config_dir); | ||
422 | |||
423 | debugfs_remove(dbg->curpsmode); | ||
424 | debugfs_remove(dbg->psstate); | ||
425 | debugfs_remove(dbg->hsstate); | ||
426 | debugfs_remove(dbg->txdnldready); | ||
427 | debugfs_remove(dbg->status_dir); | ||
428 | |||
429 | debugfs_remove(dbg->root_dir); | ||
430 | |||
431 | kfree(dbg); | ||
432 | } | ||
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h new file mode 100644 index 000000000000..411c7a77082d --- /dev/null +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Marvell Bluetooth driver: global definitions & declarations | ||
3 | * | ||
4 | * Copyright (C) 2009, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kthread.h> | ||
23 | #include <linux/bitops.h> | ||
24 | #include <net/bluetooth/bluetooth.h> | ||
25 | |||
26 | #define BTM_HEADER_LEN 4 | ||
27 | #define BTM_UPLD_SIZE 2312 | ||
28 | |||
29 | /* Time to wait until Host Sleep state change in millisecond */ | ||
30 | #define WAIT_UNTIL_HS_STATE_CHANGED 5000 | ||
31 | /* Time to wait for command response in millisecond */ | ||
32 | #define WAIT_UNTIL_CMD_RESP 5000 | ||
33 | |||
34 | struct btmrvl_thread { | ||
35 | struct task_struct *task; | ||
36 | wait_queue_head_t wait_q; | ||
37 | void *priv; | ||
38 | }; | ||
39 | |||
40 | struct btmrvl_device { | ||
41 | void *card; | ||
42 | struct hci_dev *hcidev; | ||
43 | |||
44 | u8 tx_dnld_rdy; | ||
45 | |||
46 | u8 psmode; | ||
47 | u8 pscmd; | ||
48 | u8 hsmode; | ||
49 | u8 hscmd; | ||
50 | |||
51 | /* Low byte is gap, high byte is GPIO */ | ||
52 | u16 gpio_gap; | ||
53 | |||
54 | u8 hscfgcmd; | ||
55 | u8 sendcmdflag; | ||
56 | }; | ||
57 | |||
58 | struct btmrvl_adapter { | ||
59 | u32 int_count; | ||
60 | struct sk_buff_head tx_queue; | ||
61 | u8 psmode; | ||
62 | u8 ps_state; | ||
63 | u8 hs_state; | ||
64 | u8 wakeup_tries; | ||
65 | wait_queue_head_t cmd_wait_q; | ||
66 | u8 cmd_complete; | ||
67 | }; | ||
68 | |||
69 | struct btmrvl_private { | ||
70 | struct btmrvl_device btmrvl_dev; | ||
71 | struct btmrvl_adapter *adapter; | ||
72 | struct btmrvl_thread main_thread; | ||
73 | int (*hw_host_to_card) (struct btmrvl_private *priv, | ||
74 | u8 *payload, u16 nb); | ||
75 | int (*hw_wakeup_firmware) (struct btmrvl_private *priv); | ||
76 | spinlock_t driver_lock; /* spinlock used by driver */ | ||
77 | #ifdef CONFIG_DEBUG_FS | ||
78 | void *debugfs_data; | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | #define MRVL_VENDOR_PKT 0xFE | ||
83 | |||
84 | /* Bluetooth commands */ | ||
85 | #define BT_CMD_AUTO_SLEEP_MODE 0x23 | ||
86 | #define BT_CMD_HOST_SLEEP_CONFIG 0x59 | ||
87 | #define BT_CMD_HOST_SLEEP_ENABLE 0x5A | ||
88 | #define BT_CMD_MODULE_CFG_REQ 0x5B | ||
89 | |||
90 | /* Sub-commands: Module Bringup/Shutdown Request */ | ||
91 | #define MODULE_BRINGUP_REQ 0xF1 | ||
92 | #define MODULE_SHUTDOWN_REQ 0xF2 | ||
93 | |||
94 | #define BT_EVENT_POWER_STATE 0x20 | ||
95 | |||
96 | /* Bluetooth Power States */ | ||
97 | #define BT_PS_ENABLE 0x02 | ||
98 | #define BT_PS_DISABLE 0x03 | ||
99 | #define BT_PS_SLEEP 0x01 | ||
100 | |||
101 | #define OGF 0x3F | ||
102 | |||
103 | /* Host Sleep states */ | ||
104 | #define HS_ACTIVATED 0x01 | ||
105 | #define HS_DEACTIVATED 0x00 | ||
106 | |||
107 | /* Power Save modes */ | ||
108 | #define PS_SLEEP 0x01 | ||
109 | #define PS_AWAKE 0x00 | ||
110 | |||
111 | struct btmrvl_cmd { | ||
112 | __le16 ocf_ogf; | ||
113 | u8 length; | ||
114 | u8 data[4]; | ||
115 | } __attribute__ ((packed)); | ||
116 | |||
117 | struct btmrvl_event { | ||
118 | u8 ec; /* event counter */ | ||
119 | u8 length; | ||
120 | u8 data[4]; | ||
121 | } __attribute__ ((packed)); | ||
122 | |||
123 | /* Prototype of global function */ | ||
124 | |||
125 | struct btmrvl_private *btmrvl_add_card(void *card); | ||
126 | int btmrvl_remove_card(struct btmrvl_private *priv); | ||
127 | |||
128 | void btmrvl_interrupt(struct btmrvl_private *priv); | ||
129 | |||
130 | void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); | ||
131 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); | ||
132 | |||
133 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); | ||
134 | int btmrvl_prepare_command(struct btmrvl_private *priv); | ||
135 | |||
136 | #ifdef CONFIG_DEBUG_FS | ||
137 | void btmrvl_debugfs_init(struct hci_dev *hdev); | ||
138 | void btmrvl_debugfs_remove(struct hci_dev *hdev); | ||
139 | #endif | ||
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c new file mode 100644 index 000000000000..e605563b4eaa --- /dev/null +++ b/drivers/bluetooth/btmrvl_main.c | |||
@@ -0,0 +1,624 @@ | |||
1 | /** | ||
2 | * Marvell Bluetooth driver | ||
3 | * | ||
4 | * Copyright (C) 2009, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | **/ | ||
20 | |||
21 | #include <net/bluetooth/bluetooth.h> | ||
22 | #include <net/bluetooth/hci_core.h> | ||
23 | |||
24 | #include "btmrvl_drv.h" | ||
25 | |||
26 | #define VERSION "1.0" | ||
27 | |||
28 | /* | ||
29 | * This function is called by interface specific interrupt handler. | ||
30 | * It updates Power Save & Host Sleep states, and wakes up the main | ||
31 | * thread. | ||
32 | */ | ||
33 | void btmrvl_interrupt(struct btmrvl_private *priv) | ||
34 | { | ||
35 | priv->adapter->ps_state = PS_AWAKE; | ||
36 | |||
37 | priv->adapter->wakeup_tries = 0; | ||
38 | |||
39 | priv->adapter->int_count++; | ||
40 | |||
41 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(btmrvl_interrupt); | ||
44 | |||
45 | void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) | ||
46 | { | ||
47 | struct hci_event_hdr *hdr = (void *) skb->data; | ||
48 | struct hci_ev_cmd_complete *ec; | ||
49 | u16 opcode, ocf; | ||
50 | |||
51 | if (hdr->evt == HCI_EV_CMD_COMPLETE) { | ||
52 | ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE); | ||
53 | opcode = __le16_to_cpu(ec->opcode); | ||
54 | ocf = hci_opcode_ocf(opcode); | ||
55 | if (ocf == BT_CMD_MODULE_CFG_REQ && | ||
56 | priv->btmrvl_dev.sendcmdflag) { | ||
57 | priv->btmrvl_dev.sendcmdflag = false; | ||
58 | priv->adapter->cmd_complete = true; | ||
59 | wake_up_interruptible(&priv->adapter->cmd_wait_q); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt); | ||
64 | |||
65 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) | ||
66 | { | ||
67 | struct btmrvl_adapter *adapter = priv->adapter; | ||
68 | struct btmrvl_event *event; | ||
69 | u8 ret = 0; | ||
70 | |||
71 | event = (struct btmrvl_event *) skb->data; | ||
72 | if (event->ec != 0xff) { | ||
73 | BT_DBG("Not Marvell Event=%x", event->ec); | ||
74 | ret = -EINVAL; | ||
75 | goto exit; | ||
76 | } | ||
77 | |||
78 | switch (event->data[0]) { | ||
79 | case BT_CMD_AUTO_SLEEP_MODE: | ||
80 | if (!event->data[2]) { | ||
81 | if (event->data[1] == BT_PS_ENABLE) | ||
82 | adapter->psmode = 1; | ||
83 | else | ||
84 | adapter->psmode = 0; | ||
85 | BT_DBG("PS Mode:%s", | ||
86 | (adapter->psmode) ? "Enable" : "Disable"); | ||
87 | } else { | ||
88 | BT_DBG("PS Mode command failed"); | ||
89 | } | ||
90 | break; | ||
91 | |||
92 | case BT_CMD_HOST_SLEEP_CONFIG: | ||
93 | if (!event->data[3]) | ||
94 | BT_DBG("gpio=%x, gap=%x", event->data[1], | ||
95 | event->data[2]); | ||
96 | else | ||
97 | BT_DBG("HSCFG command failed"); | ||
98 | break; | ||
99 | |||
100 | case BT_CMD_HOST_SLEEP_ENABLE: | ||
101 | if (!event->data[1]) { | ||
102 | adapter->hs_state = HS_ACTIVATED; | ||
103 | if (adapter->psmode) | ||
104 | adapter->ps_state = PS_SLEEP; | ||
105 | wake_up_interruptible(&adapter->cmd_wait_q); | ||
106 | BT_DBG("HS ACTIVATED!"); | ||
107 | } else { | ||
108 | BT_DBG("HS Enable failed"); | ||
109 | } | ||
110 | break; | ||
111 | |||
112 | case BT_CMD_MODULE_CFG_REQ: | ||
113 | if (priv->btmrvl_dev.sendcmdflag && | ||
114 | event->data[1] == MODULE_BRINGUP_REQ) { | ||
115 | BT_DBG("EVENT:%s", (event->data[2]) ? | ||
116 | "Bring-up failed" : "Bring-up succeed"); | ||
117 | } else if (priv->btmrvl_dev.sendcmdflag && | ||
118 | event->data[1] == MODULE_SHUTDOWN_REQ) { | ||
119 | BT_DBG("EVENT:%s", (event->data[2]) ? | ||
120 | "Shutdown failed" : "Shutdown succeed"); | ||
121 | } else { | ||
122 | BT_DBG("BT_CMD_MODULE_CFG_REQ resp for APP"); | ||
123 | ret = -EINVAL; | ||
124 | } | ||
125 | break; | ||
126 | |||
127 | case BT_EVENT_POWER_STATE: | ||
128 | if (event->data[1] == BT_PS_SLEEP) | ||
129 | adapter->ps_state = PS_SLEEP; | ||
130 | BT_DBG("EVENT:%s", | ||
131 | (adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE"); | ||
132 | break; | ||
133 | |||
134 | default: | ||
135 | BT_DBG("Unknown Event=%d", event->data[0]); | ||
136 | ret = -EINVAL; | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | exit: | ||
141 | if (!ret) | ||
142 | kfree_skb(skb); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(btmrvl_process_event); | ||
147 | |||
148 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | ||
149 | { | ||
150 | struct sk_buff *skb; | ||
151 | struct btmrvl_cmd *cmd; | ||
152 | int ret = 0; | ||
153 | |||
154 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
155 | if (skb == NULL) { | ||
156 | BT_ERR("No free skb"); | ||
157 | return -ENOMEM; | ||
158 | } | ||
159 | |||
160 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
161 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ)); | ||
162 | cmd->length = 1; | ||
163 | cmd->data[0] = subcmd; | ||
164 | |||
165 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
166 | |||
167 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
168 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
169 | |||
170 | priv->btmrvl_dev.sendcmdflag = true; | ||
171 | |||
172 | priv->adapter->cmd_complete = false; | ||
173 | |||
174 | BT_DBG("Queue module cfg Command"); | ||
175 | |||
176 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
177 | |||
178 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, | ||
179 | priv->adapter->cmd_complete, | ||
180 | msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) { | ||
181 | ret = -ETIMEDOUT; | ||
182 | BT_ERR("module_cfg_cmd(%x): timeout: %d", | ||
183 | subcmd, priv->btmrvl_dev.sendcmdflag); | ||
184 | } | ||
185 | |||
186 | BT_DBG("module cfg Command done"); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); | ||
191 | |||
192 | static int btmrvl_enable_hs(struct btmrvl_private *priv) | ||
193 | { | ||
194 | struct sk_buff *skb; | ||
195 | struct btmrvl_cmd *cmd; | ||
196 | int ret = 0; | ||
197 | |||
198 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
199 | if (skb == NULL) { | ||
200 | BT_ERR("No free skb"); | ||
201 | return -ENOMEM; | ||
202 | } | ||
203 | |||
204 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
205 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE)); | ||
206 | cmd->length = 0; | ||
207 | |||
208 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
209 | |||
210 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
211 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
212 | |||
213 | BT_DBG("Queue hs enable Command"); | ||
214 | |||
215 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
216 | |||
217 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, | ||
218 | priv->adapter->hs_state, | ||
219 | msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) { | ||
220 | ret = -ETIMEDOUT; | ||
221 | BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state, | ||
222 | priv->adapter->ps_state, | ||
223 | priv->adapter->wakeup_tries); | ||
224 | } | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | int btmrvl_prepare_command(struct btmrvl_private *priv) | ||
230 | { | ||
231 | struct sk_buff *skb = NULL; | ||
232 | struct btmrvl_cmd *cmd; | ||
233 | int ret = 0; | ||
234 | |||
235 | if (priv->btmrvl_dev.hscfgcmd) { | ||
236 | priv->btmrvl_dev.hscfgcmd = 0; | ||
237 | |||
238 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
239 | if (skb == NULL) { | ||
240 | BT_ERR("No free skb"); | ||
241 | return -ENOMEM; | ||
242 | } | ||
243 | |||
244 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
245 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); | ||
246 | cmd->length = 2; | ||
247 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
248 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
249 | |||
250 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
251 | |||
252 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
253 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
254 | |||
255 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", | ||
256 | cmd->data[0], cmd->data[1]); | ||
257 | } | ||
258 | |||
259 | if (priv->btmrvl_dev.pscmd) { | ||
260 | priv->btmrvl_dev.pscmd = 0; | ||
261 | |||
262 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
263 | if (skb == NULL) { | ||
264 | BT_ERR("No free skb"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
269 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE)); | ||
270 | cmd->length = 1; | ||
271 | |||
272 | if (priv->btmrvl_dev.psmode) | ||
273 | cmd->data[0] = BT_PS_ENABLE; | ||
274 | else | ||
275 | cmd->data[0] = BT_PS_DISABLE; | ||
276 | |||
277 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
278 | |||
279 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
280 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
281 | |||
282 | BT_DBG("Queue PSMODE Command:%d", cmd->data[0]); | ||
283 | } | ||
284 | |||
285 | if (priv->btmrvl_dev.hscmd) { | ||
286 | priv->btmrvl_dev.hscmd = 0; | ||
287 | |||
288 | if (priv->btmrvl_dev.hsmode) { | ||
289 | ret = btmrvl_enable_hs(priv); | ||
290 | } else { | ||
291 | ret = priv->hw_wakeup_firmware(priv); | ||
292 | priv->adapter->hs_state = HS_DEACTIVATED; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb) | ||
300 | { | ||
301 | int ret = 0; | ||
302 | |||
303 | if (!skb || !skb->data) | ||
304 | return -EINVAL; | ||
305 | |||
306 | if (!skb->len || ((skb->len + BTM_HEADER_LEN) > BTM_UPLD_SIZE)) { | ||
307 | BT_ERR("Tx Error: Bad skb length %d : %d", | ||
308 | skb->len, BTM_UPLD_SIZE); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | if (skb_headroom(skb) < BTM_HEADER_LEN) { | ||
313 | struct sk_buff *tmp = skb; | ||
314 | |||
315 | skb = skb_realloc_headroom(skb, BTM_HEADER_LEN); | ||
316 | if (!skb) { | ||
317 | BT_ERR("Tx Error: realloc_headroom failed %d", | ||
318 | BTM_HEADER_LEN); | ||
319 | skb = tmp; | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | kfree_skb(tmp); | ||
324 | } | ||
325 | |||
326 | skb_push(skb, BTM_HEADER_LEN); | ||
327 | |||
328 | /* header type: byte[3] | ||
329 | * HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor | ||
330 | * header length: byte[2][1][0] | ||
331 | */ | ||
332 | |||
333 | skb->data[0] = (skb->len & 0x0000ff); | ||
334 | skb->data[1] = (skb->len & 0x00ff00) >> 8; | ||
335 | skb->data[2] = (skb->len & 0xff0000) >> 16; | ||
336 | skb->data[3] = bt_cb(skb)->pkt_type; | ||
337 | |||
338 | if (priv->hw_host_to_card) | ||
339 | ret = priv->hw_host_to_card(priv, skb->data, skb->len); | ||
340 | |||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | static void btmrvl_init_adapter(struct btmrvl_private *priv) | ||
345 | { | ||
346 | skb_queue_head_init(&priv->adapter->tx_queue); | ||
347 | |||
348 | priv->adapter->ps_state = PS_AWAKE; | ||
349 | |||
350 | init_waitqueue_head(&priv->adapter->cmd_wait_q); | ||
351 | } | ||
352 | |||
353 | static void btmrvl_free_adapter(struct btmrvl_private *priv) | ||
354 | { | ||
355 | skb_queue_purge(&priv->adapter->tx_queue); | ||
356 | |||
357 | kfree(priv->adapter); | ||
358 | |||
359 | priv->adapter = NULL; | ||
360 | } | ||
361 | |||
362 | static int btmrvl_ioctl(struct hci_dev *hdev, | ||
363 | unsigned int cmd, unsigned long arg) | ||
364 | { | ||
365 | return -ENOIOCTLCMD; | ||
366 | } | ||
367 | |||
368 | static void btmrvl_destruct(struct hci_dev *hdev) | ||
369 | { | ||
370 | } | ||
371 | |||
372 | static int btmrvl_send_frame(struct sk_buff *skb) | ||
373 | { | ||
374 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
375 | struct btmrvl_private *priv = NULL; | ||
376 | |||
377 | BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); | ||
378 | |||
379 | if (!hdev || !hdev->driver_data) { | ||
380 | BT_ERR("Frame for unknown HCI device"); | ||
381 | return -ENODEV; | ||
382 | } | ||
383 | |||
384 | priv = (struct btmrvl_private *) hdev->driver_data; | ||
385 | if (!test_bit(HCI_RUNNING, &hdev->flags)) { | ||
386 | BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags); | ||
387 | print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET, | ||
388 | skb->data, skb->len); | ||
389 | return -EBUSY; | ||
390 | } | ||
391 | |||
392 | switch (bt_cb(skb)->pkt_type) { | ||
393 | case HCI_COMMAND_PKT: | ||
394 | hdev->stat.cmd_tx++; | ||
395 | break; | ||
396 | |||
397 | case HCI_ACLDATA_PKT: | ||
398 | hdev->stat.acl_tx++; | ||
399 | break; | ||
400 | |||
401 | case HCI_SCODATA_PKT: | ||
402 | hdev->stat.sco_tx++; | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | skb_queue_tail(&priv->adapter->tx_queue, skb); | ||
407 | |||
408 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int btmrvl_flush(struct hci_dev *hdev) | ||
414 | { | ||
415 | struct btmrvl_private *priv = hdev->driver_data; | ||
416 | |||
417 | skb_queue_purge(&priv->adapter->tx_queue); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int btmrvl_close(struct hci_dev *hdev) | ||
423 | { | ||
424 | struct btmrvl_private *priv = hdev->driver_data; | ||
425 | |||
426 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
427 | return 0; | ||
428 | |||
429 | skb_queue_purge(&priv->adapter->tx_queue); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int btmrvl_open(struct hci_dev *hdev) | ||
435 | { | ||
436 | set_bit(HCI_RUNNING, &hdev->flags); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * This function handles the event generated by firmware, rx data | ||
443 | * received from firmware, and tx data sent from kernel. | ||
444 | */ | ||
445 | static int btmrvl_service_main_thread(void *data) | ||
446 | { | ||
447 | struct btmrvl_thread *thread = data; | ||
448 | struct btmrvl_private *priv = thread->priv; | ||
449 | struct btmrvl_adapter *adapter = priv->adapter; | ||
450 | wait_queue_t wait; | ||
451 | struct sk_buff *skb; | ||
452 | ulong flags; | ||
453 | |||
454 | init_waitqueue_entry(&wait, current); | ||
455 | |||
456 | current->flags |= PF_NOFREEZE; | ||
457 | |||
458 | for (;;) { | ||
459 | add_wait_queue(&thread->wait_q, &wait); | ||
460 | |||
461 | set_current_state(TASK_INTERRUPTIBLE); | ||
462 | |||
463 | if (adapter->wakeup_tries || | ||
464 | ((!adapter->int_count) && | ||
465 | (!priv->btmrvl_dev.tx_dnld_rdy || | ||
466 | skb_queue_empty(&adapter->tx_queue)))) { | ||
467 | BT_DBG("main_thread is sleeping..."); | ||
468 | schedule(); | ||
469 | } | ||
470 | |||
471 | set_current_state(TASK_RUNNING); | ||
472 | |||
473 | remove_wait_queue(&thread->wait_q, &wait); | ||
474 | |||
475 | BT_DBG("main_thread woke up"); | ||
476 | |||
477 | if (kthread_should_stop()) { | ||
478 | BT_DBG("main_thread: break from main thread"); | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
483 | if (adapter->int_count) { | ||
484 | adapter->int_count = 0; | ||
485 | } else if (adapter->ps_state == PS_SLEEP && | ||
486 | !skb_queue_empty(&adapter->tx_queue)) { | ||
487 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
488 | adapter->wakeup_tries++; | ||
489 | priv->hw_wakeup_firmware(priv); | ||
490 | continue; | ||
491 | } | ||
492 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
493 | |||
494 | if (adapter->ps_state == PS_SLEEP) | ||
495 | continue; | ||
496 | |||
497 | if (!priv->btmrvl_dev.tx_dnld_rdy) | ||
498 | continue; | ||
499 | |||
500 | skb = skb_dequeue(&adapter->tx_queue); | ||
501 | if (skb) { | ||
502 | if (btmrvl_tx_pkt(priv, skb)) | ||
503 | priv->btmrvl_dev.hcidev->stat.err_tx++; | ||
504 | else | ||
505 | priv->btmrvl_dev.hcidev->stat.byte_tx += skb->len; | ||
506 | |||
507 | kfree_skb(skb); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | struct btmrvl_private *btmrvl_add_card(void *card) | ||
515 | { | ||
516 | struct hci_dev *hdev = NULL; | ||
517 | struct btmrvl_private *priv; | ||
518 | int ret; | ||
519 | |||
520 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
521 | if (!priv) { | ||
522 | BT_ERR("Can not allocate priv"); | ||
523 | goto err_priv; | ||
524 | } | ||
525 | |||
526 | priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL); | ||
527 | if (!priv->adapter) { | ||
528 | BT_ERR("Allocate buffer for btmrvl_adapter failed!"); | ||
529 | goto err_adapter; | ||
530 | } | ||
531 | |||
532 | btmrvl_init_adapter(priv); | ||
533 | |||
534 | hdev = hci_alloc_dev(); | ||
535 | if (!hdev) { | ||
536 | BT_ERR("Can not allocate HCI device"); | ||
537 | goto err_hdev; | ||
538 | } | ||
539 | |||
540 | BT_DBG("Starting kthread..."); | ||
541 | priv->main_thread.priv = priv; | ||
542 | spin_lock_init(&priv->driver_lock); | ||
543 | |||
544 | init_waitqueue_head(&priv->main_thread.wait_q); | ||
545 | priv->main_thread.task = kthread_run(btmrvl_service_main_thread, | ||
546 | &priv->main_thread, "btmrvl_main_service"); | ||
547 | |||
548 | priv->btmrvl_dev.hcidev = hdev; | ||
549 | priv->btmrvl_dev.card = card; | ||
550 | |||
551 | hdev->driver_data = priv; | ||
552 | |||
553 | priv->btmrvl_dev.tx_dnld_rdy = true; | ||
554 | |||
555 | hdev->type = HCI_SDIO; | ||
556 | hdev->open = btmrvl_open; | ||
557 | hdev->close = btmrvl_close; | ||
558 | hdev->flush = btmrvl_flush; | ||
559 | hdev->send = btmrvl_send_frame; | ||
560 | hdev->destruct = btmrvl_destruct; | ||
561 | hdev->ioctl = btmrvl_ioctl; | ||
562 | hdev->owner = THIS_MODULE; | ||
563 | |||
564 | ret = hci_register_dev(hdev); | ||
565 | if (ret < 0) { | ||
566 | BT_ERR("Can not register HCI device"); | ||
567 | goto err_hci_register_dev; | ||
568 | } | ||
569 | |||
570 | #ifdef CONFIG_DEBUG_FS | ||
571 | btmrvl_debugfs_init(hdev); | ||
572 | #endif | ||
573 | |||
574 | return priv; | ||
575 | |||
576 | err_hci_register_dev: | ||
577 | /* Stop the thread servicing the interrupts */ | ||
578 | kthread_stop(priv->main_thread.task); | ||
579 | |||
580 | hci_free_dev(hdev); | ||
581 | |||
582 | err_hdev: | ||
583 | btmrvl_free_adapter(priv); | ||
584 | |||
585 | err_adapter: | ||
586 | kfree(priv); | ||
587 | |||
588 | err_priv: | ||
589 | return NULL; | ||
590 | } | ||
591 | EXPORT_SYMBOL_GPL(btmrvl_add_card); | ||
592 | |||
593 | int btmrvl_remove_card(struct btmrvl_private *priv) | ||
594 | { | ||
595 | struct hci_dev *hdev; | ||
596 | |||
597 | hdev = priv->btmrvl_dev.hcidev; | ||
598 | |||
599 | wake_up_interruptible(&priv->adapter->cmd_wait_q); | ||
600 | |||
601 | kthread_stop(priv->main_thread.task); | ||
602 | |||
603 | #ifdef CONFIG_DEBUG_FS | ||
604 | btmrvl_debugfs_remove(hdev); | ||
605 | #endif | ||
606 | |||
607 | hci_unregister_dev(hdev); | ||
608 | |||
609 | hci_free_dev(hdev); | ||
610 | |||
611 | priv->btmrvl_dev.hcidev = NULL; | ||
612 | |||
613 | btmrvl_free_adapter(priv); | ||
614 | |||
615 | kfree(priv); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | EXPORT_SYMBOL_GPL(btmrvl_remove_card); | ||
620 | |||
621 | MODULE_AUTHOR("Marvell International Ltd."); | ||
622 | MODULE_DESCRIPTION("Marvell Bluetooth driver ver " VERSION); | ||
623 | MODULE_VERSION(VERSION); | ||
624 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c new file mode 100644 index 000000000000..5b33b85790f2 --- /dev/null +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -0,0 +1,1003 @@ | |||
1 | /** | ||
2 | * Marvell BT-over-SDIO driver: SDIO interface related functions. | ||
3 | * | ||
4 | * Copyright (C) 2009, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | **/ | ||
20 | |||
21 | #include <linux/firmware.h> | ||
22 | |||
23 | #include <linux/mmc/sdio_ids.h> | ||
24 | #include <linux/mmc/sdio_func.h> | ||
25 | |||
26 | #include <net/bluetooth/bluetooth.h> | ||
27 | #include <net/bluetooth/hci_core.h> | ||
28 | |||
29 | #include "btmrvl_drv.h" | ||
30 | #include "btmrvl_sdio.h" | ||
31 | |||
32 | #define VERSION "1.0" | ||
33 | |||
34 | /* The btmrvl_sdio_remove() callback function is called | ||
35 | * when user removes this module from kernel space or ejects | ||
36 | * the card from the slot. The driver handles these 2 cases | ||
37 | * differently. | ||
38 | * If the user is removing the module, a MODULE_SHUTDOWN_REQ | ||
39 | * command is sent to firmware and interrupt will be disabled. | ||
40 | * If the card is removed, there is no need to send command | ||
41 | * or disable interrupt. | ||
42 | * | ||
43 | * The variable 'user_rmmod' is used to distinguish these two | ||
44 | * scenarios. This flag is initialized as FALSE in case the card | ||
45 | * is removed, and will be set to TRUE for module removal when | ||
46 | * module_exit function is called. | ||
47 | */ | ||
48 | static u8 user_rmmod; | ||
49 | |||
50 | static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { | ||
51 | .helper = "sd8688_helper.bin", | ||
52 | .firmware = "sd8688.bin", | ||
53 | }; | ||
54 | |||
55 | static const struct sdio_device_id btmrvl_sdio_ids[] = { | ||
56 | /* Marvell SD8688 Bluetooth device */ | ||
57 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), | ||
58 | .driver_data = (unsigned long) &btmrvl_sdio_sd6888 }, | ||
59 | |||
60 | { } /* Terminating entry */ | ||
61 | }; | ||
62 | |||
63 | MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids); | ||
64 | |||
65 | static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card) | ||
66 | { | ||
67 | u8 reg; | ||
68 | int ret; | ||
69 | |||
70 | reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret); | ||
71 | if (!ret) | ||
72 | card->rx_unit = reg; | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat) | ||
78 | { | ||
79 | u8 fws0, fws1; | ||
80 | int ret; | ||
81 | |||
82 | *dat = 0; | ||
83 | |||
84 | fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); | ||
85 | |||
86 | if (!ret) | ||
87 | fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); | ||
88 | |||
89 | if (ret) | ||
90 | return -EIO; | ||
91 | |||
92 | *dat = (((u16) fws1) << 8) | fws0; | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat) | ||
98 | { | ||
99 | u8 reg; | ||
100 | int ret; | ||
101 | |||
102 | reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret); | ||
103 | if (!ret) | ||
104 | *dat = (u16) reg << card->rx_unit; | ||
105 | |||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card, | ||
110 | u8 mask) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret); | ||
115 | if (ret) { | ||
116 | BT_ERR("Unable to enable the host interrupt!"); | ||
117 | ret = -EIO; | ||
118 | } | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card, | ||
124 | u8 mask) | ||
125 | { | ||
126 | u8 host_int_mask; | ||
127 | int ret; | ||
128 | |||
129 | host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret); | ||
130 | if (ret) | ||
131 | return -EIO; | ||
132 | |||
133 | host_int_mask &= ~mask; | ||
134 | |||
135 | sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret); | ||
136 | if (ret < 0) { | ||
137 | BT_ERR("Unable to disable the host interrupt!"); | ||
138 | return -EIO; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits) | ||
145 | { | ||
146 | unsigned int tries; | ||
147 | u8 status; | ||
148 | int ret; | ||
149 | |||
150 | for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { | ||
151 | status = sdio_readb(card->func, CARD_STATUS_REG, &ret); | ||
152 | if (ret) | ||
153 | goto failed; | ||
154 | if ((status & bits) == bits) | ||
155 | return ret; | ||
156 | |||
157 | udelay(1); | ||
158 | } | ||
159 | |||
160 | ret = -ETIMEDOUT; | ||
161 | |||
162 | failed: | ||
163 | BT_ERR("FAILED! ret=%d", ret); | ||
164 | |||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card, | ||
169 | int pollnum) | ||
170 | { | ||
171 | int ret = -ETIMEDOUT; | ||
172 | u16 firmwarestat; | ||
173 | unsigned int tries; | ||
174 | |||
175 | /* Wait for firmware to become ready */ | ||
176 | for (tries = 0; tries < pollnum; tries++) { | ||
177 | if (btmrvl_sdio_read_fw_status(card, &firmwarestat) < 0) | ||
178 | continue; | ||
179 | |||
180 | if (firmwarestat == FIRMWARE_READY) { | ||
181 | ret = 0; | ||
182 | break; | ||
183 | } else { | ||
184 | msleep(10); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) | ||
192 | { | ||
193 | const struct firmware *fw_helper = NULL; | ||
194 | const u8 *helper = NULL; | ||
195 | int ret; | ||
196 | void *tmphlprbuf = NULL; | ||
197 | int tmphlprbufsz, hlprblknow, helperlen; | ||
198 | u8 *helperbuf; | ||
199 | u32 tx_len; | ||
200 | |||
201 | ret = request_firmware(&fw_helper, card->helper, | ||
202 | &card->func->dev); | ||
203 | if ((ret < 0) || !fw_helper) { | ||
204 | BT_ERR("request_firmware(helper) failed, error code = %d", | ||
205 | ret); | ||
206 | ret = -ENOENT; | ||
207 | goto done; | ||
208 | } | ||
209 | |||
210 | helper = fw_helper->data; | ||
211 | helperlen = fw_helper->size; | ||
212 | |||
213 | BT_DBG("Downloading helper image (%d bytes), block size %d bytes", | ||
214 | helperlen, SDIO_BLOCK_SIZE); | ||
215 | |||
216 | tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN); | ||
217 | |||
218 | tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL); | ||
219 | if (!tmphlprbuf) { | ||
220 | BT_ERR("Unable to allocate buffer for helper." | ||
221 | " Terminating download"); | ||
222 | ret = -ENOMEM; | ||
223 | goto done; | ||
224 | } | ||
225 | |||
226 | memset(tmphlprbuf, 0, tmphlprbufsz); | ||
227 | |||
228 | helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN); | ||
229 | |||
230 | /* Perform helper data transfer */ | ||
231 | tx_len = (FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE) | ||
232 | - SDIO_HEADER_LEN; | ||
233 | hlprblknow = 0; | ||
234 | |||
235 | do { | ||
236 | ret = btmrvl_sdio_poll_card_status(card, | ||
237 | CARD_IO_READY | DN_LD_CARD_RDY); | ||
238 | if (ret < 0) { | ||
239 | BT_ERR("Helper download poll status timeout @ %d", | ||
240 | hlprblknow); | ||
241 | goto done; | ||
242 | } | ||
243 | |||
244 | /* Check if there is more data? */ | ||
245 | if (hlprblknow >= helperlen) | ||
246 | break; | ||
247 | |||
248 | if (helperlen - hlprblknow < tx_len) | ||
249 | tx_len = helperlen - hlprblknow; | ||
250 | |||
251 | /* Little-endian */ | ||
252 | helperbuf[0] = ((tx_len & 0x000000ff) >> 0); | ||
253 | helperbuf[1] = ((tx_len & 0x0000ff00) >> 8); | ||
254 | helperbuf[2] = ((tx_len & 0x00ff0000) >> 16); | ||
255 | helperbuf[3] = ((tx_len & 0xff000000) >> 24); | ||
256 | |||
257 | memcpy(&helperbuf[SDIO_HEADER_LEN], &helper[hlprblknow], | ||
258 | tx_len); | ||
259 | |||
260 | /* Now send the data */ | ||
261 | ret = sdio_writesb(card->func, card->ioport, helperbuf, | ||
262 | FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE); | ||
263 | if (ret < 0) { | ||
264 | BT_ERR("IO error during helper download @ %d", | ||
265 | hlprblknow); | ||
266 | goto done; | ||
267 | } | ||
268 | |||
269 | hlprblknow += tx_len; | ||
270 | } while (true); | ||
271 | |||
272 | BT_DBG("Transferring helper image EOF block"); | ||
273 | |||
274 | memset(helperbuf, 0x0, SDIO_BLOCK_SIZE); | ||
275 | |||
276 | ret = sdio_writesb(card->func, card->ioport, helperbuf, | ||
277 | SDIO_BLOCK_SIZE); | ||
278 | if (ret < 0) { | ||
279 | BT_ERR("IO error in writing helper image EOF block"); | ||
280 | goto done; | ||
281 | } | ||
282 | |||
283 | ret = 0; | ||
284 | |||
285 | done: | ||
286 | kfree(tmphlprbuf); | ||
287 | if (fw_helper) | ||
288 | release_firmware(fw_helper); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) | ||
294 | { | ||
295 | const struct firmware *fw_firmware = NULL; | ||
296 | const u8 *firmware = NULL; | ||
297 | int firmwarelen, tmpfwbufsz, ret; | ||
298 | unsigned int tries, offset; | ||
299 | u8 base0, base1; | ||
300 | void *tmpfwbuf = NULL; | ||
301 | u8 *fwbuf; | ||
302 | u16 len; | ||
303 | int txlen = 0, tx_blocks = 0, count = 0; | ||
304 | |||
305 | ret = request_firmware(&fw_firmware, card->firmware, | ||
306 | &card->func->dev); | ||
307 | if ((ret < 0) || !fw_firmware) { | ||
308 | BT_ERR("request_firmware(firmware) failed, error code = %d", | ||
309 | ret); | ||
310 | ret = -ENOENT; | ||
311 | goto done; | ||
312 | } | ||
313 | |||
314 | firmware = fw_firmware->data; | ||
315 | firmwarelen = fw_firmware->size; | ||
316 | |||
317 | BT_DBG("Downloading FW image (%d bytes)", firmwarelen); | ||
318 | |||
319 | tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN); | ||
320 | tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); | ||
321 | if (!tmpfwbuf) { | ||
322 | BT_ERR("Unable to allocate buffer for firmware." | ||
323 | " Terminating download"); | ||
324 | ret = -ENOMEM; | ||
325 | goto done; | ||
326 | } | ||
327 | |||
328 | memset(tmpfwbuf, 0, tmpfwbufsz); | ||
329 | |||
330 | /* Ensure aligned firmware buffer */ | ||
331 | fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN); | ||
332 | |||
333 | /* Perform firmware data transfer */ | ||
334 | offset = 0; | ||
335 | do { | ||
336 | ret = btmrvl_sdio_poll_card_status(card, | ||
337 | CARD_IO_READY | DN_LD_CARD_RDY); | ||
338 | if (ret < 0) { | ||
339 | BT_ERR("FW download with helper poll status" | ||
340 | " timeout @ %d", offset); | ||
341 | goto done; | ||
342 | } | ||
343 | |||
344 | /* Check if there is more data ? */ | ||
345 | if (offset >= firmwarelen) | ||
346 | break; | ||
347 | |||
348 | for (tries = 0; tries < MAX_POLL_TRIES; tries++) { | ||
349 | base0 = sdio_readb(card->func, | ||
350 | SQ_READ_BASE_ADDRESS_A0_REG, &ret); | ||
351 | if (ret) { | ||
352 | BT_ERR("BASE0 register read failed:" | ||
353 | " base0 = 0x%04X(%d)." | ||
354 | " Terminating download", | ||
355 | base0, base0); | ||
356 | ret = -EIO; | ||
357 | goto done; | ||
358 | } | ||
359 | base1 = sdio_readb(card->func, | ||
360 | SQ_READ_BASE_ADDRESS_A1_REG, &ret); | ||
361 | if (ret) { | ||
362 | BT_ERR("BASE1 register read failed:" | ||
363 | " base1 = 0x%04X(%d)." | ||
364 | " Terminating download", | ||
365 | base1, base1); | ||
366 | ret = -EIO; | ||
367 | goto done; | ||
368 | } | ||
369 | |||
370 | len = (((u16) base1) << 8) | base0; | ||
371 | if (len) | ||
372 | break; | ||
373 | |||
374 | udelay(10); | ||
375 | } | ||
376 | |||
377 | if (!len) | ||
378 | break; | ||
379 | else if (len > BTM_UPLD_SIZE) { | ||
380 | BT_ERR("FW download failure @%d, invalid length %d", | ||
381 | offset, len); | ||
382 | ret = -EINVAL; | ||
383 | goto done; | ||
384 | } | ||
385 | |||
386 | txlen = len; | ||
387 | |||
388 | if (len & BIT(0)) { | ||
389 | count++; | ||
390 | if (count > MAX_WRITE_IOMEM_RETRY) { | ||
391 | BT_ERR("FW download failure @%d, " | ||
392 | "over max retry count", offset); | ||
393 | ret = -EIO; | ||
394 | goto done; | ||
395 | } | ||
396 | BT_ERR("FW CRC error indicated by the helper: " | ||
397 | "len = 0x%04X, txlen = %d", len, txlen); | ||
398 | len &= ~BIT(0); | ||
399 | /* Set txlen to 0 so as to resend from same offset */ | ||
400 | txlen = 0; | ||
401 | } else { | ||
402 | count = 0; | ||
403 | |||
404 | /* Last block ? */ | ||
405 | if (firmwarelen - offset < txlen) | ||
406 | txlen = firmwarelen - offset; | ||
407 | |||
408 | tx_blocks = | ||
409 | (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE; | ||
410 | |||
411 | memcpy(fwbuf, &firmware[offset], txlen); | ||
412 | } | ||
413 | |||
414 | ret = sdio_writesb(card->func, card->ioport, fwbuf, | ||
415 | tx_blocks * SDIO_BLOCK_SIZE); | ||
416 | |||
417 | if (ret < 0) { | ||
418 | BT_ERR("FW download, writesb(%d) failed @%d", | ||
419 | count, offset); | ||
420 | sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG, | ||
421 | &ret); | ||
422 | if (ret) | ||
423 | BT_ERR("writeb failed (CFG)"); | ||
424 | } | ||
425 | |||
426 | offset += txlen; | ||
427 | } while (true); | ||
428 | |||
429 | BT_DBG("FW download over, size %d bytes", offset); | ||
430 | |||
431 | ret = 0; | ||
432 | |||
433 | done: | ||
434 | kfree(tmpfwbuf); | ||
435 | |||
436 | if (fw_firmware) | ||
437 | release_firmware(fw_firmware); | ||
438 | |||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | ||
443 | { | ||
444 | u16 buf_len = 0; | ||
445 | int ret, buf_block_len, blksz; | ||
446 | struct sk_buff *skb = NULL; | ||
447 | u32 type; | ||
448 | u8 *payload = NULL; | ||
449 | struct hci_dev *hdev = priv->btmrvl_dev.hcidev; | ||
450 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; | ||
451 | |||
452 | if (!card || !card->func) { | ||
453 | BT_ERR("card or function is NULL!"); | ||
454 | ret = -EINVAL; | ||
455 | goto exit; | ||
456 | } | ||
457 | |||
458 | /* Read the length of data to be transferred */ | ||
459 | ret = btmrvl_sdio_read_rx_len(card, &buf_len); | ||
460 | if (ret < 0) { | ||
461 | BT_ERR("read rx_len failed"); | ||
462 | ret = -EIO; | ||
463 | goto exit; | ||
464 | } | ||
465 | |||
466 | blksz = SDIO_BLOCK_SIZE; | ||
467 | buf_block_len = (buf_len + blksz - 1) / blksz; | ||
468 | |||
469 | if (buf_len <= SDIO_HEADER_LEN | ||
470 | || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { | ||
471 | BT_ERR("invalid packet length: %d", buf_len); | ||
472 | ret = -EINVAL; | ||
473 | goto exit; | ||
474 | } | ||
475 | |||
476 | /* Allocate buffer */ | ||
477 | skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, | ||
478 | GFP_ATOMIC); | ||
479 | if (skb == NULL) { | ||
480 | BT_ERR("No free skb"); | ||
481 | goto exit; | ||
482 | } | ||
483 | |||
484 | if ((unsigned long) skb->data & (BTSDIO_DMA_ALIGN - 1)) { | ||
485 | skb_put(skb, (unsigned long) skb->data & | ||
486 | (BTSDIO_DMA_ALIGN - 1)); | ||
487 | skb_pull(skb, (unsigned long) skb->data & | ||
488 | (BTSDIO_DMA_ALIGN - 1)); | ||
489 | } | ||
490 | |||
491 | payload = skb->data; | ||
492 | |||
493 | ret = sdio_readsb(card->func, payload, card->ioport, | ||
494 | buf_block_len * blksz); | ||
495 | if (ret < 0) { | ||
496 | BT_ERR("readsb failed: %d", ret); | ||
497 | ret = -EIO; | ||
498 | goto exit; | ||
499 | } | ||
500 | |||
501 | /* This is SDIO specific header length: byte[2][1][0], type: byte[3] | ||
502 | * (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) | ||
503 | */ | ||
504 | |||
505 | buf_len = payload[0]; | ||
506 | buf_len |= (u16) payload[1] << 8; | ||
507 | type = payload[3]; | ||
508 | |||
509 | switch (type) { | ||
510 | case HCI_ACLDATA_PKT: | ||
511 | case HCI_SCODATA_PKT: | ||
512 | case HCI_EVENT_PKT: | ||
513 | bt_cb(skb)->pkt_type = type; | ||
514 | skb->dev = (void *)hdev; | ||
515 | skb_put(skb, buf_len); | ||
516 | skb_pull(skb, SDIO_HEADER_LEN); | ||
517 | |||
518 | if (type == HCI_EVENT_PKT) | ||
519 | btmrvl_check_evtpkt(priv, skb); | ||
520 | |||
521 | hci_recv_frame(skb); | ||
522 | hdev->stat.byte_rx += buf_len; | ||
523 | break; | ||
524 | |||
525 | case MRVL_VENDOR_PKT: | ||
526 | bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; | ||
527 | skb->dev = (void *)hdev; | ||
528 | skb_put(skb, buf_len); | ||
529 | skb_pull(skb, SDIO_HEADER_LEN); | ||
530 | |||
531 | if (btmrvl_process_event(priv, skb)) | ||
532 | hci_recv_frame(skb); | ||
533 | |||
534 | hdev->stat.byte_rx += buf_len; | ||
535 | break; | ||
536 | |||
537 | default: | ||
538 | BT_ERR("Unknow packet type:%d", type); | ||
539 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, | ||
540 | blksz * buf_block_len); | ||
541 | |||
542 | kfree_skb(skb); | ||
543 | skb = NULL; | ||
544 | break; | ||
545 | } | ||
546 | |||
547 | exit: | ||
548 | if (ret) { | ||
549 | hdev->stat.err_rx++; | ||
550 | if (skb) | ||
551 | kfree_skb(skb); | ||
552 | } | ||
553 | |||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg) | ||
558 | { | ||
559 | int ret; | ||
560 | u8 sdio_ireg = 0; | ||
561 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; | ||
562 | |||
563 | *ireg = 0; | ||
564 | |||
565 | sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); | ||
566 | if (ret) { | ||
567 | BT_ERR("sdio_readb: read int status register failed"); | ||
568 | ret = -EIO; | ||
569 | goto done; | ||
570 | } | ||
571 | |||
572 | if (sdio_ireg != 0) { | ||
573 | /* | ||
574 | * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS | ||
575 | * Clear the interrupt status register and re-enable the | ||
576 | * interrupt. | ||
577 | */ | ||
578 | BT_DBG("sdio_ireg = 0x%x", sdio_ireg); | ||
579 | |||
580 | sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS | | ||
581 | UP_LD_HOST_INT_STATUS), | ||
582 | HOST_INTSTATUS_REG, &ret); | ||
583 | if (ret) { | ||
584 | BT_ERR("sdio_writeb: clear int status register " | ||
585 | "failed"); | ||
586 | ret = -EIO; | ||
587 | goto done; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | if (sdio_ireg & DN_LD_HOST_INT_STATUS) { | ||
592 | if (priv->btmrvl_dev.tx_dnld_rdy) | ||
593 | BT_DBG("tx_done already received: " | ||
594 | " int_status=0x%x", sdio_ireg); | ||
595 | else | ||
596 | priv->btmrvl_dev.tx_dnld_rdy = true; | ||
597 | } | ||
598 | |||
599 | if (sdio_ireg & UP_LD_HOST_INT_STATUS) | ||
600 | btmrvl_sdio_card_to_host(priv); | ||
601 | |||
602 | *ireg = sdio_ireg; | ||
603 | |||
604 | ret = 0; | ||
605 | |||
606 | done: | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | static void btmrvl_sdio_interrupt(struct sdio_func *func) | ||
611 | { | ||
612 | struct btmrvl_private *priv; | ||
613 | struct hci_dev *hcidev; | ||
614 | struct btmrvl_sdio_card *card; | ||
615 | u8 ireg = 0; | ||
616 | |||
617 | card = sdio_get_drvdata(func); | ||
618 | if (card && card->priv) { | ||
619 | priv = card->priv; | ||
620 | hcidev = priv->btmrvl_dev.hcidev; | ||
621 | |||
622 | if (btmrvl_sdio_get_int_status(priv, &ireg)) | ||
623 | BT_ERR("reading HOST_INT_STATUS_REG failed"); | ||
624 | else | ||
625 | BT_DBG("HOST_INT_STATUS_REG %#x", ireg); | ||
626 | |||
627 | btmrvl_interrupt(priv); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) | ||
632 | { | ||
633 | struct sdio_func *func; | ||
634 | u8 reg; | ||
635 | int ret = 0; | ||
636 | |||
637 | if (!card || !card->func) { | ||
638 | BT_ERR("Error: card or function is NULL!"); | ||
639 | ret = -EINVAL; | ||
640 | goto failed; | ||
641 | } | ||
642 | |||
643 | func = card->func; | ||
644 | |||
645 | sdio_claim_host(func); | ||
646 | |||
647 | ret = sdio_enable_func(func); | ||
648 | if (ret) { | ||
649 | BT_ERR("sdio_enable_func() failed: ret=%d", ret); | ||
650 | ret = -EIO; | ||
651 | goto release_host; | ||
652 | } | ||
653 | |||
654 | ret = sdio_claim_irq(func, btmrvl_sdio_interrupt); | ||
655 | if (ret) { | ||
656 | BT_ERR("sdio_claim_irq failed: ret=%d", ret); | ||
657 | ret = -EIO; | ||
658 | goto disable_func; | ||
659 | } | ||
660 | |||
661 | ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE); | ||
662 | if (ret) { | ||
663 | BT_ERR("cannot set SDIO block size"); | ||
664 | ret = -EIO; | ||
665 | goto release_irq; | ||
666 | } | ||
667 | |||
668 | reg = sdio_readb(func, IO_PORT_0_REG, &ret); | ||
669 | if (ret < 0) { | ||
670 | ret = -EIO; | ||
671 | goto release_irq; | ||
672 | } | ||
673 | |||
674 | card->ioport = reg; | ||
675 | |||
676 | reg = sdio_readb(func, IO_PORT_1_REG, &ret); | ||
677 | if (ret < 0) { | ||
678 | ret = -EIO; | ||
679 | goto release_irq; | ||
680 | } | ||
681 | |||
682 | card->ioport |= (reg << 8); | ||
683 | |||
684 | reg = sdio_readb(func, IO_PORT_2_REG, &ret); | ||
685 | if (ret < 0) { | ||
686 | ret = -EIO; | ||
687 | goto release_irq; | ||
688 | } | ||
689 | |||
690 | card->ioport |= (reg << 16); | ||
691 | |||
692 | BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport); | ||
693 | |||
694 | sdio_set_drvdata(func, card); | ||
695 | |||
696 | sdio_release_host(func); | ||
697 | |||
698 | return 0; | ||
699 | |||
700 | release_irq: | ||
701 | sdio_release_irq(func); | ||
702 | |||
703 | disable_func: | ||
704 | sdio_disable_func(func); | ||
705 | |||
706 | release_host: | ||
707 | sdio_release_host(func); | ||
708 | |||
709 | failed: | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card) | ||
714 | { | ||
715 | if (card && card->func) { | ||
716 | sdio_claim_host(card->func); | ||
717 | sdio_release_irq(card->func); | ||
718 | sdio_disable_func(card->func); | ||
719 | sdio_release_host(card->func); | ||
720 | sdio_set_drvdata(card->func, NULL); | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card) | ||
727 | { | ||
728 | int ret; | ||
729 | |||
730 | if (!card || !card->func) | ||
731 | return -EINVAL; | ||
732 | |||
733 | sdio_claim_host(card->func); | ||
734 | |||
735 | ret = btmrvl_sdio_enable_host_int_mask(card, HIM_ENABLE); | ||
736 | |||
737 | btmrvl_sdio_get_rx_unit(card); | ||
738 | |||
739 | sdio_release_host(card->func); | ||
740 | |||
741 | return ret; | ||
742 | } | ||
743 | |||
744 | static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card) | ||
745 | { | ||
746 | int ret; | ||
747 | |||
748 | if (!card || !card->func) | ||
749 | return -EINVAL; | ||
750 | |||
751 | sdio_claim_host(card->func); | ||
752 | |||
753 | ret = btmrvl_sdio_disable_host_int_mask(card, HIM_DISABLE); | ||
754 | |||
755 | sdio_release_host(card->func); | ||
756 | |||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv, | ||
761 | u8 *payload, u16 nb) | ||
762 | { | ||
763 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; | ||
764 | int ret = 0; | ||
765 | int buf_block_len; | ||
766 | int blksz; | ||
767 | int i = 0; | ||
768 | u8 *buf = NULL; | ||
769 | void *tmpbuf = NULL; | ||
770 | int tmpbufsz; | ||
771 | |||
772 | if (!card || !card->func) { | ||
773 | BT_ERR("card or function is NULL!"); | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | |||
777 | buf = payload; | ||
778 | if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1)) { | ||
779 | tmpbufsz = ALIGN_SZ(nb, BTSDIO_DMA_ALIGN); | ||
780 | tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL); | ||
781 | if (!tmpbuf) | ||
782 | return -ENOMEM; | ||
783 | buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN); | ||
784 | memcpy(buf, payload, nb); | ||
785 | } | ||
786 | |||
787 | blksz = SDIO_BLOCK_SIZE; | ||
788 | buf_block_len = (nb + blksz - 1) / blksz; | ||
789 | |||
790 | sdio_claim_host(card->func); | ||
791 | |||
792 | do { | ||
793 | /* Transfer data to card */ | ||
794 | ret = sdio_writesb(card->func, card->ioport, buf, | ||
795 | buf_block_len * blksz); | ||
796 | if (ret < 0) { | ||
797 | i++; | ||
798 | BT_ERR("i=%d writesb failed: %d", i, ret); | ||
799 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | ||
800 | payload, nb); | ||
801 | ret = -EIO; | ||
802 | if (i > MAX_WRITE_IOMEM_RETRY) | ||
803 | goto exit; | ||
804 | } | ||
805 | } while (ret); | ||
806 | |||
807 | priv->btmrvl_dev.tx_dnld_rdy = false; | ||
808 | |||
809 | exit: | ||
810 | sdio_release_host(card->func); | ||
811 | |||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card) | ||
816 | { | ||
817 | int ret = 0; | ||
818 | |||
819 | if (!card || !card->func) { | ||
820 | BT_ERR("card or function is NULL!"); | ||
821 | return -EINVAL; | ||
822 | } | ||
823 | sdio_claim_host(card->func); | ||
824 | |||
825 | if (!btmrvl_sdio_verify_fw_download(card, 1)) { | ||
826 | BT_DBG("Firmware already downloaded!"); | ||
827 | goto done; | ||
828 | } | ||
829 | |||
830 | ret = btmrvl_sdio_download_helper(card); | ||
831 | if (ret) { | ||
832 | BT_ERR("Failed to download helper!"); | ||
833 | ret = -EIO; | ||
834 | goto done; | ||
835 | } | ||
836 | |||
837 | if (btmrvl_sdio_download_fw_w_helper(card)) { | ||
838 | BT_ERR("Failed to download firmware!"); | ||
839 | ret = -EIO; | ||
840 | goto done; | ||
841 | } | ||
842 | |||
843 | if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) { | ||
844 | BT_ERR("FW failed to be active in time!"); | ||
845 | ret = -ETIMEDOUT; | ||
846 | goto done; | ||
847 | } | ||
848 | |||
849 | done: | ||
850 | sdio_release_host(card->func); | ||
851 | |||
852 | return ret; | ||
853 | } | ||
854 | |||
855 | static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv) | ||
856 | { | ||
857 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; | ||
858 | int ret = 0; | ||
859 | |||
860 | if (!card || !card->func) { | ||
861 | BT_ERR("card or function is NULL!"); | ||
862 | return -EINVAL; | ||
863 | } | ||
864 | |||
865 | sdio_claim_host(card->func); | ||
866 | |||
867 | sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret); | ||
868 | |||
869 | sdio_release_host(card->func); | ||
870 | |||
871 | BT_DBG("wake up firmware"); | ||
872 | |||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static int btmrvl_sdio_probe(struct sdio_func *func, | ||
877 | const struct sdio_device_id *id) | ||
878 | { | ||
879 | int ret = 0; | ||
880 | struct btmrvl_private *priv = NULL; | ||
881 | struct btmrvl_sdio_card *card = NULL; | ||
882 | |||
883 | BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d", | ||
884 | id->vendor, id->device, id->class, func->num); | ||
885 | |||
886 | card = kzalloc(sizeof(*card), GFP_KERNEL); | ||
887 | if (!card) { | ||
888 | ret = -ENOMEM; | ||
889 | goto done; | ||
890 | } | ||
891 | |||
892 | card->func = func; | ||
893 | |||
894 | if (id->driver_data) { | ||
895 | struct btmrvl_sdio_device *data = (void *) id->driver_data; | ||
896 | card->helper = data->helper; | ||
897 | card->firmware = data->firmware; | ||
898 | } | ||
899 | |||
900 | if (btmrvl_sdio_register_dev(card) < 0) { | ||
901 | BT_ERR("Failed to register BT device!"); | ||
902 | ret = -ENODEV; | ||
903 | goto free_card; | ||
904 | } | ||
905 | |||
906 | /* Disable the interrupts on the card */ | ||
907 | btmrvl_sdio_disable_host_int(card); | ||
908 | |||
909 | if (btmrvl_sdio_download_fw(card)) { | ||
910 | BT_ERR("Downloading firmware failed!"); | ||
911 | ret = -ENODEV; | ||
912 | goto unreg_dev; | ||
913 | } | ||
914 | |||
915 | msleep(100); | ||
916 | |||
917 | btmrvl_sdio_enable_host_int(card); | ||
918 | |||
919 | priv = btmrvl_add_card(card); | ||
920 | if (!priv) { | ||
921 | BT_ERR("Initializing card failed!"); | ||
922 | ret = -ENODEV; | ||
923 | goto disable_host_int; | ||
924 | } | ||
925 | |||
926 | card->priv = priv; | ||
927 | |||
928 | /* Initialize the interface specific function pointers */ | ||
929 | priv->hw_host_to_card = btmrvl_sdio_host_to_card; | ||
930 | priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; | ||
931 | |||
932 | btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); | ||
933 | |||
934 | return 0; | ||
935 | |||
936 | disable_host_int: | ||
937 | btmrvl_sdio_disable_host_int(card); | ||
938 | unreg_dev: | ||
939 | btmrvl_sdio_unregister_dev(card); | ||
940 | free_card: | ||
941 | kfree(card); | ||
942 | done: | ||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | static void btmrvl_sdio_remove(struct sdio_func *func) | ||
947 | { | ||
948 | struct btmrvl_sdio_card *card; | ||
949 | |||
950 | if (func) { | ||
951 | card = sdio_get_drvdata(func); | ||
952 | if (card) { | ||
953 | /* Send SHUTDOWN command & disable interrupt | ||
954 | * if user removes the module. | ||
955 | */ | ||
956 | if (user_rmmod) { | ||
957 | btmrvl_send_module_cfg_cmd(card->priv, | ||
958 | MODULE_SHUTDOWN_REQ); | ||
959 | btmrvl_sdio_disable_host_int(card); | ||
960 | } | ||
961 | BT_DBG("unregester dev"); | ||
962 | btmrvl_sdio_unregister_dev(card); | ||
963 | btmrvl_remove_card(card->priv); | ||
964 | kfree(card); | ||
965 | } | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static struct sdio_driver bt_mrvl_sdio = { | ||
970 | .name = "btmrvl_sdio", | ||
971 | .id_table = btmrvl_sdio_ids, | ||
972 | .probe = btmrvl_sdio_probe, | ||
973 | .remove = btmrvl_sdio_remove, | ||
974 | }; | ||
975 | |||
976 | static int btmrvl_sdio_init_module(void) | ||
977 | { | ||
978 | if (sdio_register_driver(&bt_mrvl_sdio) != 0) { | ||
979 | BT_ERR("SDIO Driver Registration Failed"); | ||
980 | return -ENODEV; | ||
981 | } | ||
982 | |||
983 | /* Clear the flag in case user removes the card. */ | ||
984 | user_rmmod = 0; | ||
985 | |||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | static void btmrvl_sdio_exit_module(void) | ||
990 | { | ||
991 | /* Set the flag as user is removing this module. */ | ||
992 | user_rmmod = 1; | ||
993 | |||
994 | sdio_unregister_driver(&bt_mrvl_sdio); | ||
995 | } | ||
996 | |||
997 | module_init(btmrvl_sdio_init_module); | ||
998 | module_exit(btmrvl_sdio_exit_module); | ||
999 | |||
1000 | MODULE_AUTHOR("Marvell International Ltd."); | ||
1001 | MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION); | ||
1002 | MODULE_VERSION(VERSION); | ||
1003 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h new file mode 100644 index 000000000000..27329f107e5a --- /dev/null +++ b/drivers/bluetooth/btmrvl_sdio.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /** | ||
2 | * Marvell BT-over-SDIO driver: SDIO interface related definitions | ||
3 | * | ||
4 | * Copyright (C) 2009, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | * | ||
20 | **/ | ||
21 | |||
22 | #define SDIO_HEADER_LEN 4 | ||
23 | |||
24 | /* SD block size can not bigger than 64 due to buf size limit in firmware */ | ||
25 | /* define SD block size for data Tx/Rx */ | ||
26 | #define SDIO_BLOCK_SIZE 64 | ||
27 | |||
28 | /* Number of blocks for firmware transfer */ | ||
29 | #define FIRMWARE_TRANSFER_NBLOCK 2 | ||
30 | |||
31 | /* This is for firmware specific length */ | ||
32 | #define FW_EXTRA_LEN 36 | ||
33 | |||
34 | #define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) | ||
35 | |||
36 | #define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \ | ||
37 | (HCI_MAX_FRAME_SIZE + FW_EXTRA_LEN) | ||
38 | |||
39 | #define ALLOC_BUF_SIZE (((max_t (int, MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \ | ||
40 | MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \ | ||
41 | + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE) \ | ||
42 | * SDIO_BLOCK_SIZE) | ||
43 | |||
44 | /* The number of times to try when polling for status */ | ||
45 | #define MAX_POLL_TRIES 100 | ||
46 | |||
47 | /* Max retry number of CMD53 write */ | ||
48 | #define MAX_WRITE_IOMEM_RETRY 2 | ||
49 | |||
50 | /* Host Control Registers */ | ||
51 | #define IO_PORT_0_REG 0x00 | ||
52 | #define IO_PORT_1_REG 0x01 | ||
53 | #define IO_PORT_2_REG 0x02 | ||
54 | |||
55 | #define CONFIG_REG 0x03 | ||
56 | #define HOST_POWER_UP BIT(1) | ||
57 | #define HOST_CMD53_FIN BIT(2) | ||
58 | |||
59 | #define HOST_INT_MASK_REG 0x04 | ||
60 | #define HIM_DISABLE 0xff | ||
61 | #define HIM_ENABLE (BIT(0) | BIT(1)) | ||
62 | |||
63 | #define HOST_INTSTATUS_REG 0x05 | ||
64 | #define UP_LD_HOST_INT_STATUS BIT(0) | ||
65 | #define DN_LD_HOST_INT_STATUS BIT(1) | ||
66 | |||
67 | /* Card Control Registers */ | ||
68 | #define SQ_READ_BASE_ADDRESS_A0_REG 0x10 | ||
69 | #define SQ_READ_BASE_ADDRESS_A1_REG 0x11 | ||
70 | |||
71 | #define CARD_STATUS_REG 0x20 | ||
72 | #define DN_LD_CARD_RDY BIT(0) | ||
73 | #define CARD_IO_READY BIT(3) | ||
74 | |||
75 | #define CARD_FW_STATUS0_REG 0x40 | ||
76 | #define CARD_FW_STATUS1_REG 0x41 | ||
77 | #define FIRMWARE_READY 0xfedc | ||
78 | |||
79 | #define CARD_RX_LEN_REG 0x42 | ||
80 | #define CARD_RX_UNIT_REG 0x43 | ||
81 | |||
82 | |||
83 | struct btmrvl_sdio_card { | ||
84 | struct sdio_func *func; | ||
85 | u32 ioport; | ||
86 | const char *helper; | ||
87 | const char *firmware; | ||
88 | u8 rx_unit; | ||
89 | struct btmrvl_private *priv; | ||
90 | }; | ||
91 | |||
92 | struct btmrvl_sdio_device { | ||
93 | const char *helper; | ||
94 | const char *firmware; | ||
95 | }; | ||
96 | |||
97 | |||
98 | /* Platform specific DMA alignment */ | ||
99 | #define BTSDIO_DMA_ALIGN 8 | ||
100 | |||
101 | /* Macros for Data Alignment : size */ | ||
102 | #define ALIGN_SZ(p, a) \ | ||
103 | (((p) + ((a) - 1)) & ~((a) - 1)) | ||
104 | |||
105 | /* Macros for Data Alignment : address */ | ||
106 | #define ALIGN_ADDR(p, a) \ | ||
107 | ((((unsigned long)(p)) + (((unsigned long)(a)) - 1)) & \ | ||
108 | ~(((unsigned long)(a)) - 1)) | ||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e70c57ee4221..7ba91aa3fe8b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <net/bluetooth/bluetooth.h> | 35 | #include <net/bluetooth/bluetooth.h> |
36 | #include <net/bluetooth/hci_core.h> | 36 | #include <net/bluetooth/hci_core.h> |
37 | 37 | ||
38 | #define VERSION "0.5" | 38 | #define VERSION "0.6" |
39 | 39 | ||
40 | static int ignore_dga; | 40 | static int ignore_dga; |
41 | static int ignore_csr; | 41 | static int ignore_csr; |
@@ -145,6 +145,7 @@ static struct usb_device_id blacklist_table[] = { | |||
145 | #define BTUSB_INTR_RUNNING 0 | 145 | #define BTUSB_INTR_RUNNING 0 |
146 | #define BTUSB_BULK_RUNNING 1 | 146 | #define BTUSB_BULK_RUNNING 1 |
147 | #define BTUSB_ISOC_RUNNING 2 | 147 | #define BTUSB_ISOC_RUNNING 2 |
148 | #define BTUSB_SUSPENDING 3 | ||
148 | 149 | ||
149 | struct btusb_data { | 150 | struct btusb_data { |
150 | struct hci_dev *hdev; | 151 | struct hci_dev *hdev; |
@@ -157,11 +158,15 @@ struct btusb_data { | |||
157 | unsigned long flags; | 158 | unsigned long flags; |
158 | 159 | ||
159 | struct work_struct work; | 160 | struct work_struct work; |
161 | struct work_struct waker; | ||
160 | 162 | ||
161 | struct usb_anchor tx_anchor; | 163 | struct usb_anchor tx_anchor; |
162 | struct usb_anchor intr_anchor; | 164 | struct usb_anchor intr_anchor; |
163 | struct usb_anchor bulk_anchor; | 165 | struct usb_anchor bulk_anchor; |
164 | struct usb_anchor isoc_anchor; | 166 | struct usb_anchor isoc_anchor; |
167 | struct usb_anchor deferred; | ||
168 | int tx_in_flight; | ||
169 | spinlock_t txlock; | ||
165 | 170 | ||
166 | struct usb_endpoint_descriptor *intr_ep; | 171 | struct usb_endpoint_descriptor *intr_ep; |
167 | struct usb_endpoint_descriptor *bulk_tx_ep; | 172 | struct usb_endpoint_descriptor *bulk_tx_ep; |
@@ -174,8 +179,23 @@ struct btusb_data { | |||
174 | unsigned int sco_num; | 179 | unsigned int sco_num; |
175 | int isoc_altsetting; | 180 | int isoc_altsetting; |
176 | int suspend_count; | 181 | int suspend_count; |
182 | int did_iso_resume:1; | ||
177 | }; | 183 | }; |
178 | 184 | ||
185 | static int inc_tx(struct btusb_data *data) | ||
186 | { | ||
187 | unsigned long flags; | ||
188 | int rv; | ||
189 | |||
190 | spin_lock_irqsave(&data->txlock, flags); | ||
191 | rv = test_bit(BTUSB_SUSPENDING, &data->flags); | ||
192 | if (!rv) | ||
193 | data->tx_in_flight++; | ||
194 | spin_unlock_irqrestore(&data->txlock, flags); | ||
195 | |||
196 | return rv; | ||
197 | } | ||
198 | |||
179 | static void btusb_intr_complete(struct urb *urb) | 199 | static void btusb_intr_complete(struct urb *urb) |
180 | { | 200 | { |
181 | struct hci_dev *hdev = urb->context; | 201 | struct hci_dev *hdev = urb->context; |
@@ -202,6 +222,7 @@ static void btusb_intr_complete(struct urb *urb) | |||
202 | if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) | 222 | if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) |
203 | return; | 223 | return; |
204 | 224 | ||
225 | usb_mark_last_busy(data->udev); | ||
205 | usb_anchor_urb(urb, &data->intr_anchor); | 226 | usb_anchor_urb(urb, &data->intr_anchor); |
206 | 227 | ||
207 | err = usb_submit_urb(urb, GFP_ATOMIC); | 228 | err = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -301,7 +322,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags) | |||
301 | struct urb *urb; | 322 | struct urb *urb; |
302 | unsigned char *buf; | 323 | unsigned char *buf; |
303 | unsigned int pipe; | 324 | unsigned int pipe; |
304 | int err, size; | 325 | int err, size = HCI_MAX_FRAME_SIZE; |
305 | 326 | ||
306 | BT_DBG("%s", hdev->name); | 327 | BT_DBG("%s", hdev->name); |
307 | 328 | ||
@@ -312,8 +333,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags) | |||
312 | if (!urb) | 333 | if (!urb) |
313 | return -ENOMEM; | 334 | return -ENOMEM; |
314 | 335 | ||
315 | size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize); | ||
316 | |||
317 | buf = kmalloc(size, mem_flags); | 336 | buf = kmalloc(size, mem_flags); |
318 | if (!buf) { | 337 | if (!buf) { |
319 | usb_free_urb(urb); | 338 | usb_free_urb(urb); |
@@ -327,6 +346,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags) | |||
327 | 346 | ||
328 | urb->transfer_flags |= URB_FREE_BUFFER; | 347 | urb->transfer_flags |= URB_FREE_BUFFER; |
329 | 348 | ||
349 | usb_mark_last_busy(data->udev); | ||
330 | usb_anchor_urb(urb, &data->bulk_anchor); | 350 | usb_anchor_urb(urb, &data->bulk_anchor); |
331 | 351 | ||
332 | err = usb_submit_urb(urb, mem_flags); | 352 | err = usb_submit_urb(urb, mem_flags); |
@@ -465,6 +485,33 @@ static void btusb_tx_complete(struct urb *urb) | |||
465 | { | 485 | { |
466 | struct sk_buff *skb = urb->context; | 486 | struct sk_buff *skb = urb->context; |
467 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | 487 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; |
488 | struct btusb_data *data = hdev->driver_data; | ||
489 | |||
490 | BT_DBG("%s urb %p status %d count %d", hdev->name, | ||
491 | urb, urb->status, urb->actual_length); | ||
492 | |||
493 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
494 | goto done; | ||
495 | |||
496 | if (!urb->status) | ||
497 | hdev->stat.byte_tx += urb->transfer_buffer_length; | ||
498 | else | ||
499 | hdev->stat.err_tx++; | ||
500 | |||
501 | done: | ||
502 | spin_lock(&data->txlock); | ||
503 | data->tx_in_flight--; | ||
504 | spin_unlock(&data->txlock); | ||
505 | |||
506 | kfree(urb->setup_packet); | ||
507 | |||
508 | kfree_skb(skb); | ||
509 | } | ||
510 | |||
511 | static void btusb_isoc_tx_complete(struct urb *urb) | ||
512 | { | ||
513 | struct sk_buff *skb = urb->context; | ||
514 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
468 | 515 | ||
469 | BT_DBG("%s urb %p status %d count %d", hdev->name, | 516 | BT_DBG("%s urb %p status %d count %d", hdev->name, |
470 | urb, urb->status, urb->actual_length); | 517 | urb, urb->status, urb->actual_length); |
@@ -490,11 +537,17 @@ static int btusb_open(struct hci_dev *hdev) | |||
490 | 537 | ||
491 | BT_DBG("%s", hdev->name); | 538 | BT_DBG("%s", hdev->name); |
492 | 539 | ||
540 | err = usb_autopm_get_interface(data->intf); | ||
541 | if (err < 0) | ||
542 | return err; | ||
543 | |||
544 | data->intf->needs_remote_wakeup = 1; | ||
545 | |||
493 | if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) | 546 | if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) |
494 | return 0; | 547 | goto done; |
495 | 548 | ||
496 | if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) | 549 | if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) |
497 | return 0; | 550 | goto done; |
498 | 551 | ||
499 | err = btusb_submit_intr_urb(hdev, GFP_KERNEL); | 552 | err = btusb_submit_intr_urb(hdev, GFP_KERNEL); |
500 | if (err < 0) | 553 | if (err < 0) |
@@ -509,17 +562,28 @@ static int btusb_open(struct hci_dev *hdev) | |||
509 | set_bit(BTUSB_BULK_RUNNING, &data->flags); | 562 | set_bit(BTUSB_BULK_RUNNING, &data->flags); |
510 | btusb_submit_bulk_urb(hdev, GFP_KERNEL); | 563 | btusb_submit_bulk_urb(hdev, GFP_KERNEL); |
511 | 564 | ||
565 | done: | ||
566 | usb_autopm_put_interface(data->intf); | ||
512 | return 0; | 567 | return 0; |
513 | 568 | ||
514 | failed: | 569 | failed: |
515 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); | 570 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); |
516 | clear_bit(HCI_RUNNING, &hdev->flags); | 571 | clear_bit(HCI_RUNNING, &hdev->flags); |
572 | usb_autopm_put_interface(data->intf); | ||
517 | return err; | 573 | return err; |
518 | } | 574 | } |
519 | 575 | ||
576 | static void btusb_stop_traffic(struct btusb_data *data) | ||
577 | { | ||
578 | usb_kill_anchored_urbs(&data->intr_anchor); | ||
579 | usb_kill_anchored_urbs(&data->bulk_anchor); | ||
580 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
581 | } | ||
582 | |||
520 | static int btusb_close(struct hci_dev *hdev) | 583 | static int btusb_close(struct hci_dev *hdev) |
521 | { | 584 | { |
522 | struct btusb_data *data = hdev->driver_data; | 585 | struct btusb_data *data = hdev->driver_data; |
586 | int err; | ||
523 | 587 | ||
524 | BT_DBG("%s", hdev->name); | 588 | BT_DBG("%s", hdev->name); |
525 | 589 | ||
@@ -529,13 +593,16 @@ static int btusb_close(struct hci_dev *hdev) | |||
529 | cancel_work_sync(&data->work); | 593 | cancel_work_sync(&data->work); |
530 | 594 | ||
531 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | 595 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
532 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
533 | |||
534 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 596 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); |
535 | usb_kill_anchored_urbs(&data->bulk_anchor); | ||
536 | |||
537 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); | 597 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); |
538 | usb_kill_anchored_urbs(&data->intr_anchor); | 598 | |
599 | btusb_stop_traffic(data); | ||
600 | err = usb_autopm_get_interface(data->intf); | ||
601 | if (err < 0) | ||
602 | return 0; | ||
603 | |||
604 | data->intf->needs_remote_wakeup = 0; | ||
605 | usb_autopm_put_interface(data->intf); | ||
539 | 606 | ||
540 | return 0; | 607 | return 0; |
541 | } | 608 | } |
@@ -622,7 +689,7 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
622 | urb->dev = data->udev; | 689 | urb->dev = data->udev; |
623 | urb->pipe = pipe; | 690 | urb->pipe = pipe; |
624 | urb->context = skb; | 691 | urb->context = skb; |
625 | urb->complete = btusb_tx_complete; | 692 | urb->complete = btusb_isoc_tx_complete; |
626 | urb->interval = data->isoc_tx_ep->bInterval; | 693 | urb->interval = data->isoc_tx_ep->bInterval; |
627 | 694 | ||
628 | urb->transfer_flags = URB_ISO_ASAP; | 695 | urb->transfer_flags = URB_ISO_ASAP; |
@@ -633,12 +700,21 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
633 | le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); | 700 | le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); |
634 | 701 | ||
635 | hdev->stat.sco_tx++; | 702 | hdev->stat.sco_tx++; |
636 | break; | 703 | goto skip_waking; |
637 | 704 | ||
638 | default: | 705 | default: |
639 | return -EILSEQ; | 706 | return -EILSEQ; |
640 | } | 707 | } |
641 | 708 | ||
709 | err = inc_tx(data); | ||
710 | if (err) { | ||
711 | usb_anchor_urb(urb, &data->deferred); | ||
712 | schedule_work(&data->waker); | ||
713 | err = 0; | ||
714 | goto done; | ||
715 | } | ||
716 | |||
717 | skip_waking: | ||
642 | usb_anchor_urb(urb, &data->tx_anchor); | 718 | usb_anchor_urb(urb, &data->tx_anchor); |
643 | 719 | ||
644 | err = usb_submit_urb(urb, GFP_ATOMIC); | 720 | err = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -646,10 +722,13 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
646 | BT_ERR("%s urb %p submission failed", hdev->name, urb); | 722 | BT_ERR("%s urb %p submission failed", hdev->name, urb); |
647 | kfree(urb->setup_packet); | 723 | kfree(urb->setup_packet); |
648 | usb_unanchor_urb(urb); | 724 | usb_unanchor_urb(urb); |
725 | } else { | ||
726 | usb_mark_last_busy(data->udev); | ||
649 | } | 727 | } |
650 | 728 | ||
651 | usb_free_urb(urb); | 729 | usb_free_urb(urb); |
652 | 730 | ||
731 | done: | ||
653 | return err; | 732 | return err; |
654 | } | 733 | } |
655 | 734 | ||
@@ -721,8 +800,19 @@ static void btusb_work(struct work_struct *work) | |||
721 | { | 800 | { |
722 | struct btusb_data *data = container_of(work, struct btusb_data, work); | 801 | struct btusb_data *data = container_of(work, struct btusb_data, work); |
723 | struct hci_dev *hdev = data->hdev; | 802 | struct hci_dev *hdev = data->hdev; |
803 | int err; | ||
724 | 804 | ||
725 | if (hdev->conn_hash.sco_num > 0) { | 805 | if (hdev->conn_hash.sco_num > 0) { |
806 | if (!data->did_iso_resume) { | ||
807 | err = usb_autopm_get_interface(data->isoc); | ||
808 | if (err < 0) { | ||
809 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | ||
810 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
811 | return; | ||
812 | } | ||
813 | |||
814 | data->did_iso_resume = 1; | ||
815 | } | ||
726 | if (data->isoc_altsetting != 2) { | 816 | if (data->isoc_altsetting != 2) { |
727 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | 817 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
728 | usb_kill_anchored_urbs(&data->isoc_anchor); | 818 | usb_kill_anchored_urbs(&data->isoc_anchor); |
@@ -742,9 +832,25 @@ static void btusb_work(struct work_struct *work) | |||
742 | usb_kill_anchored_urbs(&data->isoc_anchor); | 832 | usb_kill_anchored_urbs(&data->isoc_anchor); |
743 | 833 | ||
744 | __set_isoc_interface(hdev, 0); | 834 | __set_isoc_interface(hdev, 0); |
835 | if (data->did_iso_resume) { | ||
836 | data->did_iso_resume = 0; | ||
837 | usb_autopm_put_interface(data->isoc); | ||
838 | } | ||
745 | } | 839 | } |
746 | } | 840 | } |
747 | 841 | ||
842 | static void btusb_waker(struct work_struct *work) | ||
843 | { | ||
844 | struct btusb_data *data = container_of(work, struct btusb_data, waker); | ||
845 | int err; | ||
846 | |||
847 | err = usb_autopm_get_interface(data->intf); | ||
848 | if (err < 0) | ||
849 | return; | ||
850 | |||
851 | usb_autopm_put_interface(data->intf); | ||
852 | } | ||
853 | |||
748 | static int btusb_probe(struct usb_interface *intf, | 854 | static int btusb_probe(struct usb_interface *intf, |
749 | const struct usb_device_id *id) | 855 | const struct usb_device_id *id) |
750 | { | 856 | { |
@@ -814,11 +920,14 @@ static int btusb_probe(struct usb_interface *intf, | |||
814 | spin_lock_init(&data->lock); | 920 | spin_lock_init(&data->lock); |
815 | 921 | ||
816 | INIT_WORK(&data->work, btusb_work); | 922 | INIT_WORK(&data->work, btusb_work); |
923 | INIT_WORK(&data->waker, btusb_waker); | ||
924 | spin_lock_init(&data->txlock); | ||
817 | 925 | ||
818 | init_usb_anchor(&data->tx_anchor); | 926 | init_usb_anchor(&data->tx_anchor); |
819 | init_usb_anchor(&data->intr_anchor); | 927 | init_usb_anchor(&data->intr_anchor); |
820 | init_usb_anchor(&data->bulk_anchor); | 928 | init_usb_anchor(&data->bulk_anchor); |
821 | init_usb_anchor(&data->isoc_anchor); | 929 | init_usb_anchor(&data->isoc_anchor); |
930 | init_usb_anchor(&data->deferred); | ||
822 | 931 | ||
823 | hdev = hci_alloc_dev(); | 932 | hdev = hci_alloc_dev(); |
824 | if (!hdev) { | 933 | if (!hdev) { |
@@ -943,6 +1052,7 @@ static void btusb_disconnect(struct usb_interface *intf) | |||
943 | hci_free_dev(hdev); | 1052 | hci_free_dev(hdev); |
944 | } | 1053 | } |
945 | 1054 | ||
1055 | #ifdef CONFIG_PM | ||
946 | static int btusb_suspend(struct usb_interface *intf, pm_message_t message) | 1056 | static int btusb_suspend(struct usb_interface *intf, pm_message_t message) |
947 | { | 1057 | { |
948 | struct btusb_data *data = usb_get_intfdata(intf); | 1058 | struct btusb_data *data = usb_get_intfdata(intf); |
@@ -952,22 +1062,44 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) | |||
952 | if (data->suspend_count++) | 1062 | if (data->suspend_count++) |
953 | return 0; | 1063 | return 0; |
954 | 1064 | ||
1065 | spin_lock_irq(&data->txlock); | ||
1066 | if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) { | ||
1067 | set_bit(BTUSB_SUSPENDING, &data->flags); | ||
1068 | spin_unlock_irq(&data->txlock); | ||
1069 | } else { | ||
1070 | spin_unlock_irq(&data->txlock); | ||
1071 | data->suspend_count--; | ||
1072 | return -EBUSY; | ||
1073 | } | ||
1074 | |||
955 | cancel_work_sync(&data->work); | 1075 | cancel_work_sync(&data->work); |
956 | 1076 | ||
1077 | btusb_stop_traffic(data); | ||
957 | usb_kill_anchored_urbs(&data->tx_anchor); | 1078 | usb_kill_anchored_urbs(&data->tx_anchor); |
958 | 1079 | ||
959 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
960 | usb_kill_anchored_urbs(&data->bulk_anchor); | ||
961 | usb_kill_anchored_urbs(&data->intr_anchor); | ||
962 | |||
963 | return 0; | 1080 | return 0; |
964 | } | 1081 | } |
965 | 1082 | ||
1083 | static void play_deferred(struct btusb_data *data) | ||
1084 | { | ||
1085 | struct urb *urb; | ||
1086 | int err; | ||
1087 | |||
1088 | while ((urb = usb_get_from_anchor(&data->deferred))) { | ||
1089 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
1090 | if (err < 0) | ||
1091 | break; | ||
1092 | |||
1093 | data->tx_in_flight++; | ||
1094 | } | ||
1095 | usb_scuttle_anchored_urbs(&data->deferred); | ||
1096 | } | ||
1097 | |||
966 | static int btusb_resume(struct usb_interface *intf) | 1098 | static int btusb_resume(struct usb_interface *intf) |
967 | { | 1099 | { |
968 | struct btusb_data *data = usb_get_intfdata(intf); | 1100 | struct btusb_data *data = usb_get_intfdata(intf); |
969 | struct hci_dev *hdev = data->hdev; | 1101 | struct hci_dev *hdev = data->hdev; |
970 | int err; | 1102 | int err = 0; |
971 | 1103 | ||
972 | BT_DBG("intf %p", intf); | 1104 | BT_DBG("intf %p", intf); |
973 | 1105 | ||
@@ -975,13 +1107,13 @@ static int btusb_resume(struct usb_interface *intf) | |||
975 | return 0; | 1107 | return 0; |
976 | 1108 | ||
977 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | 1109 | if (!test_bit(HCI_RUNNING, &hdev->flags)) |
978 | return 0; | 1110 | goto done; |
979 | 1111 | ||
980 | if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) { | 1112 | if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) { |
981 | err = btusb_submit_intr_urb(hdev, GFP_NOIO); | 1113 | err = btusb_submit_intr_urb(hdev, GFP_NOIO); |
982 | if (err < 0) { | 1114 | if (err < 0) { |
983 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); | 1115 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); |
984 | return err; | 1116 | goto failed; |
985 | } | 1117 | } |
986 | } | 1118 | } |
987 | 1119 | ||
@@ -989,9 +1121,10 @@ static int btusb_resume(struct usb_interface *intf) | |||
989 | err = btusb_submit_bulk_urb(hdev, GFP_NOIO); | 1121 | err = btusb_submit_bulk_urb(hdev, GFP_NOIO); |
990 | if (err < 0) { | 1122 | if (err < 0) { |
991 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 1123 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); |
992 | return err; | 1124 | goto failed; |
993 | } else | 1125 | } |
994 | btusb_submit_bulk_urb(hdev, GFP_NOIO); | 1126 | |
1127 | btusb_submit_bulk_urb(hdev, GFP_NOIO); | ||
995 | } | 1128 | } |
996 | 1129 | ||
997 | if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) { | 1130 | if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) { |
@@ -1001,16 +1134,35 @@ static int btusb_resume(struct usb_interface *intf) | |||
1001 | btusb_submit_isoc_urb(hdev, GFP_NOIO); | 1134 | btusb_submit_isoc_urb(hdev, GFP_NOIO); |
1002 | } | 1135 | } |
1003 | 1136 | ||
1137 | spin_lock_irq(&data->txlock); | ||
1138 | play_deferred(data); | ||
1139 | clear_bit(BTUSB_SUSPENDING, &data->flags); | ||
1140 | spin_unlock_irq(&data->txlock); | ||
1141 | schedule_work(&data->work); | ||
1142 | |||
1004 | return 0; | 1143 | return 0; |
1144 | |||
1145 | failed: | ||
1146 | usb_scuttle_anchored_urbs(&data->deferred); | ||
1147 | done: | ||
1148 | spin_lock_irq(&data->txlock); | ||
1149 | clear_bit(BTUSB_SUSPENDING, &data->flags); | ||
1150 | spin_unlock_irq(&data->txlock); | ||
1151 | |||
1152 | return err; | ||
1005 | } | 1153 | } |
1154 | #endif | ||
1006 | 1155 | ||
1007 | static struct usb_driver btusb_driver = { | 1156 | static struct usb_driver btusb_driver = { |
1008 | .name = "btusb", | 1157 | .name = "btusb", |
1009 | .probe = btusb_probe, | 1158 | .probe = btusb_probe, |
1010 | .disconnect = btusb_disconnect, | 1159 | .disconnect = btusb_disconnect, |
1160 | #ifdef CONFIG_PM | ||
1011 | .suspend = btusb_suspend, | 1161 | .suspend = btusb_suspend, |
1012 | .resume = btusb_resume, | 1162 | .resume = btusb_resume, |
1163 | #endif | ||
1013 | .id_table = btusb_table, | 1164 | .id_table = btusb_table, |
1165 | .supports_autosuspend = 1, | ||
1014 | }; | 1166 | }; |
1015 | 1167 | ||
1016 | static int __init btusb_init(void) | 1168 | static int __init btusb_init(void) |
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 894b2cb11ea6..40aec0fb8596 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
@@ -373,8 +373,9 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) | |||
373 | 373 | ||
374 | i = 0; | 374 | i = 0; |
375 | skb_queue_walk_safe(&bcsp->unack, skb, tmp) { | 375 | skb_queue_walk_safe(&bcsp->unack, skb, tmp) { |
376 | if (i++ >= pkts_to_be_removed) | 376 | if (i >= pkts_to_be_removed) |
377 | break; | 377 | break; |
378 | i++; | ||
378 | 379 | ||
379 | __skb_unlink(skb, &bcsp->unack); | 380 | __skb_unlink(skb, &bcsp->unack); |
380 | kfree_skb(skb); | 381 | kfree_skb(skb); |