diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/wl12xx/wl1271_rx.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (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.c | 91 |
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 | ||
30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 33 | static 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 | ||
36 | static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | 40 | static 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 */ | ||
78 | static 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 | |||
73 | static void wl1271_rx_status(struct wl1271 *wl, | 107 | static 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 | ||
125 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | 156 | static 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 | ||
162 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | 193 | void 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 | } |