diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
commit | f8965467f366fd18f01feafb5db10512d7b4422c (patch) | |
tree | 3706a9cd779859271ca61b85c63a1bc3f82d626e /drivers/net/wireless/iwmc3200wifi/rx.c | |
parent | a26272e5200765691e67d6780e52b32498fdb659 (diff) | |
parent | 2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (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.c | 79 |
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) | |||
343 | static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) | 343 | static 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 | ||