[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / drivers / bluetooth / hci_vhci.c
blob3256192dcde8f72759f0aab798b03cb9739b5a55
1 /*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
26 * Bluetooth HCI virtual device driver.
28 * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $
30 #define VERSION "1.1"
32 #include <linux/config.h>
33 #include <linux/module.h>
35 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/sched.h>
39 #include <linux/slab.h>
40 #include <linux/poll.h>
41 #include <linux/fcntl.h>
42 #include <linux/init.h>
43 #include <linux/random.h>
45 #include <linux/skbuff.h>
46 #include <linux/miscdevice.h>
48 #include <asm/system.h>
49 #include <asm/uaccess.h>
51 #include <net/bluetooth/bluetooth.h>
52 #include <net/bluetooth/hci_core.h>
53 #include "hci_vhci.h"
55 /* HCI device part */
57 static int hci_vhci_open(struct hci_dev *hdev)
59 set_bit(HCI_RUNNING, &hdev->flags);
60 return 0;
63 static int hci_vhci_flush(struct hci_dev *hdev)
65 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
66 skb_queue_purge(&hci_vhci->readq);
67 return 0;
70 static int hci_vhci_close(struct hci_dev *hdev)
72 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
73 return 0;
75 hci_vhci_flush(hdev);
76 return 0;
79 static void hci_vhci_destruct(struct hci_dev *hdev)
81 struct hci_vhci_struct *vhci;
83 if (!hdev) return;
85 vhci = (struct hci_vhci_struct *) hdev->driver_data;
86 kfree(vhci);
89 static int hci_vhci_send_frame(struct sk_buff *skb)
91 struct hci_dev* hdev = (struct hci_dev *) skb->dev;
92 struct hci_vhci_struct *hci_vhci;
94 if (!hdev) {
95 BT_ERR("Frame for uknown device (hdev=NULL)");
96 return -ENODEV;
99 if (!test_bit(HCI_RUNNING, &hdev->flags))
100 return -EBUSY;
102 hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
104 memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
105 skb_queue_tail(&hci_vhci->readq, skb);
107 if (hci_vhci->flags & VHCI_FASYNC)
108 kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN);
109 wake_up_interruptible(&hci_vhci->read_wait);
111 return 0;
114 /* Character device part */
116 /* Poll */
117 static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
119 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
121 poll_wait(file, &hci_vhci->read_wait, wait);
123 if (skb_queue_len(&hci_vhci->readq))
124 return POLLIN | POLLRDNORM;
126 return POLLOUT | POLLWRNORM;
129 /* Get packet from user space buffer(already verified) */
130 static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char __user *buf, size_t count)
132 struct sk_buff *skb;
134 if (count > HCI_MAX_FRAME_SIZE)
135 return -EINVAL;
137 if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
138 return -ENOMEM;
140 if (copy_from_user(skb_put(skb, count), buf, count)) {
141 kfree_skb(skb);
142 return -EFAULT;
145 skb->dev = (void *) hci_vhci->hdev;
146 skb->pkt_type = *((__u8 *) skb->data);
147 skb_pull(skb, 1);
149 hci_recv_frame(skb);
151 return count;
154 /* Write */
155 static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf,
156 size_t count, loff_t *pos)
158 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
160 if (!access_ok(VERIFY_READ, buf, count))
161 return -EFAULT;
163 return hci_vhci_get_user(hci_vhci, buf, count);
166 /* Put packet to user space buffer(already verified) */
167 static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci,
168 struct sk_buff *skb, char __user *buf,
169 int count)
171 int len = count, total = 0;
172 char __user *ptr = buf;
174 len = min_t(unsigned int, skb->len, len);
175 if (copy_to_user(ptr, skb->data, len))
176 return -EFAULT;
177 total += len;
179 hci_vhci->hdev->stat.byte_tx += len;
180 switch (skb->pkt_type) {
181 case HCI_COMMAND_PKT:
182 hci_vhci->hdev->stat.cmd_tx++;
183 break;
185 case HCI_ACLDATA_PKT:
186 hci_vhci->hdev->stat.acl_tx++;
187 break;
189 case HCI_SCODATA_PKT:
190 hci_vhci->hdev->stat.cmd_tx++;
191 break;
194 return total;
197 /* Read */
198 static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
200 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
201 DECLARE_WAITQUEUE(wait, current);
202 struct sk_buff *skb;
203 ssize_t ret = 0;
205 add_wait_queue(&hci_vhci->read_wait, &wait);
206 while (count) {
207 set_current_state(TASK_INTERRUPTIBLE);
209 /* Read frames from device queue */
210 if (!(skb = skb_dequeue(&hci_vhci->readq))) {
211 if (file->f_flags & O_NONBLOCK) {
212 ret = -EAGAIN;
213 break;
215 if (signal_pending(current)) {
216 ret = -ERESTARTSYS;
217 break;
220 /* Nothing to read, let's sleep */
221 schedule();
222 continue;
225 if (access_ok(VERIFY_WRITE, buf, count))
226 ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
227 else
228 ret = -EFAULT;
230 kfree_skb(skb);
231 break;
233 set_current_state(TASK_RUNNING);
234 remove_wait_queue(&hci_vhci->read_wait, &wait);
236 return ret;
239 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
241 return -ESPIPE;
244 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
246 return -EINVAL;
249 static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
251 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
252 int ret;
254 if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
255 return ret;
257 if (on)
258 hci_vhci->flags |= VHCI_FASYNC;
259 else
260 hci_vhci->flags &= ~VHCI_FASYNC;
262 return 0;
265 static int hci_vhci_chr_open(struct inode *inode, struct file * file)
267 struct hci_vhci_struct *hci_vhci = NULL;
268 struct hci_dev *hdev;
270 if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
271 return -ENOMEM;
273 memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
275 skb_queue_head_init(&hci_vhci->readq);
276 init_waitqueue_head(&hci_vhci->read_wait);
278 /* Initialize and register HCI device */
279 hdev = hci_alloc_dev();
280 if (!hdev) {
281 kfree(hci_vhci);
282 return -ENOMEM;
285 hci_vhci->hdev = hdev;
287 hdev->type = HCI_VHCI;
288 hdev->driver_data = hci_vhci;
290 hdev->open = hci_vhci_open;
291 hdev->close = hci_vhci_close;
292 hdev->flush = hci_vhci_flush;
293 hdev->send = hci_vhci_send_frame;
294 hdev->destruct = hci_vhci_destruct;
296 hdev->owner = THIS_MODULE;
298 if (hci_register_dev(hdev) < 0) {
299 kfree(hci_vhci);
300 hci_free_dev(hdev);
301 return -EBUSY;
304 file->private_data = hci_vhci;
305 return nonseekable_open(inode, file);
308 static int hci_vhci_chr_close(struct inode *inode, struct file *file)
310 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
311 struct hci_dev *hdev = hci_vhci->hdev;
313 if (hci_unregister_dev(hdev) < 0) {
314 BT_ERR("Can't unregister HCI device %s", hdev->name);
317 hci_free_dev(hdev);
319 file->private_data = NULL;
320 return 0;
323 static struct file_operations hci_vhci_fops = {
324 .owner = THIS_MODULE,
325 .llseek = hci_vhci_chr_lseek,
326 .read = hci_vhci_chr_read,
327 .write = hci_vhci_chr_write,
328 .poll = hci_vhci_chr_poll,
329 .ioctl = hci_vhci_chr_ioctl,
330 .open = hci_vhci_chr_open,
331 .release = hci_vhci_chr_close,
332 .fasync = hci_vhci_chr_fasync
335 static struct miscdevice hci_vhci_miscdev=
337 VHCI_MINOR,
338 "hci_vhci",
339 &hci_vhci_fops
342 static int __init hci_vhci_init(void)
344 BT_INFO("VHCI driver ver %s", VERSION);
346 if (misc_register(&hci_vhci_miscdev)) {
347 BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
348 return -EIO;
351 return 0;
354 static void hci_vhci_cleanup(void)
356 misc_deregister(&hci_vhci_miscdev);
359 module_init(hci_vhci_init);
360 module_exit(hci_vhci_cleanup);
362 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
363 MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
364 MODULE_LICENSE("GPL");