aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c125
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c22
2 files changed, 20 insertions, 127 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 2b2cca5e6d0f..d3d5e0853c45 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -136,131 +136,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
136} 136}
137 137
138/* 138/*
139 * Counts the number of subframes in an aggregate packet.
140 *
141 * This function parses an aggregate packet buffer, looking for
142 * subframes and counting the number of such subframe found. The
143 * function automatically skips the DA/SA fields at the beginning
144 * of each subframe and padding at the end.
145 */
146static int
147mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len)
148{
149 int pkt_count = 0, pkt_len, pad;
150
151 while (total_pkt_len > 0) {
152 /* Length will be in network format, change it to host */
153 pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN)));
154 pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ?
155 (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0;
156 data += pkt_len + pad + sizeof(struct ethhdr);
157 total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr);
158 ++pkt_count;
159 }
160
161 return pkt_count;
162}
163
164/*
165 * De-aggregate received packets.
166 *
167 * This function parses the received aggregate buffer, extracts each subframe,
168 * strips off the SNAP header from them and sends the data portion for further
169 * processing.
170 *
171 * Each subframe body is copied onto a separate buffer, which are freed by
172 * upper layer after processing. The function also performs sanity tests on
173 * the received buffer.
174 */
175int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
176 struct sk_buff *skb)
177{
178 u16 pkt_len;
179 int total_pkt_len;
180 u8 *data;
181 int pad;
182 struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
183 struct rxpd *local_rx_pd = (struct rxpd *) skb->data;
184 struct sk_buff *skb_daggr;
185 struct mwifiex_rxinfo *rx_info_daggr;
186 int ret = -1;
187 struct rx_packet_hdr *rx_pkt_hdr;
188 struct mwifiex_adapter *adapter = priv->adapter;
189 u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
190
191 data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset);
192 total_pkt_len = local_rx_pd->rx_pkt_length;
193
194 /* Sanity test */
195 if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) {
196 dev_err(adapter->dev, "total pkt len greater than buffer"
197 " size %d\n", total_pkt_len);
198 return -1;
199 }
200
201 rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len);
202
203 while (total_pkt_len > 0) {
204 rx_pkt_hdr = (struct rx_packet_hdr *) data;
205 /* Length will be in network format, change it to host */
206 pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN)));
207 if (pkt_len > total_pkt_len) {
208 dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n",
209 total_pkt_len, pkt_len);
210 break;
211 }
212
213 pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ?
214 (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0;
215
216 total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr);
217
218 if (memcmp(&rx_pkt_hdr->rfc1042_hdr,
219 rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
220 memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN);
221 data += LLC_SNAP_LEN;
222 pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN;
223 } else {
224 *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0;
225 pkt_len += sizeof(struct ethhdr);
226 }
227
228 skb_daggr = dev_alloc_skb(pkt_len);
229 if (!skb_daggr) {
230 dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n",
231 __func__);
232 return -1;
233 }
234 rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr);
235
236 rx_info_daggr->bss_index = rx_info->bss_index;
237 skb_daggr->tstamp = skb->tstamp;
238 rx_info_daggr->parent = skb;
239 skb_daggr->priority = skb->priority;
240 skb_put(skb_daggr, pkt_len);
241 memcpy(skb_daggr->data, data, pkt_len);
242
243 ret = mwifiex_recv_packet(adapter, skb_daggr);
244
245 switch (ret) {
246 case -EINPROGRESS:
247 break;
248 case -1:
249 dev_err(adapter->dev, "deaggr: host_to_card failed\n");
250 case 0:
251 mwifiex_recv_packet_complete(adapter, skb_daggr, ret);
252 break;
253 default:
254 break;
255 }
256
257 data += pkt_len + pad;
258 }
259
260 return ret;
261}
262
263/*
264 * Create aggregated packet. 139 * Create aggregated packet.
265 * 140 *
266 * This function creates an aggregated MSDU packet, by combining buffers 141 * This function creates an aggregated MSDU packet, by combining buffers
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index e047f0d8a983..1fdddece7479 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -141,10 +141,28 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
141 dev_kfree_skb_any(skb); 141 dev_kfree_skb_any(skb);
142 return ret; 142 return ret;
143 } 143 }
144
144 if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { 145 if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
145 mwifiex_11n_deaggregate_pkt(priv, skb); 146 struct sk_buff_head list;
146 return ret; 147 struct sk_buff *rx_skb;
148
149 __skb_queue_head_init(&list);
150
151 skb_pull(skb, local_rx_pd->rx_pkt_offset);
152 skb_trim(skb, local_rx_pd->rx_pkt_length);
153
154 ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
155 priv->wdev->iftype, 0, false);
156
157 while (!skb_queue_empty(&list)) {
158 rx_skb = __skb_dequeue(&list);
159 ret = mwifiex_recv_packet(adapter, rx_skb);
160 if (ret == -1)
161 dev_err(adapter->dev, "Rx of A-MSDU failed");
162 }
163 return 0;
147 } 164 }
165
148 /* 166 /*
149 * If the packet is not an unicast packet then send the packet 167 * If the packet is not an unicast packet then send the packet
150 * directly to os. Don't pass thru rx reordering 168 * directly to os. Don't pass thru rx reordering