Commit 099284bd authored by John W. Linville's avatar John W. Linville
parents 073730d7 4ebaa4ed
......@@ -163,7 +163,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
struct ath_struct *ath = hu->priv;
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
kfree(skb);
kfree_skb(skb);
return 0;
}
......@@ -217,7 +217,7 @@ static struct hci_uart_proto athp = {
.flush = ath_flush,
};
int ath_init(void)
int __init ath_init(void)
{
int err = hci_uart_register_proto(&athp);
......@@ -229,7 +229,7 @@ int ath_init(void)
return err;
}
int ath_deinit(void)
int __exit ath_deinit(void)
{
return hci_uart_unregister_proto(&athp);
}
......@@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = {
.flush = bcsp_flush
};
int bcsp_init(void)
int __init bcsp_init(void)
{
int err = hci_uart_register_proto(&bcsp);
......@@ -751,7 +751,7 @@ int bcsp_init(void)
return err;
}
int bcsp_deinit(void)
int __exit bcsp_deinit(void)
{
return hci_uart_unregister_proto(&bcsp);
}
......
......@@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
struct h4_struct *h4 = hu->priv;
register char *ptr;
struct hci_event_hdr *eh;
struct hci_acl_hdr *ah;
struct hci_sco_hdr *sh;
register int len, type, dlen;
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
hu, count, h4->rx_state, h4->rx_count);
ptr = data;
while (count) {
if (h4->rx_count) {
len = min_t(unsigned int, h4->rx_count, count);
memcpy(skb_put(h4->rx_skb, len), ptr, len);
h4->rx_count -= len; count -= len; ptr += len;
if (h4->rx_count)
continue;
switch (h4->rx_state) {
case H4_W4_DATA:
BT_DBG("Complete data");
hci_recv_frame(h4->rx_skb);
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
continue;
case H4_W4_EVENT_HDR:
eh = hci_event_hdr(h4->rx_skb);
BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
h4_check_data_len(h4, eh->plen);
continue;
case H4_W4_ACL_HDR:
ah = hci_acl_hdr(h4->rx_skb);
dlen = __le16_to_cpu(ah->dlen);
BT_DBG("ACL header: dlen %d", dlen);
h4_check_data_len(h4, dlen);
continue;
case H4_W4_SCO_HDR:
sh = hci_sco_hdr(h4->rx_skb);
BT_DBG("SCO header: dlen %d", sh->dlen);
h4_check_data_len(h4, sh->dlen);
continue;
}
}
/* H4_W4_PACKET_TYPE */
switch (*ptr) {
case HCI_EVENT_PKT:
BT_DBG("Event packet");
h4->rx_state = H4_W4_EVENT_HDR;
h4->rx_count = HCI_EVENT_HDR_SIZE;
type = HCI_EVENT_PKT;
break;
case HCI_ACLDATA_PKT:
BT_DBG("ACL packet");
h4->rx_state = H4_W4_ACL_HDR;
h4->rx_count = HCI_ACL_HDR_SIZE;
type = HCI_ACLDATA_PKT;
break;
case HCI_SCODATA_PKT:
BT_DBG("SCO packet");
h4->rx_state = H4_W4_SCO_HDR;
h4->rx_count = HCI_SCO_HDR_SIZE;
type = HCI_SCODATA_PKT;
break;
default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
hu->hdev->stat.err_rx++;
ptr++; count--;
continue;
};
ptr++; count--;
/* Allocate packet */
h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
if (!h4->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_count = 0;
return -ENOMEM;
}
h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type;
}
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
return count;
}
......@@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = {
.flush = h4_flush,
};
int h4_init(void)
int __init h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
......@@ -284,7 +185,7 @@ int h4_init(void)
return err;
}
int h4_deinit(void)
int __exit h4_deinit(void)
{
return hci_uart_unregister_proto(&h4p);
}
......@@ -517,7 +517,7 @@ static struct hci_uart_proto llp = {
.flush = ll_flush,
};
int ll_init(void)
int __init ll_init(void)
{
int err = hci_uart_register_proto(&llp);
......@@ -529,7 +529,7 @@ int ll_init(void)
return err;
}
int ll_deinit(void)
int __exit ll_deinit(void)
{
return hci_uart_unregister_proto(&llp);
}
......@@ -256,6 +256,7 @@ enum {
HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
HCI_CONN_SCO_SETUP_PEND,
};
static inline void hci_conn_hash_init(struct hci_dev *hdev)
......@@ -336,6 +337,7 @@ void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
......
......@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
}
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
struct hci_conn *sco = conn->link;
BT_DBG("%p", conn);
if (!sco)
return;
if (!status) {
if (lmp_esco_capable(conn->hdev))
hci_setup_sync(sco, conn->handle);
else
hci_add_sco(sco, conn->handle);
} else {
hci_proto_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
static void hci_conn_timeout(unsigned long arg)
{
struct hci_conn *conn = (void *) arg;
......@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
acl->power_save = 1;
hci_conn_enter_active_mode(acl);
if (lmp_esco_capable(hdev))
hci_setup_sync(sco, acl->handle);
else
hci_add_sco(sco, acl->handle);
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
/* defer SCO setup until mode change completed */
set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
return sco;
}
hci_sco_setup(acl, 0x00);
}
return sco;
......
......@@ -1149,7 +1149,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
return -EILSEQ;
do {
while (count) {
rem = hci_reassembly(hdev, type, data, count,
type - 1, GFP_ATOMIC);
if (rem < 0)
......@@ -1157,7 +1157,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
data += (count - rem);
count = rem;
} while (count);
};
return rem;
}
......@@ -1170,7 +1170,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
int type;
int rem = 0;
do {
while (count) {
struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
if (!skb) {
......@@ -1192,7 +1192,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
data += (count - rem);
count = rem;
} while (count);
};
return rem;
}
......
......@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn)
if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev);
}
......@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn)
if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev);
}
......@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
} else
conn->state = BT_CLOSED;
if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link;
if (sco) {
if (!ev->status) {
if (lmp_esco_capable(hdev))
hci_setup_sync(sco, conn->handle);
else
hci_add_sco(sco, conn->handle);
} else {
hci_proto_connect_cfm(sco, ev->status);
hci_conn_del(sco);
}
}
}
if (conn->type == ACL_LINK)
hci_sco_setup(conn, ev->status);
if (ev->status) {
hci_proto_connect_cfm(conn, ev->status);
......@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
else
conn->power_save = 0;
}
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, ev->status);
}
hci_dev_unlock(hdev);
......
......@@ -1152,7 +1152,7 @@ int __init rfcomm_init_sockets(void)
return err;
}
void rfcomm_cleanup_sockets(void)
void __exit rfcomm_cleanup_sockets(void)
{
debugfs_remove(rfcomm_sock_debugfs);
......
......@@ -1153,7 +1153,7 @@ static const struct tty_operations rfcomm_ops = {
.tiocmset = rfcomm_tty_tiocmset,
};
int rfcomm_init_ttys(void)
int __init rfcomm_init_ttys(void)
{
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
if (!rfcomm_tty_driver)
......@@ -1183,7 +1183,7 @@ int rfcomm_init_ttys(void)
return 0;
}
void rfcomm_cleanup_ttys(void)
void __exit rfcomm_cleanup_ttys(void)
{
tty_unregister_driver(rfcomm_tty_driver);
put_tty_driver(rfcomm_tty_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment