| From 5d5988e3a3bf3db72132d0991d736f396d3b6955 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 3 Sep 2018 11:27:46 +0530 |
| Subject: Bluetooth: btrsi: fix bt tx timeout issue |
| |
| From: Sanjay Kumar Konduri <sanjay.konduri@redpinesignals.com> |
| |
| [ Upstream commit 7cbfd1e2aad410d96fa6162aeb3f9cff1fecfc58 ] |
| |
| observed sometimes data is coming with unaligned address from kernel |
| BT stack. If unaligned address is passed, some data in payload is |
| stripped when packet is loading to firmware and this results, BT |
| connection timeout is happening. |
| |
| sh# hciconfig hci0 up |
| Can't init device hci0: hci0 command 0x0c03 tx timeout |
| |
| Fixed this by moving the data to aligned address. |
| |
| Signed-off-by: Sanjay Kumar Konduri <sanjay.konduri@redpinesignals.com> |
| Signed-off-by: Siva Rebbagondla <siva.rebbagondla@redpinesignals.com> |
| Signed-off-by: Marcel Holtmann <marcel@holtmann.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/bluetooth/btrsi.c | 13 ++++++++++++- |
| 1 file changed, 12 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c |
| index 60d1419590bab..3951f7b238404 100644 |
| --- a/drivers/bluetooth/btrsi.c |
| +++ b/drivers/bluetooth/btrsi.c |
| @@ -21,8 +21,9 @@ |
| #include <net/rsi_91x.h> |
| #include <net/genetlink.h> |
| |
| -#define RSI_HEADROOM_FOR_BT_HAL 16 |
| +#define RSI_DMA_ALIGN 8 |
| #define RSI_FRAME_DESC_SIZE 16 |
| +#define RSI_HEADROOM_FOR_BT_HAL (RSI_FRAME_DESC_SIZE + RSI_DMA_ALIGN) |
| |
| struct rsi_hci_adapter { |
| void *priv; |
| @@ -70,6 +71,16 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb) |
| bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb); |
| kfree_skb(skb); |
| skb = new_skb; |
| + if (!IS_ALIGNED((unsigned long)skb->data, RSI_DMA_ALIGN)) { |
| + u8 *skb_data = skb->data; |
| + int skb_len = skb->len; |
| + |
| + skb_push(skb, RSI_DMA_ALIGN); |
| + skb_pull(skb, PTR_ALIGN(skb->data, |
| + RSI_DMA_ALIGN) - skb->data); |
| + memmove(skb->data, skb_data, skb_len); |
| + skb_trim(skb, skb_len); |
| + } |
| } |
| |
| return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb, |
| -- |
| 2.20.1 |
| |