diff options
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 226 |
1 files changed, 196 insertions, 30 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 771a301003c9..3257d4fad835 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/ieee80211.h> | 44 | #include <linux/ieee80211.h> |
45 | #include <linux/if_arp.h> | 45 | #include <linux/if_arp.h> |
46 | #include <linux/list.h> | 46 | #include <linux/list.h> |
47 | #include <linux/slab.h> | ||
47 | #include <net/iw_handler.h> | 48 | #include <net/iw_handler.h> |
48 | 49 | ||
49 | #include "iwm.h" | 50 | #include "iwm.h" |
@@ -423,7 +424,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, | |||
423 | if (IS_ERR(ticket_node)) | 424 | if (IS_ERR(ticket_node)) |
424 | return PTR_ERR(ticket_node); | 425 | return PTR_ERR(ticket_node); |
425 | 426 | ||
426 | IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", | 427 | IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", |
428 | ticket->action == IWM_RX_TICKET_RELEASE ? | ||
429 | "RELEASE" : "DROP", | ||
427 | ticket->id); | 430 | ticket->id); |
428 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); | 431 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); |
429 | 432 | ||
@@ -500,6 +503,18 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, | |||
500 | return 0; | 503 | return 0; |
501 | } | 504 | } |
502 | 505 | ||
506 | static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm) | ||
507 | { | ||
508 | if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 || | ||
509 | iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) && | ||
510 | (iwm->umac_profile->sec.ucast_cipher == | ||
511 | iwm->umac_profile->sec.mcast_cipher) && | ||
512 | (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN)) | ||
513 | return 1; | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
503 | static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | 518 | static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, |
504 | unsigned long buf_size, | 519 | unsigned long buf_size, |
505 | struct iwm_wifi_cmd *cmd) | 520 | struct iwm_wifi_cmd *cmd) |
@@ -565,11 +580,17 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
565 | goto ibss; | 580 | goto ibss; |
566 | 581 | ||
567 | if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) | 582 | if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) |
568 | cfg80211_connect_result(iwm_to_ndev(iwm), | 583 | if (!iwm_is_open_wep_profile(iwm)) { |
569 | complete->bssid, | 584 | cfg80211_connect_result(iwm_to_ndev(iwm), |
570 | NULL, 0, NULL, 0, | 585 | complete->bssid, |
571 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 586 | NULL, 0, NULL, 0, |
572 | GFP_KERNEL); | 587 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
588 | GFP_KERNEL); | ||
589 | } else { | ||
590 | /* Let's try shared WEP auth */ | ||
591 | IWM_ERR(iwm, "Trying WEP shared auth\n"); | ||
592 | schedule_work(&iwm->auth_retry_worker); | ||
593 | } | ||
573 | else | 594 | else |
574 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, | 595 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, |
575 | GFP_KERNEL); | 596 | GFP_KERNEL); |
@@ -713,6 +734,19 @@ static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf, | |||
713 | return 0; | 734 | return 0; |
714 | } | 735 | } |
715 | 736 | ||
737 | static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf, | ||
738 | unsigned long buf_size, | ||
739 | struct iwm_wifi_cmd *cmd) | ||
740 | { | ||
741 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | ||
742 | |||
743 | IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n"); | ||
744 | |||
745 | wiphy_rfkill_set_hw_state(wiphy, true); | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
716 | static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | 750 | static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, |
717 | unsigned long buf_size, | 751 | unsigned long buf_size, |
718 | struct iwm_wifi_cmd *cmd) | 752 | struct iwm_wifi_cmd *cmd) |
@@ -761,7 +795,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | |||
761 | } | 795 | } |
762 | 796 | ||
763 | bss->bss = kzalloc(bss_len, GFP_KERNEL); | 797 | bss->bss = kzalloc(bss_len, GFP_KERNEL); |
764 | if (!bss) { | 798 | if (!bss->bss) { |
765 | kfree(bss); | 799 | kfree(bss); |
766 | IWM_ERR(iwm, "Couldn't allocate bss\n"); | 800 | IWM_ERR(iwm, "Couldn't allocate bss\n"); |
767 | return -ENOMEM; | 801 | return -ENOMEM; |
@@ -835,36 +869,35 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, | |||
835 | struct iwm_umac_notif_mgt_frame *mgt_frame = | 869 | struct iwm_umac_notif_mgt_frame *mgt_frame = |
836 | (struct iwm_umac_notif_mgt_frame *)buf; | 870 | (struct iwm_umac_notif_mgt_frame *)buf; |
837 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; | 871 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; |
838 | u8 *ie; | ||
839 | 872 | ||
840 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, | 873 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, |
841 | le16_to_cpu(mgt_frame->len)); | 874 | le16_to_cpu(mgt_frame->len)); |
842 | 875 | ||
843 | if (ieee80211_is_assoc_req(mgt->frame_control)) { | 876 | if (ieee80211_is_assoc_req(mgt->frame_control)) { |
844 | ie = mgt->u.assoc_req.variable;; | 877 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
845 | iwm->req_ie_len = | 878 | - offsetof(struct ieee80211_mgmt, |
846 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 879 | u.assoc_req.variable); |
847 | kfree(iwm->req_ie); | 880 | kfree(iwm->req_ie); |
848 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, | 881 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, |
849 | iwm->req_ie_len, GFP_KERNEL); | 882 | iwm->req_ie_len, GFP_KERNEL); |
850 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { | 883 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { |
851 | ie = mgt->u.reassoc_req.variable;; | 884 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
852 | iwm->req_ie_len = | 885 | - offsetof(struct ieee80211_mgmt, |
853 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 886 | u.reassoc_req.variable); |
854 | kfree(iwm->req_ie); | 887 | kfree(iwm->req_ie); |
855 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, | 888 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, |
856 | iwm->req_ie_len, GFP_KERNEL); | 889 | iwm->req_ie_len, GFP_KERNEL); |
857 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { | 890 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { |
858 | ie = mgt->u.assoc_resp.variable;; | 891 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
859 | iwm->resp_ie_len = | 892 | - offsetof(struct ieee80211_mgmt, |
860 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 893 | u.assoc_resp.variable); |
861 | kfree(iwm->resp_ie); | 894 | kfree(iwm->resp_ie); |
862 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, | 895 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, |
863 | iwm->resp_ie_len, GFP_KERNEL); | 896 | iwm->resp_ie_len, GFP_KERNEL); |
864 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { | 897 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { |
865 | ie = mgt->u.reassoc_resp.variable;; | 898 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
866 | iwm->resp_ie_len = | 899 | - offsetof(struct ieee80211_mgmt, |
867 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 900 | u.reassoc_resp.variable); |
868 | kfree(iwm->resp_ie); | 901 | kfree(iwm->resp_ie); |
869 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, | 902 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, |
870 | iwm->resp_ie_len, GFP_KERNEL); | 903 | iwm->resp_ie_len, GFP_KERNEL); |
@@ -899,6 +932,8 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, | |||
899 | case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: | 932 | case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: |
900 | IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); | 933 | IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); |
901 | break; | 934 | break; |
935 | case WIFI_IF_NTFY_RADIO_PREEMPTION: | ||
936 | return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd); | ||
902 | case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: | 937 | case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: |
903 | return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); | 938 | return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); |
904 | case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: | 939 | case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: |
@@ -1052,12 +1087,83 @@ static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf, | |||
1052 | return 0; | 1087 | return 0; |
1053 | } | 1088 | } |
1054 | 1089 | ||
1090 | static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf, | ||
1091 | unsigned long buf_size, | ||
1092 | struct iwm_wifi_cmd *cmd) | ||
1093 | { | ||
1094 | struct iwm_umac_notif_stop_resume_tx *stp_res_tx = | ||
1095 | (struct iwm_umac_notif_stop_resume_tx *)buf; | ||
1096 | struct iwm_sta_info *sta_info; | ||
1097 | struct iwm_tid_info *tid_info; | ||
1098 | u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id); | ||
1099 | u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk); | ||
1100 | int bit, ret = 0; | ||
1101 | bool stop = false; | ||
1102 | |||
1103 | IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n" | ||
1104 | "\tflags: 0x%x\n" | ||
1105 | "\tSTA id: %d\n" | ||
1106 | "\tTID bitmask: 0x%x\n", | ||
1107 | stp_res_tx->flags, stp_res_tx->sta_id, | ||
1108 | stp_res_tx->stop_resume_tid_msk); | ||
1109 | |||
1110 | if (stp_res_tx->flags & UMAC_STOP_TX_FLAG) | ||
1111 | stop = true; | ||
1112 | |||
1113 | sta_info = &iwm->sta_table[sta_id]; | ||
1114 | if (!sta_info->valid) { | ||
1115 | IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n", | ||
1116 | sta_id, stp_res_tx->sta_id); | ||
1117 | return -EINVAL; | ||
1118 | } | ||
1119 | |||
1120 | for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) { | ||
1121 | tid_info = &sta_info->tid_info[bit]; | ||
1122 | |||
1123 | mutex_lock(&tid_info->mutex); | ||
1124 | tid_info->stopped = stop; | ||
1125 | mutex_unlock(&tid_info->mutex); | ||
1126 | |||
1127 | if (!stop) { | ||
1128 | struct iwm_tx_queue *txq; | ||
1129 | int queue = iwm_tid_to_queue(bit); | ||
1130 | |||
1131 | if (queue < 0) | ||
1132 | continue; | ||
1133 | |||
1134 | txq = &iwm->txq[queue]; | ||
1135 | /* | ||
1136 | * If we resume, we have to move our SKBs | ||
1137 | * back to the tx queue and queue some work. | ||
1138 | */ | ||
1139 | spin_lock_bh(&txq->lock); | ||
1140 | skb_queue_splice_init(&txq->queue, &txq->stopped_queue); | ||
1141 | spin_unlock_bh(&txq->lock); | ||
1142 | |||
1143 | queue_work(txq->wq, &txq->worker); | ||
1144 | } | ||
1145 | |||
1146 | } | ||
1147 | |||
1148 | /* We send an ACK only for the stop case */ | ||
1149 | if (stop) | ||
1150 | ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx); | ||
1151 | |||
1152 | return ret; | ||
1153 | } | ||
1154 | |||
1055 | static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | 1155 | static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, |
1056 | unsigned long buf_size, | 1156 | unsigned long buf_size, |
1057 | struct iwm_wifi_cmd *cmd) | 1157 | struct iwm_wifi_cmd *cmd) |
1058 | { | 1158 | { |
1059 | struct iwm_umac_wifi_if *hdr = | 1159 | struct iwm_umac_wifi_if *hdr; |
1060 | (struct iwm_umac_wifi_if *)cmd->buf.payload; | 1160 | |
1161 | if (cmd == NULL) { | ||
1162 | IWM_ERR(iwm, "Couldn't find expected wifi command\n"); | ||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload; | ||
1061 | 1167 | ||
1062 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " | 1168 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " |
1063 | "oid is 0x%x\n", hdr->oid); | 1169 | "oid is 0x%x\n", hdr->oid); |
@@ -1079,6 +1185,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | |||
1079 | return 0; | 1185 | return 0; |
1080 | } | 1186 | } |
1081 | 1187 | ||
1188 | #define CT_KILL_DELAY (30 * HZ) | ||
1082 | static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, | 1189 | static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, |
1083 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) | 1190 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) |
1084 | { | 1191 | { |
@@ -1091,7 +1198,20 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, | |||
1091 | flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", | 1198 | flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", |
1092 | flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); | 1199 | flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); |
1093 | 1200 | ||
1094 | wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED); | 1201 | if (flags & IWM_CARD_STATE_CTKILL_DISABLED) { |
1202 | /* | ||
1203 | * We got a CTKILL event: We bring the interface down in | ||
1204 | * oder to cool the device down, and try to bring it up | ||
1205 | * 30 seconds later. If it's still too hot, we'll go through | ||
1206 | * this code path again. | ||
1207 | */ | ||
1208 | cancel_delayed_work_sync(&iwm->ct_kill_delay); | ||
1209 | schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY); | ||
1210 | } | ||
1211 | |||
1212 | wiphy_rfkill_set_hw_state(wiphy, flags & | ||
1213 | (IWM_CARD_STATE_HW_DISABLED | | ||
1214 | IWM_CARD_STATE_CTKILL_DISABLED)); | ||
1095 | 1215 | ||
1096 | return 0; | 1216 | return 0; |
1097 | } | 1217 | } |
@@ -1282,6 +1402,14 @@ int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size) | |||
1282 | 1402 | ||
1283 | switch (le32_to_cpu(hdr->cmd)) { | 1403 | switch (le32_to_cpu(hdr->cmd)) { |
1284 | case UMAC_REBOOT_BARKER: | 1404 | case UMAC_REBOOT_BARKER: |
1405 | if (test_bit(IWM_STATUS_READY, &iwm->status)) { | ||
1406 | IWM_ERR(iwm, "Unexpected BARKER\n"); | ||
1407 | |||
1408 | schedule_work(&iwm->reset_worker); | ||
1409 | |||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1285 | return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, | 1413 | return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, |
1286 | IWM_SRC_UDMA, buf, buf_size); | 1414 | IWM_SRC_UDMA, buf, buf_size); |
1287 | case UMAC_ACK_BARKER: | 1415 | case UMAC_ACK_BARKER: |
@@ -1308,6 +1436,7 @@ static const iwm_handler iwm_umac_handlers[] = | |||
1308 | [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, | 1436 | [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, |
1309 | [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, | 1437 | [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, |
1310 | [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, | 1438 | [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, |
1439 | [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx, | ||
1311 | [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, | 1440 | [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, |
1312 | [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, | 1441 | [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, |
1313 | }; | 1442 | }; |
@@ -1405,6 +1534,33 @@ static void classify8023(struct sk_buff *skb) | |||
1405 | } | 1534 | } |
1406 | } | 1535 | } |
1407 | 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 | |||
1408 | static void iwm_rx_process_packet(struct iwm_priv *iwm, | 1564 | static void iwm_rx_process_packet(struct iwm_priv *iwm, |
1409 | struct iwm_rx_packet *packet, | 1565 | struct iwm_rx_packet *packet, |
1410 | struct iwm_rx_ticket_node *ticket_node) | 1566 | struct iwm_rx_ticket_node *ticket_node) |
@@ -1419,36 +1575,46 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1419 | switch (le16_to_cpu(ticket_node->ticket->action)) { | 1575 | switch (le16_to_cpu(ticket_node->ticket->action)) { |
1420 | case IWM_RX_TICKET_RELEASE: | 1576 | case IWM_RX_TICKET_RELEASE: |
1421 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); | 1577 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); |
1422 | classify8023(skb); | 1578 | |
1423 | 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 | |||
1424 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); | 1589 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); |
1425 | if (ret < 0) { | 1590 | if (ret < 0) { |
1426 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " | 1591 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " |
1427 | "%d\n", ret); | 1592 | "%d\n", ret); |
1593 | kfree_skb(packet->skb); | ||
1428 | break; | 1594 | break; |
1429 | } | 1595 | } |
1430 | 1596 | ||
1431 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); | 1597 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); |
1432 | 1598 | ||
1433 | skb->dev = iwm_to_ndev(iwm); | 1599 | ndev->stats.rx_packets++; |
1600 | ndev->stats.rx_bytes += skb->len; | ||
1601 | |||
1434 | skb->protocol = eth_type_trans(skb, ndev); | 1602 | skb->protocol = eth_type_trans(skb, ndev); |
1435 | skb->ip_summed = CHECKSUM_NONE; | 1603 | skb->ip_summed = CHECKSUM_NONE; |
1436 | memset(skb->cb, 0, sizeof(skb->cb)); | 1604 | memset(skb->cb, 0, sizeof(skb->cb)); |
1437 | 1605 | ||
1438 | ndev->stats.rx_packets++; | ||
1439 | ndev->stats.rx_bytes += skb->len; | ||
1440 | |||
1441 | if (netif_rx_ni(skb) == NET_RX_DROP) { | 1606 | if (netif_rx_ni(skb) == NET_RX_DROP) { |
1442 | IWM_ERR(iwm, "Packet dropped\n"); | 1607 | IWM_ERR(iwm, "Packet dropped\n"); |
1443 | ndev->stats.rx_dropped++; | 1608 | ndev->stats.rx_dropped++; |
1444 | } | 1609 | } |
1445 | break; | 1610 | break; |
1446 | case IWM_RX_TICKET_DROP: | 1611 | case IWM_RX_TICKET_DROP: |
1447 | IWM_DBG_RX(iwm, DBG, "DROP packet\n"); | 1612 | IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n", |
1613 | le16_to_cpu(ticket_node->ticket->flags)); | ||
1448 | kfree_skb(packet->skb); | 1614 | kfree_skb(packet->skb); |
1449 | break; | 1615 | break; |
1450 | default: | 1616 | default: |
1451 | IWM_ERR(iwm, "Unknow ticket action: %d\n", | 1617 | IWM_ERR(iwm, "Unknown ticket action: %d\n", |
1452 | le16_to_cpu(ticket_node->ticket->action)); | 1618 | le16_to_cpu(ticket_node->ticket->action)); |
1453 | kfree_skb(packet->skb); | 1619 | kfree_skb(packet->skb); |
1454 | } | 1620 | } |