Source
14
14
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
15
*/
16
16
#include <linux/module.h>
17
17
#include <linux/kernel.h>
18
18
#include <net/bluetooth/bluetooth.h>
19
19
#include <net/bluetooth/hci_core.h>
20
20
#include <asm/unaligned.h>
21
21
#include <net/rsi_91x.h>
22
22
#include <net/genetlink.h>
23
23
24
-
#define RSI_HEADROOM_FOR_BT_HAL 16
24
+
#define RSI_DMA_ALIGN 8
25
25
#define RSI_FRAME_DESC_SIZE 16
26
+
#define RSI_HEADROOM_FOR_BT_HAL (RSI_FRAME_DESC_SIZE + RSI_DMA_ALIGN)
26
27
27
28
struct rsi_hci_adapter {
28
29
void *priv;
29
30
struct rsi_proto_ops *proto_ops;
30
31
struct hci_dev *hdev;
31
32
};
32
33
33
34
static int rsi_hci_open(struct hci_dev *hdev)
34
35
{
35
36
return 0;
63
64
}
64
65
65
66
if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
66
67
/* Insufficient skb headroom - allocate a new skb */
67
68
new_skb = skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_HAL);
68
69
if (unlikely(!new_skb))
69
70
return -ENOMEM;
70
71
bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb);
71
72
kfree_skb(skb);
72
73
skb = new_skb;
74
+
if (!IS_ALIGNED((unsigned long)skb->data, RSI_DMA_ALIGN)) {
75
+
u8 *skb_data = skb->data;
76
+
int skb_len = skb->len;
77
+
78
+
skb_push(skb, RSI_DMA_ALIGN);
79
+
skb_pull(skb, PTR_ALIGN(skb->data,
80
+
RSI_DMA_ALIGN) - skb->data);
81
+
memmove(skb->data, skb_data, skb_len);
82
+
skb_trim(skb, skb_len);
83
+
}
73
84
}
74
85
75
86
return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
76
87
RSI_BT_Q);
77
88
}
78
89
79
90
static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
80
91
{
81
92
struct rsi_hci_adapter *h_adapter = priv;
82
93
struct hci_dev *hdev = h_adapter->hdev;