diff options
Diffstat (limited to 'drivers/bluetooth/hci_vhci.c')
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index f67ea1c090cb..aba31210c802 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -50,6 +50,7 @@ struct vhci_data { | |||
50 | wait_queue_head_t read_wait; | 50 | wait_queue_head_t read_wait; |
51 | struct sk_buff_head readq; | 51 | struct sk_buff_head readq; |
52 | 52 | ||
53 | struct mutex open_mutex; | ||
53 | struct delayed_work open_timeout; | 54 | struct delayed_work open_timeout; |
54 | }; | 55 | }; |
55 | 56 | ||
@@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
87 | return 0; | 88 | return 0; |
88 | } | 89 | } |
89 | 90 | ||
90 | static int vhci_create_device(struct vhci_data *data, __u8 opcode) | 91 | static int __vhci_create_device(struct vhci_data *data, __u8 opcode) |
91 | { | 92 | { |
92 | struct hci_dev *hdev; | 93 | struct hci_dev *hdev; |
93 | struct sk_buff *skb; | 94 | struct sk_buff *skb; |
94 | __u8 dev_type; | 95 | __u8 dev_type; |
95 | 96 | ||
97 | if (data->hdev) | ||
98 | return -EBADFD; | ||
99 | |||
96 | /* bits 0-1 are dev_type (BR/EDR or AMP) */ | 100 | /* bits 0-1 are dev_type (BR/EDR or AMP) */ |
97 | dev_type = opcode & 0x03; | 101 | dev_type = opcode & 0x03; |
98 | 102 | ||
@@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode) | |||
151 | return 0; | 155 | return 0; |
152 | } | 156 | } |
153 | 157 | ||
158 | static int vhci_create_device(struct vhci_data *data, __u8 opcode) | ||
159 | { | ||
160 | int err; | ||
161 | |||
162 | mutex_lock(&data->open_mutex); | ||
163 | err = __vhci_create_device(data, opcode); | ||
164 | mutex_unlock(&data->open_mutex); | ||
165 | |||
166 | return err; | ||
167 | } | ||
168 | |||
154 | static inline ssize_t vhci_get_user(struct vhci_data *data, | 169 | static inline ssize_t vhci_get_user(struct vhci_data *data, |
155 | struct iov_iter *from) | 170 | struct iov_iter *from) |
156 | { | 171 | { |
@@ -191,11 +206,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, | |||
191 | case HCI_VENDOR_PKT: | 206 | case HCI_VENDOR_PKT: |
192 | cancel_delayed_work_sync(&data->open_timeout); | 207 | cancel_delayed_work_sync(&data->open_timeout); |
193 | 208 | ||
194 | if (data->hdev) { | ||
195 | kfree_skb(skb); | ||
196 | return -EBADFD; | ||
197 | } | ||
198 | |||
199 | opcode = *((__u8 *) skb->data); | 209 | opcode = *((__u8 *) skb->data); |
200 | skb_pull(skb, 1); | 210 | skb_pull(skb, 1); |
201 | 211 | ||
@@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file) | |||
320 | skb_queue_head_init(&data->readq); | 330 | skb_queue_head_init(&data->readq); |
321 | init_waitqueue_head(&data->read_wait); | 331 | init_waitqueue_head(&data->read_wait); |
322 | 332 | ||
333 | mutex_init(&data->open_mutex); | ||
323 | INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout); | 334 | INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout); |
324 | 335 | ||
325 | file->private_data = data; | 336 | file->private_data = data; |