aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_rx.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/wl12xx/wl1271_rx.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_rx.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c91
1 files changed, 58 insertions, 33 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index ad8b6904c5eb..c723d9c7e131 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -21,23 +21,27 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/gfp.h>
25
24#include "wl1271.h" 26#include "wl1271.h"
25#include "wl1271_acx.h" 27#include "wl1271_acx.h"
26#include "wl1271_reg.h" 28#include "wl1271_reg.h"
27#include "wl1271_rx.h" 29#include "wl1271_rx.h"
28#include "wl1271_spi.h" 30#include "wl1271_spi.h"
31#include "wl1271_io.h"
29 32
30static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, 33static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
31 u32 drv_rx_counter) 34 u32 drv_rx_counter)
32{ 35{
33 return status->rx_pkt_descs[drv_rx_counter] & RX_MEM_BLOCK_MASK; 36 return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
37 RX_MEM_BLOCK_MASK;
34} 38}
35 39
36static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, 40static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
37 u32 drv_rx_counter) 41 u32 drv_rx_counter)
38{ 42{
39 return (status->rx_pkt_descs[drv_rx_counter] & RX_BUF_SIZE_MASK) >> 43 return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
40 RX_BUF_SIZE_SHIFT_DIV; 44 RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
41} 45}
42 46
43/* The values of this table must match the wl1271_rates[] array */ 47/* The values of this table must match the wl1271_rates[] array */
@@ -70,6 +74,36 @@ static u8 wl1271_rx_rate_to_idx[] = {
70 0 /* WL1271_RATE_1 */ 74 0 /* WL1271_RATE_1 */
71}; 75};
72 76
77/* The values of this table must match the wl1271_rates[] array */
78static u8 wl1271_5_ghz_rx_rate_to_idx[] = {
79 /* MCS rates are used only with 11n */
80 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
81 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
82 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
83 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
84 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
85 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
86 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
87 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
88
89 7, /* WL1271_RATE_54 */
90 6, /* WL1271_RATE_48 */
91 5, /* WL1271_RATE_36 */
92 4, /* WL1271_RATE_24 */
93
94 /* TI-specific rate */
95 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */
96
97 3, /* WL1271_RATE_18 */
98 2, /* WL1271_RATE_12 */
99 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */
100 1, /* WL1271_RATE_9 */
101 0, /* WL1271_RATE_6 */
102 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */
103 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */
104 WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */
105};
106
73static void wl1271_rx_status(struct wl1271 *wl, 107static void wl1271_rx_status(struct wl1271 *wl,
74 struct wl1271_rx_descriptor *desc, 108 struct wl1271_rx_descriptor *desc,
75 struct ieee80211_rx_status *status, 109 struct ieee80211_rx_status *status,
@@ -77,12 +111,21 @@ static void wl1271_rx_status(struct wl1271 *wl,
77{ 111{
78 memset(status, 0, sizeof(struct ieee80211_rx_status)); 112 memset(status, 0, sizeof(struct ieee80211_rx_status));
79 113
80 if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) 114 if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
115 WL1271_RX_DESC_BAND_BG) {
81 status->band = IEEE80211_BAND_2GHZ; 116 status->band = IEEE80211_BAND_2GHZ;
82 else 117 status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
118 } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
119 WL1271_RX_DESC_BAND_A) {
120 status->band = IEEE80211_BAND_5GHZ;
121 status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate];
122 } else
83 wl1271_warning("unsupported band 0x%x", 123 wl1271_warning("unsupported band 0x%x",
84 desc->flags & WL1271_RX_DESC_BAND_MASK); 124 desc->flags & WL1271_RX_DESC_BAND_MASK);
85 125
126 if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED))
127 wl1271_warning("unsupported rate");
128
86 /* 129 /*
87 * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the 130 * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the
88 * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we 131 * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we
@@ -91,12 +134,6 @@ static void wl1271_rx_status(struct wl1271 *wl,
91 */ 134 */
92 status->signal = desc->rssi; 135 status->signal = desc->rssi;
93 136
94 /* FIXME: Should this be optimized? */
95 status->qual = (desc->rssi - WL1271_RX_MIN_RSSI) * 100 /
96 (WL1271_RX_MAX_RSSI - WL1271_RX_MIN_RSSI);
97 status->qual = min(status->qual, 100);
98 status->qual = max(status->qual, 0);
99
100 /* 137 /*
101 * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we 138 * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we
102 * need to divide by two for now, but TI has been discussing about 139 * need to divide by two for now, but TI has been discussing about
@@ -109,17 +146,11 @@ static void wl1271_rx_status(struct wl1271 *wl,
109 if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { 146 if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
110 status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; 147 status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
111 148
112 if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL))) 149 if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL)))
113 status->flag |= RX_FLAG_DECRYPTED; 150 status->flag |= RX_FLAG_DECRYPTED;
114 151 if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL))
115 if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
116 status->flag |= RX_FLAG_MMIC_ERROR; 152 status->flag |= RX_FLAG_MMIC_ERROR;
117 } 153 }
118
119 status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
120
121 if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)
122 wl1271_warning("unsupported rate");
123} 154}
124 155
125static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) 156static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
@@ -131,14 +162,14 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
131 u8 *buf; 162 u8 *buf;
132 u8 beacon = 0; 163 u8 beacon = 0;
133 164
134 skb = dev_alloc_skb(length); 165 skb = __dev_alloc_skb(length, GFP_KERNEL);
135 if (!skb) { 166 if (!skb) {
136 wl1271_error("Couldn't allocate RX frame"); 167 wl1271_error("Couldn't allocate RX frame");
137 return; 168 return;
138 } 169 }
139 170
140 buf = skb_put(skb, length); 171 buf = skb_put(skb, length);
141 wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); 172 wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
142 173
143 /* the data read starts with the descriptor */ 174 /* the data read starts with the descriptor */
144 desc = (struct wl1271_rx_descriptor *) buf; 175 desc = (struct wl1271_rx_descriptor *) buf;
@@ -156,7 +187,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
156 beacon ? "beacon" : ""); 187 beacon ? "beacon" : "");
157 188
158 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); 189 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
159 ieee80211_rx(wl->hw, skb); 190 ieee80211_rx_ni(wl->hw, skb);
160} 191}
161 192
162void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) 193void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
@@ -176,25 +207,19 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
176 break; 207 break;
177 } 208 }
178 209
179 wl->rx_mem_pool_addr.addr = 210 wl->rx_mem_pool_addr.addr = (mem_block << 8) +
180 (mem_block << 8) + wl_mem_map->packet_memory_pool_start; 211 le32_to_cpu(wl_mem_map->packet_memory_pool_start);
181 wl->rx_mem_pool_addr.addr_extra = 212 wl->rx_mem_pool_addr.addr_extra =
182 wl->rx_mem_pool_addr.addr + 4; 213 wl->rx_mem_pool_addr.addr + 4;
183 214
184 /* Choose the block we want to read */ 215 /* Choose the block we want to read */
185 wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA, 216 wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
186 &wl->rx_mem_pool_addr, 217 sizeof(wl->rx_mem_pool_addr), false);
187 sizeof(wl->rx_mem_pool_addr), false);
188 218
189 wl1271_rx_handle_data(wl, buf_size); 219 wl1271_rx_handle_data(wl, buf_size);
190 220
191 wl->rx_counter++; 221 wl->rx_counter++;
192 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; 222 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
223 wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
193 } 224 }
194
195 wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
196
197 /* This is a workaround for some problems in the chip */
198 wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1);
199
200} 225}