aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/rx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 00:04:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 00:04:44 -0400
commitf8965467f366fd18f01feafb5db10512d7b4422c (patch)
tree3706a9cd779859271ca61b85c63a1bc3f82d626e /drivers/net/wireless/iwmc3200wifi/rx.c
parenta26272e5200765691e67d6780e52b32498fdb659 (diff)
parent2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits) qlcnic: adding co maintainer ixgbe: add support for active DA cables ixgbe: dcb, do not tag tc_prio_control frames ixgbe: fix ixgbe_tx_is_paused logic ixgbe: always enable vlan strip/insert when DCB is enabled ixgbe: remove some redundant code in setting FCoE FIP filter ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp ixgbe: fix header len when unsplit packet overflows to data buffer ipv6: Never schedule DAD timer on dead address ipv6: Use POSTDAD state ipv6: Use state_lock to protect ifa state ipv6: Replace inet6_ifaddr->dead with state cxgb4: notify upper drivers if the device is already up when they load cxgb4: keep interrupts available when the ports are brought down cxgb4: fix initial addition of MAC address cnic: Return SPQ credit to bnx2x after ring setup and shutdown. cnic: Convert cnic_local_flags to atomic ops. can: Fix SJA1000 command register writes on SMP systems bridge: fix build for CONFIG_SYSFS disabled ARCNET: Limit com20020 PCI ID matches for SOHARD cards ... Fix up various conflicts with pcmcia tree drivers/net/ {pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and wireless/orinoco/spectrum_cs.c} and feature removal (Documentation/feature-removal-schedule.txt). Also fix a non-content conflict due to pm_qos_requirement getting renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 3257d4fad835..e1184deca559 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -343,15 +343,17 @@ static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
343static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) 343static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
344{ 344{
345 u8 id_hash = IWM_RX_ID_GET_HASH(id); 345 u8 id_hash = IWM_RX_ID_GET_HASH(id);
346 struct list_head *packet_list; 346 struct iwm_rx_packet *packet;
347 struct iwm_rx_packet *packet, *next;
348
349 packet_list = &iwm->rx_packets[id_hash];
350 347
351 list_for_each_entry_safe(packet, next, packet_list, node) 348 spin_lock(&iwm->packet_lock[id_hash]);
352 if (packet->id == id) 349 list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
350 if (packet->id == id) {
351 list_del(&packet->node);
352 spin_unlock(&iwm->packet_lock[id_hash]);
353 return packet; 353 return packet;
354 }
354 355
356 spin_unlock(&iwm->packet_lock[id_hash]);
355 return NULL; 357 return NULL;
356} 358}
357 359
@@ -389,18 +391,22 @@ void iwm_rx_free(struct iwm_priv *iwm)
389 struct iwm_rx_packet *packet, *np; 391 struct iwm_rx_packet *packet, *np;
390 int i; 392 int i;
391 393
394 spin_lock(&iwm->ticket_lock);
392 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { 395 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
393 list_del(&ticket->node); 396 list_del(&ticket->node);
394 iwm_rx_ticket_node_free(ticket); 397 iwm_rx_ticket_node_free(ticket);
395 } 398 }
399 spin_unlock(&iwm->ticket_lock);
396 400
397 for (i = 0; i < IWM_RX_ID_HASH; i++) { 401 for (i = 0; i < IWM_RX_ID_HASH; i++) {
402 spin_lock(&iwm->packet_lock[i]);
398 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], 403 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
399 node) { 404 node) {
400 list_del(&packet->node); 405 list_del(&packet->node);
401 kfree_skb(packet->skb); 406 kfree_skb(packet->skb);
402 kfree(packet); 407 kfree(packet);
403 } 408 }
409 spin_unlock(&iwm->packet_lock[i]);
404 } 410 }
405} 411}
406 412
@@ -425,10 +431,13 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
425 return PTR_ERR(ticket_node); 431 return PTR_ERR(ticket_node);
426 432
427 IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", 433 IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
428 ticket->action == IWM_RX_TICKET_RELEASE ? 434 __le16_to_cpu(ticket->action) ==
435 IWM_RX_TICKET_RELEASE ?
429 "RELEASE" : "DROP", 436 "RELEASE" : "DROP",
430 ticket->id); 437 ticket->id);
438 spin_lock(&iwm->ticket_lock);
431 list_add_tail(&ticket_node->node, &iwm->rx_tickets); 439 list_add_tail(&ticket_node->node, &iwm->rx_tickets);
440 spin_unlock(&iwm->ticket_lock);
432 441
433 /* 442 /*
434 * We received an Rx ticket, most likely there's 443 * We received an Rx ticket, most likely there's
@@ -461,6 +470,7 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
461 struct iwm_rx_packet *packet; 470 struct iwm_rx_packet *packet;
462 u16 id, buf_offset; 471 u16 id, buf_offset;
463 u32 packet_size; 472 u32 packet_size;
473 u8 id_hash;
464 474
465 IWM_DBG_RX(iwm, DBG, "\n"); 475 IWM_DBG_RX(iwm, DBG, "\n");
466 476
@@ -478,7 +488,10 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
478 if (IS_ERR(packet)) 488 if (IS_ERR(packet))
479 return PTR_ERR(packet); 489 return PTR_ERR(packet);
480 490
481 list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); 491 id_hash = IWM_RX_ID_GET_HASH(id);
492 spin_lock(&iwm->packet_lock[id_hash]);
493 list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
494 spin_unlock(&iwm->packet_lock[id_hash]);
482 495
483 /* We might (unlikely) have received the packet _after_ the ticket */ 496 /* We might (unlikely) have received the packet _after_ the ticket */
484 queue_work(iwm->rx_wq, &iwm->rx_worker); 497 queue_work(iwm->rx_wq, &iwm->rx_worker);
@@ -519,6 +532,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
519 unsigned long buf_size, 532 unsigned long buf_size,
520 struct iwm_wifi_cmd *cmd) 533 struct iwm_wifi_cmd *cmd)
521{ 534{
535 struct wiphy *wiphy = iwm_to_wiphy(iwm);
536 struct ieee80211_channel *chan;
522 struct iwm_umac_notif_assoc_complete *complete = 537 struct iwm_umac_notif_assoc_complete *complete =
523 (struct iwm_umac_notif_assoc_complete *)buf; 538 (struct iwm_umac_notif_assoc_complete *)buf;
524 539
@@ -527,6 +542,18 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
527 542
528 switch (le32_to_cpu(complete->status)) { 543 switch (le32_to_cpu(complete->status)) {
529 case UMAC_ASSOC_COMPLETE_SUCCESS: 544 case UMAC_ASSOC_COMPLETE_SUCCESS:
545 chan = ieee80211_get_channel(wiphy,
546 ieee80211_channel_to_frequency(complete->channel));
547 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
548 /* Associated to a unallowed channel, disassociate. */
549 __iwm_invalidate_mlme_profile(iwm);
550 IWM_WARN(iwm, "Couldn't associate with %pM due to "
551 "channel %d is disabled. Check your local "
552 "regulatory setting.\n",
553 complete->bssid, complete->channel);
554 goto failure;
555 }
556
530 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 557 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
531 memcpy(iwm->bssid, complete->bssid, ETH_ALEN); 558 memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
532 iwm->channel = complete->channel; 559 iwm->channel = complete->channel;
@@ -563,6 +590,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
563 GFP_KERNEL); 590 GFP_KERNEL);
564 break; 591 break;
565 case UMAC_ASSOC_COMPLETE_FAILURE: 592 case UMAC_ASSOC_COMPLETE_FAILURE:
593 failure:
566 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 594 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
567 memset(iwm->bssid, 0, ETH_ALEN); 595 memset(iwm->bssid, 0, ETH_ALEN);
568 iwm->channel = 0; 596 iwm->channel = 0;
@@ -757,7 +785,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
757 (struct iwm_umac_notif_bss_info *)buf; 785 (struct iwm_umac_notif_bss_info *)buf;
758 struct ieee80211_channel *channel; 786 struct ieee80211_channel *channel;
759 struct ieee80211_supported_band *band; 787 struct ieee80211_supported_band *band;
760 struct iwm_bss_info *bss, *next; 788 struct iwm_bss_info *bss;
761 s32 signal; 789 s32 signal;
762 int freq; 790 int freq;
763 u16 frame_len = le16_to_cpu(umac_bss->frame_len); 791 u16 frame_len = le16_to_cpu(umac_bss->frame_len);
@@ -776,7 +804,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
776 IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); 804 IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
777 IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); 805 IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
778 806
779 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) 807 list_for_each_entry(bss, &iwm->bss_list, node)
780 if (bss->bss->table_idx == umac_bss->table_idx) 808 if (bss->bss->table_idx == umac_bss->table_idx)
781 break; 809 break;
782 810
@@ -843,16 +871,15 @@ static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
843 int i; 871 int i;
844 872
845 for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { 873 for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
846 table_idx = (le16_to_cpu(bss_rm->entries[i]) 874 table_idx = le16_to_cpu(bss_rm->entries[i]) &
847 & IWM_BSS_REMOVE_INDEX_MSK); 875 IWM_BSS_REMOVE_INDEX_MSK;
848 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) 876 list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
849 if (bss->bss->table_idx == cpu_to_le16(table_idx)) { 877 if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
850 struct ieee80211_mgmt *mgmt; 878 struct ieee80211_mgmt *mgmt;
851 879
852 mgmt = (struct ieee80211_mgmt *) 880 mgmt = (struct ieee80211_mgmt *)
853 (bss->bss->frame_buf); 881 (bss->bss->frame_buf);
854 IWM_DBG_MLME(iwm, ERR, 882 IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n",
855 "BSS removed: %pM\n",
856 mgmt->bssid); 883 mgmt->bssid);
857 list_del(&bss->node); 884 list_del(&bss->node);
858 kfree(bss->bss); 885 kfree(bss->bss);
@@ -1224,18 +1251,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
1224 u8 source, cmd_id; 1251 u8 source, cmd_id;
1225 u16 seq_num; 1252 u16 seq_num;
1226 u32 count; 1253 u32 count;
1227 u8 resp;
1228 1254
1229 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; 1255 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1230 cmd_id = wifi_hdr->sw_hdr.cmd.cmd; 1256 cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1231
1232 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); 1257 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1233 if (source >= IWM_SRC_NUM) { 1258 if (source >= IWM_SRC_NUM) {
1234 IWM_CRIT(iwm, "invalid source %d\n", source); 1259 IWM_CRIT(iwm, "invalid source %d\n", source);
1235 return -EINVAL; 1260 return -EINVAL;
1236 } 1261 }
1237 1262
1238 count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); 1263 if (cmd_id == REPLY_RX_MPDU_CMD)
1264 trace_iwm_rx_packet(iwm, buf, buf_size);
1265 else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
1266 (source == UMAC_HDI_IN_SOURCE_FW))
1267 trace_iwm_rx_ticket(iwm, buf, buf_size);
1268 else
1269 trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
1270
1271 count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
1239 count += sizeof(struct iwm_umac_wifi_in_hdr) - 1272 count += sizeof(struct iwm_umac_wifi_in_hdr) -
1240 sizeof(struct iwm_dev_cmd_hdr); 1273 sizeof(struct iwm_dev_cmd_hdr);
1241 if (count > buf_size) { 1274 if (count > buf_size) {
@@ -1243,8 +1276,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
1243 return -EINVAL; 1276 return -EINVAL;
1244 } 1277 }
1245 1278
1246 resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS);
1247
1248 seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); 1279 seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
1249 1280
1250 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", 1281 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
@@ -1317,8 +1348,9 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
1317{ 1348{
1318 u8 seq_num; 1349 u8 seq_num;
1319 struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; 1350 struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
1320 struct iwm_nonwifi_cmd *cmd, *next; 1351 struct iwm_nonwifi_cmd *cmd;
1321 1352
1353 trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
1322 seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); 1354 seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
1323 1355
1324 /* 1356 /*
@@ -1329,7 +1361,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
1329 * That means we only support synchronised non wifi command response 1361 * That means we only support synchronised non wifi command response
1330 * schemes. 1362 * schemes.
1331 */ 1363 */
1332 list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) 1364 list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
1333 if (cmd->seq_num == seq_num) { 1365 if (cmd->seq_num == seq_num) {
1334 cmd->resp_received = 1; 1366 cmd->resp_received = 1;
1335 cmd->buf.len = buf_size; 1367 cmd->buf.len = buf_size;
@@ -1648,6 +1680,7 @@ void iwm_rx_worker(struct work_struct *work)
1648 * We stop whenever a ticket is missing its packet, as we're 1680 * We stop whenever a ticket is missing its packet, as we're
1649 * supposed to send the packets in order. 1681 * supposed to send the packets in order.
1650 */ 1682 */
1683 spin_lock(&iwm->ticket_lock);
1651 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { 1684 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
1652 struct iwm_rx_packet *packet = 1685 struct iwm_rx_packet *packet =
1653 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); 1686 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
@@ -1656,12 +1689,12 @@ void iwm_rx_worker(struct work_struct *work)
1656 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " 1689 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
1657 "to be handled first\n", 1690 "to be handled first\n",
1658 le16_to_cpu(ticket->ticket->id)); 1691 le16_to_cpu(ticket->ticket->id));
1659 return; 1692 break;
1660 } 1693 }
1661 1694
1662 list_del(&ticket->node); 1695 list_del(&ticket->node);
1663 list_del(&packet->node);
1664 iwm_rx_process_packet(iwm, packet, ticket); 1696 iwm_rx_process_packet(iwm, packet, ticket);
1665 } 1697 }
1698 spin_unlock(&iwm->ticket_lock);
1666} 1699}
1667 1700