wlcore/wl12xx: add hw op for getting rx buffer data alignment
authorArik Nemtsov <arik@wizery.com>
Mon, 12 Dec 2011 10:11:43 +0000 (12:11 +0200)
committerLuciano Coelho <coelho@ti.com>
Thu, 12 Apr 2012 05:43:59 +0000 (08:43 +0300)
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>
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/wlcore.h

index 790c622afba761d9a1ccef30460881e7109305f9..43c2c7fcd4bd143853d7da2ceb8e0e9dbb5decc7 100644 (file)
@@ -31,6 +31,7 @@
 #include "../wlcore/io.h"
 #include "../wlcore/acx.h"
 #include "../wlcore/tx.h"
+#include "../wlcore/rx.h"
 #include "../wlcore/boot.h"
 
 #include "reg.h"
@@ -734,6 +735,15 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
        }
 }
 
+static enum wl_rx_buf_align
+wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
+{
+       if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
+               return WLCORE_RX_BUF_UNALIGNED;
+
+       return WLCORE_RX_BUF_ALIGNED;
+}
+
 static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
 {
        bool supported = false;
@@ -805,6 +815,7 @@ static struct wlcore_ops wl12xx_ops = {
        .calc_tx_blocks         = wl12xx_calc_tx_blocks,
        .set_tx_desc_blocks     = wl12xx_set_tx_desc_blocks,
        .set_tx_desc_data_len   = wl12xx_set_tx_desc_data_len,
+       .get_rx_buf_align       = wl12xx_get_rx_buf_align,
        .get_pg_ver             = wl12xx_get_pg_ver,
        .get_mac                = wl12xx_get_mac,
 };
index 7342f86020cec68b2e238efa9bb1300349d4125c..fe6b839242947c24398872c979f75a136f0253e6 100644 (file)
@@ -23,6 +23,7 @@
 #define __WLCORE_HW_OPS_H__
 
 #include "wlcore.h"
+#include "rx.h"
 
 static inline u32
 wlcore_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,
        wl->ops->set_tx_desc_data_len(wl, desc, skb);
 }
 
+static inline enum wl_rx_buf_align
+wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
+{
+
+       if (!wl->ops->get_rx_buf_align)
+               BUG_ON(1);
+
+       return wl->ops->get_rx_buf_align(wl, rx_desc);
+}
+
 #endif
index f5811d63c79a351b6738c01b766dea9a119a0024..d1e420649d31f7521f3e2dc56a251fb2faaf2def 100644 (file)
@@ -30,6 +30,7 @@
 #include "rx.h"
 #include "tx.h"
 #include "io.h"
+#include "hw_ops.h"
 
 /*
  * 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)
        return pkt_len;
 }
 
-static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
-                                   u32 drv_rx_counter)
-{
-       /* Convert the value to bool */
-       return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
-               RX_BUF_UNALIGNED_PAYLOAD);
-}
-
 static void wl1271_rx_status(struct wl1271 *wl,
                             struct wl1271_rx_descriptor *desc,
                             struct ieee80211_rx_status *status,
@@ -114,7 +107,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
 }
 
 static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
-                                bool unaligned, u8 *hlid)
+                                enum wl_rx_buf_align rx_align, u8 *hlid)
 {
        struct wl1271_rx_descriptor *desc;
        struct sk_buff *skb;
@@ -122,7 +115,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        u8 *buf;
        u8 beacon = 0;
        u8 is_data = 0;
-       u8 reserved = unaligned ? NET_IP_ALIGN : 0;
+       u8 reserved = 0;
        u16 seq_num;
 
        /*
@@ -132,6 +125,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        if (unlikely(wl->plt))
                return -EINVAL;
 
+       if (rx_align == WLCORE_RX_BUF_UNALIGNED)
+               reserved = NET_IP_ALIGN;
+
        /* the data read starts with the descriptor */
        desc = (struct wl1271_rx_descriptor *) data;
 
@@ -177,6 +173,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
         * payload aligned to 4 bytes.
         */
        memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
+       if (rx_align == WLCORE_RX_BUF_PADDED)
+               skb_pull(skb, NET_IP_ALIGN);
+
        *hlid = desc->hlid;
 
        hdr = (struct ieee80211_hdr *)skb->data;
@@ -213,7 +212,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
        u32 pkt_len, align_pkt_len;
        u32 pkt_offset, des;
        u8 hlid;
-       bool unaligned = false;
+       enum wl_rx_buf_align rx_align;
 
        while (drv_rx_counter != fw_rx_counter) {
                buf_size = 0;
@@ -264,8 +263,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                while (pkt_offset < buf_size) {
                        des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
                        pkt_len = wlcore_rx_get_buf_size(wl, des);
-                       unaligned = wl12xx_rx_get_unaligned(status,
-                                       drv_rx_counter);
+                       rx_align = wlcore_hw_get_rx_buf_align(wl, des);
 
                        /*
                         * 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)
                         */
                        if (wl1271_rx_handle_data(wl,
                                                  wl->aggr_buf + pkt_offset,
-                                                 pkt_len, unaligned,
+                                                 pkt_len, rx_align,
                                                  &hlid) == 1) {
                                if (hlid < WL12XX_MAX_LINKS)
                                        __set_bit(hlid, active_hlids);
index b30b1534637c3e9c42834a2b8acc854988fe0a4c..18eb38be7aa2d0c24d40b11cdc58b749e1ce1e54 100644 (file)
 /* If set, the start of IP payload is not 4 bytes aligned */
 #define RX_BUF_UNALIGNED_PAYLOAD     BIT(20)
 
+/* Describes the alignment state of a Rx buffer */
+enum wl_rx_buf_align {
+       WLCORE_RX_BUF_ALIGNED,
+       WLCORE_RX_BUF_UNALIGNED,
+       WLCORE_RX_BUF_PADDED,
+};
+
 enum {
        WL12XX_RX_CLASS_UNKNOWN,
        WL12XX_RX_CLASS_MANAGEMENT,
index 9fc57e863eb50bec66ebd275b905664cd5ece054..3c2ded57c0d9924f5cc18972b74d2f61205cf98a 100644 (file)
 #include "wl12xx.h"
 #include "event.h"
 
-struct wl1271_tx_hw_descr;
-
 /* The maximum number of Tx descriptors in all chip families */
 #define WLCORE_MAX_TX_DESCRIPTORS 32
 
+/* forward declaration */
+struct wl1271_tx_hw_descr;
+enum wl_rx_buf_align;
 struct wlcore_ops {
        int (*identify_chip)(struct wl1271 *wl);
        int (*boot)(struct wl1271 *wl);
@@ -44,6 +45,8 @@ struct wlcore_ops {
        void (*set_tx_desc_data_len)(struct wl1271 *wl,
                                     struct wl1271_tx_hw_descr *desc,
                                     struct sk_buff *skb);
+       enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
+                                                u32 rx_desc);
        s8 (*get_pg_ver)(struct wl1271 *wl);
        void (*get_mac)(struct wl1271 *wl);
 };