diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
commit | 4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch) | |
tree | 0789ba36d96dba330416a1e6a9a68e891a78802a /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | 35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff) | |
parent | 18b6c9a2213d3b6e0212e8b225abf95f7564206a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 322 |
1 files changed, 248 insertions, 74 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 29f7510ecdd7..c96513bddb10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -311,7 +311,7 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) | |||
311 | list_add(&frame->list, &priv->free_frames); | 311 | list_add(&frame->list, &priv->free_frames); |
312 | } | 312 | } |
313 | 313 | ||
314 | static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | 314 | static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, |
315 | struct ieee80211_hdr *hdr, | 315 | struct ieee80211_hdr *hdr, |
316 | int left) | 316 | int left) |
317 | { | 317 | { |
@@ -328,34 +328,74 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | |||
328 | return priv->ibss_beacon->len; | 328 | return priv->ibss_beacon->len; |
329 | } | 329 | } |
330 | 330 | ||
331 | /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ | ||
332 | static void iwl_set_beacon_tim(struct iwl_priv *priv, | ||
333 | struct iwl_tx_beacon_cmd *tx_beacon_cmd, | ||
334 | u8 *beacon, u32 frame_size) | ||
335 | { | ||
336 | u16 tim_idx; | ||
337 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; | ||
338 | |||
339 | /* | ||
340 | * The index is relative to frame start but we start looking at the | ||
341 | * variable-length part of the beacon. | ||
342 | */ | ||
343 | tim_idx = mgmt->u.beacon.variable - beacon; | ||
344 | |||
345 | /* Parse variable-length elements of beacon to find WLAN_EID_TIM */ | ||
346 | while ((tim_idx < (frame_size - 2)) && | ||
347 | (beacon[tim_idx] != WLAN_EID_TIM)) | ||
348 | tim_idx += beacon[tim_idx+1] + 2; | ||
349 | |||
350 | /* If TIM field was found, set variables */ | ||
351 | if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) { | ||
352 | tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx); | ||
353 | tx_beacon_cmd->tim_size = beacon[tim_idx+1]; | ||
354 | } else | ||
355 | IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); | ||
356 | } | ||
357 | |||
331 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | 358 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, |
332 | struct iwl_frame *frame, u8 rate) | 359 | struct iwl_frame *frame) |
333 | { | 360 | { |
334 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 361 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
335 | unsigned int frame_size; | 362 | u32 frame_size; |
363 | u32 rate_flags; | ||
364 | u32 rate; | ||
365 | /* | ||
366 | * We have to set up the TX command, the TX Beacon command, and the | ||
367 | * beacon contents. | ||
368 | */ | ||
336 | 369 | ||
370 | /* Initialize memory */ | ||
337 | tx_beacon_cmd = &frame->u.beacon; | 371 | tx_beacon_cmd = &frame->u.beacon; |
338 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 372 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
339 | 373 | ||
340 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | 374 | /* Set up TX beacon contents */ |
341 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
342 | |||
343 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, | 375 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, |
344 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 376 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
377 | if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) | ||
378 | return 0; | ||
345 | 379 | ||
346 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 380 | /* Set up TX command fields */ |
347 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 381 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
382 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | ||
383 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
384 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | ||
385 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | ||
348 | 386 | ||
349 | if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) | 387 | /* Set up TX beacon command fields */ |
350 | tx_beacon_cmd->tx.rate_n_flags = | 388 | iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, |
351 | iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); | 389 | frame_size); |
352 | else | ||
353 | tx_beacon_cmd->tx.rate_n_flags = | ||
354 | iwl_hw_set_rate_n_flags(rate, 0); | ||
355 | 390 | ||
356 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | 391 | /* Set up packet rate and flags */ |
357 | TX_CMD_FLG_TSF_MSK | | 392 | rate = iwl_rate_get_lowest_plcp(priv); |
358 | TX_CMD_FLG_STA_RATE_MSK; | 393 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); |
394 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
395 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | ||
396 | rate_flags |= RATE_MCS_CCK_MSK; | ||
397 | tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, | ||
398 | rate_flags); | ||
359 | 399 | ||
360 | return sizeof(*tx_beacon_cmd) + frame_size; | 400 | return sizeof(*tx_beacon_cmd) + frame_size; |
361 | } | 401 | } |
@@ -364,19 +404,20 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv) | |||
364 | struct iwl_frame *frame; | 404 | struct iwl_frame *frame; |
365 | unsigned int frame_size; | 405 | unsigned int frame_size; |
366 | int rc; | 406 | int rc; |
367 | u8 rate; | ||
368 | 407 | ||
369 | frame = iwl_get_free_frame(priv); | 408 | frame = iwl_get_free_frame(priv); |
370 | |||
371 | if (!frame) { | 409 | if (!frame) { |
372 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " | 410 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " |
373 | "command.\n"); | 411 | "command.\n"); |
374 | return -ENOMEM; | 412 | return -ENOMEM; |
375 | } | 413 | } |
376 | 414 | ||
377 | rate = iwl_rate_get_lowest_plcp(priv); | 415 | frame_size = iwl_hw_get_beacon_cmd(priv, frame); |
378 | 416 | if (!frame_size) { | |
379 | frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate); | 417 | IWL_ERR(priv, "Error configuring the beacon command\n"); |
418 | iwl_free_frame(priv, frame); | ||
419 | return -EINVAL; | ||
420 | } | ||
380 | 421 | ||
381 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, | 422 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, |
382 | &frame->u.cmd[0]); | 423 | &frame->u.cmd[0]); |
@@ -613,7 +654,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) | |||
613 | if (!iwl_is_ready_rf(priv)) | 654 | if (!iwl_is_ready_rf(priv)) |
614 | return; | 655 | return; |
615 | 656 | ||
616 | iwl_send_statistics_request(priv, CMD_ASYNC); | 657 | iwl_send_statistics_request(priv, CMD_ASYNC, false); |
617 | } | 658 | } |
618 | 659 | ||
619 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 660 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
@@ -730,7 +771,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
730 | * statistics request from the host as well as for the periodic | 771 | * statistics request from the host as well as for the periodic |
731 | * statistics notifications (after received beacons) from the uCode. | 772 | * statistics notifications (after received beacons) from the uCode. |
732 | */ | 773 | */ |
733 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; | 774 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; |
734 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | 775 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
735 | 776 | ||
736 | iwl_setup_spectrum_handlers(priv); | 777 | iwl_setup_spectrum_handlers(priv); |
@@ -1038,7 +1079,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1038 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 1079 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
1039 | iwl_rx_handle(priv); | 1080 | iwl_rx_handle(priv); |
1040 | priv->isr_stats.rx++; | 1081 | priv->isr_stats.rx++; |
1041 | iwl_leds_background(priv); | ||
1042 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 1082 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
1043 | } | 1083 | } |
1044 | 1084 | ||
@@ -1226,19 +1266,27 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1226 | * 3- update RX shared data to indicate last write index. | 1266 | * 3- update RX shared data to indicate last write index. |
1227 | * 4- send interrupt. | 1267 | * 4- send interrupt. |
1228 | * This could lead to RX race, driver could receive RX interrupt | 1268 | * This could lead to RX race, driver could receive RX interrupt |
1229 | * but the shared data changes does not reflect this. | 1269 | * but the shared data changes does not reflect this; |
1230 | * this could lead to RX race, RX periodic will solve this race | 1270 | * periodic interrupt will detect any dangling Rx activity. |
1231 | */ | 1271 | */ |
1232 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1272 | |
1273 | /* Disable periodic interrupt; we use it as just a one-shot. */ | ||
1274 | iwl_write8(priv, CSR_INT_PERIODIC_REG, | ||
1233 | CSR_INT_PERIODIC_DIS); | 1275 | CSR_INT_PERIODIC_DIS); |
1234 | iwl_rx_handle(priv); | 1276 | iwl_rx_handle(priv); |
1235 | /* Only set RX periodic if real RX is received. */ | 1277 | |
1278 | /* | ||
1279 | * Enable periodic interrupt in 8 msec only if we received | ||
1280 | * real RX interrupt (instead of just periodic int), to catch | ||
1281 | * any dangling Rx interrupt. If it was just the periodic | ||
1282 | * interrupt, there was no dangling Rx activity, and no need | ||
1283 | * to extend the periodic interrupt; one-shot is enough. | ||
1284 | */ | ||
1236 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 1285 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
1237 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1286 | iwl_write8(priv, CSR_INT_PERIODIC_REG, |
1238 | CSR_INT_PERIODIC_ENA); | 1287 | CSR_INT_PERIODIC_ENA); |
1239 | 1288 | ||
1240 | priv->isr_stats.rx++; | 1289 | priv->isr_stats.rx++; |
1241 | iwl_leds_background(priv); | ||
1242 | } | 1290 | } |
1243 | 1291 | ||
1244 | /* This "Tx" DMA channel is used only for loading uCode */ | 1292 | /* This "Tx" DMA channel is used only for loading uCode */ |
@@ -1557,7 +1605,6 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1557 | return ret; | 1605 | return ret; |
1558 | } | 1606 | } |
1559 | 1607 | ||
1560 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1561 | static const char *desc_lookup_text[] = { | 1608 | static const char *desc_lookup_text[] = { |
1562 | "OK", | 1609 | "OK", |
1563 | "FAIL", | 1610 | "FAIL", |
@@ -1710,10 +1757,42 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1710 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1757 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1711 | } | 1758 | } |
1712 | 1759 | ||
1760 | /** | ||
1761 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | ||
1762 | */ | ||
1763 | static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1764 | u32 num_wraps, u32 next_entry, | ||
1765 | u32 size, u32 mode) | ||
1766 | { | ||
1767 | /* | ||
1768 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1769 | * i.e the entries just before the next ont that uCode would fill. | ||
1770 | */ | ||
1771 | if (num_wraps) { | ||
1772 | if (next_entry < size) { | ||
1773 | iwl_print_event_log(priv, | ||
1774 | capacity - (size - next_entry), | ||
1775 | size - next_entry, mode); | ||
1776 | iwl_print_event_log(priv, 0, | ||
1777 | next_entry, mode); | ||
1778 | } else | ||
1779 | iwl_print_event_log(priv, next_entry - size, | ||
1780 | size, mode); | ||
1781 | } else { | ||
1782 | if (next_entry < size) | ||
1783 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
1784 | else | ||
1785 | iwl_print_event_log(priv, next_entry - size, | ||
1786 | size, mode); | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1713 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1790 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
1714 | #define MAX_EVENT_LOG_SIZE (512) | 1791 | #define MAX_EVENT_LOG_SIZE (512) |
1715 | 1792 | ||
1716 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | 1793 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1794 | |||
1795 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | ||
1717 | { | 1796 | { |
1718 | u32 base; /* SRAM byte address of event log header */ | 1797 | u32 base; /* SRAM byte address of event log header */ |
1719 | u32 capacity; /* event log capacity in # entries */ | 1798 | u32 capacity; /* event log capacity in # entries */ |
@@ -1758,19 +1837,37 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1758 | return; | 1837 | return; |
1759 | } | 1838 | } |
1760 | 1839 | ||
1761 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | 1840 | #ifdef CONFIG_IWLWIFI_DEBUG |
1762 | size, num_wraps); | 1841 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)) |
1763 | 1842 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | |
1764 | /* if uCode has wrapped back to top of log, start at the oldest entry, | 1843 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1765 | * i.e the next one that uCode would fill. */ | 1844 | #else |
1766 | if (num_wraps) | 1845 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) |
1767 | iwl_print_event_log(priv, next_entry, | 1846 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1768 | capacity - next_entry, mode); | 1847 | #endif |
1769 | /* (then/else) start at top of log */ | 1848 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", |
1770 | iwl_print_event_log(priv, 0, next_entry, mode); | 1849 | size); |
1771 | 1850 | ||
1772 | } | 1851 | #ifdef CONFIG_IWLWIFI_DEBUG |
1852 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
1853 | /* | ||
1854 | * if uCode has wrapped back to top of log, | ||
1855 | * start at the oldest entry, | ||
1856 | * i.e the next one that uCode would fill. | ||
1857 | */ | ||
1858 | if (num_wraps) | ||
1859 | iwl_print_event_log(priv, next_entry, | ||
1860 | capacity - next_entry, mode); | ||
1861 | /* (then/else) start at top of log */ | ||
1862 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
1863 | } else | ||
1864 | iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
1865 | next_entry, size, mode); | ||
1866 | #else | ||
1867 | iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
1868 | next_entry, size, mode); | ||
1773 | #endif | 1869 | #endif |
1870 | } | ||
1774 | 1871 | ||
1775 | /** | 1872 | /** |
1776 | * iwl_alive_start - called after REPLY_ALIVE notification received | 1873 | * iwl_alive_start - called after REPLY_ALIVE notification received |
@@ -2360,16 +2457,14 @@ static int iwl_setup_mac(struct iwl_priv *priv) | |||
2360 | BIT(NL80211_IFTYPE_STATION) | | 2457 | BIT(NL80211_IFTYPE_STATION) | |
2361 | BIT(NL80211_IFTYPE_ADHOC); | 2458 | BIT(NL80211_IFTYPE_ADHOC); |
2362 | 2459 | ||
2363 | hw->wiphy->custom_regulatory = true; | 2460 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY | |
2364 | 2461 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | |
2365 | /* Firmware does not support this */ | ||
2366 | hw->wiphy->disable_beacon_hints = true; | ||
2367 | 2462 | ||
2368 | /* | 2463 | /* |
2369 | * For now, disable PS by default because it affects | 2464 | * For now, disable PS by default because it affects |
2370 | * RX performance significantly. | 2465 | * RX performance significantly. |
2371 | */ | 2466 | */ |
2372 | hw->wiphy->ps_default = false; | 2467 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
2373 | 2468 | ||
2374 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2469 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
2375 | /* we create the 802.11 header and a zero-length SSID element */ | 2470 | /* we create the 802.11 header and a zero-length SSID element */ |
@@ -2523,6 +2618,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2523 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 2618 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
2524 | "Attempting to continue.\n"); | 2619 | "Attempting to continue.\n"); |
2525 | 2620 | ||
2621 | /* AP has all antennas */ | ||
2622 | priv->chain_noise_data.active_chains = | ||
2623 | priv->hw_params.valid_rx_ant; | ||
2624 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2526 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2625 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2527 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2626 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2528 | 2627 | ||
@@ -2551,6 +2650,7 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2551 | /* restore RXON assoc */ | 2650 | /* restore RXON assoc */ |
2552 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2651 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2553 | iwlcore_commit_rxon(priv); | 2652 | iwlcore_commit_rxon(priv); |
2653 | iwl_reset_qos(priv); | ||
2554 | spin_lock_irqsave(&priv->lock, flags); | 2654 | spin_lock_irqsave(&priv->lock, flags); |
2555 | iwl_activate_qos(priv, 1); | 2655 | iwl_activate_qos(priv, 1); |
2556 | spin_unlock_irqrestore(&priv->lock, flags); | 2656 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -2646,6 +2746,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2646 | } | 2746 | } |
2647 | 2747 | ||
2648 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 2748 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2749 | struct ieee80211_vif *vif, | ||
2649 | enum ieee80211_ampdu_mlme_action action, | 2750 | enum ieee80211_ampdu_mlme_action action, |
2650 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2751 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2651 | { | 2752 | { |
@@ -2699,6 +2800,45 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, | |||
2699 | return 0; | 2800 | return 0; |
2700 | } | 2801 | } |
2701 | 2802 | ||
2803 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | ||
2804 | struct ieee80211_vif *vif, | ||
2805 | enum sta_notify_cmd cmd, | ||
2806 | struct ieee80211_sta *sta) | ||
2807 | { | ||
2808 | struct iwl_priv *priv = hw->priv; | ||
2809 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
2810 | int sta_id; | ||
2811 | |||
2812 | /* | ||
2813 | * TODO: We really should use this callback to | ||
2814 | * actually maintain the station table in | ||
2815 | * the device. | ||
2816 | */ | ||
2817 | |||
2818 | switch (cmd) { | ||
2819 | case STA_NOTIFY_ADD: | ||
2820 | atomic_set(&sta_priv->pending_frames, 0); | ||
2821 | if (vif->type == NL80211_IFTYPE_AP) | ||
2822 | sta_priv->client = true; | ||
2823 | break; | ||
2824 | case STA_NOTIFY_SLEEP: | ||
2825 | WARN_ON(!sta_priv->client); | ||
2826 | sta_priv->asleep = true; | ||
2827 | if (atomic_read(&sta_priv->pending_frames) > 0) | ||
2828 | ieee80211_sta_block_awake(hw, sta, true); | ||
2829 | break; | ||
2830 | case STA_NOTIFY_AWAKE: | ||
2831 | WARN_ON(!sta_priv->client); | ||
2832 | sta_priv->asleep = false; | ||
2833 | sta_id = iwl_find_station(priv, sta->addr); | ||
2834 | if (sta_id != IWL_INVALID_STATION) | ||
2835 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
2836 | break; | ||
2837 | default: | ||
2838 | break; | ||
2839 | } | ||
2840 | } | ||
2841 | |||
2702 | /***************************************************************************** | 2842 | /***************************************************************************** |
2703 | * | 2843 | * |
2704 | * sysfs attributes | 2844 | * sysfs attributes |
@@ -2893,7 +3033,7 @@ static ssize_t show_statistics(struct device *d, | |||
2893 | return -EAGAIN; | 3033 | return -EAGAIN; |
2894 | 3034 | ||
2895 | mutex_lock(&priv->mutex); | 3035 | mutex_lock(&priv->mutex); |
2896 | rc = iwl_send_statistics_request(priv, 0); | 3036 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); |
2897 | mutex_unlock(&priv->mutex); | 3037 | mutex_unlock(&priv->mutex); |
2898 | 3038 | ||
2899 | if (rc) { | 3039 | if (rc) { |
@@ -3045,10 +3185,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3045 | priv->band = IEEE80211_BAND_2GHZ; | 3185 | priv->band = IEEE80211_BAND_2GHZ; |
3046 | 3186 | ||
3047 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3187 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3048 | if (priv->cfg->support_sm_ps) | ||
3049 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
3050 | else | ||
3051 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
3052 | 3188 | ||
3053 | /* Choose which receivers/antennas to use */ | 3189 | /* Choose which receivers/antennas to use */ |
3054 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3190 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
@@ -3130,7 +3266,8 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3130 | .reset_tsf = iwl_mac_reset_tsf, | 3266 | .reset_tsf = iwl_mac_reset_tsf, |
3131 | .bss_info_changed = iwl_bss_info_changed, | 3267 | .bss_info_changed = iwl_bss_info_changed, |
3132 | .ampdu_action = iwl_mac_ampdu_action, | 3268 | .ampdu_action = iwl_mac_ampdu_action, |
3133 | .hw_scan = iwl_mac_hw_scan | 3269 | .hw_scan = iwl_mac_hw_scan, |
3270 | .sta_notify = iwl_mac_sta_notify, | ||
3134 | }; | 3271 | }; |
3135 | 3272 | ||
3136 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3273 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3454,23 +3591,63 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3454 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | 3591 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, |
3455 | #endif /* CONFIG_IWL4965 */ | 3592 | #endif /* CONFIG_IWL4965 */ |
3456 | #ifdef CONFIG_IWL5000 | 3593 | #ifdef CONFIG_IWL5000 |
3457 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, | 3594 | /* 5100 Series WiFi */ |
3458 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, | 3595 | {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ |
3459 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, | 3596 | {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3460 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, | 3597 | {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ |
3461 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, | 3598 | {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3462 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, | 3599 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ |
3463 | {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3600 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3464 | {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3601 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ |
3465 | {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3602 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3466 | {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3603 | {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ |
3467 | /* 5350 WiFi/WiMax */ | 3604 | {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3468 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, | 3605 | {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ |
3469 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, | 3606 | {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3470 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, | 3607 | {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ |
3471 | /* 5150 Wifi/WiMax */ | 3608 | {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3472 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3609 | {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ |
3473 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3610 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3611 | {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ | ||
3612 | {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ | ||
3613 | {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ | ||
3614 | {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ | ||
3615 | {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ | ||
3616 | {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ | ||
3617 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ | ||
3618 | {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ | ||
3619 | |||
3620 | /* 5300 Series WiFi */ | ||
3621 | {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3622 | {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3623 | {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3624 | {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3625 | {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3626 | {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3627 | {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3628 | {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3629 | {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3630 | {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3631 | {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3632 | {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3633 | |||
3634 | /* 5350 Series WiFi/WiMax */ | ||
3635 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3636 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3637 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3638 | |||
3639 | /* 5150 Series Wifi/WiMax */ | ||
3640 | {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3641 | {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3642 | {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3643 | {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3644 | {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3645 | {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3646 | |||
3647 | {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3648 | {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3649 | {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3650 | {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3474 | 3651 | ||
3475 | /* 6x00 Series */ | 3652 | /* 6x00 Series */ |
3476 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, | 3653 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, |
@@ -3485,13 +3662,10 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3485 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3662 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3486 | 3663 | ||
3487 | /* 6x50 WiFi/WiMax Series */ | 3664 | /* 6x50 WiFi/WiMax Series */ |
3488 | {IWL_PCI_DEVICE(0x0086, 0x1101, iwl6050_3agn_cfg)}, | ||
3489 | {IWL_PCI_DEVICE(0x0086, 0x1121, iwl6050_3agn_cfg)}, | ||
3490 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3665 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
3491 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, | 3666 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, |
3492 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, | 3667 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, |
3493 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, | 3668 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, |
3494 | {IWL_PCI_DEVICE(0x0088, 0x1111, iwl6050_3agn_cfg)}, | ||
3495 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, | 3669 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, |
3496 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, | 3670 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, |
3497 | 3671 | ||