diff options
author | Zhu Yi <yi.zhu@intel.com> | 2009-11-30 21:18:38 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-12-22 13:31:16 -0500 |
commit | 18974b5b0b5e758d416c550553b143e5c8038281 (patch) | |
tree | 58a50707ace9a9be37c525e6fd72cba18b90fde3 /drivers | |
parent | eaf85ca7fecb218fc41ff57c1642ca73b097aabb (diff) |
iwmc3200wifi: rx aggregation support
When the device receives an A-MSDU frame (indicated by flag
IWM_RX_TICKET_AMSDU_MSK), use ieee80211_amsdu_to_8023s to convert
it to a list of 802.3 frames and handled them to upper layer.
Cc: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 72c27a3e5528..6bd253ac533f 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -1534,6 +1534,33 @@ static void classify8023(struct sk_buff *skb) | |||
1534 | } | 1534 | } |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) | ||
1538 | { | ||
1539 | struct wireless_dev *wdev = iwm_to_wdev(iwm); | ||
1540 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
1541 | struct sk_buff_head list; | ||
1542 | struct sk_buff *frame; | ||
1543 | |||
1544 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); | ||
1545 | |||
1546 | __skb_queue_head_init(&list); | ||
1547 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); | ||
1548 | |||
1549 | while ((frame = __skb_dequeue(&list))) { | ||
1550 | ndev->stats.rx_packets++; | ||
1551 | ndev->stats.rx_bytes += frame->len; | ||
1552 | |||
1553 | frame->protocol = eth_type_trans(frame, ndev); | ||
1554 | frame->ip_summed = CHECKSUM_NONE; | ||
1555 | memset(frame->cb, 0, sizeof(frame->cb)); | ||
1556 | |||
1557 | if (netif_rx_ni(frame) == NET_RX_DROP) { | ||
1558 | IWM_ERR(iwm, "Packet dropped\n"); | ||
1559 | ndev->stats.rx_dropped++; | ||
1560 | } | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1537 | static void iwm_rx_process_packet(struct iwm_priv *iwm, | 1564 | static void iwm_rx_process_packet(struct iwm_priv *iwm, |
1538 | struct iwm_rx_packet *packet, | 1565 | struct iwm_rx_packet *packet, |
1539 | struct iwm_rx_ticket_node *ticket_node) | 1566 | struct iwm_rx_ticket_node *ticket_node) |
@@ -1548,25 +1575,34 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1548 | switch (le16_to_cpu(ticket_node->ticket->action)) { | 1575 | switch (le16_to_cpu(ticket_node->ticket->action)) { |
1549 | case IWM_RX_TICKET_RELEASE: | 1576 | case IWM_RX_TICKET_RELEASE: |
1550 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); | 1577 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); |
1551 | classify8023(skb); | 1578 | |
1552 | iwm_rx_adjust_packet(iwm, packet, ticket_node); | 1579 | iwm_rx_adjust_packet(iwm, packet, ticket_node); |
1580 | skb->dev = iwm_to_ndev(iwm); | ||
1581 | classify8023(skb); | ||
1582 | |||
1583 | if (le16_to_cpu(ticket_node->ticket->flags) & | ||
1584 | IWM_RX_TICKET_AMSDU_MSK) { | ||
1585 | iwm_rx_process_amsdu(iwm, skb); | ||
1586 | break; | ||
1587 | } | ||
1588 | |||
1553 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); | 1589 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); |
1554 | if (ret < 0) { | 1590 | if (ret < 0) { |
1555 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " | 1591 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " |
1556 | "%d\n", ret); | 1592 | "%d\n", ret); |
1593 | kfree_skb(packet->skb); | ||
1557 | break; | 1594 | break; |
1558 | } | 1595 | } |
1559 | 1596 | ||
1560 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); | 1597 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); |
1561 | 1598 | ||
1562 | skb->dev = iwm_to_ndev(iwm); | 1599 | ndev->stats.rx_packets++; |
1600 | ndev->stats.rx_bytes += skb->len; | ||
1601 | |||
1563 | skb->protocol = eth_type_trans(skb, ndev); | 1602 | skb->protocol = eth_type_trans(skb, ndev); |
1564 | skb->ip_summed = CHECKSUM_NONE; | 1603 | skb->ip_summed = CHECKSUM_NONE; |
1565 | memset(skb->cb, 0, sizeof(skb->cb)); | 1604 | memset(skb->cb, 0, sizeof(skb->cb)); |
1566 | 1605 | ||
1567 | ndev->stats.rx_packets++; | ||
1568 | ndev->stats.rx_bytes += skb->len; | ||
1569 | |||
1570 | if (netif_rx_ni(skb) == NET_RX_DROP) { | 1606 | if (netif_rx_ni(skb) == NET_RX_DROP) { |
1571 | IWM_ERR(iwm, "Packet dropped\n"); | 1607 | IWM_ERR(iwm, "Packet dropped\n"); |
1572 | ndev->stats.rx_dropped++; | 1608 | ndev->stats.rx_dropped++; |