aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-12-12 05:11:43 -0500
committerLuciano Coelho <coelho@ti.com>2012-04-12 01:43:59 -0400
commitcd70f6a48b3fbb841a127361ee4ac0752f9d29a2 (patch)
treefebdd2ba7cafd3115837b70c028e6f39b59d9493
parent5766435e2f704d0b2ec071639dcfd8f039aeb674 (diff)
wlcore/wl12xx: add hw op for getting rx buffer data alignment
An aligned data buffer is such where the Ethernet portion of the packet starts on a 4-byte boundary. Some chip families support padding the Rx data buffer to achieve such alignment, others rely on the host to perform it. Implement the HW op for getting alignment state in wl12xx. Add support for HW-padded alignment in the Rx flow. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h11
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.c26
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.h7
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h7
5 files changed, 46 insertions, 16 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 790c622afba7..43c2c7fcd4bd 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -31,6 +31,7 @@
31#include "../wlcore/io.h" 31#include "../wlcore/io.h"
32#include "../wlcore/acx.h" 32#include "../wlcore/acx.h"
33#include "../wlcore/tx.h" 33#include "../wlcore/tx.h"
34#include "../wlcore/rx.h"
34#include "../wlcore/boot.h" 35#include "../wlcore/boot.h"
35 36
36#include "reg.h" 37#include "reg.h"
@@ -734,6 +735,15 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
734 } 735 }
735} 736}
736 737
738static enum wl_rx_buf_align
739wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
740{
741 if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
742 return WLCORE_RX_BUF_UNALIGNED;
743
744 return WLCORE_RX_BUF_ALIGNED;
745}
746
737static bool wl12xx_mac_in_fuse(struct wl1271 *wl) 747static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
738{ 748{
739 bool supported = false; 749 bool supported = false;
@@ -805,6 +815,7 @@ static struct wlcore_ops wl12xx_ops = {
805 .calc_tx_blocks = wl12xx_calc_tx_blocks, 815 .calc_tx_blocks = wl12xx_calc_tx_blocks,
806 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, 816 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
807 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, 817 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
818 .get_rx_buf_align = wl12xx_get_rx_buf_align,
808 .get_pg_ver = wl12xx_get_pg_ver, 819 .get_pg_ver = wl12xx_get_pg_ver,
809 .get_mac = wl12xx_get_mac, 820 .get_mac = wl12xx_get_mac,
810}; 821};
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 7342f86020ce..fe6b83924294 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -23,6 +23,7 @@
23#define __WLCORE_HW_OPS_H__ 23#define __WLCORE_HW_OPS_H__
24 24
25#include "wlcore.h" 25#include "wlcore.h"
26#include "rx.h"
26 27
27static inline u32 28static inline u32
28wlcore_hw_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) 29wlcore_hw_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
@@ -54,4 +55,14 @@ wlcore_hw_set_tx_desc_data_len(struct wl1271 *wl,
54 wl->ops->set_tx_desc_data_len(wl, desc, skb); 55 wl->ops->set_tx_desc_data_len(wl, desc, skb);
55} 56}
56 57
58static inline enum wl_rx_buf_align
59wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
60{
61
62 if (!wl->ops->get_rx_buf_align)
63 BUG_ON(1);
64
65 return wl->ops->get_rx_buf_align(wl, rx_desc);
66}
67
57#endif 68#endif
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index f5811d63c79a..d1e420649d31 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -30,6 +30,7 @@
30#include "rx.h" 30#include "rx.h"
31#include "tx.h" 31#include "tx.h"
32#include "io.h" 32#include "io.h"
33#include "hw_ops.h"
33 34
34/* 35/*
35 * TODO: this is here just for now, it must be removed when the data 36 * TODO: this is here just for now, it must be removed when the data
@@ -62,14 +63,6 @@ static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len)
62 return pkt_len; 63 return pkt_len;
63} 64}
64 65
65static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
66 u32 drv_rx_counter)
67{
68 /* Convert the value to bool */
69 return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
70 RX_BUF_UNALIGNED_PAYLOAD);
71}
72
73static void wl1271_rx_status(struct wl1271 *wl, 66static void wl1271_rx_status(struct wl1271 *wl,
74 struct wl1271_rx_descriptor *desc, 67 struct wl1271_rx_descriptor *desc,
75 struct ieee80211_rx_status *status, 68 struct ieee80211_rx_status *status,
@@ -114,7 +107,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
114} 107}
115 108
116static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, 109static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
117 bool unaligned, u8 *hlid) 110 enum wl_rx_buf_align rx_align, u8 *hlid)
118{ 111{
119 struct wl1271_rx_descriptor *desc; 112 struct wl1271_rx_descriptor *desc;
120 struct sk_buff *skb; 113 struct sk_buff *skb;
@@ -122,7 +115,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
122 u8 *buf; 115 u8 *buf;
123 u8 beacon = 0; 116 u8 beacon = 0;
124 u8 is_data = 0; 117 u8 is_data = 0;
125 u8 reserved = unaligned ? NET_IP_ALIGN : 0; 118 u8 reserved = 0;
126 u16 seq_num; 119 u16 seq_num;
127 120
128 /* 121 /*
@@ -132,6 +125,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
132 if (unlikely(wl->plt)) 125 if (unlikely(wl->plt))
133 return -EINVAL; 126 return -EINVAL;
134 127
128 if (rx_align == WLCORE_RX_BUF_UNALIGNED)
129 reserved = NET_IP_ALIGN;
130
135 /* the data read starts with the descriptor */ 131 /* the data read starts with the descriptor */
136 desc = (struct wl1271_rx_descriptor *) data; 132 desc = (struct wl1271_rx_descriptor *) data;
137 133
@@ -177,6 +173,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
177 * payload aligned to 4 bytes. 173 * payload aligned to 4 bytes.
178 */ 174 */
179 memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); 175 memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
176 if (rx_align == WLCORE_RX_BUF_PADDED)
177 skb_pull(skb, NET_IP_ALIGN);
178
180 *hlid = desc->hlid; 179 *hlid = desc->hlid;
181 180
182 hdr = (struct ieee80211_hdr *)skb->data; 181 hdr = (struct ieee80211_hdr *)skb->data;
@@ -213,7 +212,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
213 u32 pkt_len, align_pkt_len; 212 u32 pkt_len, align_pkt_len;
214 u32 pkt_offset, des; 213 u32 pkt_offset, des;
215 u8 hlid; 214 u8 hlid;
216 bool unaligned = false; 215 enum wl_rx_buf_align rx_align;
217 216
218 while (drv_rx_counter != fw_rx_counter) { 217 while (drv_rx_counter != fw_rx_counter) {
219 buf_size = 0; 218 buf_size = 0;
@@ -264,8 +263,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
264 while (pkt_offset < buf_size) { 263 while (pkt_offset < buf_size) {
265 des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); 264 des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
266 pkt_len = wlcore_rx_get_buf_size(wl, des); 265 pkt_len = wlcore_rx_get_buf_size(wl, des);
267 unaligned = wl12xx_rx_get_unaligned(status, 266 rx_align = wlcore_hw_get_rx_buf_align(wl, des);
268 drv_rx_counter);
269 267
270 /* 268 /*
271 * the handle data call can only fail in memory-outage 269 * the handle data call can only fail in memory-outage
@@ -274,7 +272,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
274 */ 272 */
275 if (wl1271_rx_handle_data(wl, 273 if (wl1271_rx_handle_data(wl,
276 wl->aggr_buf + pkt_offset, 274 wl->aggr_buf + pkt_offset,
277 pkt_len, unaligned, 275 pkt_len, rx_align,
278 &hlid) == 1) { 276 &hlid) == 1) {
279 if (hlid < WL12XX_MAX_LINKS) 277 if (hlid < WL12XX_MAX_LINKS)
280 __set_bit(hlid, active_hlids); 278 __set_bit(hlid, active_hlids);
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index b30b1534637c..18eb38be7aa2 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -102,6 +102,13 @@
102/* If set, the start of IP payload is not 4 bytes aligned */ 102/* If set, the start of IP payload is not 4 bytes aligned */
103#define RX_BUF_UNALIGNED_PAYLOAD BIT(20) 103#define RX_BUF_UNALIGNED_PAYLOAD BIT(20)
104 104
105/* Describes the alignment state of a Rx buffer */
106enum wl_rx_buf_align {
107 WLCORE_RX_BUF_ALIGNED,
108 WLCORE_RX_BUF_UNALIGNED,
109 WLCORE_RX_BUF_PADDED,
110};
111
105enum { 112enum {
106 WL12XX_RX_CLASS_UNKNOWN, 113 WL12XX_RX_CLASS_UNKNOWN,
107 WL12XX_RX_CLASS_MANAGEMENT, 114 WL12XX_RX_CLASS_MANAGEMENT,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 9fc57e863eb5..3c2ded57c0d9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -27,11 +27,12 @@
27#include "wl12xx.h" 27#include "wl12xx.h"
28#include "event.h" 28#include "event.h"
29 29
30struct wl1271_tx_hw_descr;
31
32/* The maximum number of Tx descriptors in all chip families */ 30/* The maximum number of Tx descriptors in all chip families */
33#define WLCORE_MAX_TX_DESCRIPTORS 32 31#define WLCORE_MAX_TX_DESCRIPTORS 32
34 32
33/* forward declaration */
34struct wl1271_tx_hw_descr;
35enum wl_rx_buf_align;
35struct wlcore_ops { 36struct wlcore_ops {
36 int (*identify_chip)(struct wl1271 *wl); 37 int (*identify_chip)(struct wl1271 *wl);
37 int (*boot)(struct wl1271 *wl); 38 int (*boot)(struct wl1271 *wl);
@@ -44,6 +45,8 @@ struct wlcore_ops {
44 void (*set_tx_desc_data_len)(struct wl1271 *wl, 45 void (*set_tx_desc_data_len)(struct wl1271 *wl,
45 struct wl1271_tx_hw_descr *desc, 46 struct wl1271_tx_hw_descr *desc,
46 struct sk_buff *skb); 47 struct sk_buff *skb);
48 enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
49 u32 rx_desc);
47 s8 (*get_pg_ver)(struct wl1271 *wl); 50 s8 (*get_pg_ver)(struct wl1271 *wl);
48 void (*get_mac)(struct wl1271 *wl); 51 void (*get_mac)(struct wl1271 *wl);
49}; 52};