wlcore: introduce Rx block-size alignment HW quirk
authorArik Nemtsov <arik@wizery.com>
Mon, 12 Dec 2011 10:09:12 +0000 (12:09 +0200)
committerLuciano Coelho <coelho@ti.com>
Thu, 12 Apr 2012 05:43:59 +0000 (08:43 +0300)
For chip-families that support aligned buffers in the Rx side. The Rx
flow changes slightly for these chips.

Currently these modifications rely on a hard-coded block-size of 256.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/wlcore.h

index db761af4b3c1459fd8ea4f98d69a7e0f4e8e4cf4..f5811d63c79a351b6738c01b766dea9a119a0024 100644 (file)
@@ -44,11 +44,22 @@ static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
                RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
-                                u32 drv_rx_counter)
+static u32 wlcore_rx_get_buf_size(struct wl1271 *wl,
+                                 u32 rx_pkt_desc)
 {
-       return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
-               RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
+       if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
+               return (rx_pkt_desc & ALIGNED_RX_BUF_SIZE_MASK) >>
+                      ALIGNED_RX_BUF_SIZE_SHIFT;
+
+       return (rx_pkt_desc & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
+}
+
+static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len)
+{
+       if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
+               return ALIGN(pkt_len, WL12XX_BUS_BLOCK_SIZE);
+
+       return pkt_len;
 }
 
 static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
@@ -199,8 +210,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
        u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
        u32 rx_counter;
        u32 mem_block;
-       u32 pkt_length;
-       u32 pkt_offset;
+       u32 pkt_len, align_pkt_len;
+       u32 pkt_offset, des;
        u8 hlid;
        bool unaligned = false;
 
@@ -208,10 +219,13 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                buf_size = 0;
                rx_counter = drv_rx_counter;
                while (rx_counter != fw_rx_counter) {
-                       pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
-                       if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
+                       des = le32_to_cpu(status->rx_pkt_descs[rx_counter]);
+                       pkt_len = wlcore_rx_get_buf_size(wl, des);
+                       align_pkt_len = wlcore_rx_get_align_buf_size(wl,
+                                                                    pkt_len);
+                       if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE)
                                break;
-                       buf_size += pkt_length;
+                       buf_size += align_pkt_len;
                        rx_counter++;
                        rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
                }
@@ -248,9 +262,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                /* Split data into separate packets */
                pkt_offset = 0;
                while (pkt_offset < buf_size) {
-                       pkt_length = wl12xx_rx_get_buf_size(status,
-                                       drv_rx_counter);
-
+                       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);
 
@@ -261,7 +274,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                         */
                        if (wl1271_rx_handle_data(wl,
                                                  wl->aggr_buf + pkt_offset,
-                                                 pkt_length, unaligned,
+                                                 pkt_len, unaligned,
                                                  &hlid) == 1) {
                                if (hlid < WL12XX_MAX_LINKS)
                                        __set_bit(hlid, active_hlids);
@@ -274,7 +287,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                        wl->rx_counter++;
                        drv_rx_counter++;
                        drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
-                       pkt_offset += pkt_length;
+                       pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len);
                }
        }
 
index 86ba6b1d0cdc42a59889cb364d95f29d6c911d2b..b30b1534637c3e9c42834a2b8acc854988fe0a4c 100644 (file)
@@ -96,6 +96,9 @@
 #define RX_MEM_BLOCK_MASK            0xFF
 #define RX_BUF_SIZE_MASK             0xFFF00
 #define RX_BUF_SIZE_SHIFT_DIV        6
+#define ALIGNED_RX_BUF_SIZE_MASK     0xFFFF00
+#define ALIGNED_RX_BUF_SIZE_SHIFT    8
+
 /* If set, the start of IP payload is not 4 bytes aligned */
 #define RX_BUF_UNALIGNED_PAYLOAD     BIT(20)
 
index 3c0fbc6ce750dbf139922514c6f3daa2af34fd4b..9fc57e863eb50bec66ebd275b905664cd5ece054 100644 (file)
@@ -346,6 +346,9 @@ int wlcore_free_hw(struct wl1271 *wl);
 /* wl127x and SPI don't support SDIO block size alignment */
 #define WLCORE_QUIRK_NO_BLOCKSIZE_ALIGNMENT    BIT(2)
 
+/* means aggregated Rx packets are aligned to a SDIO block */
+#define WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN                BIT(3)
+
 /* Older firmwares did not implement the FW logger over bus feature */
 #define WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED     BIT(4)