Loading drivers/bluetooth/btmrvl_sdio.c +17 −11 Original line number Diff line number Diff line Loading @@ -492,7 +492,7 @@ done: static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) { u16 buf_len = 0; int ret, buf_block_len, blksz; int ret, num_blocks, blksz; struct sk_buff *skb = NULL; u32 type; u8 *payload = NULL; Loading @@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) } blksz = SDIO_BLOCK_SIZE; buf_block_len = (buf_len + blksz - 1) / blksz; num_blocks = DIV_ROUND_UP(buf_len, blksz); if (buf_len <= SDIO_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { || (num_blocks * blksz) > ALLOC_BUF_SIZE) { BT_ERR("invalid packet length: %d", buf_len); ret = -EINVAL; goto exit; } /* Allocate buffer */ skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); if (skb == NULL) { BT_ERR("No free skb"); goto exit; Loading @@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) payload = skb->data; ret = sdio_readsb(card->func, payload, card->ioport, buf_block_len * blksz); num_blocks * blksz); if (ret < 0) { BT_ERR("readsb failed: %d", ret); ret = -EIO; Loading @@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) */ buf_len = payload[0]; buf_len |= (u16) payload[1] << 8; buf_len |= payload[1] << 8; buf_len |= payload[2] << 16; if (buf_len > blksz * num_blocks) { BT_ERR("Skip incorrect packet: hdrlen %d buffer %d", buf_len, blksz * num_blocks); ret = -EIO; goto exit; } type = payload[3]; switch (type) { Loading Loading @@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) default: BT_ERR("Unknown packet type:%d", type); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, blksz * buf_block_len); BT_ERR("hex: %*ph", blksz * num_blocks, payload); kfree_skb(skb); skb = NULL; Loading Loading @@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv, if (ret < 0) { i++; BT_ERR("i=%d writesb failed: %d", i, ret); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, nb); BT_ERR("hex: %*ph", nb, payload); ret = -EIO; if (i > MAX_WRITE_IOMEM_RETRY) goto exit; Loading include/net/bluetooth/a2mp.h +23 −1 Original line number Diff line number Diff line Loading @@ -19,13 +19,25 @@ #define A2MP_FEAT_EXT 0x8000 enum amp_mgr_state { READ_LOC_AMP_INFO, READ_LOC_AMP_ASSOC, READ_LOC_AMP_ASSOC_FINAL, }; struct amp_mgr { struct list_head list; struct l2cap_conn *l2cap_conn; struct l2cap_chan *a2mp_chan; struct l2cap_chan *bredr_chan; struct kref kref; __u8 ident; __u8 handle; enum amp_mgr_state state; unsigned long flags; struct list_head amp_ctrls; struct mutex amp_ctrls_lock; }; struct a2mp_cmd { Loading Loading @@ -118,9 +130,19 @@ struct a2mp_physlink_rsp { #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 #define A2MP_STATUS_SECURITY_VIOLATION 0x06 void amp_mgr_get(struct amp_mgr *mgr); extern struct list_head amp_mgr_list; extern struct mutex amp_mgr_list_lock; struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); int amp_mgr_put(struct amp_mgr *mgr); u8 __next_ident(struct amp_mgr *mgr); struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, struct sk_buff *skb); struct amp_mgr *amp_mgr_lookup_by_state(u8 state); void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); void a2mp_discover_amp(struct l2cap_chan *chan); void a2mp_send_getinfo_rsp(struct hci_dev *hdev); void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); #endif /* __A2MP_H */ include/net/bluetooth/amp.h 0 → 100644 +50 −0 Original line number Diff line number Diff line /* Copyright (c) 2011,2012 Intel Corp. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 and only version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef __AMP_H #define __AMP_H struct amp_ctrl { struct list_head list; struct kref kref; __u8 id; __u16 assoc_len_so_far; __u16 assoc_rem_len; __u16 assoc_len; __u8 *assoc; }; int amp_ctrl_put(struct amp_ctrl *ctrl); void amp_ctrl_get(struct amp_ctrl *ctrl); struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); void amp_ctrl_list_flush(struct amp_mgr *mgr); struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, u8 remote_id, bool out); int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); void amp_read_loc_assoc_final_data(struct hci_dev *hdev, struct hci_conn *hcon); void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, struct hci_conn *hcon); void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, struct hci_conn *hcon); void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); #endif /* __AMP_H */ include/net/bluetooth/bluetooth.h +0 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src) } void baswap(bdaddr_t *dst, bdaddr_t *src); char *batostr(bdaddr_t *ba); /* Common socket structures and functions */ Loading include/net/bluetooth/hci.h +39 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define HCI_LINK_KEY_SIZE 16 #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) #define HCI_MAX_AMP_ASSOC_SIZE 672 /* HCI dev events */ #define HCI_DEV_REG 1 #define HCI_DEV_UNREG 2 Loading Loading @@ -196,6 +198,7 @@ enum { #define ACL_START_NO_FLUSH 0x00 #define ACL_CONT 0x01 #define ACL_START 0x02 #define ACL_COMPLETE 0x03 #define ACL_ACTIVE_BCAST 0x04 #define ACL_PICO_BCAST 0x08 Loading @@ -205,6 +208,7 @@ enum { #define ESCO_LINK 0x02 /* Low Energy links do not have defined link type. Use invented one */ #define LE_LINK 0x80 #define AMP_LINK 0x81 /* LMP features */ #define LMP_3SLOT 0x01 Loading Loading @@ -562,6 +566,40 @@ struct hci_cp_disconn_phy_link { __u8 reason; } __packed; struct ext_flow_spec { __u8 id; __u8 stype; __le16 msdu; __le32 sdu_itime; __le32 acc_lat; __le32 flush_to; } __packed; #define HCI_OP_CREATE_LOGICAL_LINK 0x0438 #define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439 struct hci_cp_create_accept_logical_link { __u8 phy_handle; struct ext_flow_spec tx_flow_spec; struct ext_flow_spec rx_flow_spec; } __packed; #define HCI_OP_DISCONN_LOGICAL_LINK 0x043a struct hci_cp_disconn_logical_link { __le16 log_handle; } __packed; #define HCI_OP_LOGICAL_LINK_CANCEL 0x043b struct hci_cp_logical_link_cancel { __u8 phy_handle; __u8 flow_spec_id; } __packed; struct hci_rp_logical_link_cancel { __u8 status; __u8 phy_handle; __u8 flow_spec_id; } __packed; #define HCI_OP_SNIFF_MODE 0x0803 struct hci_cp_sniff_mode { __le16 handle; Loading Loading
drivers/bluetooth/btmrvl_sdio.c +17 −11 Original line number Diff line number Diff line Loading @@ -492,7 +492,7 @@ done: static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) { u16 buf_len = 0; int ret, buf_block_len, blksz; int ret, num_blocks, blksz; struct sk_buff *skb = NULL; u32 type; u8 *payload = NULL; Loading @@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) } blksz = SDIO_BLOCK_SIZE; buf_block_len = (buf_len + blksz - 1) / blksz; num_blocks = DIV_ROUND_UP(buf_len, blksz); if (buf_len <= SDIO_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { || (num_blocks * blksz) > ALLOC_BUF_SIZE) { BT_ERR("invalid packet length: %d", buf_len); ret = -EINVAL; goto exit; } /* Allocate buffer */ skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); if (skb == NULL) { BT_ERR("No free skb"); goto exit; Loading @@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) payload = skb->data; ret = sdio_readsb(card->func, payload, card->ioport, buf_block_len * blksz); num_blocks * blksz); if (ret < 0) { BT_ERR("readsb failed: %d", ret); ret = -EIO; Loading @@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) */ buf_len = payload[0]; buf_len |= (u16) payload[1] << 8; buf_len |= payload[1] << 8; buf_len |= payload[2] << 16; if (buf_len > blksz * num_blocks) { BT_ERR("Skip incorrect packet: hdrlen %d buffer %d", buf_len, blksz * num_blocks); ret = -EIO; goto exit; } type = payload[3]; switch (type) { Loading Loading @@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) default: BT_ERR("Unknown packet type:%d", type); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, blksz * buf_block_len); BT_ERR("hex: %*ph", blksz * num_blocks, payload); kfree_skb(skb); skb = NULL; Loading Loading @@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv, if (ret < 0) { i++; BT_ERR("i=%d writesb failed: %d", i, ret); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, nb); BT_ERR("hex: %*ph", nb, payload); ret = -EIO; if (i > MAX_WRITE_IOMEM_RETRY) goto exit; Loading
include/net/bluetooth/a2mp.h +23 −1 Original line number Diff line number Diff line Loading @@ -19,13 +19,25 @@ #define A2MP_FEAT_EXT 0x8000 enum amp_mgr_state { READ_LOC_AMP_INFO, READ_LOC_AMP_ASSOC, READ_LOC_AMP_ASSOC_FINAL, }; struct amp_mgr { struct list_head list; struct l2cap_conn *l2cap_conn; struct l2cap_chan *a2mp_chan; struct l2cap_chan *bredr_chan; struct kref kref; __u8 ident; __u8 handle; enum amp_mgr_state state; unsigned long flags; struct list_head amp_ctrls; struct mutex amp_ctrls_lock; }; struct a2mp_cmd { Loading Loading @@ -118,9 +130,19 @@ struct a2mp_physlink_rsp { #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 #define A2MP_STATUS_SECURITY_VIOLATION 0x06 void amp_mgr_get(struct amp_mgr *mgr); extern struct list_head amp_mgr_list; extern struct mutex amp_mgr_list_lock; struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); int amp_mgr_put(struct amp_mgr *mgr); u8 __next_ident(struct amp_mgr *mgr); struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, struct sk_buff *skb); struct amp_mgr *amp_mgr_lookup_by_state(u8 state); void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); void a2mp_discover_amp(struct l2cap_chan *chan); void a2mp_send_getinfo_rsp(struct hci_dev *hdev); void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); #endif /* __A2MP_H */
include/net/bluetooth/amp.h 0 → 100644 +50 −0 Original line number Diff line number Diff line /* Copyright (c) 2011,2012 Intel Corp. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 and only version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef __AMP_H #define __AMP_H struct amp_ctrl { struct list_head list; struct kref kref; __u8 id; __u16 assoc_len_so_far; __u16 assoc_rem_len; __u16 assoc_len; __u8 *assoc; }; int amp_ctrl_put(struct amp_ctrl *ctrl); void amp_ctrl_get(struct amp_ctrl *ctrl); struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); void amp_ctrl_list_flush(struct amp_mgr *mgr); struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, u8 remote_id, bool out); int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); void amp_read_loc_assoc_final_data(struct hci_dev *hdev, struct hci_conn *hcon); void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, struct hci_conn *hcon); void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, struct hci_conn *hcon); void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); #endif /* __AMP_H */
include/net/bluetooth/bluetooth.h +0 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src) } void baswap(bdaddr_t *dst, bdaddr_t *src); char *batostr(bdaddr_t *ba); /* Common socket structures and functions */ Loading
include/net/bluetooth/hci.h +39 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define HCI_LINK_KEY_SIZE 16 #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) #define HCI_MAX_AMP_ASSOC_SIZE 672 /* HCI dev events */ #define HCI_DEV_REG 1 #define HCI_DEV_UNREG 2 Loading Loading @@ -196,6 +198,7 @@ enum { #define ACL_START_NO_FLUSH 0x00 #define ACL_CONT 0x01 #define ACL_START 0x02 #define ACL_COMPLETE 0x03 #define ACL_ACTIVE_BCAST 0x04 #define ACL_PICO_BCAST 0x08 Loading @@ -205,6 +208,7 @@ enum { #define ESCO_LINK 0x02 /* Low Energy links do not have defined link type. Use invented one */ #define LE_LINK 0x80 #define AMP_LINK 0x81 /* LMP features */ #define LMP_3SLOT 0x01 Loading Loading @@ -562,6 +566,40 @@ struct hci_cp_disconn_phy_link { __u8 reason; } __packed; struct ext_flow_spec { __u8 id; __u8 stype; __le16 msdu; __le32 sdu_itime; __le32 acc_lat; __le32 flush_to; } __packed; #define HCI_OP_CREATE_LOGICAL_LINK 0x0438 #define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439 struct hci_cp_create_accept_logical_link { __u8 phy_handle; struct ext_flow_spec tx_flow_spec; struct ext_flow_spec rx_flow_spec; } __packed; #define HCI_OP_DISCONN_LOGICAL_LINK 0x043a struct hci_cp_disconn_logical_link { __le16 log_handle; } __packed; #define HCI_OP_LOGICAL_LINK_CANCEL 0x043b struct hci_cp_logical_link_cancel { __u8 phy_handle; __u8 flow_spec_id; } __packed; struct hci_rp_logical_link_cancel { __u8 status; __u8 phy_handle; __u8 flow_spec_id; } __packed; #define HCI_OP_SNIFF_MODE 0x0803 struct hci_cp_sniff_mode { __le16 handle; Loading