diff options
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 6d6ed748517..d32adeab68a 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -868,36 +868,35 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, | |||
868 | struct iwm_umac_notif_mgt_frame *mgt_frame = | 868 | struct iwm_umac_notif_mgt_frame *mgt_frame = |
869 | (struct iwm_umac_notif_mgt_frame *)buf; | 869 | (struct iwm_umac_notif_mgt_frame *)buf; |
870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; | 870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; |
871 | u8 *ie; | ||
872 | 871 | ||
873 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, | 872 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, |
874 | le16_to_cpu(mgt_frame->len)); | 873 | le16_to_cpu(mgt_frame->len)); |
875 | 874 | ||
876 | if (ieee80211_is_assoc_req(mgt->frame_control)) { | 875 | if (ieee80211_is_assoc_req(mgt->frame_control)) { |
877 | ie = mgt->u.assoc_req.variable;; | 876 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
878 | iwm->req_ie_len = | 877 | - offsetof(struct ieee80211_mgmt, |
879 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 878 | u.assoc_req.variable); |
880 | kfree(iwm->req_ie); | 879 | kfree(iwm->req_ie); |
881 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, | 880 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, |
882 | iwm->req_ie_len, GFP_KERNEL); | 881 | iwm->req_ie_len, GFP_KERNEL); |
883 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { | 882 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { |
884 | ie = mgt->u.reassoc_req.variable;; | 883 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
885 | iwm->req_ie_len = | 884 | - offsetof(struct ieee80211_mgmt, |
886 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 885 | u.reassoc_req.variable); |
887 | kfree(iwm->req_ie); | 886 | kfree(iwm->req_ie); |
888 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, | 887 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, |
889 | iwm->req_ie_len, GFP_KERNEL); | 888 | iwm->req_ie_len, GFP_KERNEL); |
890 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { | 889 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { |
891 | ie = mgt->u.assoc_resp.variable;; | 890 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
892 | iwm->resp_ie_len = | 891 | - offsetof(struct ieee80211_mgmt, |
893 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 892 | u.assoc_resp.variable); |
894 | kfree(iwm->resp_ie); | 893 | kfree(iwm->resp_ie); |
895 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, | 894 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, |
896 | iwm->resp_ie_len, GFP_KERNEL); | 895 | iwm->resp_ie_len, GFP_KERNEL); |
897 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { | 896 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { |
898 | ie = mgt->u.reassoc_resp.variable;; | 897 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
899 | iwm->resp_ie_len = | 898 | - offsetof(struct ieee80211_mgmt, |
900 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 899 | u.reassoc_resp.variable); |
901 | kfree(iwm->resp_ie); | 900 | kfree(iwm->resp_ie); |
902 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, | 901 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, |
903 | iwm->resp_ie_len, GFP_KERNEL); | 902 | iwm->resp_ie_len, GFP_KERNEL); |
@@ -1534,6 +1533,33 @@ static void classify8023(struct sk_buff *skb) | |||
1534 | } | 1533 | } |
1535 | } | 1534 | } |
1536 | 1535 | ||
1536 | static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) | ||
1537 | { | ||
1538 | struct wireless_dev *wdev = iwm_to_wdev(iwm); | ||
1539 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
1540 | struct sk_buff_head list; | ||
1541 | struct sk_buff *frame; | ||
1542 | |||
1543 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); | ||
1544 | |||
1545 | __skb_queue_head_init(&list); | ||
1546 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); | ||
1547 | |||
1548 | while ((frame = __skb_dequeue(&list))) { | ||
1549 | ndev->stats.rx_packets++; | ||
1550 | ndev->stats.rx_bytes += frame->len; | ||
1551 | |||
1552 | frame->protocol = eth_type_trans(frame, ndev); | ||
1553 | frame->ip_summed = CHECKSUM_NONE; | ||
1554 | memset(frame->cb, 0, sizeof(frame->cb)); | ||
1555 | |||
1556 | if (netif_rx_ni(frame) == NET_RX_DROP) { | ||
1557 | IWM_ERR(iwm, "Packet dropped\n"); | ||
1558 | ndev->stats.rx_dropped++; | ||
1559 | } | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1537 | static void iwm_rx_process_packet(struct iwm_priv *iwm, | 1563 | static void iwm_rx_process_packet(struct iwm_priv *iwm, |
1538 | struct iwm_rx_packet *packet, | 1564 | struct iwm_rx_packet *packet, |
1539 | struct iwm_rx_ticket_node *ticket_node) | 1565 | struct iwm_rx_ticket_node *ticket_node) |
@@ -1548,25 +1574,34 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1548 | switch (le16_to_cpu(ticket_node->ticket->action)) { | 1574 | switch (le16_to_cpu(ticket_node->ticket->action)) { |
1549 | case IWM_RX_TICKET_RELEASE: | 1575 | case IWM_RX_TICKET_RELEASE: |
1550 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); | 1576 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); |
1551 | classify8023(skb); | 1577 | |
1552 | iwm_rx_adjust_packet(iwm, packet, ticket_node); | 1578 | iwm_rx_adjust_packet(iwm, packet, ticket_node); |
1579 | skb->dev = iwm_to_ndev(iwm); | ||
1580 | classify8023(skb); | ||
1581 | |||
1582 | if (le16_to_cpu(ticket_node->ticket->flags) & | ||
1583 | IWM_RX_TICKET_AMSDU_MSK) { | ||
1584 | iwm_rx_process_amsdu(iwm, skb); | ||
1585 | break; | ||
1586 | } | ||
1587 | |||
1553 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); | 1588 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); |
1554 | if (ret < 0) { | 1589 | if (ret < 0) { |
1555 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " | 1590 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " |
1556 | "%d\n", ret); | 1591 | "%d\n", ret); |
1592 | kfree_skb(packet->skb); | ||
1557 | break; | 1593 | break; |
1558 | } | 1594 | } |
1559 | 1595 | ||
1560 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); | 1596 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); |
1561 | 1597 | ||
1562 | skb->dev = iwm_to_ndev(iwm); | 1598 | ndev->stats.rx_packets++; |
1599 | ndev->stats.rx_bytes += skb->len; | ||
1600 | |||
1563 | skb->protocol = eth_type_trans(skb, ndev); | 1601 | skb->protocol = eth_type_trans(skb, ndev); |
1564 | skb->ip_summed = CHECKSUM_NONE; | 1602 | skb->ip_summed = CHECKSUM_NONE; |
1565 | memset(skb->cb, 0, sizeof(skb->cb)); | 1603 | memset(skb->cb, 0, sizeof(skb->cb)); |
1566 | 1604 | ||
1567 | ndev->stats.rx_packets++; | ||
1568 | ndev->stats.rx_bytes += skb->len; | ||
1569 | |||
1570 | if (netif_rx_ni(skb) == NET_RX_DROP) { | 1605 | if (netif_rx_ni(skb) == NET_RX_DROP) { |
1571 | IWM_ERR(iwm, "Packet dropped\n"); | 1606 | IWM_ERR(iwm, "Packet dropped\n"); |
1572 | ndev->stats.rx_dropped++; | 1607 | ndev->stats.rx_dropped++; |