diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 1477 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-mac80211.c | 1521 |
4 files changed, 1540 insertions, 1475 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index c73e5ed8db5e..a7ab280994c8 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # WIFI | 1 | # WIFI |
2 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o | 2 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o |
3 | iwlwifi-objs := iwl-agn.o iwl-agn-rs.o | 3 | iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o |
4 | iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o | 4 | iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o |
5 | iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o | 5 | iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o |
6 | iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o | 6 | iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7514b17193ad..e235e84de8b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -508,16 +508,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
508 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 508 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
509 | } | 509 | } |
510 | 510 | ||
511 | |||
512 | struct iwlagn_ucode_capabilities { | ||
513 | u32 max_probe_length; | ||
514 | u32 standard_phy_calibration_size; | ||
515 | u32 flags; | ||
516 | }; | ||
517 | |||
518 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | 511 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); |
519 | static int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||
520 | struct iwlagn_ucode_capabilities *capa); | ||
521 | 512 | ||
522 | #define UCODE_EXPERIMENTAL_INDEX 100 | 513 | #define UCODE_EXPERIMENTAL_INDEX 100 |
523 | #define UCODE_EXPERIMENTAL_TAG "exp" | 514 | #define UCODE_EXPERIMENTAL_TAG "exp" |
@@ -1307,7 +1298,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
1307 | 1298 | ||
1308 | static void iwl_cancel_deferred_work(struct iwl_priv *priv); | 1299 | static void iwl_cancel_deferred_work(struct iwl_priv *priv); |
1309 | 1300 | ||
1310 | static void __iwl_down(struct iwl_priv *priv) | 1301 | void __iwl_down(struct iwl_priv *priv) |
1311 | { | 1302 | { |
1312 | int exit_pending; | 1303 | int exit_pending; |
1313 | 1304 | ||
@@ -1370,7 +1361,7 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1370 | priv->beacon_skb = NULL; | 1361 | priv->beacon_skb = NULL; |
1371 | } | 1362 | } |
1372 | 1363 | ||
1373 | static void iwl_down(struct iwl_priv *priv) | 1364 | void iwl_down(struct iwl_priv *priv) |
1374 | { | 1365 | { |
1375 | mutex_lock(&priv->shrd->mutex); | 1366 | mutex_lock(&priv->shrd->mutex); |
1376 | __iwl_down(priv); | 1367 | __iwl_down(priv); |
@@ -1379,55 +1370,6 @@ static void iwl_down(struct iwl_priv *priv) | |||
1379 | iwl_cancel_deferred_work(priv); | 1370 | iwl_cancel_deferred_work(priv); |
1380 | } | 1371 | } |
1381 | 1372 | ||
1382 | #define MAX_HW_RESTARTS 5 | ||
1383 | |||
1384 | static int __iwl_up(struct iwl_priv *priv) | ||
1385 | { | ||
1386 | struct iwl_rxon_context *ctx; | ||
1387 | int ret; | ||
1388 | |||
1389 | lockdep_assert_held(&priv->shrd->mutex); | ||
1390 | |||
1391 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { | ||
1392 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | ||
1393 | return -EIO; | ||
1394 | } | ||
1395 | |||
1396 | for_each_context(priv, ctx) { | ||
1397 | ret = iwlagn_alloc_bcast_station(priv, ctx); | ||
1398 | if (ret) { | ||
1399 | iwl_dealloc_bcast_stations(priv); | ||
1400 | return ret; | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | ret = iwlagn_run_init_ucode(priv); | ||
1405 | if (ret) { | ||
1406 | IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); | ||
1407 | goto error; | ||
1408 | } | ||
1409 | |||
1410 | ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); | ||
1411 | if (ret) { | ||
1412 | IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); | ||
1413 | goto error; | ||
1414 | } | ||
1415 | |||
1416 | ret = iwl_alive_start(priv); | ||
1417 | if (ret) | ||
1418 | goto error; | ||
1419 | return 0; | ||
1420 | |||
1421 | error: | ||
1422 | set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); | ||
1423 | __iwl_down(priv); | ||
1424 | clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); | ||
1425 | |||
1426 | IWL_ERR(priv, "Unable to initialize device.\n"); | ||
1427 | return ret; | ||
1428 | } | ||
1429 | |||
1430 | |||
1431 | /***************************************************************************** | 1373 | /***************************************************************************** |
1432 | * | 1374 | * |
1433 | * Workqueue callbacks | 1375 | * Workqueue callbacks |
@@ -1455,7 +1397,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
1455 | mutex_unlock(&priv->shrd->mutex); | 1397 | mutex_unlock(&priv->shrd->mutex); |
1456 | } | 1398 | } |
1457 | 1399 | ||
1458 | static void iwlagn_prepare_restart(struct iwl_priv *priv) | 1400 | void iwlagn_prepare_restart(struct iwl_priv *priv) |
1459 | { | 1401 | { |
1460 | struct iwl_rxon_context *ctx; | 1402 | struct iwl_rxon_context *ctx; |
1461 | bool bt_full_concurrent; | 1403 | bool bt_full_concurrent; |
@@ -1512,1181 +1454,8 @@ static void iwl_bg_restart(struct work_struct *data) | |||
1512 | } | 1454 | } |
1513 | } | 1455 | } |
1514 | 1456 | ||
1515 | /***************************************************************************** | ||
1516 | * | ||
1517 | * mac80211 entry point functions | ||
1518 | * | ||
1519 | *****************************************************************************/ | ||
1520 | |||
1521 | static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = { | ||
1522 | { | ||
1523 | .max = 1, | ||
1524 | .types = BIT(NL80211_IFTYPE_STATION), | ||
1525 | }, | ||
1526 | { | ||
1527 | .max = 1, | ||
1528 | .types = BIT(NL80211_IFTYPE_AP), | ||
1529 | }, | ||
1530 | }; | ||
1531 | |||
1532 | static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = { | ||
1533 | { | ||
1534 | .max = 2, | ||
1535 | .types = BIT(NL80211_IFTYPE_STATION), | ||
1536 | }, | ||
1537 | }; | ||
1538 | |||
1539 | static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = { | ||
1540 | { | ||
1541 | .max = 1, | ||
1542 | .types = BIT(NL80211_IFTYPE_STATION), | ||
1543 | }, | ||
1544 | { | ||
1545 | .max = 1, | ||
1546 | .types = BIT(NL80211_IFTYPE_P2P_GO) | | ||
1547 | BIT(NL80211_IFTYPE_AP), | ||
1548 | }, | ||
1549 | }; | ||
1550 | |||
1551 | static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = { | ||
1552 | { | ||
1553 | .max = 2, | ||
1554 | .types = BIT(NL80211_IFTYPE_STATION), | ||
1555 | }, | ||
1556 | { | ||
1557 | .max = 1, | ||
1558 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT), | ||
1559 | }, | ||
1560 | }; | ||
1561 | |||
1562 | static const struct ieee80211_iface_combination | ||
1563 | iwlagn_iface_combinations_dualmode[] = { | ||
1564 | { .num_different_channels = 1, | ||
1565 | .max_interfaces = 2, | ||
1566 | .beacon_int_infra_match = true, | ||
1567 | .limits = iwlagn_sta_ap_limits, | ||
1568 | .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits), | ||
1569 | }, | ||
1570 | { .num_different_channels = 1, | ||
1571 | .max_interfaces = 2, | ||
1572 | .limits = iwlagn_2sta_limits, | ||
1573 | .n_limits = ARRAY_SIZE(iwlagn_2sta_limits), | ||
1574 | }, | ||
1575 | }; | ||
1576 | |||
1577 | static const struct ieee80211_iface_combination | ||
1578 | iwlagn_iface_combinations_p2p[] = { | ||
1579 | { .num_different_channels = 1, | ||
1580 | .max_interfaces = 2, | ||
1581 | .beacon_int_infra_match = true, | ||
1582 | .limits = iwlagn_p2p_sta_go_limits, | ||
1583 | .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits), | ||
1584 | }, | ||
1585 | { .num_different_channels = 1, | ||
1586 | .max_interfaces = 2, | ||
1587 | .limits = iwlagn_p2p_2sta_limits, | ||
1588 | .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits), | ||
1589 | }, | ||
1590 | }; | ||
1591 | |||
1592 | /* | ||
1593 | * Not a mac80211 entry point function, but it fits in with all the | ||
1594 | * other mac80211 functions grouped here. | ||
1595 | */ | ||
1596 | static int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||
1597 | struct iwlagn_ucode_capabilities *capa) | ||
1598 | { | ||
1599 | int ret; | ||
1600 | struct ieee80211_hw *hw = priv->hw; | ||
1601 | struct iwl_rxon_context *ctx; | ||
1602 | |||
1603 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
1604 | |||
1605 | /* Tell mac80211 our characteristics */ | ||
1606 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1607 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
1608 | IEEE80211_HW_NEED_DTIM_PERIOD | | ||
1609 | IEEE80211_HW_SPECTRUM_MGMT | | ||
1610 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | ||
1611 | |||
1612 | /* | ||
1613 | * Including the following line will crash some AP's. This | ||
1614 | * workaround removes the stimulus which causes the crash until | ||
1615 | * the AP software can be fixed. | ||
1616 | hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
1617 | */ | ||
1618 | |||
1619 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
1620 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
1621 | |||
1622 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1623 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
1624 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
1625 | |||
1626 | if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) | ||
1627 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | ||
1628 | |||
1629 | hw->sta_data_size = sizeof(struct iwl_station_priv); | ||
1630 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
1631 | |||
1632 | for_each_context(priv, ctx) { | ||
1633 | hw->wiphy->interface_modes |= ctx->interface_modes; | ||
1634 | hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; | ||
1635 | } | ||
1636 | |||
1637 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
1638 | |||
1639 | if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) { | ||
1640 | hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p; | ||
1641 | hw->wiphy->n_iface_combinations = | ||
1642 | ARRAY_SIZE(iwlagn_iface_combinations_p2p); | ||
1643 | } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | ||
1644 | hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode; | ||
1645 | hw->wiphy->n_iface_combinations = | ||
1646 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); | ||
1647 | } | ||
1648 | |||
1649 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
1650 | |||
1651 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | ||
1652 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | ||
1653 | WIPHY_FLAG_IBSS_RSN; | ||
1654 | |||
1655 | if (trans(priv)->ucode_wowlan.code.len && | ||
1656 | device_can_wakeup(bus(priv)->dev)) { | ||
1657 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | ||
1658 | WIPHY_WOWLAN_DISCONNECT | | ||
1659 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | | ||
1660 | WIPHY_WOWLAN_RFKILL_RELEASE; | ||
1661 | if (!iwlagn_mod_params.sw_crypto) | ||
1662 | hw->wiphy->wowlan.flags |= | ||
1663 | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | | ||
1664 | WIPHY_WOWLAN_GTK_REKEY_FAILURE; | ||
1665 | |||
1666 | hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; | ||
1667 | hw->wiphy->wowlan.pattern_min_len = | ||
1668 | IWLAGN_WOWLAN_MIN_PATTERN_LEN; | ||
1669 | hw->wiphy->wowlan.pattern_max_len = | ||
1670 | IWLAGN_WOWLAN_MAX_PATTERN_LEN; | ||
1671 | } | ||
1672 | |||
1673 | if (iwlagn_mod_params.power_save) | ||
1674 | hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1675 | else | ||
1676 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1677 | |||
1678 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
1679 | /* we create the 802.11 header and a zero-length SSID element */ | ||
1680 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; | ||
1681 | |||
1682 | /* Default value; 4 EDCA QOS priorities */ | ||
1683 | hw->queues = 4; | ||
1684 | |||
1685 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
1686 | |||
1687 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
1688 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1689 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1690 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
1691 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1692 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1693 | |||
1694 | iwl_leds_init(priv); | ||
1695 | |||
1696 | ret = ieee80211_register_hw(priv->hw); | ||
1697 | if (ret) { | ||
1698 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
1699 | return ret; | ||
1700 | } | ||
1701 | priv->mac80211_registered = 1; | ||
1702 | |||
1703 | return 0; | ||
1704 | } | ||
1705 | |||
1706 | |||
1707 | static int iwlagn_mac_start(struct ieee80211_hw *hw) | ||
1708 | { | ||
1709 | struct iwl_priv *priv = hw->priv; | ||
1710 | int ret; | ||
1711 | |||
1712 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1713 | |||
1714 | /* we should be verifying the device is ready to be opened */ | ||
1715 | mutex_lock(&priv->shrd->mutex); | ||
1716 | ret = __iwl_up(priv); | ||
1717 | mutex_unlock(&priv->shrd->mutex); | ||
1718 | if (ret) | ||
1719 | return ret; | ||
1720 | |||
1721 | IWL_DEBUG_INFO(priv, "Start UP work done.\n"); | ||
1722 | |||
1723 | /* Now we should be done, and the READY bit should be set. */ | ||
1724 | if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) | ||
1725 | ret = -EIO; | ||
1726 | |||
1727 | iwlagn_led_enable(priv); | ||
1728 | |||
1729 | priv->is_open = 1; | ||
1730 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1731 | return 0; | ||
1732 | } | ||
1733 | |||
1734 | static void iwlagn_mac_stop(struct ieee80211_hw *hw) | ||
1735 | { | ||
1736 | struct iwl_priv *priv = hw->priv; | ||
1737 | |||
1738 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1739 | |||
1740 | if (!priv->is_open) | ||
1741 | return; | ||
1742 | |||
1743 | priv->is_open = 0; | ||
1744 | |||
1745 | iwl_down(priv); | ||
1746 | |||
1747 | flush_workqueue(priv->shrd->workqueue); | ||
1748 | |||
1749 | /* User space software may expect getting rfkill changes | ||
1750 | * even if interface is down */ | ||
1751 | iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); | ||
1752 | iwl_enable_rfkill_int(priv); | ||
1753 | |||
1754 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1755 | } | ||
1756 | |||
1757 | #ifdef CONFIG_PM_SLEEP | ||
1758 | static int iwlagn_send_patterns(struct iwl_priv *priv, | ||
1759 | struct cfg80211_wowlan *wowlan) | ||
1760 | { | ||
1761 | struct iwlagn_wowlan_patterns_cmd *pattern_cmd; | ||
1762 | struct iwl_host_cmd cmd = { | ||
1763 | .id = REPLY_WOWLAN_PATTERNS, | ||
1764 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
1765 | .flags = CMD_SYNC, | ||
1766 | }; | ||
1767 | int i, err; | ||
1768 | |||
1769 | if (!wowlan->n_patterns) | ||
1770 | return 0; | ||
1771 | |||
1772 | cmd.len[0] = sizeof(*pattern_cmd) + | ||
1773 | wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern); | ||
1774 | |||
1775 | pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); | ||
1776 | if (!pattern_cmd) | ||
1777 | return -ENOMEM; | ||
1778 | |||
1779 | pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns); | ||
1780 | |||
1781 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
1782 | int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | ||
1783 | |||
1784 | memcpy(&pattern_cmd->patterns[i].mask, | ||
1785 | wowlan->patterns[i].mask, mask_len); | ||
1786 | memcpy(&pattern_cmd->patterns[i].pattern, | ||
1787 | wowlan->patterns[i].pattern, | ||
1788 | wowlan->patterns[i].pattern_len); | ||
1789 | pattern_cmd->patterns[i].mask_size = mask_len; | ||
1790 | pattern_cmd->patterns[i].pattern_size = | ||
1791 | wowlan->patterns[i].pattern_len; | ||
1792 | } | ||
1793 | |||
1794 | cmd.data[0] = pattern_cmd; | ||
1795 | err = iwl_trans_send_cmd(trans(priv), &cmd); | ||
1796 | kfree(pattern_cmd); | ||
1797 | return err; | ||
1798 | } | ||
1799 | #endif | ||
1800 | |||
1801 | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||
1802 | struct ieee80211_vif *vif, | ||
1803 | struct cfg80211_gtk_rekey_data *data) | ||
1804 | { | ||
1805 | struct iwl_priv *priv = hw->priv; | ||
1806 | |||
1807 | if (iwlagn_mod_params.sw_crypto) | ||
1808 | return; | ||
1809 | |||
1810 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1811 | mutex_lock(&priv->shrd->mutex); | ||
1812 | |||
1813 | if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) | ||
1814 | goto out; | ||
1815 | |||
1816 | memcpy(priv->kek, data->kek, NL80211_KEK_LEN); | ||
1817 | memcpy(priv->kck, data->kck, NL80211_KCK_LEN); | ||
1818 | priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr)); | ||
1819 | priv->have_rekey_data = true; | ||
1820 | |||
1821 | out: | ||
1822 | mutex_unlock(&priv->shrd->mutex); | ||
1823 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1824 | } | ||
1825 | |||
1826 | struct wowlan_key_data { | ||
1827 | struct iwl_rxon_context *ctx; | ||
1828 | struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc; | ||
1829 | struct iwlagn_wowlan_tkip_params_cmd *tkip; | ||
1830 | const u8 *bssid; | ||
1831 | bool error, use_rsc_tsc, use_tkip; | ||
1832 | }; | ||
1833 | |||
1834 | #ifdef CONFIG_PM_SLEEP | ||
1835 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) | ||
1836 | { | ||
1837 | int i; | ||
1838 | |||
1839 | for (i = 0; i < IWLAGN_P1K_SIZE; i++) | ||
1840 | out[i] = cpu_to_le16(p1k[i]); | ||
1841 | } | ||
1842 | |||
1843 | static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, | ||
1844 | struct ieee80211_vif *vif, | ||
1845 | struct ieee80211_sta *sta, | ||
1846 | struct ieee80211_key_conf *key, | ||
1847 | void *_data) | ||
1848 | { | ||
1849 | struct iwl_priv *priv = hw->priv; | ||
1850 | struct wowlan_key_data *data = _data; | ||
1851 | struct iwl_rxon_context *ctx = data->ctx; | ||
1852 | struct aes_sc *aes_sc, *aes_tx_sc = NULL; | ||
1853 | struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL; | ||
1854 | struct iwlagn_p1k_cache *rx_p1ks; | ||
1855 | u8 *rx_mic_key; | ||
1856 | struct ieee80211_key_seq seq; | ||
1857 | u32 cur_rx_iv32 = 0; | ||
1858 | u16 p1k[IWLAGN_P1K_SIZE]; | ||
1859 | int ret, i; | ||
1860 | |||
1861 | mutex_lock(&priv->shrd->mutex); | ||
1862 | |||
1863 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
1864 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
1865 | !sta && !ctx->key_mapping_keys) | ||
1866 | ret = iwl_set_default_wep_key(priv, ctx, key); | ||
1867 | else | ||
1868 | ret = iwl_set_dynamic_key(priv, ctx, key, sta); | ||
1869 | |||
1870 | if (ret) { | ||
1871 | IWL_ERR(priv, "Error setting key during suspend!\n"); | ||
1872 | data->error = true; | ||
1873 | } | ||
1874 | |||
1875 | switch (key->cipher) { | ||
1876 | case WLAN_CIPHER_SUITE_TKIP: | ||
1877 | if (sta) { | ||
1878 | tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; | ||
1879 | tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc; | ||
1880 | |||
1881 | rx_p1ks = data->tkip->rx_uni; | ||
1882 | |||
1883 | ieee80211_get_key_tx_seq(key, &seq); | ||
1884 | tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16); | ||
1885 | tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32); | ||
1886 | |||
1887 | ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k); | ||
1888 | iwlagn_convert_p1k(p1k, data->tkip->tx.p1k); | ||
1889 | |||
1890 | memcpy(data->tkip->mic_keys.tx, | ||
1891 | &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], | ||
1892 | IWLAGN_MIC_KEY_SIZE); | ||
1893 | |||
1894 | rx_mic_key = data->tkip->mic_keys.rx_unicast; | ||
1895 | } else { | ||
1896 | tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; | ||
1897 | rx_p1ks = data->tkip->rx_multi; | ||
1898 | rx_mic_key = data->tkip->mic_keys.rx_mcast; | ||
1899 | } | ||
1900 | |||
1901 | /* | ||
1902 | * For non-QoS this relies on the fact that both the uCode and | ||
1903 | * mac80211 use TID 0 (as they need to to avoid replay attacks) | ||
1904 | * for checking the IV in the frames. | ||
1905 | */ | ||
1906 | for (i = 0; i < IWLAGN_NUM_RSC; i++) { | ||
1907 | ieee80211_get_key_rx_seq(key, i, &seq); | ||
1908 | tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16); | ||
1909 | tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32); | ||
1910 | /* wrapping isn't allowed, AP must rekey */ | ||
1911 | if (seq.tkip.iv32 > cur_rx_iv32) | ||
1912 | cur_rx_iv32 = seq.tkip.iv32; | ||
1913 | } | ||
1914 | |||
1915 | ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k); | ||
1916 | iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k); | ||
1917 | ieee80211_get_tkip_rx_p1k(key, data->bssid, | ||
1918 | cur_rx_iv32 + 1, p1k); | ||
1919 | iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k); | ||
1920 | |||
1921 | memcpy(rx_mic_key, | ||
1922 | &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], | ||
1923 | IWLAGN_MIC_KEY_SIZE); | ||
1924 | |||
1925 | data->use_tkip = true; | ||
1926 | data->use_rsc_tsc = true; | ||
1927 | break; | ||
1928 | case WLAN_CIPHER_SUITE_CCMP: | ||
1929 | if (sta) { | ||
1930 | u8 *pn = seq.ccmp.pn; | ||
1931 | |||
1932 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; | ||
1933 | aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; | ||
1934 | |||
1935 | ieee80211_get_key_tx_seq(key, &seq); | ||
1936 | aes_tx_sc->pn = cpu_to_le64( | ||
1937 | (u64)pn[5] | | ||
1938 | ((u64)pn[4] << 8) | | ||
1939 | ((u64)pn[3] << 16) | | ||
1940 | ((u64)pn[2] << 24) | | ||
1941 | ((u64)pn[1] << 32) | | ||
1942 | ((u64)pn[0] << 40)); | ||
1943 | } else | ||
1944 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; | ||
1945 | |||
1946 | /* | ||
1947 | * For non-QoS this relies on the fact that both the uCode and | ||
1948 | * mac80211 use TID 0 for checking the IV in the frames. | ||
1949 | */ | ||
1950 | for (i = 0; i < IWLAGN_NUM_RSC; i++) { | ||
1951 | u8 *pn = seq.ccmp.pn; | ||
1952 | |||
1953 | ieee80211_get_key_rx_seq(key, i, &seq); | ||
1954 | aes_sc->pn = cpu_to_le64( | ||
1955 | (u64)pn[5] | | ||
1956 | ((u64)pn[4] << 8) | | ||
1957 | ((u64)pn[3] << 16) | | ||
1958 | ((u64)pn[2] << 24) | | ||
1959 | ((u64)pn[1] << 32) | | ||
1960 | ((u64)pn[0] << 40)); | ||
1961 | } | ||
1962 | data->use_rsc_tsc = true; | ||
1963 | break; | ||
1964 | } | ||
1965 | |||
1966 | mutex_unlock(&priv->shrd->mutex); | ||
1967 | } | ||
1968 | |||
1969 | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | ||
1970 | struct cfg80211_wowlan *wowlan) | ||
1971 | { | ||
1972 | struct iwl_priv *priv = hw->priv; | ||
1973 | struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; | ||
1974 | struct iwl_rxon_cmd rxon; | ||
1975 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1976 | struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; | ||
1977 | struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; | ||
1978 | struct wowlan_key_data key_data = { | ||
1979 | .ctx = ctx, | ||
1980 | .bssid = ctx->active.bssid_addr, | ||
1981 | .use_rsc_tsc = false, | ||
1982 | .tkip = &tkip_cmd, | ||
1983 | .use_tkip = false, | ||
1984 | }; | ||
1985 | struct iwlagn_d3_config_cmd d3_cfg_cmd = {}; | ||
1986 | int ret, i; | ||
1987 | u16 seq; | ||
1988 | |||
1989 | if (WARN_ON(!wowlan)) | ||
1990 | return -EINVAL; | ||
1991 | |||
1992 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1993 | mutex_lock(&priv->shrd->mutex); | ||
1994 | |||
1995 | /* Don't attempt WoWLAN when not associated, tear down instead. */ | ||
1996 | if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || | ||
1997 | !iwl_is_associated_ctx(ctx)) { | ||
1998 | ret = 1; | ||
1999 | goto out; | ||
2000 | } | ||
2001 | |||
2002 | key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); | ||
2003 | if (!key_data.rsc_tsc) { | ||
2004 | ret = -ENOMEM; | ||
2005 | goto out; | ||
2006 | } | ||
2007 | |||
2008 | memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd)); | ||
2009 | |||
2010 | /* | ||
2011 | * We know the last used seqno, and the uCode expects to know that | ||
2012 | * one, it will increment before TX. | ||
2013 | */ | ||
2014 | seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ; | ||
2015 | wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq); | ||
2016 | |||
2017 | /* | ||
2018 | * For QoS counters, we store the one to use next, so subtract 0x10 | ||
2019 | * since the uCode will add 0x10 before using the value. | ||
2020 | */ | ||
2021 | for (i = 0; i < 8; i++) { | ||
2022 | seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; | ||
2023 | seq -= 0x10; | ||
2024 | wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); | ||
2025 | } | ||
2026 | |||
2027 | if (wowlan->disconnect) | ||
2028 | wakeup_filter_cmd.enabled |= | ||
2029 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS | | ||
2030 | IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE); | ||
2031 | if (wowlan->magic_pkt) | ||
2032 | wakeup_filter_cmd.enabled |= | ||
2033 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET); | ||
2034 | if (wowlan->gtk_rekey_failure) | ||
2035 | wakeup_filter_cmd.enabled |= | ||
2036 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL); | ||
2037 | if (wowlan->eap_identity_req) | ||
2038 | wakeup_filter_cmd.enabled |= | ||
2039 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ); | ||
2040 | if (wowlan->four_way_handshake) | ||
2041 | wakeup_filter_cmd.enabled |= | ||
2042 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE); | ||
2043 | if (wowlan->n_patterns) | ||
2044 | wakeup_filter_cmd.enabled |= | ||
2045 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH); | ||
2046 | |||
2047 | if (wowlan->rfkill_release) | ||
2048 | d3_cfg_cmd.wakeup_flags |= | ||
2049 | cpu_to_le32(IWLAGN_D3_WAKEUP_RFKILL); | ||
2050 | |||
2051 | iwl_scan_cancel_timeout(priv, 200); | ||
2052 | |||
2053 | memcpy(&rxon, &ctx->active, sizeof(rxon)); | ||
2054 | |||
2055 | iwl_trans_stop_device(trans(priv)); | ||
2056 | |||
2057 | priv->shrd->wowlan = true; | ||
2058 | |||
2059 | ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); | ||
2060 | if (ret) | ||
2061 | goto error; | ||
2062 | |||
2063 | /* now configure WoWLAN ucode */ | ||
2064 | ret = iwl_alive_start(priv); | ||
2065 | if (ret) | ||
2066 | goto error; | ||
2067 | |||
2068 | memcpy(&ctx->staging, &rxon, sizeof(rxon)); | ||
2069 | ret = iwlagn_commit_rxon(priv, ctx); | ||
2070 | if (ret) | ||
2071 | goto error; | ||
2072 | |||
2073 | ret = iwl_power_update_mode(priv, true); | ||
2074 | if (ret) | ||
2075 | goto error; | ||
2076 | |||
2077 | if (!iwlagn_mod_params.sw_crypto) { | ||
2078 | /* mark all keys clear */ | ||
2079 | priv->ucode_key_table = 0; | ||
2080 | ctx->key_mapping_keys = 0; | ||
2081 | |||
2082 | /* | ||
2083 | * This needs to be unlocked due to lock ordering | ||
2084 | * constraints. Since we're in the suspend path | ||
2085 | * that isn't really a problem though. | ||
2086 | */ | ||
2087 | mutex_unlock(&priv->shrd->mutex); | ||
2088 | ieee80211_iter_keys(priv->hw, ctx->vif, | ||
2089 | iwlagn_wowlan_program_keys, | ||
2090 | &key_data); | ||
2091 | mutex_lock(&priv->shrd->mutex); | ||
2092 | if (key_data.error) { | ||
2093 | ret = -EIO; | ||
2094 | goto error; | ||
2095 | } | ||
2096 | |||
2097 | if (key_data.use_rsc_tsc) { | ||
2098 | struct iwl_host_cmd rsc_tsc_cmd = { | ||
2099 | .id = REPLY_WOWLAN_TSC_RSC_PARAMS, | ||
2100 | .flags = CMD_SYNC, | ||
2101 | .data[0] = key_data.rsc_tsc, | ||
2102 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
2103 | .len[0] = sizeof(*key_data.rsc_tsc), | ||
2104 | }; | ||
2105 | |||
2106 | ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); | ||
2107 | if (ret) | ||
2108 | goto error; | ||
2109 | } | ||
2110 | |||
2111 | if (key_data.use_tkip) { | ||
2112 | ret = iwl_trans_send_cmd_pdu(trans(priv), | ||
2113 | REPLY_WOWLAN_TKIP_PARAMS, | ||
2114 | CMD_SYNC, sizeof(tkip_cmd), | ||
2115 | &tkip_cmd); | ||
2116 | if (ret) | ||
2117 | goto error; | ||
2118 | } | ||
2119 | |||
2120 | if (priv->have_rekey_data) { | ||
2121 | memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd)); | ||
2122 | memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN); | ||
2123 | kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN); | ||
2124 | memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN); | ||
2125 | kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); | ||
2126 | kek_kck_cmd.replay_ctr = priv->replay_ctr; | ||
2127 | |||
2128 | ret = iwl_trans_send_cmd_pdu(trans(priv), | ||
2129 | REPLY_WOWLAN_KEK_KCK_MATERIAL, | ||
2130 | CMD_SYNC, sizeof(kek_kck_cmd), | ||
2131 | &kek_kck_cmd); | ||
2132 | if (ret) | ||
2133 | goto error; | ||
2134 | } | ||
2135 | } | ||
2136 | |||
2137 | ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC, | ||
2138 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | ||
2139 | if (ret) | ||
2140 | goto error; | ||
2141 | |||
2142 | ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, | ||
2143 | CMD_SYNC, sizeof(wakeup_filter_cmd), | ||
2144 | &wakeup_filter_cmd); | ||
2145 | if (ret) | ||
2146 | goto error; | ||
2147 | |||
2148 | ret = iwlagn_send_patterns(priv, wowlan); | ||
2149 | if (ret) | ||
2150 | goto error; | ||
2151 | |||
2152 | device_set_wakeup_enable(bus(priv)->dev, true); | ||
2153 | |||
2154 | /* Now let the ucode operate on its own */ | ||
2155 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, | ||
2156 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
2157 | |||
2158 | goto out; | ||
2159 | |||
2160 | error: | ||
2161 | priv->shrd->wowlan = false; | ||
2162 | iwlagn_prepare_restart(priv); | ||
2163 | ieee80211_restart_hw(priv->hw); | ||
2164 | out: | ||
2165 | mutex_unlock(&priv->shrd->mutex); | ||
2166 | kfree(key_data.rsc_tsc); | ||
2167 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2168 | |||
2169 | return ret; | ||
2170 | } | ||
2171 | |||
2172 | static int iwlagn_mac_resume(struct ieee80211_hw *hw) | ||
2173 | { | ||
2174 | struct iwl_priv *priv = hw->priv; | ||
2175 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2176 | struct ieee80211_vif *vif; | ||
2177 | unsigned long flags; | ||
2178 | u32 base, status = 0xffffffff; | ||
2179 | int ret = -EIO; | ||
2180 | |||
2181 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2182 | mutex_lock(&priv->shrd->mutex); | ||
2183 | |||
2184 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | ||
2185 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
2186 | |||
2187 | base = priv->device_pointers.error_event_table; | ||
2188 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | ||
2189 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); | ||
2190 | ret = iwl_grab_nic_access_silent(bus(priv)); | ||
2191 | if (ret == 0) { | ||
2192 | iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); | ||
2193 | status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | ||
2194 | iwl_release_nic_access(bus(priv)); | ||
2195 | } | ||
2196 | spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); | ||
2197 | |||
2198 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
2199 | if (ret == 0) { | ||
2200 | struct iwl_trans *trans = trans(priv); | ||
2201 | if (!priv->wowlan_sram) | ||
2202 | priv->wowlan_sram = | ||
2203 | kzalloc(trans->ucode_wowlan.data.len, | ||
2204 | GFP_KERNEL); | ||
2205 | |||
2206 | if (priv->wowlan_sram) | ||
2207 | _iwl_read_targ_mem_words( | ||
2208 | bus(priv), 0x800000, priv->wowlan_sram, | ||
2209 | trans->ucode_wowlan.data.len / 4); | ||
2210 | } | ||
2211 | #endif | ||
2212 | } | ||
2213 | |||
2214 | /* we'll clear ctx->vif during iwlagn_prepare_restart() */ | ||
2215 | vif = ctx->vif; | ||
2216 | |||
2217 | priv->shrd->wowlan = false; | ||
2218 | |||
2219 | device_set_wakeup_enable(bus(priv)->dev, false); | ||
2220 | |||
2221 | iwlagn_prepare_restart(priv); | ||
2222 | |||
2223 | memset((void *)&ctx->active, 0, sizeof(ctx->active)); | ||
2224 | iwl_connection_init_rx_config(priv, ctx); | ||
2225 | iwlagn_set_rxon_chain(priv, ctx); | ||
2226 | |||
2227 | mutex_unlock(&priv->shrd->mutex); | ||
2228 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2229 | |||
2230 | ieee80211_resume_disconnect(vif); | ||
2231 | |||
2232 | return 1; | ||
2233 | } | ||
2234 | #endif | ||
2235 | |||
2236 | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
2237 | { | ||
2238 | struct iwl_priv *priv = hw->priv; | ||
2239 | |||
2240 | IWL_DEBUG_MACDUMP(priv, "enter\n"); | ||
2241 | |||
2242 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | ||
2243 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | ||
2244 | |||
2245 | if (iwlagn_tx_skb(priv, skb)) | ||
2246 | dev_kfree_skb_any(skb); | ||
2247 | |||
2248 | IWL_DEBUG_MACDUMP(priv, "leave\n"); | ||
2249 | } | ||
2250 | |||
2251 | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||
2252 | struct ieee80211_vif *vif, | ||
2253 | struct ieee80211_key_conf *keyconf, | ||
2254 | struct ieee80211_sta *sta, | ||
2255 | u32 iv32, u16 *phase1key) | ||
2256 | { | ||
2257 | struct iwl_priv *priv = hw->priv; | ||
2258 | |||
2259 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | ||
2260 | } | ||
2261 | |||
2262 | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
2263 | struct ieee80211_vif *vif, | ||
2264 | struct ieee80211_sta *sta, | ||
2265 | struct ieee80211_key_conf *key) | ||
2266 | { | ||
2267 | struct iwl_priv *priv = hw->priv; | ||
2268 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2269 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
2270 | int ret; | ||
2271 | bool is_default_wep_key = false; | ||
2272 | |||
2273 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2274 | |||
2275 | if (iwlagn_mod_params.sw_crypto) { | ||
2276 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | ||
2277 | return -EOPNOTSUPP; | ||
2278 | } | ||
2279 | |||
2280 | /* | ||
2281 | * We could program these keys into the hardware as well, but we | ||
2282 | * don't expect much multicast traffic in IBSS and having keys | ||
2283 | * for more stations is probably more useful. | ||
2284 | * | ||
2285 | * Mark key TX-only and return 0. | ||
2286 | */ | ||
2287 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
2288 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
2289 | key->hw_key_idx = WEP_INVALID_OFFSET; | ||
2290 | return 0; | ||
2291 | } | ||
2292 | |||
2293 | /* If they key was TX-only, accept deletion */ | ||
2294 | if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) | ||
2295 | return 0; | ||
2296 | |||
2297 | mutex_lock(&priv->shrd->mutex); | ||
2298 | iwl_scan_cancel_timeout(priv, 100); | ||
2299 | |||
2300 | BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); | ||
2301 | |||
2302 | /* | ||
2303 | * If we are getting WEP group key and we didn't receive any key mapping | ||
2304 | * so far, we are in legacy wep mode (group key only), otherwise we are | ||
2305 | * in 1X mode. | ||
2306 | * In legacy wep mode, we use another host command to the uCode. | ||
2307 | */ | ||
2308 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
2309 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { | ||
2310 | if (cmd == SET_KEY) | ||
2311 | is_default_wep_key = !ctx->key_mapping_keys; | ||
2312 | else | ||
2313 | is_default_wep_key = | ||
2314 | key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT; | ||
2315 | } | ||
2316 | |||
2317 | |||
2318 | switch (cmd) { | ||
2319 | case SET_KEY: | ||
2320 | if (is_default_wep_key) { | ||
2321 | ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); | ||
2322 | break; | ||
2323 | } | ||
2324 | ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta); | ||
2325 | if (ret) { | ||
2326 | /* | ||
2327 | * can't add key for RX, but we don't need it | ||
2328 | * in the device for TX so still return 0 | ||
2329 | */ | ||
2330 | ret = 0; | ||
2331 | key->hw_key_idx = WEP_INVALID_OFFSET; | ||
2332 | } | ||
2333 | |||
2334 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); | ||
2335 | break; | ||
2336 | case DISABLE_KEY: | ||
2337 | if (is_default_wep_key) | ||
2338 | ret = iwl_remove_default_wep_key(priv, ctx, key); | ||
2339 | else | ||
2340 | ret = iwl_remove_dynamic_key(priv, ctx, key, sta); | ||
2341 | |||
2342 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); | ||
2343 | break; | ||
2344 | default: | ||
2345 | ret = -EINVAL; | ||
2346 | } | ||
2347 | |||
2348 | mutex_unlock(&priv->shrd->mutex); | ||
2349 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2350 | |||
2351 | return ret; | ||
2352 | } | ||
2353 | |||
2354 | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||
2355 | struct ieee80211_vif *vif, | ||
2356 | enum ieee80211_ampdu_mlme_action action, | ||
2357 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
2358 | u8 buf_size) | ||
2359 | { | ||
2360 | struct iwl_priv *priv = hw->priv; | ||
2361 | int ret = -EINVAL; | ||
2362 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; | ||
2363 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
2364 | |||
2365 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | ||
2366 | sta->addr, tid); | ||
2367 | |||
2368 | if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)) | ||
2369 | return -EACCES; | ||
2370 | |||
2371 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2372 | mutex_lock(&priv->shrd->mutex); | ||
2373 | |||
2374 | switch (action) { | ||
2375 | case IEEE80211_AMPDU_RX_START: | ||
2376 | IWL_DEBUG_HT(priv, "start Rx\n"); | ||
2377 | ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); | ||
2378 | break; | ||
2379 | case IEEE80211_AMPDU_RX_STOP: | ||
2380 | IWL_DEBUG_HT(priv, "stop Rx\n"); | ||
2381 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | ||
2382 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | ||
2383 | ret = 0; | ||
2384 | break; | ||
2385 | case IEEE80211_AMPDU_TX_START: | ||
2386 | IWL_DEBUG_HT(priv, "start Tx\n"); | ||
2387 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | ||
2388 | break; | ||
2389 | case IEEE80211_AMPDU_TX_STOP: | ||
2390 | IWL_DEBUG_HT(priv, "stop Tx\n"); | ||
2391 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | ||
2392 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | ||
2393 | priv->agg_tids_count--; | ||
2394 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2395 | priv->agg_tids_count); | ||
2396 | } | ||
2397 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | ||
2398 | ret = 0; | ||
2399 | if (!priv->agg_tids_count && priv->cfg->ht_params && | ||
2400 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
2401 | /* | ||
2402 | * switch off RTS/CTS if it was previously enabled | ||
2403 | */ | ||
2404 | sta_priv->lq_sta.lq.general_params.flags &= | ||
2405 | ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
2406 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
2407 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
2408 | } | ||
2409 | break; | ||
2410 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2411 | buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); | ||
2412 | |||
2413 | iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), | ||
2414 | tid, buf_size); | ||
2415 | |||
2416 | /* | ||
2417 | * If the limit is 0, then it wasn't initialised yet, | ||
2418 | * use the default. We can do that since we take the | ||
2419 | * minimum below, and we don't want to go above our | ||
2420 | * default due to hardware restrictions. | ||
2421 | */ | ||
2422 | if (sta_priv->max_agg_bufsize == 0) | ||
2423 | sta_priv->max_agg_bufsize = | ||
2424 | LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
2425 | |||
2426 | /* | ||
2427 | * Even though in theory the peer could have different | ||
2428 | * aggregation reorder buffer sizes for different sessions, | ||
2429 | * our ucode doesn't allow for that and has a global limit | ||
2430 | * for each station. Therefore, use the minimum of all the | ||
2431 | * aggregation sessions and our default value. | ||
2432 | */ | ||
2433 | sta_priv->max_agg_bufsize = | ||
2434 | min(sta_priv->max_agg_bufsize, buf_size); | ||
2435 | |||
2436 | if (priv->cfg->ht_params && | ||
2437 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
2438 | /* | ||
2439 | * switch to RTS/CTS if it is the prefer protection | ||
2440 | * method for HT traffic | ||
2441 | */ | ||
2442 | |||
2443 | sta_priv->lq_sta.lq.general_params.flags |= | ||
2444 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
2445 | } | ||
2446 | priv->agg_tids_count++; | ||
2447 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2448 | priv->agg_tids_count); | ||
2449 | |||
2450 | sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = | ||
2451 | sta_priv->max_agg_bufsize; | ||
2452 | |||
2453 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
2454 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
2455 | |||
2456 | IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", | ||
2457 | sta->addr, tid); | ||
2458 | ret = 0; | ||
2459 | break; | ||
2460 | } | ||
2461 | mutex_unlock(&priv->shrd->mutex); | ||
2462 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2463 | return ret; | ||
2464 | } | ||
2465 | |||
2466 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | ||
2467 | struct ieee80211_vif *vif, | ||
2468 | struct ieee80211_sta *sta) | ||
2469 | { | ||
2470 | struct iwl_priv *priv = hw->priv; | ||
2471 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
2472 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2473 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | ||
2474 | int ret = 0; | ||
2475 | u8 sta_id; | ||
2476 | |||
2477 | IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n", | ||
2478 | sta->addr); | ||
2479 | mutex_lock(&priv->shrd->mutex); | ||
2480 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | ||
2481 | sta->addr); | ||
2482 | sta_priv->sta_id = IWL_INVALID_STATION; | ||
2483 | |||
2484 | atomic_set(&sta_priv->pending_frames, 0); | ||
2485 | if (vif->type == NL80211_IFTYPE_AP) | ||
2486 | sta_priv->client = true; | ||
2487 | |||
2488 | ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr, | ||
2489 | is_ap, sta, &sta_id); | ||
2490 | if (ret) { | ||
2491 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
2492 | sta->addr, ret); | ||
2493 | /* Should we return success if return code is EEXIST ? */ | ||
2494 | goto out; | ||
2495 | } | ||
2496 | |||
2497 | sta_priv->sta_id = sta_id; | ||
2498 | 1457 | ||
2499 | /* Initialize rate scaling */ | ||
2500 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
2501 | sta->addr); | ||
2502 | iwl_rs_rate_init(priv, sta, sta_id); | ||
2503 | out: | ||
2504 | mutex_unlock(&priv->shrd->mutex); | ||
2505 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2506 | 1458 | ||
2507 | return ret; | ||
2508 | } | ||
2509 | |||
2510 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
2511 | struct ieee80211_channel_switch *ch_switch) | ||
2512 | { | ||
2513 | struct iwl_priv *priv = hw->priv; | ||
2514 | const struct iwl_channel_info *ch_info; | ||
2515 | struct ieee80211_conf *conf = &hw->conf; | ||
2516 | struct ieee80211_channel *channel = ch_switch->channel; | ||
2517 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
2518 | /* | ||
2519 | * MULTI-FIXME | ||
2520 | * When we add support for multiple interfaces, we need to | ||
2521 | * revisit this. The channel switch command in the device | ||
2522 | * only affects the BSS context, but what does that really | ||
2523 | * mean? And what if we get a CSA on the second interface? | ||
2524 | * This needs a lot of work. | ||
2525 | */ | ||
2526 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2527 | u16 ch; | ||
2528 | |||
2529 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2530 | |||
2531 | mutex_lock(&priv->shrd->mutex); | ||
2532 | |||
2533 | if (iwl_is_rfkill(priv->shrd)) | ||
2534 | goto out; | ||
2535 | |||
2536 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || | ||
2537 | test_bit(STATUS_SCANNING, &priv->shrd->status) || | ||
2538 | test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) | ||
2539 | goto out; | ||
2540 | |||
2541 | if (!iwl_is_associated_ctx(ctx)) | ||
2542 | goto out; | ||
2543 | |||
2544 | if (!priv->cfg->lib->set_channel_switch) | ||
2545 | goto out; | ||
2546 | |||
2547 | ch = channel->hw_value; | ||
2548 | if (le16_to_cpu(ctx->active.channel) == ch) | ||
2549 | goto out; | ||
2550 | |||
2551 | ch_info = iwl_get_channel_info(priv, channel->band, ch); | ||
2552 | if (!is_channel_valid(ch_info)) { | ||
2553 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | ||
2554 | goto out; | ||
2555 | } | ||
2556 | |||
2557 | spin_lock_irq(&priv->shrd->lock); | ||
2558 | |||
2559 | priv->current_ht_config.smps = conf->smps_mode; | ||
2560 | |||
2561 | /* Configure HT40 channels */ | ||
2562 | ctx->ht.enabled = conf_is_ht(conf); | ||
2563 | if (ctx->ht.enabled) { | ||
2564 | if (conf_is_ht40_minus(conf)) { | ||
2565 | ctx->ht.extension_chan_offset = | ||
2566 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
2567 | ctx->ht.is_40mhz = true; | ||
2568 | } else if (conf_is_ht40_plus(conf)) { | ||
2569 | ctx->ht.extension_chan_offset = | ||
2570 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
2571 | ctx->ht.is_40mhz = true; | ||
2572 | } else { | ||
2573 | ctx->ht.extension_chan_offset = | ||
2574 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
2575 | ctx->ht.is_40mhz = false; | ||
2576 | } | ||
2577 | } else | ||
2578 | ctx->ht.is_40mhz = false; | ||
2579 | |||
2580 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | ||
2581 | ctx->staging.flags = 0; | ||
2582 | |||
2583 | iwl_set_rxon_channel(priv, channel, ctx); | ||
2584 | iwl_set_rxon_ht(priv, ht_conf); | ||
2585 | iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); | ||
2586 | |||
2587 | spin_unlock_irq(&priv->shrd->lock); | ||
2588 | |||
2589 | iwl_set_rate(priv); | ||
2590 | /* | ||
2591 | * at this point, staging_rxon has the | ||
2592 | * configuration for channel switch | ||
2593 | */ | ||
2594 | set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); | ||
2595 | priv->switch_channel = cpu_to_le16(ch); | ||
2596 | if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { | ||
2597 | clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); | ||
2598 | priv->switch_channel = 0; | ||
2599 | ieee80211_chswitch_done(ctx->vif, false); | ||
2600 | } | ||
2601 | |||
2602 | out: | ||
2603 | mutex_unlock(&priv->shrd->mutex); | ||
2604 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2605 | } | ||
2606 | |||
2607 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
2608 | unsigned int changed_flags, | ||
2609 | unsigned int *total_flags, | ||
2610 | u64 multicast) | ||
2611 | { | ||
2612 | struct iwl_priv *priv = hw->priv; | ||
2613 | __le32 filter_or = 0, filter_nand = 0; | ||
2614 | struct iwl_rxon_context *ctx; | ||
2615 | |||
2616 | #define CHK(test, flag) do { \ | ||
2617 | if (*total_flags & (test)) \ | ||
2618 | filter_or |= (flag); \ | ||
2619 | else \ | ||
2620 | filter_nand |= (flag); \ | ||
2621 | } while (0) | ||
2622 | |||
2623 | IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", | ||
2624 | changed_flags, *total_flags); | ||
2625 | |||
2626 | CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); | ||
2627 | /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */ | ||
2628 | CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); | ||
2629 | CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); | ||
2630 | |||
2631 | #undef CHK | ||
2632 | |||
2633 | mutex_lock(&priv->shrd->mutex); | ||
2634 | |||
2635 | for_each_context(priv, ctx) { | ||
2636 | ctx->staging.filter_flags &= ~filter_nand; | ||
2637 | ctx->staging.filter_flags |= filter_or; | ||
2638 | |||
2639 | /* | ||
2640 | * Not committing directly because hardware can perform a scan, | ||
2641 | * but we'll eventually commit the filter flags change anyway. | ||
2642 | */ | ||
2643 | } | ||
2644 | |||
2645 | mutex_unlock(&priv->shrd->mutex); | ||
2646 | |||
2647 | /* | ||
2648 | * Receiving all multicast frames is always enabled by the | ||
2649 | * default flags setup in iwl_connection_init_rx_config() | ||
2650 | * since we currently do not support programming multicast | ||
2651 | * filters into the device. | ||
2652 | */ | ||
2653 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | ||
2654 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
2655 | } | ||
2656 | |||
2657 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | ||
2658 | { | ||
2659 | struct iwl_priv *priv = hw->priv; | ||
2660 | |||
2661 | mutex_lock(&priv->shrd->mutex); | ||
2662 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2663 | |||
2664 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { | ||
2665 | IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); | ||
2666 | goto done; | ||
2667 | } | ||
2668 | if (iwl_is_rfkill(priv->shrd)) { | ||
2669 | IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); | ||
2670 | goto done; | ||
2671 | } | ||
2672 | |||
2673 | /* | ||
2674 | * mac80211 will not push any more frames for transmit | ||
2675 | * until the flush is completed | ||
2676 | */ | ||
2677 | if (drop) { | ||
2678 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | ||
2679 | if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { | ||
2680 | IWL_ERR(priv, "flush request fail\n"); | ||
2681 | goto done; | ||
2682 | } | ||
2683 | } | ||
2684 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); | ||
2685 | iwl_trans_wait_tx_queue_empty(trans(priv)); | ||
2686 | done: | ||
2687 | mutex_unlock(&priv->shrd->mutex); | ||
2688 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2689 | } | ||
2690 | 1459 | ||
2691 | void iwlagn_disable_roc(struct iwl_priv *priv) | 1460 | void iwlagn_disable_roc(struct iwl_priv *priv) |
2692 | { | 1461 | { |
@@ -2720,160 +1489,6 @@ static void iwlagn_disable_roc_work(struct work_struct *work) | |||
2720 | mutex_unlock(&priv->shrd->mutex); | 1489 | mutex_unlock(&priv->shrd->mutex); |
2721 | } | 1490 | } |
2722 | 1491 | ||
2723 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | ||
2724 | struct ieee80211_channel *channel, | ||
2725 | enum nl80211_channel_type channel_type, | ||
2726 | int duration) | ||
2727 | { | ||
2728 | struct iwl_priv *priv = hw->priv; | ||
2729 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
2730 | int err = 0; | ||
2731 | |||
2732 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
2733 | return -EOPNOTSUPP; | ||
2734 | |||
2735 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) | ||
2736 | return -EOPNOTSUPP; | ||
2737 | |||
2738 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2739 | mutex_lock(&priv->shrd->mutex); | ||
2740 | |||
2741 | if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { | ||
2742 | err = -EBUSY; | ||
2743 | goto out; | ||
2744 | } | ||
2745 | |||
2746 | priv->hw_roc_channel = channel; | ||
2747 | priv->hw_roc_chantype = channel_type; | ||
2748 | priv->hw_roc_duration = duration; | ||
2749 | priv->hw_roc_start_notified = false; | ||
2750 | cancel_delayed_work(&priv->hw_roc_disable_work); | ||
2751 | |||
2752 | if (!ctx->is_active) { | ||
2753 | ctx->is_active = true; | ||
2754 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
2755 | memcpy(ctx->staging.node_addr, | ||
2756 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
2757 | ETH_ALEN); | ||
2758 | memcpy(ctx->staging.bssid_addr, | ||
2759 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
2760 | ETH_ALEN); | ||
2761 | err = iwlagn_commit_rxon(priv, ctx); | ||
2762 | if (err) | ||
2763 | goto out; | ||
2764 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK | | ||
2765 | RXON_FILTER_PROMISC_MSK | | ||
2766 | RXON_FILTER_CTL2HOST_MSK; | ||
2767 | |||
2768 | err = iwlagn_commit_rxon(priv, ctx); | ||
2769 | if (err) { | ||
2770 | iwlagn_disable_roc(priv); | ||
2771 | goto out; | ||
2772 | } | ||
2773 | priv->hw_roc_setup = true; | ||
2774 | } | ||
2775 | |||
2776 | err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band); | ||
2777 | if (err) | ||
2778 | iwlagn_disable_roc(priv); | ||
2779 | |||
2780 | out: | ||
2781 | mutex_unlock(&priv->shrd->mutex); | ||
2782 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2783 | |||
2784 | return err; | ||
2785 | } | ||
2786 | |||
2787 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||
2788 | { | ||
2789 | struct iwl_priv *priv = hw->priv; | ||
2790 | |||
2791 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
2792 | return -EOPNOTSUPP; | ||
2793 | |||
2794 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2795 | mutex_lock(&priv->shrd->mutex); | ||
2796 | iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); | ||
2797 | iwlagn_disable_roc(priv); | ||
2798 | mutex_unlock(&priv->shrd->mutex); | ||
2799 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2800 | |||
2801 | return 0; | ||
2802 | } | ||
2803 | |||
2804 | static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, | ||
2805 | struct ieee80211_vif *vif, | ||
2806 | const u8 *bssid, | ||
2807 | enum ieee80211_tx_sync_type type) | ||
2808 | { | ||
2809 | struct iwl_priv *priv = hw->priv; | ||
2810 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2811 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
2812 | int ret; | ||
2813 | u8 sta_id; | ||
2814 | |||
2815 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2816 | mutex_lock(&priv->shrd->mutex); | ||
2817 | |||
2818 | if (iwl_is_associated_ctx(ctx)) { | ||
2819 | ret = 0; | ||
2820 | goto out; | ||
2821 | } | ||
2822 | |||
2823 | if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { | ||
2824 | ret = -EBUSY; | ||
2825 | goto out; | ||
2826 | } | ||
2827 | |||
2828 | ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); | ||
2829 | if (ret) | ||
2830 | goto out; | ||
2831 | |||
2832 | if (WARN_ON(sta_id != ctx->ap_sta_id)) { | ||
2833 | ret = -EIO; | ||
2834 | goto out_remove_sta; | ||
2835 | } | ||
2836 | |||
2837 | memcpy(ctx->bssid, bssid, ETH_ALEN); | ||
2838 | ctx->preauth_bssid = true; | ||
2839 | |||
2840 | ret = iwlagn_commit_rxon(priv, ctx); | ||
2841 | |||
2842 | if (ret == 0) | ||
2843 | goto out; | ||
2844 | |||
2845 | out_remove_sta: | ||
2846 | iwl_remove_station(priv, sta_id, bssid); | ||
2847 | out: | ||
2848 | mutex_unlock(&priv->shrd->mutex); | ||
2849 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2850 | |||
2851 | return ret; | ||
2852 | } | ||
2853 | |||
2854 | static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, | ||
2855 | struct ieee80211_vif *vif, | ||
2856 | const u8 *bssid, | ||
2857 | enum ieee80211_tx_sync_type type) | ||
2858 | { | ||
2859 | struct iwl_priv *priv = hw->priv; | ||
2860 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2861 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
2862 | |||
2863 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2864 | mutex_lock(&priv->shrd->mutex); | ||
2865 | |||
2866 | if (iwl_is_associated_ctx(ctx)) | ||
2867 | goto out; | ||
2868 | |||
2869 | iwl_remove_station(priv, ctx->ap_sta_id, bssid); | ||
2870 | ctx->preauth_bssid = false; | ||
2871 | /* no need to commit */ | ||
2872 | out: | ||
2873 | mutex_unlock(&priv->shrd->mutex); | ||
2874 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2875 | } | ||
2876 | |||
2877 | /***************************************************************************** | 1492 | /***************************************************************************** |
2878 | * | 1493 | * |
2879 | * driver setup and teardown | 1494 | * driver setup and teardown |
@@ -3029,76 +1644,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3029 | #endif | 1644 | #endif |
3030 | } | 1645 | } |
3031 | 1646 | ||
3032 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||
3033 | enum ieee80211_rssi_event rssi_event) | ||
3034 | { | ||
3035 | struct iwl_priv *priv = hw->priv; | ||
3036 | |||
3037 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3038 | mutex_lock(&priv->shrd->mutex); | ||
3039 | |||
3040 | if (priv->cfg->bt_params && | ||
3041 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
3042 | if (rssi_event == RSSI_EVENT_LOW) | ||
3043 | priv->bt_enable_pspoll = true; | ||
3044 | else if (rssi_event == RSSI_EVENT_HIGH) | ||
3045 | priv->bt_enable_pspoll = false; | ||
3046 | |||
3047 | iwlagn_send_advance_bt_config(priv); | ||
3048 | } else { | ||
3049 | IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled," | ||
3050 | "ignoring RSSI callback\n"); | ||
3051 | } | ||
3052 | 1647 | ||
3053 | mutex_unlock(&priv->shrd->mutex); | ||
3054 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3055 | } | ||
3056 | |||
3057 | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||
3058 | struct ieee80211_sta *sta, bool set) | ||
3059 | { | ||
3060 | struct iwl_priv *priv = hw->priv; | ||
3061 | |||
3062 | queue_work(priv->shrd->workqueue, &priv->beacon_update); | ||
3063 | |||
3064 | return 0; | ||
3065 | } | ||
3066 | |||
3067 | struct ieee80211_ops iwlagn_hw_ops = { | ||
3068 | .tx = iwlagn_mac_tx, | ||
3069 | .start = iwlagn_mac_start, | ||
3070 | .stop = iwlagn_mac_stop, | ||
3071 | #ifdef CONFIG_PM_SLEEP | ||
3072 | .suspend = iwlagn_mac_suspend, | ||
3073 | .resume = iwlagn_mac_resume, | ||
3074 | #endif | ||
3075 | .add_interface = iwlagn_mac_add_interface, | ||
3076 | .remove_interface = iwlagn_mac_remove_interface, | ||
3077 | .change_interface = iwlagn_mac_change_interface, | ||
3078 | .config = iwlagn_mac_config, | ||
3079 | .configure_filter = iwlagn_configure_filter, | ||
3080 | .set_key = iwlagn_mac_set_key, | ||
3081 | .update_tkip_key = iwlagn_mac_update_tkip_key, | ||
3082 | .set_rekey_data = iwlagn_mac_set_rekey_data, | ||
3083 | .conf_tx = iwlagn_mac_conf_tx, | ||
3084 | .bss_info_changed = iwlagn_bss_info_changed, | ||
3085 | .ampdu_action = iwlagn_mac_ampdu_action, | ||
3086 | .hw_scan = iwlagn_mac_hw_scan, | ||
3087 | .sta_notify = iwlagn_mac_sta_notify, | ||
3088 | .sta_add = iwlagn_mac_sta_add, | ||
3089 | .sta_remove = iwlagn_mac_sta_remove, | ||
3090 | .channel_switch = iwlagn_mac_channel_switch, | ||
3091 | .flush = iwlagn_mac_flush, | ||
3092 | .tx_last_beacon = iwlagn_mac_tx_last_beacon, | ||
3093 | .remain_on_channel = iwlagn_mac_remain_on_channel, | ||
3094 | .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, | ||
3095 | .rssi_callback = iwlagn_mac_rssi_callback, | ||
3096 | CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd) | ||
3097 | CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump) | ||
3098 | .tx_sync = iwlagn_mac_tx_sync, | ||
3099 | .finish_tx_sync = iwlagn_mac_finish_tx_sync, | ||
3100 | .set_tim = iwlagn_mac_set_tim, | ||
3101 | }; | ||
3102 | 1648 | ||
3103 | static u32 iwl_hw_detect(struct iwl_priv *priv) | 1649 | static u32 iwl_hw_detect(struct iwl_priv *priv) |
3104 | { | 1650 | { |
@@ -3132,24 +1678,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv) | |||
3132 | return priv->cfg->lib->set_hw_params(priv); | 1678 | return priv->cfg->lib->set_hw_params(priv); |
3133 | } | 1679 | } |
3134 | 1680 | ||
3135 | /* This function both allocates and initializes hw and priv. */ | ||
3136 | static struct ieee80211_hw *iwl_alloc_all(void) | ||
3137 | { | ||
3138 | struct iwl_priv *priv; | ||
3139 | /* mac80211 allocates memory for this device instance, including | ||
3140 | * space for this driver's private structure */ | ||
3141 | struct ieee80211_hw *hw; | ||
3142 | |||
3143 | hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops); | ||
3144 | if (!hw) | ||
3145 | goto out; | ||
3146 | 1681 | ||
3147 | priv = hw->priv; | ||
3148 | priv->hw = hw; | ||
3149 | |||
3150 | out: | ||
3151 | return hw; | ||
3152 | } | ||
3153 | 1682 | ||
3154 | int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | 1683 | int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, |
3155 | struct iwl_cfg *cfg) | 1684 | struct iwl_cfg *cfg) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 7cc5cd8deeea..72af93345592 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -65,6 +65,12 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | 67 | ||
68 | struct iwlagn_ucode_capabilities { | ||
69 | u32 max_probe_length; | ||
70 | u32 standard_phy_calibration_size; | ||
71 | u32 flags; | ||
72 | }; | ||
73 | |||
68 | extern struct ieee80211_ops iwlagn_hw_ops; | 74 | extern struct ieee80211_ops iwlagn_hw_ops; |
69 | 75 | ||
70 | int iwl_reset_ict(struct iwl_trans *trans); | 76 | int iwl_reset_ict(struct iwl_trans *trans); |
@@ -77,6 +83,15 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) | |||
77 | hdr->data_valid = 1; | 83 | hdr->data_valid = 1; |
78 | } | 84 | } |
79 | 85 | ||
86 | void __iwl_down(struct iwl_priv *priv); | ||
87 | void iwl_down(struct iwl_priv *priv); | ||
88 | void iwlagn_prepare_restart(struct iwl_priv *priv); | ||
89 | |||
90 | /* MAC80211 */ | ||
91 | struct ieee80211_hw *iwl_alloc_all(void); | ||
92 | int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||
93 | struct iwlagn_ucode_capabilities *capa); | ||
94 | |||
80 | /* RXON */ | 95 | /* RXON */ |
81 | int iwlagn_set_pan_params(struct iwl_priv *priv); | 96 | int iwlagn_set_pan_params(struct iwl_priv *priv); |
82 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 97 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c new file mode 100644 index 000000000000..43d795d472e0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -0,0 +1,1521 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/dma-mapping.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/netdevice.h> | ||
38 | #include <linux/firmware.h> | ||
39 | #include <linux/etherdevice.h> | ||
40 | #include <linux/if_arp.h> | ||
41 | |||
42 | #include <net/mac80211.h> | ||
43 | |||
44 | #include <asm/div64.h> | ||
45 | |||
46 | #include "iwl-eeprom.h" | ||
47 | #include "iwl-dev.h" | ||
48 | #include "iwl-core.h" | ||
49 | #include "iwl-io.h" | ||
50 | #include "iwl-agn-calib.h" | ||
51 | #include "iwl-agn.h" | ||
52 | #include "iwl-shared.h" | ||
53 | #include "iwl-bus.h" | ||
54 | #include "iwl-trans.h" | ||
55 | |||
56 | /***************************************************************************** | ||
57 | * | ||
58 | * mac80211 entry point functions | ||
59 | * | ||
60 | *****************************************************************************/ | ||
61 | |||
62 | static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = { | ||
63 | { | ||
64 | .max = 1, | ||
65 | .types = BIT(NL80211_IFTYPE_STATION), | ||
66 | }, | ||
67 | { | ||
68 | .max = 1, | ||
69 | .types = BIT(NL80211_IFTYPE_AP), | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = { | ||
74 | { | ||
75 | .max = 2, | ||
76 | .types = BIT(NL80211_IFTYPE_STATION), | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = { | ||
81 | { | ||
82 | .max = 1, | ||
83 | .types = BIT(NL80211_IFTYPE_STATION), | ||
84 | }, | ||
85 | { | ||
86 | .max = 1, | ||
87 | .types = BIT(NL80211_IFTYPE_P2P_GO) | | ||
88 | BIT(NL80211_IFTYPE_AP), | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = { | ||
93 | { | ||
94 | .max = 2, | ||
95 | .types = BIT(NL80211_IFTYPE_STATION), | ||
96 | }, | ||
97 | { | ||
98 | .max = 1, | ||
99 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT), | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | static const struct ieee80211_iface_combination | ||
104 | iwlagn_iface_combinations_dualmode[] = { | ||
105 | { .num_different_channels = 1, | ||
106 | .max_interfaces = 2, | ||
107 | .beacon_int_infra_match = true, | ||
108 | .limits = iwlagn_sta_ap_limits, | ||
109 | .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits), | ||
110 | }, | ||
111 | { .num_different_channels = 1, | ||
112 | .max_interfaces = 2, | ||
113 | .limits = iwlagn_2sta_limits, | ||
114 | .n_limits = ARRAY_SIZE(iwlagn_2sta_limits), | ||
115 | }, | ||
116 | }; | ||
117 | |||
118 | static const struct ieee80211_iface_combination | ||
119 | iwlagn_iface_combinations_p2p[] = { | ||
120 | { .num_different_channels = 1, | ||
121 | .max_interfaces = 2, | ||
122 | .beacon_int_infra_match = true, | ||
123 | .limits = iwlagn_p2p_sta_go_limits, | ||
124 | .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits), | ||
125 | }, | ||
126 | { .num_different_channels = 1, | ||
127 | .max_interfaces = 2, | ||
128 | .limits = iwlagn_p2p_2sta_limits, | ||
129 | .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits), | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | /* | ||
134 | * Not a mac80211 entry point function, but it fits in with all the | ||
135 | * other mac80211 functions grouped here. | ||
136 | */ | ||
137 | int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||
138 | struct iwlagn_ucode_capabilities *capa) | ||
139 | { | ||
140 | int ret; | ||
141 | struct ieee80211_hw *hw = priv->hw; | ||
142 | struct iwl_rxon_context *ctx; | ||
143 | |||
144 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
145 | |||
146 | /* Tell mac80211 our characteristics */ | ||
147 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
148 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
149 | IEEE80211_HW_NEED_DTIM_PERIOD | | ||
150 | IEEE80211_HW_SPECTRUM_MGMT | | ||
151 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | ||
152 | |||
153 | /* | ||
154 | * Including the following line will crash some AP's. This | ||
155 | * workaround removes the stimulus which causes the crash until | ||
156 | * the AP software can be fixed. | ||
157 | hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
158 | */ | ||
159 | |||
160 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
161 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
162 | |||
163 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
164 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
165 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
166 | |||
167 | if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) | ||
168 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | ||
169 | |||
170 | hw->sta_data_size = sizeof(struct iwl_station_priv); | ||
171 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
172 | |||
173 | for_each_context(priv, ctx) { | ||
174 | hw->wiphy->interface_modes |= ctx->interface_modes; | ||
175 | hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; | ||
176 | } | ||
177 | |||
178 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
179 | |||
180 | if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) { | ||
181 | hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p; | ||
182 | hw->wiphy->n_iface_combinations = | ||
183 | ARRAY_SIZE(iwlagn_iface_combinations_p2p); | ||
184 | } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | ||
185 | hw->wiphy->iface_combinations = | ||
186 | iwlagn_iface_combinations_dualmode; | ||
187 | hw->wiphy->n_iface_combinations = | ||
188 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); | ||
189 | } | ||
190 | |||
191 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
192 | |||
193 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | ||
194 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | ||
195 | WIPHY_FLAG_IBSS_RSN; | ||
196 | |||
197 | if (trans(priv)->ucode_wowlan.code.len && | ||
198 | device_can_wakeup(bus(priv)->dev)) { | ||
199 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | ||
200 | WIPHY_WOWLAN_DISCONNECT | | ||
201 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | | ||
202 | WIPHY_WOWLAN_RFKILL_RELEASE; | ||
203 | if (!iwlagn_mod_params.sw_crypto) | ||
204 | hw->wiphy->wowlan.flags |= | ||
205 | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | | ||
206 | WIPHY_WOWLAN_GTK_REKEY_FAILURE; | ||
207 | |||
208 | hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; | ||
209 | hw->wiphy->wowlan.pattern_min_len = | ||
210 | IWLAGN_WOWLAN_MIN_PATTERN_LEN; | ||
211 | hw->wiphy->wowlan.pattern_max_len = | ||
212 | IWLAGN_WOWLAN_MAX_PATTERN_LEN; | ||
213 | } | ||
214 | |||
215 | if (iwlagn_mod_params.power_save) | ||
216 | hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
217 | else | ||
218 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
219 | |||
220 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
221 | /* we create the 802.11 header and a zero-length SSID element */ | ||
222 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; | ||
223 | |||
224 | /* Default value; 4 EDCA QOS priorities */ | ||
225 | hw->queues = 4; | ||
226 | |||
227 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
228 | |||
229 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
230 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
231 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
232 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
233 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
234 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
235 | |||
236 | iwl_leds_init(priv); | ||
237 | |||
238 | ret = ieee80211_register_hw(priv->hw); | ||
239 | if (ret) { | ||
240 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
241 | return ret; | ||
242 | } | ||
243 | priv->mac80211_registered = 1; | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int __iwl_up(struct iwl_priv *priv) | ||
249 | { | ||
250 | struct iwl_rxon_context *ctx; | ||
251 | int ret; | ||
252 | |||
253 | lockdep_assert_held(&priv->shrd->mutex); | ||
254 | |||
255 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { | ||
256 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | ||
257 | return -EIO; | ||
258 | } | ||
259 | |||
260 | for_each_context(priv, ctx) { | ||
261 | ret = iwlagn_alloc_bcast_station(priv, ctx); | ||
262 | if (ret) { | ||
263 | iwl_dealloc_bcast_stations(priv); | ||
264 | return ret; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | ret = iwlagn_run_init_ucode(priv); | ||
269 | if (ret) { | ||
270 | IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); | ||
271 | goto error; | ||
272 | } | ||
273 | |||
274 | ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); | ||
275 | if (ret) { | ||
276 | IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); | ||
277 | goto error; | ||
278 | } | ||
279 | |||
280 | ret = iwl_alive_start(priv); | ||
281 | if (ret) | ||
282 | goto error; | ||
283 | return 0; | ||
284 | |||
285 | error: | ||
286 | set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); | ||
287 | __iwl_down(priv); | ||
288 | clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); | ||
289 | |||
290 | IWL_ERR(priv, "Unable to initialize device.\n"); | ||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | static int iwlagn_mac_start(struct ieee80211_hw *hw) | ||
295 | { | ||
296 | struct iwl_priv *priv = hw->priv; | ||
297 | int ret; | ||
298 | |||
299 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
300 | |||
301 | /* we should be verifying the device is ready to be opened */ | ||
302 | mutex_lock(&priv->shrd->mutex); | ||
303 | ret = __iwl_up(priv); | ||
304 | mutex_unlock(&priv->shrd->mutex); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | |||
308 | IWL_DEBUG_INFO(priv, "Start UP work done.\n"); | ||
309 | |||
310 | /* Now we should be done, and the READY bit should be set. */ | ||
311 | if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) | ||
312 | ret = -EIO; | ||
313 | |||
314 | iwlagn_led_enable(priv); | ||
315 | |||
316 | priv->is_open = 1; | ||
317 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static void iwlagn_mac_stop(struct ieee80211_hw *hw) | ||
322 | { | ||
323 | struct iwl_priv *priv = hw->priv; | ||
324 | |||
325 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
326 | |||
327 | if (!priv->is_open) | ||
328 | return; | ||
329 | |||
330 | priv->is_open = 0; | ||
331 | |||
332 | iwl_down(priv); | ||
333 | |||
334 | flush_workqueue(priv->shrd->workqueue); | ||
335 | |||
336 | /* User space software may expect getting rfkill changes | ||
337 | * even if interface is down */ | ||
338 | iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); | ||
339 | iwl_enable_rfkill_int(priv); | ||
340 | |||
341 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
342 | } | ||
343 | |||
344 | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||
345 | struct ieee80211_vif *vif, | ||
346 | struct cfg80211_gtk_rekey_data *data) | ||
347 | { | ||
348 | struct iwl_priv *priv = hw->priv; | ||
349 | |||
350 | if (iwlagn_mod_params.sw_crypto) | ||
351 | return; | ||
352 | |||
353 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
354 | mutex_lock(&priv->shrd->mutex); | ||
355 | |||
356 | if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) | ||
357 | goto out; | ||
358 | |||
359 | memcpy(priv->kek, data->kek, NL80211_KEK_LEN); | ||
360 | memcpy(priv->kck, data->kck, NL80211_KCK_LEN); | ||
361 | priv->replay_ctr = | ||
362 | cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr)); | ||
363 | priv->have_rekey_data = true; | ||
364 | |||
365 | out: | ||
366 | mutex_unlock(&priv->shrd->mutex); | ||
367 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
368 | } | ||
369 | |||
370 | #ifdef CONFIG_PM_SLEEP | ||
371 | struct wowlan_key_data { | ||
372 | struct iwl_rxon_context *ctx; | ||
373 | struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc; | ||
374 | struct iwlagn_wowlan_tkip_params_cmd *tkip; | ||
375 | const u8 *bssid; | ||
376 | bool error, use_rsc_tsc, use_tkip; | ||
377 | }; | ||
378 | |||
379 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) | ||
380 | { | ||
381 | int i; | ||
382 | |||
383 | for (i = 0; i < IWLAGN_P1K_SIZE; i++) | ||
384 | out[i] = cpu_to_le16(p1k[i]); | ||
385 | } | ||
386 | |||
387 | static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, | ||
388 | struct ieee80211_vif *vif, | ||
389 | struct ieee80211_sta *sta, | ||
390 | struct ieee80211_key_conf *key, | ||
391 | void *_data) | ||
392 | { | ||
393 | struct iwl_priv *priv = hw->priv; | ||
394 | struct wowlan_key_data *data = _data; | ||
395 | struct iwl_rxon_context *ctx = data->ctx; | ||
396 | struct aes_sc *aes_sc, *aes_tx_sc = NULL; | ||
397 | struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL; | ||
398 | struct iwlagn_p1k_cache *rx_p1ks; | ||
399 | u8 *rx_mic_key; | ||
400 | struct ieee80211_key_seq seq; | ||
401 | u32 cur_rx_iv32 = 0; | ||
402 | u16 p1k[IWLAGN_P1K_SIZE]; | ||
403 | int ret, i; | ||
404 | |||
405 | mutex_lock(&priv->shrd->mutex); | ||
406 | |||
407 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
408 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
409 | !sta && !ctx->key_mapping_keys) | ||
410 | ret = iwl_set_default_wep_key(priv, ctx, key); | ||
411 | else | ||
412 | ret = iwl_set_dynamic_key(priv, ctx, key, sta); | ||
413 | |||
414 | if (ret) { | ||
415 | IWL_ERR(priv, "Error setting key during suspend!\n"); | ||
416 | data->error = true; | ||
417 | } | ||
418 | |||
419 | switch (key->cipher) { | ||
420 | case WLAN_CIPHER_SUITE_TKIP: | ||
421 | if (sta) { | ||
422 | tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; | ||
423 | tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc; | ||
424 | |||
425 | rx_p1ks = data->tkip->rx_uni; | ||
426 | |||
427 | ieee80211_get_key_tx_seq(key, &seq); | ||
428 | tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16); | ||
429 | tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32); | ||
430 | |||
431 | ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k); | ||
432 | iwlagn_convert_p1k(p1k, data->tkip->tx.p1k); | ||
433 | |||
434 | memcpy(data->tkip->mic_keys.tx, | ||
435 | &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], | ||
436 | IWLAGN_MIC_KEY_SIZE); | ||
437 | |||
438 | rx_mic_key = data->tkip->mic_keys.rx_unicast; | ||
439 | } else { | ||
440 | tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; | ||
441 | rx_p1ks = data->tkip->rx_multi; | ||
442 | rx_mic_key = data->tkip->mic_keys.rx_mcast; | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * For non-QoS this relies on the fact that both the uCode and | ||
447 | * mac80211 use TID 0 (as they need to to avoid replay attacks) | ||
448 | * for checking the IV in the frames. | ||
449 | */ | ||
450 | for (i = 0; i < IWLAGN_NUM_RSC; i++) { | ||
451 | ieee80211_get_key_rx_seq(key, i, &seq); | ||
452 | tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16); | ||
453 | tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32); | ||
454 | /* wrapping isn't allowed, AP must rekey */ | ||
455 | if (seq.tkip.iv32 > cur_rx_iv32) | ||
456 | cur_rx_iv32 = seq.tkip.iv32; | ||
457 | } | ||
458 | |||
459 | ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k); | ||
460 | iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k); | ||
461 | ieee80211_get_tkip_rx_p1k(key, data->bssid, | ||
462 | cur_rx_iv32 + 1, p1k); | ||
463 | iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k); | ||
464 | |||
465 | memcpy(rx_mic_key, | ||
466 | &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], | ||
467 | IWLAGN_MIC_KEY_SIZE); | ||
468 | |||
469 | data->use_tkip = true; | ||
470 | data->use_rsc_tsc = true; | ||
471 | break; | ||
472 | case WLAN_CIPHER_SUITE_CCMP: | ||
473 | if (sta) { | ||
474 | u8 *pn = seq.ccmp.pn; | ||
475 | |||
476 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; | ||
477 | aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; | ||
478 | |||
479 | ieee80211_get_key_tx_seq(key, &seq); | ||
480 | aes_tx_sc->pn = cpu_to_le64( | ||
481 | (u64)pn[5] | | ||
482 | ((u64)pn[4] << 8) | | ||
483 | ((u64)pn[3] << 16) | | ||
484 | ((u64)pn[2] << 24) | | ||
485 | ((u64)pn[1] << 32) | | ||
486 | ((u64)pn[0] << 40)); | ||
487 | } else | ||
488 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; | ||
489 | |||
490 | /* | ||
491 | * For non-QoS this relies on the fact that both the uCode and | ||
492 | * mac80211 use TID 0 for checking the IV in the frames. | ||
493 | */ | ||
494 | for (i = 0; i < IWLAGN_NUM_RSC; i++) { | ||
495 | u8 *pn = seq.ccmp.pn; | ||
496 | |||
497 | ieee80211_get_key_rx_seq(key, i, &seq); | ||
498 | aes_sc->pn = cpu_to_le64( | ||
499 | (u64)pn[5] | | ||
500 | ((u64)pn[4] << 8) | | ||
501 | ((u64)pn[3] << 16) | | ||
502 | ((u64)pn[2] << 24) | | ||
503 | ((u64)pn[1] << 32) | | ||
504 | ((u64)pn[0] << 40)); | ||
505 | } | ||
506 | data->use_rsc_tsc = true; | ||
507 | break; | ||
508 | } | ||
509 | |||
510 | mutex_unlock(&priv->shrd->mutex); | ||
511 | } | ||
512 | |||
513 | static int iwlagn_send_patterns(struct iwl_priv *priv, | ||
514 | struct cfg80211_wowlan *wowlan) | ||
515 | { | ||
516 | struct iwlagn_wowlan_patterns_cmd *pattern_cmd; | ||
517 | struct iwl_host_cmd cmd = { | ||
518 | .id = REPLY_WOWLAN_PATTERNS, | ||
519 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
520 | .flags = CMD_SYNC, | ||
521 | }; | ||
522 | int i, err; | ||
523 | |||
524 | if (!wowlan->n_patterns) | ||
525 | return 0; | ||
526 | |||
527 | cmd.len[0] = sizeof(*pattern_cmd) + | ||
528 | wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern); | ||
529 | |||
530 | pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); | ||
531 | if (!pattern_cmd) | ||
532 | return -ENOMEM; | ||
533 | |||
534 | pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns); | ||
535 | |||
536 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
537 | int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | ||
538 | |||
539 | memcpy(&pattern_cmd->patterns[i].mask, | ||
540 | wowlan->patterns[i].mask, mask_len); | ||
541 | memcpy(&pattern_cmd->patterns[i].pattern, | ||
542 | wowlan->patterns[i].pattern, | ||
543 | wowlan->patterns[i].pattern_len); | ||
544 | pattern_cmd->patterns[i].mask_size = mask_len; | ||
545 | pattern_cmd->patterns[i].pattern_size = | ||
546 | wowlan->patterns[i].pattern_len; | ||
547 | } | ||
548 | |||
549 | cmd.data[0] = pattern_cmd; | ||
550 | err = iwl_trans_send_cmd(trans(priv), &cmd); | ||
551 | kfree(pattern_cmd); | ||
552 | return err; | ||
553 | } | ||
554 | |||
555 | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | ||
556 | struct cfg80211_wowlan *wowlan) | ||
557 | { | ||
558 | struct iwl_priv *priv = hw->priv; | ||
559 | struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; | ||
560 | struct iwl_rxon_cmd rxon; | ||
561 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
562 | struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; | ||
563 | struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; | ||
564 | struct wowlan_key_data key_data = { | ||
565 | .ctx = ctx, | ||
566 | .bssid = ctx->active.bssid_addr, | ||
567 | .use_rsc_tsc = false, | ||
568 | .tkip = &tkip_cmd, | ||
569 | .use_tkip = false, | ||
570 | }; | ||
571 | struct iwlagn_d3_config_cmd d3_cfg_cmd = {}; | ||
572 | int ret, i; | ||
573 | u16 seq; | ||
574 | |||
575 | if (WARN_ON(!wowlan)) | ||
576 | return -EINVAL; | ||
577 | |||
578 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
579 | mutex_lock(&priv->shrd->mutex); | ||
580 | |||
581 | /* Don't attempt WoWLAN when not associated, tear down instead. */ | ||
582 | if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || | ||
583 | !iwl_is_associated_ctx(ctx)) { | ||
584 | ret = 1; | ||
585 | goto out; | ||
586 | } | ||
587 | |||
588 | key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); | ||
589 | if (!key_data.rsc_tsc) { | ||
590 | ret = -ENOMEM; | ||
591 | goto out; | ||
592 | } | ||
593 | |||
594 | memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd)); | ||
595 | |||
596 | /* | ||
597 | * We know the last used seqno, and the uCode expects to know that | ||
598 | * one, it will increment before TX. | ||
599 | */ | ||
600 | seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ; | ||
601 | wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq); | ||
602 | |||
603 | /* | ||
604 | * For QoS counters, we store the one to use next, so subtract 0x10 | ||
605 | * since the uCode will add 0x10 before using the value. | ||
606 | */ | ||
607 | for (i = 0; i < 8; i++) { | ||
608 | seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; | ||
609 | seq -= 0x10; | ||
610 | wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); | ||
611 | } | ||
612 | |||
613 | if (wowlan->disconnect) | ||
614 | wakeup_filter_cmd.enabled |= | ||
615 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS | | ||
616 | IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE); | ||
617 | if (wowlan->magic_pkt) | ||
618 | wakeup_filter_cmd.enabled |= | ||
619 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET); | ||
620 | if (wowlan->gtk_rekey_failure) | ||
621 | wakeup_filter_cmd.enabled |= | ||
622 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL); | ||
623 | if (wowlan->eap_identity_req) | ||
624 | wakeup_filter_cmd.enabled |= | ||
625 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ); | ||
626 | if (wowlan->four_way_handshake) | ||
627 | wakeup_filter_cmd.enabled |= | ||
628 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE); | ||
629 | if (wowlan->n_patterns) | ||
630 | wakeup_filter_cmd.enabled |= | ||
631 | cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH); | ||
632 | |||
633 | if (wowlan->rfkill_release) | ||
634 | d3_cfg_cmd.wakeup_flags |= | ||
635 | cpu_to_le32(IWLAGN_D3_WAKEUP_RFKILL); | ||
636 | |||
637 | iwl_scan_cancel_timeout(priv, 200); | ||
638 | |||
639 | memcpy(&rxon, &ctx->active, sizeof(rxon)); | ||
640 | |||
641 | iwl_trans_stop_device(trans(priv)); | ||
642 | |||
643 | priv->shrd->wowlan = true; | ||
644 | |||
645 | ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); | ||
646 | if (ret) | ||
647 | goto error; | ||
648 | |||
649 | /* now configure WoWLAN ucode */ | ||
650 | ret = iwl_alive_start(priv); | ||
651 | if (ret) | ||
652 | goto error; | ||
653 | |||
654 | memcpy(&ctx->staging, &rxon, sizeof(rxon)); | ||
655 | ret = iwlagn_commit_rxon(priv, ctx); | ||
656 | if (ret) | ||
657 | goto error; | ||
658 | |||
659 | ret = iwl_power_update_mode(priv, true); | ||
660 | if (ret) | ||
661 | goto error; | ||
662 | |||
663 | if (!iwlagn_mod_params.sw_crypto) { | ||
664 | /* mark all keys clear */ | ||
665 | priv->ucode_key_table = 0; | ||
666 | ctx->key_mapping_keys = 0; | ||
667 | |||
668 | /* | ||
669 | * This needs to be unlocked due to lock ordering | ||
670 | * constraints. Since we're in the suspend path | ||
671 | * that isn't really a problem though. | ||
672 | */ | ||
673 | mutex_unlock(&priv->shrd->mutex); | ||
674 | ieee80211_iter_keys(priv->hw, ctx->vif, | ||
675 | iwlagn_wowlan_program_keys, | ||
676 | &key_data); | ||
677 | mutex_lock(&priv->shrd->mutex); | ||
678 | if (key_data.error) { | ||
679 | ret = -EIO; | ||
680 | goto error; | ||
681 | } | ||
682 | |||
683 | if (key_data.use_rsc_tsc) { | ||
684 | struct iwl_host_cmd rsc_tsc_cmd = { | ||
685 | .id = REPLY_WOWLAN_TSC_RSC_PARAMS, | ||
686 | .flags = CMD_SYNC, | ||
687 | .data[0] = key_data.rsc_tsc, | ||
688 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
689 | .len[0] = sizeof(*key_data.rsc_tsc), | ||
690 | }; | ||
691 | |||
692 | ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); | ||
693 | if (ret) | ||
694 | goto error; | ||
695 | } | ||
696 | |||
697 | if (key_data.use_tkip) { | ||
698 | ret = iwl_trans_send_cmd_pdu(trans(priv), | ||
699 | REPLY_WOWLAN_TKIP_PARAMS, | ||
700 | CMD_SYNC, sizeof(tkip_cmd), | ||
701 | &tkip_cmd); | ||
702 | if (ret) | ||
703 | goto error; | ||
704 | } | ||
705 | |||
706 | if (priv->have_rekey_data) { | ||
707 | memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd)); | ||
708 | memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN); | ||
709 | kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN); | ||
710 | memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN); | ||
711 | kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); | ||
712 | kek_kck_cmd.replay_ctr = priv->replay_ctr; | ||
713 | |||
714 | ret = iwl_trans_send_cmd_pdu(trans(priv), | ||
715 | REPLY_WOWLAN_KEK_KCK_MATERIAL, | ||
716 | CMD_SYNC, sizeof(kek_kck_cmd), | ||
717 | &kek_kck_cmd); | ||
718 | if (ret) | ||
719 | goto error; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC, | ||
724 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | ||
725 | if (ret) | ||
726 | goto error; | ||
727 | |||
728 | ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, | ||
729 | CMD_SYNC, sizeof(wakeup_filter_cmd), | ||
730 | &wakeup_filter_cmd); | ||
731 | if (ret) | ||
732 | goto error; | ||
733 | |||
734 | ret = iwlagn_send_patterns(priv, wowlan); | ||
735 | if (ret) | ||
736 | goto error; | ||
737 | |||
738 | device_set_wakeup_enable(bus(priv)->dev, true); | ||
739 | |||
740 | /* Now let the ucode operate on its own */ | ||
741 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, | ||
742 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
743 | |||
744 | goto out; | ||
745 | |||
746 | error: | ||
747 | priv->shrd->wowlan = false; | ||
748 | iwlagn_prepare_restart(priv); | ||
749 | ieee80211_restart_hw(priv->hw); | ||
750 | out: | ||
751 | mutex_unlock(&priv->shrd->mutex); | ||
752 | kfree(key_data.rsc_tsc); | ||
753 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
754 | |||
755 | return ret; | ||
756 | } | ||
757 | |||
758 | static int iwlagn_mac_resume(struct ieee80211_hw *hw) | ||
759 | { | ||
760 | struct iwl_priv *priv = hw->priv; | ||
761 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
762 | struct ieee80211_vif *vif; | ||
763 | unsigned long flags; | ||
764 | u32 base, status = 0xffffffff; | ||
765 | int ret = -EIO; | ||
766 | |||
767 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
768 | mutex_lock(&priv->shrd->mutex); | ||
769 | |||
770 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | ||
771 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
772 | |||
773 | base = priv->device_pointers.error_event_table; | ||
774 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | ||
775 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); | ||
776 | ret = iwl_grab_nic_access_silent(bus(priv)); | ||
777 | if (ret == 0) { | ||
778 | iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); | ||
779 | status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | ||
780 | iwl_release_nic_access(bus(priv)); | ||
781 | } | ||
782 | spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); | ||
783 | |||
784 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
785 | if (ret == 0) { | ||
786 | struct iwl_trans *trans = trans(priv); | ||
787 | if (!priv->wowlan_sram) | ||
788 | priv->wowlan_sram = | ||
789 | kzalloc(trans->ucode_wowlan.data.len, | ||
790 | GFP_KERNEL); | ||
791 | |||
792 | if (priv->wowlan_sram) | ||
793 | _iwl_read_targ_mem_words( | ||
794 | bus(priv), 0x800000, priv->wowlan_sram, | ||
795 | trans->ucode_wowlan.data.len / 4); | ||
796 | } | ||
797 | #endif | ||
798 | } | ||
799 | |||
800 | /* we'll clear ctx->vif during iwlagn_prepare_restart() */ | ||
801 | vif = ctx->vif; | ||
802 | |||
803 | priv->shrd->wowlan = false; | ||
804 | |||
805 | device_set_wakeup_enable(bus(priv)->dev, false); | ||
806 | |||
807 | iwlagn_prepare_restart(priv); | ||
808 | |||
809 | memset((void *)&ctx->active, 0, sizeof(ctx->active)); | ||
810 | iwl_connection_init_rx_config(priv, ctx); | ||
811 | iwlagn_set_rxon_chain(priv, ctx); | ||
812 | |||
813 | mutex_unlock(&priv->shrd->mutex); | ||
814 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
815 | |||
816 | ieee80211_resume_disconnect(vif); | ||
817 | |||
818 | return 1; | ||
819 | } | ||
820 | |||
821 | #endif | ||
822 | |||
823 | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
824 | { | ||
825 | struct iwl_priv *priv = hw->priv; | ||
826 | |||
827 | IWL_DEBUG_MACDUMP(priv, "enter\n"); | ||
828 | |||
829 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | ||
830 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | ||
831 | |||
832 | if (iwlagn_tx_skb(priv, skb)) | ||
833 | dev_kfree_skb_any(skb); | ||
834 | |||
835 | IWL_DEBUG_MACDUMP(priv, "leave\n"); | ||
836 | } | ||
837 | |||
838 | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||
839 | struct ieee80211_vif *vif, | ||
840 | struct ieee80211_key_conf *keyconf, | ||
841 | struct ieee80211_sta *sta, | ||
842 | u32 iv32, u16 *phase1key) | ||
843 | { | ||
844 | struct iwl_priv *priv = hw->priv; | ||
845 | |||
846 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | ||
847 | } | ||
848 | |||
849 | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
850 | struct ieee80211_vif *vif, | ||
851 | struct ieee80211_sta *sta, | ||
852 | struct ieee80211_key_conf *key) | ||
853 | { | ||
854 | struct iwl_priv *priv = hw->priv; | ||
855 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
856 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
857 | int ret; | ||
858 | bool is_default_wep_key = false; | ||
859 | |||
860 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
861 | |||
862 | if (iwlagn_mod_params.sw_crypto) { | ||
863 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | ||
864 | return -EOPNOTSUPP; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * We could program these keys into the hardware as well, but we | ||
869 | * don't expect much multicast traffic in IBSS and having keys | ||
870 | * for more stations is probably more useful. | ||
871 | * | ||
872 | * Mark key TX-only and return 0. | ||
873 | */ | ||
874 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
875 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
876 | key->hw_key_idx = WEP_INVALID_OFFSET; | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | /* If they key was TX-only, accept deletion */ | ||
881 | if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) | ||
882 | return 0; | ||
883 | |||
884 | mutex_lock(&priv->shrd->mutex); | ||
885 | iwl_scan_cancel_timeout(priv, 100); | ||
886 | |||
887 | BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); | ||
888 | |||
889 | /* | ||
890 | * If we are getting WEP group key and we didn't receive any key mapping | ||
891 | * so far, we are in legacy wep mode (group key only), otherwise we are | ||
892 | * in 1X mode. | ||
893 | * In legacy wep mode, we use another host command to the uCode. | ||
894 | */ | ||
895 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
896 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { | ||
897 | if (cmd == SET_KEY) | ||
898 | is_default_wep_key = !ctx->key_mapping_keys; | ||
899 | else | ||
900 | is_default_wep_key = | ||
901 | key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT; | ||
902 | } | ||
903 | |||
904 | |||
905 | switch (cmd) { | ||
906 | case SET_KEY: | ||
907 | if (is_default_wep_key) { | ||
908 | ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); | ||
909 | break; | ||
910 | } | ||
911 | ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta); | ||
912 | if (ret) { | ||
913 | /* | ||
914 | * can't add key for RX, but we don't need it | ||
915 | * in the device for TX so still return 0 | ||
916 | */ | ||
917 | ret = 0; | ||
918 | key->hw_key_idx = WEP_INVALID_OFFSET; | ||
919 | } | ||
920 | |||
921 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); | ||
922 | break; | ||
923 | case DISABLE_KEY: | ||
924 | if (is_default_wep_key) | ||
925 | ret = iwl_remove_default_wep_key(priv, ctx, key); | ||
926 | else | ||
927 | ret = iwl_remove_dynamic_key(priv, ctx, key, sta); | ||
928 | |||
929 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); | ||
930 | break; | ||
931 | default: | ||
932 | ret = -EINVAL; | ||
933 | } | ||
934 | |||
935 | mutex_unlock(&priv->shrd->mutex); | ||
936 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
937 | |||
938 | return ret; | ||
939 | } | ||
940 | |||
941 | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||
942 | struct ieee80211_vif *vif, | ||
943 | enum ieee80211_ampdu_mlme_action action, | ||
944 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
945 | u8 buf_size) | ||
946 | { | ||
947 | struct iwl_priv *priv = hw->priv; | ||
948 | int ret = -EINVAL; | ||
949 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; | ||
950 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
951 | |||
952 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | ||
953 | sta->addr, tid); | ||
954 | |||
955 | if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)) | ||
956 | return -EACCES; | ||
957 | |||
958 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
959 | mutex_lock(&priv->shrd->mutex); | ||
960 | |||
961 | switch (action) { | ||
962 | case IEEE80211_AMPDU_RX_START: | ||
963 | IWL_DEBUG_HT(priv, "start Rx\n"); | ||
964 | ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); | ||
965 | break; | ||
966 | case IEEE80211_AMPDU_RX_STOP: | ||
967 | IWL_DEBUG_HT(priv, "stop Rx\n"); | ||
968 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | ||
969 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | ||
970 | ret = 0; | ||
971 | break; | ||
972 | case IEEE80211_AMPDU_TX_START: | ||
973 | IWL_DEBUG_HT(priv, "start Tx\n"); | ||
974 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | ||
975 | break; | ||
976 | case IEEE80211_AMPDU_TX_STOP: | ||
977 | IWL_DEBUG_HT(priv, "stop Tx\n"); | ||
978 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | ||
979 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | ||
980 | priv->agg_tids_count--; | ||
981 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
982 | priv->agg_tids_count); | ||
983 | } | ||
984 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | ||
985 | ret = 0; | ||
986 | if (!priv->agg_tids_count && priv->cfg->ht_params && | ||
987 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
988 | /* | ||
989 | * switch off RTS/CTS if it was previously enabled | ||
990 | */ | ||
991 | sta_priv->lq_sta.lq.general_params.flags &= | ||
992 | ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
993 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
994 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
995 | } | ||
996 | break; | ||
997 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
998 | buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); | ||
999 | |||
1000 | iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), | ||
1001 | tid, buf_size); | ||
1002 | |||
1003 | /* | ||
1004 | * If the limit is 0, then it wasn't initialised yet, | ||
1005 | * use the default. We can do that since we take the | ||
1006 | * minimum below, and we don't want to go above our | ||
1007 | * default due to hardware restrictions. | ||
1008 | */ | ||
1009 | if (sta_priv->max_agg_bufsize == 0) | ||
1010 | sta_priv->max_agg_bufsize = | ||
1011 | LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
1012 | |||
1013 | /* | ||
1014 | * Even though in theory the peer could have different | ||
1015 | * aggregation reorder buffer sizes for different sessions, | ||
1016 | * our ucode doesn't allow for that and has a global limit | ||
1017 | * for each station. Therefore, use the minimum of all the | ||
1018 | * aggregation sessions and our default value. | ||
1019 | */ | ||
1020 | sta_priv->max_agg_bufsize = | ||
1021 | min(sta_priv->max_agg_bufsize, buf_size); | ||
1022 | |||
1023 | if (priv->cfg->ht_params && | ||
1024 | priv->cfg->ht_params->use_rts_for_aggregation) { | ||
1025 | /* | ||
1026 | * switch to RTS/CTS if it is the prefer protection | ||
1027 | * method for HT traffic | ||
1028 | */ | ||
1029 | |||
1030 | sta_priv->lq_sta.lq.general_params.flags |= | ||
1031 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
1032 | } | ||
1033 | priv->agg_tids_count++; | ||
1034 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
1035 | priv->agg_tids_count); | ||
1036 | |||
1037 | sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = | ||
1038 | sta_priv->max_agg_bufsize; | ||
1039 | |||
1040 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
1041 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
1042 | |||
1043 | IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", | ||
1044 | sta->addr, tid); | ||
1045 | ret = 0; | ||
1046 | break; | ||
1047 | } | ||
1048 | mutex_unlock(&priv->shrd->mutex); | ||
1049 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1050 | return ret; | ||
1051 | } | ||
1052 | |||
1053 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | ||
1054 | struct ieee80211_vif *vif, | ||
1055 | struct ieee80211_sta *sta) | ||
1056 | { | ||
1057 | struct iwl_priv *priv = hw->priv; | ||
1058 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1059 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1060 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | ||
1061 | int ret = 0; | ||
1062 | u8 sta_id; | ||
1063 | |||
1064 | IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n", | ||
1065 | sta->addr); | ||
1066 | mutex_lock(&priv->shrd->mutex); | ||
1067 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | ||
1068 | sta->addr); | ||
1069 | sta_priv->sta_id = IWL_INVALID_STATION; | ||
1070 | |||
1071 | atomic_set(&sta_priv->pending_frames, 0); | ||
1072 | if (vif->type == NL80211_IFTYPE_AP) | ||
1073 | sta_priv->client = true; | ||
1074 | |||
1075 | ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr, | ||
1076 | is_ap, sta, &sta_id); | ||
1077 | if (ret) { | ||
1078 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
1079 | sta->addr, ret); | ||
1080 | /* Should we return success if return code is EEXIST ? */ | ||
1081 | goto out; | ||
1082 | } | ||
1083 | |||
1084 | sta_priv->sta_id = sta_id; | ||
1085 | |||
1086 | /* Initialize rate scaling */ | ||
1087 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
1088 | sta->addr); | ||
1089 | iwl_rs_rate_init(priv, sta, sta_id); | ||
1090 | out: | ||
1091 | mutex_unlock(&priv->shrd->mutex); | ||
1092 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1093 | |||
1094 | return ret; | ||
1095 | } | ||
1096 | |||
1097 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
1098 | struct ieee80211_channel_switch *ch_switch) | ||
1099 | { | ||
1100 | struct iwl_priv *priv = hw->priv; | ||
1101 | const struct iwl_channel_info *ch_info; | ||
1102 | struct ieee80211_conf *conf = &hw->conf; | ||
1103 | struct ieee80211_channel *channel = ch_switch->channel; | ||
1104 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
1105 | /* | ||
1106 | * MULTI-FIXME | ||
1107 | * When we add support for multiple interfaces, we need to | ||
1108 | * revisit this. The channel switch command in the device | ||
1109 | * only affects the BSS context, but what does that really | ||
1110 | * mean? And what if we get a CSA on the second interface? | ||
1111 | * This needs a lot of work. | ||
1112 | */ | ||
1113 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1114 | u16 ch; | ||
1115 | |||
1116 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1117 | |||
1118 | mutex_lock(&priv->shrd->mutex); | ||
1119 | |||
1120 | if (iwl_is_rfkill(priv->shrd)) | ||
1121 | goto out; | ||
1122 | |||
1123 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || | ||
1124 | test_bit(STATUS_SCANNING, &priv->shrd->status) || | ||
1125 | test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) | ||
1126 | goto out; | ||
1127 | |||
1128 | if (!iwl_is_associated_ctx(ctx)) | ||
1129 | goto out; | ||
1130 | |||
1131 | if (!priv->cfg->lib->set_channel_switch) | ||
1132 | goto out; | ||
1133 | |||
1134 | ch = channel->hw_value; | ||
1135 | if (le16_to_cpu(ctx->active.channel) == ch) | ||
1136 | goto out; | ||
1137 | |||
1138 | ch_info = iwl_get_channel_info(priv, channel->band, ch); | ||
1139 | if (!is_channel_valid(ch_info)) { | ||
1140 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | ||
1141 | goto out; | ||
1142 | } | ||
1143 | |||
1144 | spin_lock_irq(&priv->shrd->lock); | ||
1145 | |||
1146 | priv->current_ht_config.smps = conf->smps_mode; | ||
1147 | |||
1148 | /* Configure HT40 channels */ | ||
1149 | ctx->ht.enabled = conf_is_ht(conf); | ||
1150 | if (ctx->ht.enabled) { | ||
1151 | if (conf_is_ht40_minus(conf)) { | ||
1152 | ctx->ht.extension_chan_offset = | ||
1153 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1154 | ctx->ht.is_40mhz = true; | ||
1155 | } else if (conf_is_ht40_plus(conf)) { | ||
1156 | ctx->ht.extension_chan_offset = | ||
1157 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1158 | ctx->ht.is_40mhz = true; | ||
1159 | } else { | ||
1160 | ctx->ht.extension_chan_offset = | ||
1161 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
1162 | ctx->ht.is_40mhz = false; | ||
1163 | } | ||
1164 | } else | ||
1165 | ctx->ht.is_40mhz = false; | ||
1166 | |||
1167 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | ||
1168 | ctx->staging.flags = 0; | ||
1169 | |||
1170 | iwl_set_rxon_channel(priv, channel, ctx); | ||
1171 | iwl_set_rxon_ht(priv, ht_conf); | ||
1172 | iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); | ||
1173 | |||
1174 | spin_unlock_irq(&priv->shrd->lock); | ||
1175 | |||
1176 | iwl_set_rate(priv); | ||
1177 | /* | ||
1178 | * at this point, staging_rxon has the | ||
1179 | * configuration for channel switch | ||
1180 | */ | ||
1181 | set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); | ||
1182 | priv->switch_channel = cpu_to_le16(ch); | ||
1183 | if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { | ||
1184 | clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); | ||
1185 | priv->switch_channel = 0; | ||
1186 | ieee80211_chswitch_done(ctx->vif, false); | ||
1187 | } | ||
1188 | |||
1189 | out: | ||
1190 | mutex_unlock(&priv->shrd->mutex); | ||
1191 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1192 | } | ||
1193 | |||
1194 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
1195 | unsigned int changed_flags, | ||
1196 | unsigned int *total_flags, | ||
1197 | u64 multicast) | ||
1198 | { | ||
1199 | struct iwl_priv *priv = hw->priv; | ||
1200 | __le32 filter_or = 0, filter_nand = 0; | ||
1201 | struct iwl_rxon_context *ctx; | ||
1202 | |||
1203 | #define CHK(test, flag) do { \ | ||
1204 | if (*total_flags & (test)) \ | ||
1205 | filter_or |= (flag); \ | ||
1206 | else \ | ||
1207 | filter_nand |= (flag); \ | ||
1208 | } while (0) | ||
1209 | |||
1210 | IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", | ||
1211 | changed_flags, *total_flags); | ||
1212 | |||
1213 | CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); | ||
1214 | /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */ | ||
1215 | CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); | ||
1216 | CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); | ||
1217 | |||
1218 | #undef CHK | ||
1219 | |||
1220 | mutex_lock(&priv->shrd->mutex); | ||
1221 | |||
1222 | for_each_context(priv, ctx) { | ||
1223 | ctx->staging.filter_flags &= ~filter_nand; | ||
1224 | ctx->staging.filter_flags |= filter_or; | ||
1225 | |||
1226 | /* | ||
1227 | * Not committing directly because hardware can perform a scan, | ||
1228 | * but we'll eventually commit the filter flags change anyway. | ||
1229 | */ | ||
1230 | } | ||
1231 | |||
1232 | mutex_unlock(&priv->shrd->mutex); | ||
1233 | |||
1234 | /* | ||
1235 | * Receiving all multicast frames is always enabled by the | ||
1236 | * default flags setup in iwl_connection_init_rx_config() | ||
1237 | * since we currently do not support programming multicast | ||
1238 | * filters into the device. | ||
1239 | */ | ||
1240 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | ||
1241 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
1242 | } | ||
1243 | |||
1244 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | ||
1245 | { | ||
1246 | struct iwl_priv *priv = hw->priv; | ||
1247 | |||
1248 | mutex_lock(&priv->shrd->mutex); | ||
1249 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1250 | |||
1251 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { | ||
1252 | IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); | ||
1253 | goto done; | ||
1254 | } | ||
1255 | if (iwl_is_rfkill(priv->shrd)) { | ||
1256 | IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); | ||
1257 | goto done; | ||
1258 | } | ||
1259 | |||
1260 | /* | ||
1261 | * mac80211 will not push any more frames for transmit | ||
1262 | * until the flush is completed | ||
1263 | */ | ||
1264 | if (drop) { | ||
1265 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | ||
1266 | if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { | ||
1267 | IWL_ERR(priv, "flush request fail\n"); | ||
1268 | goto done; | ||
1269 | } | ||
1270 | } | ||
1271 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); | ||
1272 | iwl_trans_wait_tx_queue_empty(trans(priv)); | ||
1273 | done: | ||
1274 | mutex_unlock(&priv->shrd->mutex); | ||
1275 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1276 | } | ||
1277 | |||
1278 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | ||
1279 | struct ieee80211_channel *channel, | ||
1280 | enum nl80211_channel_type channel_type, | ||
1281 | int duration) | ||
1282 | { | ||
1283 | struct iwl_priv *priv = hw->priv; | ||
1284 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
1285 | int err = 0; | ||
1286 | |||
1287 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
1288 | return -EOPNOTSUPP; | ||
1289 | |||
1290 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) | ||
1291 | return -EOPNOTSUPP; | ||
1292 | |||
1293 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1294 | mutex_lock(&priv->shrd->mutex); | ||
1295 | |||
1296 | if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { | ||
1297 | err = -EBUSY; | ||
1298 | goto out; | ||
1299 | } | ||
1300 | |||
1301 | priv->hw_roc_channel = channel; | ||
1302 | priv->hw_roc_chantype = channel_type; | ||
1303 | priv->hw_roc_duration = duration; | ||
1304 | priv->hw_roc_start_notified = false; | ||
1305 | cancel_delayed_work(&priv->hw_roc_disable_work); | ||
1306 | |||
1307 | if (!ctx->is_active) { | ||
1308 | ctx->is_active = true; | ||
1309 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
1310 | memcpy(ctx->staging.node_addr, | ||
1311 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
1312 | ETH_ALEN); | ||
1313 | memcpy(ctx->staging.bssid_addr, | ||
1314 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
1315 | ETH_ALEN); | ||
1316 | err = iwlagn_commit_rxon(priv, ctx); | ||
1317 | if (err) | ||
1318 | goto out; | ||
1319 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK | | ||
1320 | RXON_FILTER_PROMISC_MSK | | ||
1321 | RXON_FILTER_CTL2HOST_MSK; | ||
1322 | |||
1323 | err = iwlagn_commit_rxon(priv, ctx); | ||
1324 | if (err) { | ||
1325 | iwlagn_disable_roc(priv); | ||
1326 | goto out; | ||
1327 | } | ||
1328 | priv->hw_roc_setup = true; | ||
1329 | } | ||
1330 | |||
1331 | err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band); | ||
1332 | if (err) | ||
1333 | iwlagn_disable_roc(priv); | ||
1334 | |||
1335 | out: | ||
1336 | mutex_unlock(&priv->shrd->mutex); | ||
1337 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1338 | |||
1339 | return err; | ||
1340 | } | ||
1341 | |||
1342 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||
1343 | { | ||
1344 | struct iwl_priv *priv = hw->priv; | ||
1345 | |||
1346 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
1347 | return -EOPNOTSUPP; | ||
1348 | |||
1349 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1350 | mutex_lock(&priv->shrd->mutex); | ||
1351 | iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); | ||
1352 | iwlagn_disable_roc(priv); | ||
1353 | mutex_unlock(&priv->shrd->mutex); | ||
1354 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1355 | |||
1356 | return 0; | ||
1357 | } | ||
1358 | |||
1359 | static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, | ||
1360 | struct ieee80211_vif *vif, | ||
1361 | const u8 *bssid, | ||
1362 | enum ieee80211_tx_sync_type type) | ||
1363 | { | ||
1364 | struct iwl_priv *priv = hw->priv; | ||
1365 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1366 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
1367 | int ret; | ||
1368 | u8 sta_id; | ||
1369 | |||
1370 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1371 | mutex_lock(&priv->shrd->mutex); | ||
1372 | |||
1373 | if (iwl_is_associated_ctx(ctx)) { | ||
1374 | ret = 0; | ||
1375 | goto out; | ||
1376 | } | ||
1377 | |||
1378 | if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, | ||
1379 | &priv->shrd->status)) { | ||
1380 | ret = -EBUSY; | ||
1381 | goto out; | ||
1382 | } | ||
1383 | |||
1384 | ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); | ||
1385 | if (ret) | ||
1386 | goto out; | ||
1387 | |||
1388 | if (WARN_ON(sta_id != ctx->ap_sta_id)) { | ||
1389 | ret = -EIO; | ||
1390 | goto out_remove_sta; | ||
1391 | } | ||
1392 | |||
1393 | memcpy(ctx->bssid, bssid, ETH_ALEN); | ||
1394 | ctx->preauth_bssid = true; | ||
1395 | |||
1396 | ret = iwlagn_commit_rxon(priv, ctx); | ||
1397 | |||
1398 | if (ret == 0) | ||
1399 | goto out; | ||
1400 | |||
1401 | out_remove_sta: | ||
1402 | iwl_remove_station(priv, sta_id, bssid); | ||
1403 | out: | ||
1404 | mutex_unlock(&priv->shrd->mutex); | ||
1405 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1406 | |||
1407 | return ret; | ||
1408 | } | ||
1409 | |||
1410 | static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, | ||
1411 | struct ieee80211_vif *vif, | ||
1412 | const u8 *bssid, | ||
1413 | enum ieee80211_tx_sync_type type) | ||
1414 | { | ||
1415 | struct iwl_priv *priv = hw->priv; | ||
1416 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1417 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
1418 | |||
1419 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1420 | mutex_lock(&priv->shrd->mutex); | ||
1421 | |||
1422 | if (iwl_is_associated_ctx(ctx)) | ||
1423 | goto out; | ||
1424 | |||
1425 | iwl_remove_station(priv, ctx->ap_sta_id, bssid); | ||
1426 | ctx->preauth_bssid = false; | ||
1427 | /* no need to commit */ | ||
1428 | out: | ||
1429 | mutex_unlock(&priv->shrd->mutex); | ||
1430 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1431 | } | ||
1432 | |||
1433 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||
1434 | enum ieee80211_rssi_event rssi_event) | ||
1435 | { | ||
1436 | struct iwl_priv *priv = hw->priv; | ||
1437 | |||
1438 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
1439 | mutex_lock(&priv->shrd->mutex); | ||
1440 | |||
1441 | if (priv->cfg->bt_params && | ||
1442 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
1443 | if (rssi_event == RSSI_EVENT_LOW) | ||
1444 | priv->bt_enable_pspoll = true; | ||
1445 | else if (rssi_event == RSSI_EVENT_HIGH) | ||
1446 | priv->bt_enable_pspoll = false; | ||
1447 | |||
1448 | iwlagn_send_advance_bt_config(priv); | ||
1449 | } else { | ||
1450 | IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled," | ||
1451 | "ignoring RSSI callback\n"); | ||
1452 | } | ||
1453 | |||
1454 | mutex_unlock(&priv->shrd->mutex); | ||
1455 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1456 | } | ||
1457 | |||
1458 | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||
1459 | struct ieee80211_sta *sta, bool set) | ||
1460 | { | ||
1461 | struct iwl_priv *priv = hw->priv; | ||
1462 | |||
1463 | queue_work(priv->shrd->workqueue, &priv->beacon_update); | ||
1464 | |||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1468 | struct ieee80211_ops iwlagn_hw_ops = { | ||
1469 | .tx = iwlagn_mac_tx, | ||
1470 | .start = iwlagn_mac_start, | ||
1471 | .stop = iwlagn_mac_stop, | ||
1472 | #ifdef CONFIG_PM_SLEEP | ||
1473 | .suspend = iwlagn_mac_suspend, | ||
1474 | .resume = iwlagn_mac_resume, | ||
1475 | #endif | ||
1476 | .add_interface = iwlagn_mac_add_interface, | ||
1477 | .remove_interface = iwlagn_mac_remove_interface, | ||
1478 | .change_interface = iwlagn_mac_change_interface, | ||
1479 | .config = iwlagn_mac_config, | ||
1480 | .configure_filter = iwlagn_configure_filter, | ||
1481 | .set_key = iwlagn_mac_set_key, | ||
1482 | .update_tkip_key = iwlagn_mac_update_tkip_key, | ||
1483 | .set_rekey_data = iwlagn_mac_set_rekey_data, | ||
1484 | .conf_tx = iwlagn_mac_conf_tx, | ||
1485 | .bss_info_changed = iwlagn_bss_info_changed, | ||
1486 | .ampdu_action = iwlagn_mac_ampdu_action, | ||
1487 | .hw_scan = iwlagn_mac_hw_scan, | ||
1488 | .sta_notify = iwlagn_mac_sta_notify, | ||
1489 | .sta_add = iwlagn_mac_sta_add, | ||
1490 | .sta_remove = iwlagn_mac_sta_remove, | ||
1491 | .channel_switch = iwlagn_mac_channel_switch, | ||
1492 | .flush = iwlagn_mac_flush, | ||
1493 | .tx_last_beacon = iwlagn_mac_tx_last_beacon, | ||
1494 | .remain_on_channel = iwlagn_mac_remain_on_channel, | ||
1495 | .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, | ||
1496 | .rssi_callback = iwlagn_mac_rssi_callback, | ||
1497 | CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd) | ||
1498 | CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump) | ||
1499 | .tx_sync = iwlagn_mac_tx_sync, | ||
1500 | .finish_tx_sync = iwlagn_mac_finish_tx_sync, | ||
1501 | .set_tim = iwlagn_mac_set_tim, | ||
1502 | }; | ||
1503 | |||
1504 | /* This function both allocates and initializes hw and priv. */ | ||
1505 | struct ieee80211_hw *iwl_alloc_all(void) | ||
1506 | { | ||
1507 | struct iwl_priv *priv; | ||
1508 | /* mac80211 allocates memory for this device instance, including | ||
1509 | * space for this driver's private structure */ | ||
1510 | struct ieee80211_hw *hw; | ||
1511 | |||
1512 | hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops); | ||
1513 | if (!hw) | ||
1514 | goto out; | ||
1515 | |||
1516 | priv = hw->priv; | ||
1517 | priv->hw = hw; | ||
1518 | |||
1519 | out: | ||
1520 | return hw; | ||
1521 | } | ||