diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 609 |
1 files changed, 406 insertions, 203 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index aef4f71f1981..69e17d782883 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | 120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { |
121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | 121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", |
122 | le16_to_cpu(priv->switch_rxon.channel)); | 122 | le16_to_cpu(priv->switch_rxon.channel)); |
123 | priv->switch_rxon.switch_in_progress = false; | 123 | iwl_chswitch_done(priv, false); |
124 | } | 124 | } |
125 | 125 | ||
126 | /* If we don't need to send a full RXON, we can use | 126 | /* If we don't need to send a full RXON, we can use |
@@ -367,7 +367,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
367 | 367 | ||
368 | /* Set up packet rate and flags */ | 368 | /* Set up packet rate and flags */ |
369 | rate = iwl_rate_get_lowest_plcp(priv); | 369 | rate = iwl_rate_get_lowest_plcp(priv); |
370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | 370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
371 | priv->hw_params.valid_tx_ant); | ||
371 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 372 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
372 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | 373 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) |
373 | rate_flags |= RATE_MCS_CCK_MSK; | 374 | rate_flags |= RATE_MCS_CCK_MSK; |
@@ -474,18 +475,25 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
474 | /* Unmap tx_cmd */ | 475 | /* Unmap tx_cmd */ |
475 | if (num_tbs) | 476 | if (num_tbs) |
476 | pci_unmap_single(dev, | 477 | pci_unmap_single(dev, |
477 | pci_unmap_addr(&txq->meta[index], mapping), | 478 | dma_unmap_addr(&txq->meta[index], mapping), |
478 | pci_unmap_len(&txq->meta[index], len), | 479 | dma_unmap_len(&txq->meta[index], len), |
479 | PCI_DMA_BIDIRECTIONAL); | 480 | PCI_DMA_BIDIRECTIONAL); |
480 | 481 | ||
481 | /* Unmap chunks, if any. */ | 482 | /* Unmap chunks, if any. */ |
482 | for (i = 1; i < num_tbs; i++) { | 483 | for (i = 1; i < num_tbs; i++) |
483 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | 484 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), |
484 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | 485 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); |
485 | 486 | ||
486 | if (txq->txb) { | 487 | /* free SKB */ |
487 | dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); | 488 | if (txq->txb) { |
488 | txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; | 489 | struct sk_buff *skb; |
490 | |||
491 | skb = txq->txb[txq->q.read_ptr].skb; | ||
492 | |||
493 | /* can be called from irqs-disabled context */ | ||
494 | if (skb) { | ||
495 | dev_kfree_skb_any(skb); | ||
496 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
489 | } | 497 | } |
490 | } | 498 | } |
491 | } | 499 | } |
@@ -1466,7 +1474,12 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1466 | " expected_ack_cnt = %d\n", | 1474 | " expected_ack_cnt = %d\n", |
1467 | actual_ack_cnt_delta, expected_ack_cnt_delta); | 1475 | actual_ack_cnt_delta, expected_ack_cnt_delta); |
1468 | 1476 | ||
1469 | #ifdef CONFIG_IWLWIFI_DEBUG | 1477 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1478 | /* | ||
1479 | * This is ifdef'ed on DEBUGFS because otherwise the | ||
1480 | * statistics aren't available. If DEBUGFS is set but | ||
1481 | * DEBUG is not, these will just compile out. | ||
1482 | */ | ||
1470 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | 1483 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", |
1471 | priv->delta_statistics.tx.rx_detected_cnt); | 1484 | priv->delta_statistics.tx.rx_detected_cnt); |
1472 | IWL_DEBUG_RADIO(priv, | 1485 | IWL_DEBUG_RADIO(priv, |
@@ -1484,6 +1497,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1484 | } | 1497 | } |
1485 | 1498 | ||
1486 | 1499 | ||
1500 | /***************************************************************************** | ||
1501 | * | ||
1502 | * sysfs attributes | ||
1503 | * | ||
1504 | *****************************************************************************/ | ||
1505 | |||
1506 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1507 | |||
1508 | /* | ||
1509 | * The following adds a new attribute to the sysfs representation | ||
1510 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) | ||
1511 | * used for controlling the debug level. | ||
1512 | * | ||
1513 | * See the level definitions in iwl for details. | ||
1514 | * | ||
1515 | * The debug_level being managed using sysfs below is a per device debug | ||
1516 | * level that is used instead of the global debug level if it (the per | ||
1517 | * device debug level) is set. | ||
1518 | */ | ||
1519 | static ssize_t show_debug_level(struct device *d, | ||
1520 | struct device_attribute *attr, char *buf) | ||
1521 | { | ||
1522 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1523 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); | ||
1524 | } | ||
1525 | static ssize_t store_debug_level(struct device *d, | ||
1526 | struct device_attribute *attr, | ||
1527 | const char *buf, size_t count) | ||
1528 | { | ||
1529 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1530 | unsigned long val; | ||
1531 | int ret; | ||
1532 | |||
1533 | ret = strict_strtoul(buf, 0, &val); | ||
1534 | if (ret) | ||
1535 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | ||
1536 | else { | ||
1537 | priv->debug_level = val; | ||
1538 | if (iwl_alloc_traffic_mem(priv)) | ||
1539 | IWL_ERR(priv, | ||
1540 | "Not enough memory to generate traffic log\n"); | ||
1541 | } | ||
1542 | return strnlen(buf, count); | ||
1543 | } | ||
1544 | |||
1545 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
1546 | show_debug_level, store_debug_level); | ||
1547 | |||
1548 | |||
1549 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
1550 | |||
1551 | |||
1552 | static ssize_t show_temperature(struct device *d, | ||
1553 | struct device_attribute *attr, char *buf) | ||
1554 | { | ||
1555 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1556 | |||
1557 | if (!iwl_is_alive(priv)) | ||
1558 | return -EAGAIN; | ||
1559 | |||
1560 | return sprintf(buf, "%d\n", priv->temperature); | ||
1561 | } | ||
1562 | |||
1563 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
1564 | |||
1565 | static ssize_t show_tx_power(struct device *d, | ||
1566 | struct device_attribute *attr, char *buf) | ||
1567 | { | ||
1568 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1569 | |||
1570 | if (!iwl_is_ready_rf(priv)) | ||
1571 | return sprintf(buf, "off\n"); | ||
1572 | else | ||
1573 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
1574 | } | ||
1575 | |||
1576 | static ssize_t store_tx_power(struct device *d, | ||
1577 | struct device_attribute *attr, | ||
1578 | const char *buf, size_t count) | ||
1579 | { | ||
1580 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1581 | unsigned long val; | ||
1582 | int ret; | ||
1583 | |||
1584 | ret = strict_strtoul(buf, 10, &val); | ||
1585 | if (ret) | ||
1586 | IWL_INFO(priv, "%s is not in decimal form.\n", buf); | ||
1587 | else { | ||
1588 | ret = iwl_set_tx_power(priv, val, false); | ||
1589 | if (ret) | ||
1590 | IWL_ERR(priv, "failed setting tx power (0x%d).\n", | ||
1591 | ret); | ||
1592 | else | ||
1593 | ret = count; | ||
1594 | } | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | ||
1599 | |||
1600 | static ssize_t show_rts_ht_protection(struct device *d, | ||
1601 | struct device_attribute *attr, char *buf) | ||
1602 | { | ||
1603 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1604 | |||
1605 | return sprintf(buf, "%s\n", | ||
1606 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | ||
1607 | } | ||
1608 | |||
1609 | static ssize_t store_rts_ht_protection(struct device *d, | ||
1610 | struct device_attribute *attr, | ||
1611 | const char *buf, size_t count) | ||
1612 | { | ||
1613 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1614 | unsigned long val; | ||
1615 | int ret; | ||
1616 | |||
1617 | ret = strict_strtoul(buf, 10, &val); | ||
1618 | if (ret) | ||
1619 | IWL_INFO(priv, "Input is not in decimal form.\n"); | ||
1620 | else { | ||
1621 | if (!iwl_is_associated(priv)) | ||
1622 | priv->cfg->use_rts_for_ht = val ? true : false; | ||
1623 | else | ||
1624 | IWL_ERR(priv, "Sta associated with AP - " | ||
1625 | "Change protection mechanism is not allowed\n"); | ||
1626 | ret = count; | ||
1627 | } | ||
1628 | return ret; | ||
1629 | } | ||
1630 | |||
1631 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
1632 | show_rts_ht_protection, store_rts_ht_protection); | ||
1633 | |||
1634 | |||
1635 | static struct attribute *iwl_sysfs_entries[] = { | ||
1636 | &dev_attr_temperature.attr, | ||
1637 | &dev_attr_tx_power.attr, | ||
1638 | &dev_attr_rts_ht_protection.attr, | ||
1639 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1640 | &dev_attr_debug_level.attr, | ||
1641 | #endif | ||
1642 | NULL | ||
1643 | }; | ||
1644 | |||
1645 | static struct attribute_group iwl_attribute_group = { | ||
1646 | .name = NULL, /* put in device directory */ | ||
1647 | .attrs = iwl_sysfs_entries, | ||
1648 | }; | ||
1649 | |||
1487 | /****************************************************************************** | 1650 | /****************************************************************************** |
1488 | * | 1651 | * |
1489 | * uCode download functions | 1652 | * uCode download functions |
@@ -1544,6 +1707,9 @@ struct iwlagn_firmware_pieces { | |||
1544 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | 1707 | size_t inst_size, data_size, init_size, init_data_size, boot_size; |
1545 | 1708 | ||
1546 | u32 build; | 1709 | u32 build; |
1710 | |||
1711 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1712 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1547 | }; | 1713 | }; |
1548 | 1714 | ||
1549 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | 1715 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, |
@@ -1721,6 +1887,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1721 | capa->max_probe_length = | 1887 | capa->max_probe_length = |
1722 | le32_to_cpup((__le32 *)tlv_data); | 1888 | le32_to_cpup((__le32 *)tlv_data); |
1723 | break; | 1889 | break; |
1890 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
1891 | if (tlv_len != 4) | ||
1892 | return -EINVAL; | ||
1893 | pieces->init_evtlog_ptr = | ||
1894 | le32_to_cpup((__le32 *)tlv_data); | ||
1895 | break; | ||
1896 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
1897 | if (tlv_len != 4) | ||
1898 | return -EINVAL; | ||
1899 | pieces->init_evtlog_size = | ||
1900 | le32_to_cpup((__le32 *)tlv_data); | ||
1901 | break; | ||
1902 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
1903 | if (tlv_len != 4) | ||
1904 | return -EINVAL; | ||
1905 | pieces->init_errlog_ptr = | ||
1906 | le32_to_cpup((__le32 *)tlv_data); | ||
1907 | break; | ||
1908 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
1909 | if (tlv_len != 4) | ||
1910 | return -EINVAL; | ||
1911 | pieces->inst_evtlog_ptr = | ||
1912 | le32_to_cpup((__le32 *)tlv_data); | ||
1913 | break; | ||
1914 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
1915 | if (tlv_len != 4) | ||
1916 | return -EINVAL; | ||
1917 | pieces->inst_evtlog_size = | ||
1918 | le32_to_cpup((__le32 *)tlv_data); | ||
1919 | break; | ||
1920 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
1921 | if (tlv_len != 4) | ||
1922 | return -EINVAL; | ||
1923 | pieces->inst_errlog_ptr = | ||
1924 | le32_to_cpup((__le32 *)tlv_data); | ||
1925 | break; | ||
1724 | default: | 1926 | default: |
1725 | break; | 1927 | break; |
1726 | } | 1928 | } |
@@ -1913,6 +2115,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1913 | goto err_pci_alloc; | 2115 | goto err_pci_alloc; |
1914 | } | 2116 | } |
1915 | 2117 | ||
2118 | /* Now that we can no longer fail, copy information */ | ||
2119 | |||
2120 | /* | ||
2121 | * The (size - 16) / 12 formula is based on the information recorded | ||
2122 | * for each event, which is of mode 1 (including timestamp) for all | ||
2123 | * new microcodes that include this information. | ||
2124 | */ | ||
2125 | priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
2126 | if (pieces.init_evtlog_size) | ||
2127 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
2128 | else | ||
2129 | priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; | ||
2130 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; | ||
2131 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
2132 | if (pieces.inst_evtlog_size) | ||
2133 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
2134 | else | ||
2135 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | ||
2136 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
2137 | |||
1916 | /* Copy images into buffers for card's bus-master reads ... */ | 2138 | /* Copy images into buffers for card's bus-master reads ... */ |
1917 | 2139 | ||
1918 | /* Runtime instructions (first block of data in file) */ | 2140 | /* Runtime instructions (first block of data in file) */ |
@@ -1965,6 +2187,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1965 | if (err) | 2187 | if (err) |
1966 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | 2188 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); |
1967 | 2189 | ||
2190 | err = sysfs_create_group(&priv->pci_dev->dev.kobj, | ||
2191 | &iwl_attribute_group); | ||
2192 | if (err) { | ||
2193 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
2194 | goto out_unbind; | ||
2195 | } | ||
2196 | |||
1968 | /* We have our copies now, allow OS release its copies */ | 2197 | /* We have our copies now, allow OS release its copies */ |
1969 | release_firmware(ucode_raw); | 2198 | release_firmware(ucode_raw); |
1970 | complete(&priv->_agn.firmware_loading_complete); | 2199 | complete(&priv->_agn.firmware_loading_complete); |
@@ -2038,10 +2267,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2038 | u32 blink1, blink2, ilink1, ilink2; | 2267 | u32 blink1, blink2, ilink1, ilink2; |
2039 | u32 pc, hcmd; | 2268 | u32 pc, hcmd; |
2040 | 2269 | ||
2041 | if (priv->ucode_type == UCODE_INIT) | 2270 | if (priv->ucode_type == UCODE_INIT) { |
2042 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 2271 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
2043 | else | 2272 | if (!base) |
2273 | base = priv->_agn.init_errlog_ptr; | ||
2274 | } else { | ||
2044 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 2275 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
2276 | if (!base) | ||
2277 | base = priv->_agn.inst_errlog_ptr; | ||
2278 | } | ||
2045 | 2279 | ||
2046 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2280 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2047 | IWL_ERR(priv, | 2281 | IWL_ERR(priv, |
@@ -2101,10 +2335,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
2101 | 2335 | ||
2102 | if (num_events == 0) | 2336 | if (num_events == 0) |
2103 | return pos; | 2337 | return pos; |
2104 | if (priv->ucode_type == UCODE_INIT) | 2338 | |
2339 | if (priv->ucode_type == UCODE_INIT) { | ||
2105 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2340 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2106 | else | 2341 | if (!base) |
2342 | base = priv->_agn.init_evtlog_ptr; | ||
2343 | } else { | ||
2107 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2344 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2345 | if (!base) | ||
2346 | base = priv->_agn.inst_evtlog_ptr; | ||
2347 | } | ||
2108 | 2348 | ||
2109 | if (mode == 0) | 2349 | if (mode == 0) |
2110 | event_size = 2 * sizeof(u32); | 2350 | event_size = 2 * sizeof(u32); |
@@ -2206,13 +2446,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2206 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 2446 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
2207 | u32 next_entry; /* index of next entry to be written by uCode */ | 2447 | u32 next_entry; /* index of next entry to be written by uCode */ |
2208 | u32 size; /* # entries that we'll print */ | 2448 | u32 size; /* # entries that we'll print */ |
2449 | u32 logsize; | ||
2209 | int pos = 0; | 2450 | int pos = 0; |
2210 | size_t bufsz = 0; | 2451 | size_t bufsz = 0; |
2211 | 2452 | ||
2212 | if (priv->ucode_type == UCODE_INIT) | 2453 | if (priv->ucode_type == UCODE_INIT) { |
2213 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2454 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2214 | else | 2455 | logsize = priv->_agn.init_evtlog_size; |
2456 | if (!base) | ||
2457 | base = priv->_agn.init_evtlog_ptr; | ||
2458 | } else { | ||
2215 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2459 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2460 | logsize = priv->_agn.inst_evtlog_size; | ||
2461 | if (!base) | ||
2462 | base = priv->_agn.inst_evtlog_ptr; | ||
2463 | } | ||
2216 | 2464 | ||
2217 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2465 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2218 | IWL_ERR(priv, | 2466 | IWL_ERR(priv, |
@@ -2227,16 +2475,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2227 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2475 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
2228 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2476 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
2229 | 2477 | ||
2230 | if (capacity > priv->cfg->max_event_log_size) { | 2478 | if (capacity > logsize) { |
2231 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2479 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
2232 | capacity, priv->cfg->max_event_log_size); | 2480 | capacity, logsize); |
2233 | capacity = priv->cfg->max_event_log_size; | 2481 | capacity = logsize; |
2234 | } | 2482 | } |
2235 | 2483 | ||
2236 | if (next_entry > priv->cfg->max_event_log_size) { | 2484 | if (next_entry > logsize) { |
2237 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2485 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
2238 | next_entry, priv->cfg->max_event_log_size); | 2486 | next_entry, logsize); |
2239 | next_entry = priv->cfg->max_event_log_size; | 2487 | next_entry = logsize; |
2240 | } | 2488 | } |
2241 | 2489 | ||
2242 | size = num_wraps ? capacity : next_entry; | 2490 | size = num_wraps ? capacity : next_entry; |
@@ -2361,8 +2609,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2361 | 2609 | ||
2362 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2610 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2363 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2611 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2364 | |||
2365 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | ||
2366 | } | 2612 | } |
2367 | 2613 | ||
2368 | /* Configure Bluetooth device coexistence support */ | 2614 | /* Configure Bluetooth device coexistence support */ |
@@ -2777,20 +3023,16 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2777 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3023 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2778 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3024 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2779 | 3025 | ||
2780 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3026 | if (vif->bss_conf.use_short_preamble) |
2781 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3027 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2782 | else | 3028 | else |
2783 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3029 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2784 | 3030 | ||
2785 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3031 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2786 | if (vif->bss_conf.assoc_capability & | 3032 | if (vif->bss_conf.use_short_slot) |
2787 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2788 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3033 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2789 | else | 3034 | else |
2790 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3035 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2791 | |||
2792 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2793 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
2794 | } | 3036 | } |
2795 | 3037 | ||
2796 | iwlcore_commit_rxon(priv); | 3038 | iwlcore_commit_rxon(priv); |
@@ -3016,8 +3258,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3016 | 3258 | ||
3017 | priv->staging_rxon.assoc_id = 0; | 3259 | priv->staging_rxon.assoc_id = 0; |
3018 | 3260 | ||
3019 | if (vif->bss_conf.assoc_capability & | 3261 | if (vif->bss_conf.use_short_preamble) |
3020 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3021 | priv->staging_rxon.flags |= | 3262 | priv->staging_rxon.flags |= |
3022 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3263 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3023 | else | 3264 | else |
@@ -3025,17 +3266,12 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3025 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3266 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3026 | 3267 | ||
3027 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3268 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3028 | if (vif->bss_conf.assoc_capability & | 3269 | if (vif->bss_conf.use_short_slot) |
3029 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
3030 | priv->staging_rxon.flags |= | 3270 | priv->staging_rxon.flags |= |
3031 | RXON_FLG_SHORT_SLOT_MSK; | 3271 | RXON_FLG_SHORT_SLOT_MSK; |
3032 | else | 3272 | else |
3033 | priv->staging_rxon.flags &= | 3273 | priv->staging_rxon.flags &= |
3034 | ~RXON_FLG_SHORT_SLOT_MSK; | 3274 | ~RXON_FLG_SHORT_SLOT_MSK; |
3035 | |||
3036 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3037 | priv->staging_rxon.flags &= | ||
3038 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3039 | } | 3275 | } |
3040 | /* restore RXON assoc */ | 3276 | /* restore RXON assoc */ |
3041 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3277 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
@@ -3081,17 +3317,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3081 | return -EOPNOTSUPP; | 3317 | return -EOPNOTSUPP; |
3082 | } | 3318 | } |
3083 | 3319 | ||
3084 | if (sta) { | 3320 | sta_id = iwl_sta_id_or_broadcast(priv, sta); |
3085 | sta_id = iwl_sta_id(sta); | 3321 | if (sta_id == IWL_INVALID_STATION) |
3086 | 3322 | return -EINVAL; | |
3087 | if (sta_id == IWL_INVALID_STATION) { | ||
3088 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3089 | sta->addr); | ||
3090 | return -EINVAL; | ||
3091 | } | ||
3092 | } else { | ||
3093 | sta_id = priv->hw_params.bcast_sta_id; | ||
3094 | } | ||
3095 | 3323 | ||
3096 | mutex_lock(&priv->mutex); | 3324 | mutex_lock(&priv->mutex); |
3097 | iwl_scan_cancel_timeout(priv, 100); | 3325 | iwl_scan_cancel_timeout(priv, 100); |
@@ -3262,141 +3490,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3262 | return 0; | 3490 | return 0; |
3263 | } | 3491 | } |
3264 | 3492 | ||
3265 | /***************************************************************************** | 3493 | static void iwl_mac_channel_switch(struct ieee80211_hw *hw, |
3266 | * | 3494 | struct ieee80211_channel_switch *ch_switch) |
3267 | * sysfs attributes | ||
3268 | * | ||
3269 | *****************************************************************************/ | ||
3270 | |||
3271 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3272 | |||
3273 | /* | ||
3274 | * The following adds a new attribute to the sysfs representation | ||
3275 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) | ||
3276 | * used for controlling the debug level. | ||
3277 | * | ||
3278 | * See the level definitions in iwl for details. | ||
3279 | * | ||
3280 | * The debug_level being managed using sysfs below is a per device debug | ||
3281 | * level that is used instead of the global debug level if it (the per | ||
3282 | * device debug level) is set. | ||
3283 | */ | ||
3284 | static ssize_t show_debug_level(struct device *d, | ||
3285 | struct device_attribute *attr, char *buf) | ||
3286 | { | ||
3287 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3288 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); | ||
3289 | } | ||
3290 | static ssize_t store_debug_level(struct device *d, | ||
3291 | struct device_attribute *attr, | ||
3292 | const char *buf, size_t count) | ||
3293 | { | ||
3294 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3295 | unsigned long val; | ||
3296 | int ret; | ||
3297 | |||
3298 | ret = strict_strtoul(buf, 0, &val); | ||
3299 | if (ret) | ||
3300 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | ||
3301 | else { | ||
3302 | priv->debug_level = val; | ||
3303 | if (iwl_alloc_traffic_mem(priv)) | ||
3304 | IWL_ERR(priv, | ||
3305 | "Not enough memory to generate traffic log\n"); | ||
3306 | } | ||
3307 | return strnlen(buf, count); | ||
3308 | } | ||
3309 | |||
3310 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
3311 | show_debug_level, store_debug_level); | ||
3312 | |||
3313 | |||
3314 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
3315 | |||
3316 | |||
3317 | static ssize_t show_temperature(struct device *d, | ||
3318 | struct device_attribute *attr, char *buf) | ||
3319 | { | 3495 | { |
3320 | struct iwl_priv *priv = dev_get_drvdata(d); | 3496 | struct iwl_priv *priv = hw->priv; |
3321 | 3497 | const struct iwl_channel_info *ch_info; | |
3322 | if (!iwl_is_alive(priv)) | 3498 | struct ieee80211_conf *conf = &hw->conf; |
3323 | return -EAGAIN; | 3499 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
3324 | 3500 | u16 ch; | |
3325 | return sprintf(buf, "%d\n", priv->temperature); | 3501 | unsigned long flags = 0; |
3326 | } | ||
3327 | |||
3328 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
3329 | |||
3330 | static ssize_t show_tx_power(struct device *d, | ||
3331 | struct device_attribute *attr, char *buf) | ||
3332 | { | ||
3333 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3334 | |||
3335 | if (!iwl_is_ready_rf(priv)) | ||
3336 | return sprintf(buf, "off\n"); | ||
3337 | else | ||
3338 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
3339 | } | ||
3340 | 3502 | ||
3341 | static ssize_t store_tx_power(struct device *d, | 3503 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
3342 | struct device_attribute *attr, | ||
3343 | const char *buf, size_t count) | ||
3344 | { | ||
3345 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3346 | unsigned long val; | ||
3347 | int ret; | ||
3348 | 3504 | ||
3349 | ret = strict_strtoul(buf, 10, &val); | 3505 | if (iwl_is_rfkill(priv)) |
3350 | if (ret) | 3506 | goto out_exit; |
3351 | IWL_INFO(priv, "%s is not in decimal form.\n", buf); | ||
3352 | else { | ||
3353 | ret = iwl_set_tx_power(priv, val, false); | ||
3354 | if (ret) | ||
3355 | IWL_ERR(priv, "failed setting tx power (0x%d).\n", | ||
3356 | ret); | ||
3357 | else | ||
3358 | ret = count; | ||
3359 | } | ||
3360 | return ret; | ||
3361 | } | ||
3362 | 3507 | ||
3363 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | 3508 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || |
3509 | test_bit(STATUS_SCANNING, &priv->status)) | ||
3510 | goto out_exit; | ||
3364 | 3511 | ||
3365 | static ssize_t show_rts_ht_protection(struct device *d, | 3512 | if (!iwl_is_associated(priv)) |
3366 | struct device_attribute *attr, char *buf) | 3513 | goto out_exit; |
3367 | { | ||
3368 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3369 | 3514 | ||
3370 | return sprintf(buf, "%s\n", | 3515 | /* channel switch in progress */ |
3371 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | 3516 | if (priv->switch_rxon.switch_in_progress == true) |
3372 | } | 3517 | goto out_exit; |
3373 | 3518 | ||
3374 | static ssize_t store_rts_ht_protection(struct device *d, | 3519 | mutex_lock(&priv->mutex); |
3375 | struct device_attribute *attr, | 3520 | if (priv->cfg->ops->lib->set_channel_switch) { |
3376 | const char *buf, size_t count) | 3521 | |
3377 | { | 3522 | ch = ieee80211_frequency_to_channel( |
3378 | struct iwl_priv *priv = dev_get_drvdata(d); | 3523 | ch_switch->channel->center_freq); |
3379 | unsigned long val; | 3524 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { |
3380 | int ret; | 3525 | ch_info = iwl_get_channel_info(priv, |
3381 | 3526 | conf->channel->band, | |
3382 | ret = strict_strtoul(buf, 10, &val); | 3527 | ch); |
3383 | if (ret) | 3528 | if (!is_channel_valid(ch_info)) { |
3384 | IWL_INFO(priv, "Input is not in decimal form.\n"); | 3529 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); |
3385 | else { | 3530 | goto out; |
3386 | if (!iwl_is_associated(priv)) | 3531 | } |
3387 | priv->cfg->use_rts_for_ht = val ? true : false; | 3532 | spin_lock_irqsave(&priv->lock, flags); |
3388 | else | 3533 | |
3389 | IWL_ERR(priv, "Sta associated with AP - " | 3534 | priv->current_ht_config.smps = conf->smps_mode; |
3390 | "Change protection mechanism is not allowed\n"); | 3535 | |
3391 | ret = count; | 3536 | /* Configure HT40 channels */ |
3537 | ht_conf->is_ht = conf_is_ht(conf); | ||
3538 | if (ht_conf->is_ht) { | ||
3539 | if (conf_is_ht40_minus(conf)) { | ||
3540 | ht_conf->extension_chan_offset = | ||
3541 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
3542 | ht_conf->is_40mhz = true; | ||
3543 | } else if (conf_is_ht40_plus(conf)) { | ||
3544 | ht_conf->extension_chan_offset = | ||
3545 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
3546 | ht_conf->is_40mhz = true; | ||
3547 | } else { | ||
3548 | ht_conf->extension_chan_offset = | ||
3549 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
3550 | ht_conf->is_40mhz = false; | ||
3551 | } | ||
3552 | } else | ||
3553 | ht_conf->is_40mhz = false; | ||
3554 | |||
3555 | /* if we are switching from ht to 2.4 clear flags | ||
3556 | * from any ht related info since 2.4 does not | ||
3557 | * support ht */ | ||
3558 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
3559 | priv->staging_rxon.flags = 0; | ||
3560 | |||
3561 | iwl_set_rxon_channel(priv, conf->channel); | ||
3562 | iwl_set_rxon_ht(priv, ht_conf); | ||
3563 | iwl_set_flags_for_band(priv, conf->channel->band, | ||
3564 | priv->vif); | ||
3565 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3566 | |||
3567 | iwl_set_rate(priv); | ||
3568 | /* | ||
3569 | * at this point, staging_rxon has the | ||
3570 | * configuration for channel switch | ||
3571 | */ | ||
3572 | if (priv->cfg->ops->lib->set_channel_switch(priv, | ||
3573 | ch_switch)) | ||
3574 | priv->switch_rxon.switch_in_progress = false; | ||
3575 | } | ||
3392 | } | 3576 | } |
3393 | return ret; | 3577 | out: |
3578 | mutex_unlock(&priv->mutex); | ||
3579 | out_exit: | ||
3580 | if (!priv->switch_rxon.switch_in_progress) | ||
3581 | ieee80211_chswitch_done(priv->vif, false); | ||
3582 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3394 | } | 3583 | } |
3395 | 3584 | ||
3396 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
3397 | show_rts_ht_protection, store_rts_ht_protection); | ||
3398 | |||
3399 | |||
3400 | /***************************************************************************** | 3585 | /***************************************************************************** |
3401 | * | 3586 | * |
3402 | * driver setup and teardown | 3587 | * driver setup and teardown |
@@ -3550,21 +3735,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3550 | kfree(priv->scan_cmd); | 3735 | kfree(priv->scan_cmd); |
3551 | } | 3736 | } |
3552 | 3737 | ||
3553 | static struct attribute *iwl_sysfs_entries[] = { | ||
3554 | &dev_attr_temperature.attr, | ||
3555 | &dev_attr_tx_power.attr, | ||
3556 | &dev_attr_rts_ht_protection.attr, | ||
3557 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3558 | &dev_attr_debug_level.attr, | ||
3559 | #endif | ||
3560 | NULL | ||
3561 | }; | ||
3562 | |||
3563 | static struct attribute_group iwl_attribute_group = { | ||
3564 | .name = NULL, /* put in device directory */ | ||
3565 | .attrs = iwl_sysfs_entries, | ||
3566 | }; | ||
3567 | |||
3568 | static struct ieee80211_ops iwl_hw_ops = { | 3738 | static struct ieee80211_ops iwl_hw_ops = { |
3569 | .tx = iwl_mac_tx, | 3739 | .tx = iwl_mac_tx, |
3570 | .start = iwl_mac_start, | 3740 | .start = iwl_mac_start, |
@@ -3583,6 +3753,7 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3583 | .sta_notify = iwl_mac_sta_notify, | 3753 | .sta_notify = iwl_mac_sta_notify, |
3584 | .sta_add = iwlagn_mac_sta_add, | 3754 | .sta_add = iwlagn_mac_sta_add, |
3585 | .sta_remove = iwl_mac_sta_remove, | 3755 | .sta_remove = iwl_mac_sta_remove, |
3756 | .channel_switch = iwl_mac_channel_switch, | ||
3586 | }; | 3757 | }; |
3587 | 3758 | ||
3588 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3759 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3593,6 +3764,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3593 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 3764 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
3594 | unsigned long flags; | 3765 | unsigned long flags; |
3595 | u16 pci_cmd; | 3766 | u16 pci_cmd; |
3767 | u8 perm_addr[ETH_ALEN]; | ||
3596 | 3768 | ||
3597 | /************************ | 3769 | /************************ |
3598 | * 1. Allocating HW data | 3770 | * 1. Allocating HW data |
@@ -3622,9 +3794,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3622 | priv->pci_dev = pdev; | 3794 | priv->pci_dev = pdev; |
3623 | priv->inta_mask = CSR_INI_SET_MASK; | 3795 | priv->inta_mask = CSR_INI_SET_MASK; |
3624 | 3796 | ||
3625 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3626 | atomic_set(&priv->restrict_refcnt, 0); | ||
3627 | #endif | ||
3628 | if (iwl_alloc_traffic_mem(priv)) | 3797 | if (iwl_alloc_traffic_mem(priv)) |
3629 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3798 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
3630 | 3799 | ||
@@ -3713,9 +3882,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3713 | goto out_free_eeprom; | 3882 | goto out_free_eeprom; |
3714 | 3883 | ||
3715 | /* extract MAC Address */ | 3884 | /* extract MAC Address */ |
3716 | iwl_eeprom_get_mac(priv, priv->mac_addr); | 3885 | iwl_eeprom_get_mac(priv, perm_addr); |
3717 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); | 3886 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); |
3718 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | 3887 | SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); |
3719 | 3888 | ||
3720 | /************************ | 3889 | /************************ |
3721 | * 5. Setup HW constants | 3890 | * 5. Setup HW constants |
@@ -3750,11 +3919,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3750 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); | 3919 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); |
3751 | goto out_disable_msi; | 3920 | goto out_disable_msi; |
3752 | } | 3921 | } |
3753 | err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); | ||
3754 | if (err) { | ||
3755 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
3756 | goto out_free_irq; | ||
3757 | } | ||
3758 | 3922 | ||
3759 | iwl_setup_deferred_work(priv); | 3923 | iwl_setup_deferred_work(priv); |
3760 | iwl_setup_rx_handlers(priv); | 3924 | iwl_setup_rx_handlers(priv); |
@@ -3788,15 +3952,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3788 | 3952 | ||
3789 | err = iwl_request_firmware(priv, true); | 3953 | err = iwl_request_firmware(priv, true); |
3790 | if (err) | 3954 | if (err) |
3791 | goto out_remove_sysfs; | 3955 | goto out_destroy_workqueue; |
3792 | 3956 | ||
3793 | return 0; | 3957 | return 0; |
3794 | 3958 | ||
3795 | out_remove_sysfs: | 3959 | out_destroy_workqueue: |
3796 | destroy_workqueue(priv->workqueue); | 3960 | destroy_workqueue(priv->workqueue); |
3797 | priv->workqueue = NULL; | 3961 | priv->workqueue = NULL; |
3798 | sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); | ||
3799 | out_free_irq: | ||
3800 | free_irq(priv->pci_dev->irq, priv); | 3962 | free_irq(priv->pci_dev->irq, priv); |
3801 | iwl_free_isr_ict(priv); | 3963 | iwl_free_isr_ict(priv); |
3802 | out_disable_msi: | 3964 | out_disable_msi: |
@@ -3989,6 +4151,47 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3989 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, | 4151 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, |
3990 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, | 4152 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, |
3991 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, | 4153 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, |
4154 | {IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)}, | ||
4155 | {IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)}, | ||
4156 | {IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)}, | ||
4157 | {IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)}, | ||
4158 | {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)}, | ||
4159 | {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)}, | ||
4160 | {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)}, | ||
4161 | {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)}, | ||
4162 | {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)}, | ||
4163 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)}, | ||
4164 | {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)}, | ||
4165 | |||
4166 | /* 6x00 Series Gen2b */ | ||
4167 | {IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)}, | ||
4168 | {IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)}, | ||
4169 | {IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)}, | ||
4170 | {IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)}, | ||
4171 | {IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4172 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4173 | {IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4174 | {IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4175 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4176 | {IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
4177 | {IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4178 | {IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)}, | ||
4179 | {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)}, | ||
4180 | {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)}, | ||
4181 | {IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)}, | ||
4182 | {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)}, | ||
4183 | {IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)}, | ||
4184 | {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)}, | ||
4185 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4186 | {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)}, | ||
4187 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4188 | {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4189 | {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)}, | ||
4190 | {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4191 | {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4192 | {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4193 | {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)}, | ||
4194 | {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
3992 | 4195 | ||
3993 | /* 6x50 WiFi/WiMax Series */ | 4196 | /* 6x50 WiFi/WiMax Series */ |
3994 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 4197 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |