diff options
author | Chin-Ran Lo <crlo@marvell.com> | 2014-06-06 22:37:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-16 11:23:33 -0400 |
commit | bca463e80825433203f0c0de4bf6518f50a9b30d (patch) | |
tree | cf942fb8553ee53732bfac0ca5f05c9984042f8d | |
parent | f15ec3451daf137a63d9cdc65ac5f863ce91fce5 (diff) |
mwifiex: fix tx_info/rx_info overlap with PCIe dma_mapping
On PCIe Tx data path, network interface specific tx_info
parameters such as bss_num and bss_type are saved at
"skb->cb + sizeof(dma_addr_t)" (returned by MWIFIEX_SKB_TXCB).
Later mwifiex_map_pci_memory() called from
mwifiex_pcie_send_data() will memcpy
sizeof(struct mwifiex_dma_mapping) bytes to save PCIe DMA
address and length information at beginning of skb->cb.
This accidently overwrites bss_num and bss_type saved in skb->cb
previously because bss_num/bss_type and mwifiex_dma_mapping data
overlap.
Similarly, on PCIe Rx data path, rx_info parameters overlaps
with PCIe DMA address and length information too.
Fix it by defining mwifiex_cb structure and having
MWIFIEX_SKB_TXCB and MWIFIEX_SKB_RXCB return the correct address
of tx_info/rx_info using the structure members.
Also add a BUILD_BUG_ON to maks sure that mwifiex_cb structure
doesn't exceed the size of skb->cb.
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Signed-off-by: Chin-Ran Lo <crlo@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/util.h | 43 |
2 files changed, 35 insertions, 12 deletions
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 574d4b597468..2cc9b6fca490 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -50,7 +50,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
50 | return -1; | 50 | return -1; |
51 | } | 51 | } |
52 | mapping.len = size; | 52 | mapping.len = size; |
53 | memcpy(skb->cb, &mapping, sizeof(mapping)); | 53 | mwifiex_store_mapping(skb, &mapping); |
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
@@ -60,7 +60,7 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, | |||
60 | struct pcie_service_card *card = adapter->card; | 60 | struct pcie_service_card *card = adapter->card; |
61 | struct mwifiex_dma_mapping mapping; | 61 | struct mwifiex_dma_mapping mapping; |
62 | 62 | ||
63 | MWIFIEX_SKB_PACB(skb, &mapping); | 63 | mwifiex_get_mapping(skb, &mapping); |
64 | pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); | 64 | pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h index ddae57021397..caadb3737b9e 100644 --- a/drivers/net/wireless/mwifiex/util.h +++ b/drivers/net/wireless/mwifiex/util.h | |||
@@ -20,32 +20,55 @@ | |||
20 | #ifndef _MWIFIEX_UTIL_H_ | 20 | #ifndef _MWIFIEX_UTIL_H_ |
21 | #define _MWIFIEX_UTIL_H_ | 21 | #define _MWIFIEX_UTIL_H_ |
22 | 22 | ||
23 | struct mwifiex_dma_mapping { | ||
24 | dma_addr_t addr; | ||
25 | size_t len; | ||
26 | }; | ||
27 | |||
28 | struct mwifiex_cb { | ||
29 | struct mwifiex_dma_mapping dma_mapping; | ||
30 | union { | ||
31 | struct mwifiex_rxinfo rx_info; | ||
32 | struct mwifiex_txinfo tx_info; | ||
33 | }; | ||
34 | }; | ||
35 | |||
23 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) | 36 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) |
24 | { | 37 | { |
25 | return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t)); | 38 | struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; |
39 | |||
40 | BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb)); | ||
41 | return &cb->rx_info; | ||
26 | } | 42 | } |
27 | 43 | ||
28 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) | 44 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) |
29 | { | 45 | { |
30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t)); | 46 | struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; |
47 | |||
48 | return &cb->tx_info; | ||
31 | } | 49 | } |
32 | 50 | ||
33 | struct mwifiex_dma_mapping { | 51 | static inline void mwifiex_store_mapping(struct sk_buff *skb, |
34 | dma_addr_t addr; | 52 | struct mwifiex_dma_mapping *mapping) |
35 | size_t len; | 53 | { |
36 | }; | 54 | struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; |
55 | |||
56 | memcpy(&cb->dma_mapping, mapping, sizeof(*mapping)); | ||
57 | } | ||
37 | 58 | ||
38 | static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, | 59 | static inline void mwifiex_get_mapping(struct sk_buff *skb, |
39 | struct mwifiex_dma_mapping *mapping) | 60 | struct mwifiex_dma_mapping *mapping) |
40 | { | 61 | { |
41 | memcpy(mapping, skb->cb, sizeof(*mapping)); | 62 | struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; |
63 | |||
64 | memcpy(mapping, &cb->dma_mapping, sizeof(*mapping)); | ||
42 | } | 65 | } |
43 | 66 | ||
44 | static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) | 67 | static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) |
45 | { | 68 | { |
46 | struct mwifiex_dma_mapping mapping; | 69 | struct mwifiex_dma_mapping mapping; |
47 | 70 | ||
48 | MWIFIEX_SKB_PACB(skb, &mapping); | 71 | mwifiex_get_mapping(skb, &mapping); |
49 | 72 | ||
50 | return mapping.addr; | 73 | return mapping.addr; |
51 | } | 74 | } |