Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4-rc6 337 lines 8.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Texas Instrument's Bluetooth Driver For Shared Transport. 4 * 5 * Bluetooth Driver acts as interface between HCI core and 6 * TI Shared Transport Layer. 7 * 8 * Copyright (C) 2009-2010 Texas Instruments 9 * Author: Raja Mani <raja_mani@ti.com> 10 * Pavan Savoy <pavan_savoy@ti.com> 11 */ 12 13#include <linux/platform_device.h> 14#include <net/bluetooth/bluetooth.h> 15#include <net/bluetooth/hci_core.h> 16#include <net/bluetooth/hci.h> 17 18#include <linux/ti_wilink_st.h> 19#include <linux/module.h> 20 21/* Bluetooth Driver Version */ 22#define VERSION "1.0" 23#define MAX_BT_CHNL_IDS 3 24 25/* Number of seconds to wait for registration completion 26 * when ST returns PENDING status. 27 */ 28#define BT_REGISTER_TIMEOUT 6000 /* 6 sec */ 29 30/** 31 * struct ti_st - driver operation structure 32 * @hdev: hci device pointer which binds to bt driver 33 * @reg_status: ST registration callback status 34 * @st_write: write function provided by the ST driver 35 * to be used by the driver during send_frame. 36 * @wait_reg_completion - completion sync between ti_st_open 37 * and st_reg_completion_cb. 38 */ 39struct ti_st { 40 struct hci_dev *hdev; 41 int reg_status; 42 long (*st_write) (struct sk_buff *); 43 struct completion wait_reg_completion; 44}; 45 46/* Increments HCI counters based on pocket ID (cmd,acl,sco) */ 47static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type) 48{ 49 struct hci_dev *hdev = hst->hdev; 50 51 /* Update HCI stat counters */ 52 switch (pkt_type) { 53 case HCI_COMMAND_PKT: 54 hdev->stat.cmd_tx++; 55 break; 56 57 case HCI_ACLDATA_PKT: 58 hdev->stat.acl_tx++; 59 break; 60 61 case HCI_SCODATA_PKT: 62 hdev->stat.sco_tx++; 63 break; 64 } 65} 66 67/* ------- Interfaces to Shared Transport ------ */ 68 69/* Called by ST layer to indicate protocol registration completion 70 * status.ti_st_open() function will wait for signal from this 71 * API when st_register() function returns ST_PENDING. 72 */ 73static void st_reg_completion_cb(void *priv_data, int data) 74{ 75 struct ti_st *lhst = priv_data; 76 77 /* Save registration status for use in ti_st_open() */ 78 lhst->reg_status = data; 79 /* complete the wait in ti_st_open() */ 80 complete(&lhst->wait_reg_completion); 81} 82 83/* Called by Shared Transport layer when receive data is available */ 84static long st_receive(void *priv_data, struct sk_buff *skb) 85{ 86 struct ti_st *lhst = priv_data; 87 int err; 88 89 if (!skb) 90 return -EFAULT; 91 92 if (!lhst) { 93 kfree_skb(skb); 94 return -EFAULT; 95 } 96 97 /* Forward skb to HCI core layer */ 98 err = hci_recv_frame(lhst->hdev, skb); 99 if (err < 0) { 100 BT_ERR("Unable to push skb to HCI core(%d)", err); 101 return err; 102 } 103 104 lhst->hdev->stat.byte_rx += skb->len; 105 106 return 0; 107} 108 109/* ------- Interfaces to HCI layer ------ */ 110/* protocol structure registered with shared transport */ 111static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = { 112 { 113 .chnl_id = HCI_EVENT_PKT, /* HCI Events */ 114 .hdr_len = sizeof(struct hci_event_hdr), 115 .offset_len_in_hdr = offsetof(struct hci_event_hdr, plen), 116 .len_size = 1, /* sizeof(plen) in struct hci_event_hdr */ 117 .reserve = 8, 118 }, 119 { 120 .chnl_id = HCI_ACLDATA_PKT, /* ACL */ 121 .hdr_len = sizeof(struct hci_acl_hdr), 122 .offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen), 123 .len_size = 2, /* sizeof(dlen) in struct hci_acl_hdr */ 124 .reserve = 8, 125 }, 126 { 127 .chnl_id = HCI_SCODATA_PKT, /* SCO */ 128 .hdr_len = sizeof(struct hci_sco_hdr), 129 .offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen), 130 .len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */ 131 .reserve = 8, 132 }, 133}; 134 135/* Called from HCI core to initialize the device */ 136static int ti_st_open(struct hci_dev *hdev) 137{ 138 unsigned long timeleft; 139 struct ti_st *hst; 140 int err, i; 141 142 BT_DBG("%s %p", hdev->name, hdev); 143 144 /* provide contexts for callbacks from ST */ 145 hst = hci_get_drvdata(hdev); 146 147 for (i = 0; i < MAX_BT_CHNL_IDS; i++) { 148 ti_st_proto[i].priv_data = hst; 149 ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE; 150 ti_st_proto[i].recv = st_receive; 151 ti_st_proto[i].reg_complete_cb = st_reg_completion_cb; 152 153 /* Prepare wait-for-completion handler */ 154 init_completion(&hst->wait_reg_completion); 155 /* Reset ST registration callback status flag, 156 * this value will be updated in 157 * st_reg_completion_cb() 158 * function whenever it called from ST driver. 159 */ 160 hst->reg_status = -EINPROGRESS; 161 162 err = st_register(&ti_st_proto[i]); 163 if (!err) 164 goto done; 165 166 if (err != -EINPROGRESS) { 167 BT_ERR("st_register failed %d", err); 168 return err; 169 } 170 171 /* ST is busy with either protocol 172 * registration or firmware download. 173 */ 174 BT_DBG("waiting for registration " 175 "completion signal from ST"); 176 timeleft = wait_for_completion_timeout 177 (&hst->wait_reg_completion, 178 msecs_to_jiffies(BT_REGISTER_TIMEOUT)); 179 if (!timeleft) { 180 BT_ERR("Timeout(%d sec),didn't get reg " 181 "completion signal from ST", 182 BT_REGISTER_TIMEOUT / 1000); 183 return -ETIMEDOUT; 184 } 185 186 /* Is ST registration callback 187 * called with ERROR status? 188 */ 189 if (hst->reg_status != 0) { 190 BT_ERR("ST registration completed with invalid " 191 "status %d", hst->reg_status); 192 return -EAGAIN; 193 } 194 195done: 196 hst->st_write = ti_st_proto[i].write; 197 if (!hst->st_write) { 198 BT_ERR("undefined ST write function"); 199 for (i = 0; i < MAX_BT_CHNL_IDS; i++) { 200 /* Undo registration with ST */ 201 err = st_unregister(&ti_st_proto[i]); 202 if (err) 203 BT_ERR("st_unregister() failed with " 204 "error %d", err); 205 hst->st_write = NULL; 206 } 207 return -EIO; 208 } 209 } 210 return 0; 211} 212 213/* Close device */ 214static int ti_st_close(struct hci_dev *hdev) 215{ 216 int err, i; 217 struct ti_st *hst = hci_get_drvdata(hdev); 218 219 for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) { 220 err = st_unregister(&ti_st_proto[i]); 221 if (err) 222 BT_ERR("st_unregister(%d) failed with error %d", 223 ti_st_proto[i].chnl_id, err); 224 } 225 226 hst->st_write = NULL; 227 228 return err; 229} 230 231static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 232{ 233 struct ti_st *hst; 234 long len; 235 int pkt_type; 236 237 hst = hci_get_drvdata(hdev); 238 239 /* Prepend skb with frame type */ 240 memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); 241 242 BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb), 243 skb->len); 244 245 /* Insert skb to shared transport layer's transmit queue. 246 * Freeing skb memory is taken care in shared transport layer, 247 * so don't free skb memory here. 248 */ 249 pkt_type = hci_skb_pkt_type(skb); 250 len = hst->st_write(skb); 251 if (len < 0) { 252 BT_ERR("ST write failed (%ld)", len); 253 /* Try Again, would only fail if UART has gone bad */ 254 return -EAGAIN; 255 } 256 257 /* ST accepted our skb. So, Go ahead and do rest */ 258 hdev->stat.byte_tx += len; 259 ti_st_tx_complete(hst, pkt_type); 260 261 return 0; 262} 263 264static int bt_ti_probe(struct platform_device *pdev) 265{ 266 struct ti_st *hst; 267 struct hci_dev *hdev; 268 int err; 269 270 hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL); 271 if (!hst) 272 return -ENOMEM; 273 274 /* Expose "hciX" device to user space */ 275 hdev = hci_alloc_dev(); 276 if (!hdev) 277 return -ENOMEM; 278 279 BT_DBG("hdev %p", hdev); 280 281 hst->hdev = hdev; 282 hdev->bus = HCI_UART; 283 hci_set_drvdata(hdev, hst); 284 hdev->open = ti_st_open; 285 hdev->close = ti_st_close; 286 hdev->flush = NULL; 287 hdev->send = ti_st_send_frame; 288 289 err = hci_register_dev(hdev); 290 if (err < 0) { 291 BT_ERR("Can't register HCI device error %d", err); 292 hci_free_dev(hdev); 293 return err; 294 } 295 296 BT_DBG("HCI device registered (hdev %p)", hdev); 297 298 dev_set_drvdata(&pdev->dev, hst); 299 return 0; 300} 301 302static int bt_ti_remove(struct platform_device *pdev) 303{ 304 struct hci_dev *hdev; 305 struct ti_st *hst = dev_get_drvdata(&pdev->dev); 306 307 if (!hst) 308 return -EFAULT; 309 310 BT_DBG("%s", hst->hdev->name); 311 312 hdev = hst->hdev; 313 ti_st_close(hdev); 314 hci_unregister_dev(hdev); 315 316 hci_free_dev(hdev); 317 318 dev_set_drvdata(&pdev->dev, NULL); 319 return 0; 320} 321 322static struct platform_driver btwilink_driver = { 323 .probe = bt_ti_probe, 324 .remove = bt_ti_remove, 325 .driver = { 326 .name = "btwilink", 327 }, 328}; 329 330module_platform_driver(btwilink_driver); 331 332/* ------ Module Info ------ */ 333 334MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>"); 335MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION); 336MODULE_VERSION(VERSION); 337MODULE_LICENSE("GPL");