diff options
| author | Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 2015-03-15 10:00:19 -0400 |
|---|---|---|
| committer | Kalle Valo <kvalo@codeaurora.org> | 2015-03-20 02:33:19 -0400 |
| commit | c406ea7c7406f00aa1fb6c697d47d070fd222037 (patch) | |
| tree | 6d47a0202ed18a8219011422c81de335be8ff25b /drivers/net/wireless/ath | |
| parent | cec94d8cf5c2e5347ed9264cc94210e6376c7a46 (diff) | |
wil6210: Align Rx frames on 4*n+2 by having SNAP
For the networking code and for hardware network accelerators,
it is better to have IP header 4*n aligned. On the other side,
DMA on Rx path require buffer to be aligned on 4*n as well.
Having 14 bytes of Ethernet header, these 2 alignment
requests are in contradiction.
To solve this, order hardware offload block to not remove
SNAP header. This adds extra 6 bytes between addresses and
ethertype, making it 20 bytes total. This way, both buffer and
IP header are 4*n aligned. Remaining is only to remove SNAP
by shifting addresses 6 bytes. This involves data copying, so
this feature should be disabled unless required by the platform.
Module parameter "rx_align_2" (bool, default - false)
introduced to control this feature. Feature is completely disabled
when parameter is false.
Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath')
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 27 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.h | 3 |
4 files changed, 33 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 3feb86c47795..2453470bc191 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
| @@ -33,6 +33,15 @@ module_param(rtap_include_phy_info, bool, S_IRUGO); | |||
| 33 | MODULE_PARM_DESC(rtap_include_phy_info, | 33 | MODULE_PARM_DESC(rtap_include_phy_info, |
| 34 | " Include PHY info in the radiotap header, default - no"); | 34 | " Include PHY info in the radiotap header, default - no"); |
| 35 | 35 | ||
| 36 | bool rx_align_2; | ||
| 37 | module_param(rx_align_2, bool, S_IRUGO); | ||
| 38 | MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); | ||
| 39 | |||
| 40 | static inline uint wil_rx_snaplen(void) | ||
| 41 | { | ||
| 42 | return rx_align_2 ? 6 : 0; | ||
| 43 | } | ||
| 44 | |||
| 36 | static inline int wil_vring_is_empty(struct vring *vring) | 45 | static inline int wil_vring_is_empty(struct vring *vring) |
| 37 | { | 46 | { |
| 38 | return vring->swhead == vring->swtail; | 47 | return vring->swhead == vring->swtail; |
| @@ -209,7 +218,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | |||
| 209 | u32 i, int headroom) | 218 | u32 i, int headroom) |
| 210 | { | 219 | { |
| 211 | struct device *dev = wil_to_dev(wil); | 220 | struct device *dev = wil_to_dev(wil); |
| 212 | unsigned int sz = mtu_max + ETH_HLEN; | 221 | unsigned int sz = mtu_max + ETH_HLEN + wil_rx_snaplen(); |
| 213 | struct vring_rx_desc dd, *d = ⅆ | 222 | struct vring_rx_desc dd, *d = ⅆ |
| 214 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; | 223 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; |
| 215 | dma_addr_t pa; | 224 | dma_addr_t pa; |
| @@ -365,7 +374,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 365 | struct vring_rx_desc *d; | 374 | struct vring_rx_desc *d; |
| 366 | struct sk_buff *skb; | 375 | struct sk_buff *skb; |
| 367 | dma_addr_t pa; | 376 | dma_addr_t pa; |
| 368 | unsigned int sz = mtu_max + ETH_HLEN; | 377 | unsigned int snaplen = wil_rx_snaplen(); |
| 378 | unsigned int sz = mtu_max + ETH_HLEN + snaplen; | ||
| 369 | u16 dmalen; | 379 | u16 dmalen; |
| 370 | u8 ftype; | 380 | u8 ftype; |
| 371 | int cid; | 381 | int cid; |
| @@ -438,7 +448,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 438 | return NULL; | 448 | return NULL; |
| 439 | } | 449 | } |
| 440 | 450 | ||
| 441 | if (unlikely(skb->len < ETH_HLEN)) { | 451 | if (unlikely(skb->len < ETH_HLEN + snaplen)) { |
| 442 | wil_err(wil, "Short frame, len = %d\n", skb->len); | 452 | wil_err(wil, "Short frame, len = %d\n", skb->len); |
| 443 | /* TODO: process it (i.e. BAR) */ | 453 | /* TODO: process it (i.e. BAR) */ |
| 444 | kfree_skb(skb); | 454 | kfree_skb(skb); |
| @@ -460,6 +470,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 460 | */ | 470 | */ |
| 461 | } | 471 | } |
| 462 | 472 | ||
| 473 | if (snaplen) { | ||
| 474 | /* Packet layout | ||
| 475 | * +-------+-------+---------+------------+------+ | ||
| 476 | * | SA(6) | DA(6) | SNAP(6) | ETHTYPE(2) | DATA | | ||
| 477 | * +-------+-------+---------+------------+------+ | ||
| 478 | * Need to remove SNAP, shifting SA and DA forward | ||
| 479 | */ | ||
| 480 | memmove(skb->data + snaplen, skb->data, 2 * ETH_ALEN); | ||
| 481 | skb_pull(skb, snaplen); | ||
| 482 | } | ||
| 483 | |||
| 463 | return skb; | 484 | return skb; |
| 464 | } | 485 | } |
| 465 | 486 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index c1a71ab75a0e..a6b096eb7dee 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
| @@ -28,6 +28,7 @@ extern unsigned int mtu_max; | |||
| 28 | extern unsigned short rx_ring_overflow_thrsh; | 28 | extern unsigned short rx_ring_overflow_thrsh; |
| 29 | extern int agg_wsize; | 29 | extern int agg_wsize; |
| 30 | extern u32 vring_idle_trsh; | 30 | extern u32 vring_idle_trsh; |
| 31 | extern bool rx_align_2; | ||
| 31 | 32 | ||
| 32 | #define WIL_NAME "wil6210" | 33 | #define WIL_NAME "wil6210" |
| 33 | #define WIL_FW_NAME "wil6210.fw" /* code */ | 34 | #define WIL_FW_NAME "wil6210.fw" /* code */ |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 021313524913..8c18a46582db 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
| @@ -1109,6 +1109,11 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
| 1109 | */ | 1109 | */ |
| 1110 | cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS); | 1110 | cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS); |
| 1111 | } | 1111 | } |
| 1112 | |||
| 1113 | if (rx_align_2) | ||
| 1114 | cmd.l2_802_3_offload_ctrl |= | ||
| 1115 | L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK; | ||
| 1116 | |||
| 1112 | /* typical time for secure PCP is 840ms */ | 1117 | /* typical time for secure PCP is 840ms */ |
| 1113 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | 1118 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), |
| 1114 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | 1119 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 8a4af613e191..0979650e675d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
| @@ -687,6 +687,9 @@ struct wmi_cfg_rx_chain_cmd { | |||
| 687 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) | 687 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) |
| 688 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) | 688 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) |
| 689 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) | 689 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) |
| 690 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1) | ||
| 691 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1) | ||
| 692 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2) | ||
| 690 | u8 l2_802_3_offload_ctrl; | 693 | u8 l2_802_3_offload_ctrl; |
| 691 | 694 | ||
| 692 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) | 695 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) |
