diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 225 |
1 files changed, 176 insertions, 49 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index fc23ba5309bd..f9c14c66434e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1368,18 +1368,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1368 | unsigned int rate; | 1368 | unsigned int rate; |
1369 | u16 ctl; | 1369 | u16 ctl; |
1370 | int antenna; | 1370 | int antenna; |
1371 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); | ||
1371 | 1372 | ||
1372 | bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); | 1373 | bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); |
1373 | len = min((size_t) dev->wl->current_beacon->len, | 1374 | len = min((size_t) dev->wl->current_beacon->len, |
1374 | 0x200 - sizeof(struct b43_plcp_hdr6)); | 1375 | 0x200 - sizeof(struct b43_plcp_hdr6)); |
1375 | rate = dev->wl->beacon_txctl.tx_rate->hw_value; | 1376 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; |
1376 | 1377 | ||
1377 | b43_write_template_common(dev, (const u8 *)bcn, | 1378 | b43_write_template_common(dev, (const u8 *)bcn, |
1378 | len, ram_offset, shm_size_offset, rate); | 1379 | len, ram_offset, shm_size_offset, rate); |
1379 | 1380 | ||
1380 | /* Write the PHY TX control parameters. */ | 1381 | /* Write the PHY TX control parameters. */ |
1381 | antenna = b43_antenna_from_ieee80211(dev, | 1382 | antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); |
1382 | dev->wl->beacon_txctl.antenna_sel_tx); | ||
1383 | antenna = b43_antenna_to_phyctl(antenna); | 1383 | antenna = b43_antenna_to_phyctl(antenna); |
1384 | ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); | 1384 | ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); |
1385 | /* We can't send beacons with short preamble. Would get PHY errors. */ | 1385 | /* We can't send beacons with short preamble. Would get PHY errors. */ |
@@ -1430,11 +1430,17 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1430 | i += ie_len + 2; | 1430 | i += ie_len + 2; |
1431 | } | 1431 | } |
1432 | if (!tim_found) { | 1432 | if (!tim_found) { |
1433 | b43warn(dev->wl, "Did not find a valid TIM IE in " | 1433 | /* |
1434 | "the beacon template packet. AP or IBSS operation " | 1434 | * If ucode wants to modify TIM do it behind the beacon, this |
1435 | "may be broken.\n"); | 1435 | * will happen, for example, when doing mesh networking. |
1436 | } else | 1436 | */ |
1437 | b43dbg(dev->wl, "Updated beacon template\n"); | 1437 | b43_shm_write16(dev, B43_SHM_SHARED, |
1438 | B43_SHM_SH_TIMBPOS, | ||
1439 | len + sizeof(struct b43_plcp_hdr6)); | ||
1440 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
1441 | B43_SHM_SH_DTIMPER, 0); | ||
1442 | } | ||
1443 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); | ||
1438 | } | 1444 | } |
1439 | 1445 | ||
1440 | static void b43_write_probe_resp_plcp(struct b43_wldev *dev, | 1446 | static void b43_write_probe_resp_plcp(struct b43_wldev *dev, |
@@ -1549,7 +1555,8 @@ static void handle_irq_beacon(struct b43_wldev *dev) | |||
1549 | struct b43_wl *wl = dev->wl; | 1555 | struct b43_wl *wl = dev->wl; |
1550 | u32 cmd, beacon0_valid, beacon1_valid; | 1556 | u32 cmd, beacon0_valid, beacon1_valid; |
1551 | 1557 | ||
1552 | if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) | 1558 | if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) && |
1559 | !b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | ||
1553 | return; | 1560 | return; |
1554 | 1561 | ||
1555 | /* This is the bottom half of the asynchronous beacon update. */ | 1562 | /* This is the bottom half of the asynchronous beacon update. */ |
@@ -1613,8 +1620,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
1613 | 1620 | ||
1614 | /* Asynchronously update the packet templates in template RAM. | 1621 | /* Asynchronously update the packet templates in template RAM. |
1615 | * Locking: Requires wl->irq_lock to be locked. */ | 1622 | * Locking: Requires wl->irq_lock to be locked. */ |
1616 | static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon, | 1623 | static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) |
1617 | const struct ieee80211_tx_control *txctl) | ||
1618 | { | 1624 | { |
1619 | /* This is the top half of the ansynchronous beacon update. | 1625 | /* This is the top half of the ansynchronous beacon update. |
1620 | * The bottom half is the beacon IRQ. | 1626 | * The bottom half is the beacon IRQ. |
@@ -1625,7 +1631,6 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon, | |||
1625 | if (wl->current_beacon) | 1631 | if (wl->current_beacon) |
1626 | dev_kfree_skb_any(wl->current_beacon); | 1632 | dev_kfree_skb_any(wl->current_beacon); |
1627 | wl->current_beacon = beacon; | 1633 | wl->current_beacon = beacon; |
1628 | memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl)); | ||
1629 | wl->beacon0_uploaded = 0; | 1634 | wl->beacon0_uploaded = 0; |
1630 | wl->beacon1_uploaded = 0; | 1635 | wl->beacon1_uploaded = 0; |
1631 | queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); | 1636 | queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); |
@@ -1664,9 +1669,100 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) | |||
1664 | b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); | 1669 | b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); |
1665 | } | 1670 | } |
1666 | 1671 | ||
1672 | static void b43_handle_firmware_panic(struct b43_wldev *dev) | ||
1673 | { | ||
1674 | u16 reason; | ||
1675 | |||
1676 | /* Read the register that contains the reason code for the panic. */ | ||
1677 | reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_FWPANIC_REASON_REG); | ||
1678 | b43err(dev->wl, "Whoopsy, firmware panic! Reason: %u\n", reason); | ||
1679 | |||
1680 | switch (reason) { | ||
1681 | default: | ||
1682 | b43dbg(dev->wl, "The panic reason is unknown.\n"); | ||
1683 | /* fallthrough */ | ||
1684 | case B43_FWPANIC_DIE: | ||
1685 | /* Do not restart the controller or firmware. | ||
1686 | * The device is nonfunctional from now on. | ||
1687 | * Restarting would result in this panic to trigger again, | ||
1688 | * so we avoid that recursion. */ | ||
1689 | break; | ||
1690 | case B43_FWPANIC_RESTART: | ||
1691 | b43_controller_restart(dev, "Microcode panic"); | ||
1692 | break; | ||
1693 | } | ||
1694 | } | ||
1695 | |||
1667 | static void handle_irq_ucode_debug(struct b43_wldev *dev) | 1696 | static void handle_irq_ucode_debug(struct b43_wldev *dev) |
1668 | { | 1697 | { |
1669 | //TODO | 1698 | unsigned int i, cnt; |
1699 | u16 reason, marker_id, marker_line; | ||
1700 | __le16 *buf; | ||
1701 | |||
1702 | /* The proprietary firmware doesn't have this IRQ. */ | ||
1703 | if (!dev->fw.opensource) | ||
1704 | return; | ||
1705 | |||
1706 | /* Read the register that contains the reason code for this IRQ. */ | ||
1707 | reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG); | ||
1708 | |||
1709 | switch (reason) { | ||
1710 | case B43_DEBUGIRQ_PANIC: | ||
1711 | b43_handle_firmware_panic(dev); | ||
1712 | break; | ||
1713 | case B43_DEBUGIRQ_DUMP_SHM: | ||
1714 | if (!B43_DEBUG) | ||
1715 | break; /* Only with driver debugging enabled. */ | ||
1716 | buf = kmalloc(4096, GFP_ATOMIC); | ||
1717 | if (!buf) { | ||
1718 | b43dbg(dev->wl, "SHM-dump: Failed to allocate memory\n"); | ||
1719 | goto out; | ||
1720 | } | ||
1721 | for (i = 0; i < 4096; i += 2) { | ||
1722 | u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, i); | ||
1723 | buf[i / 2] = cpu_to_le16(tmp); | ||
1724 | } | ||
1725 | b43info(dev->wl, "Shared memory dump:\n"); | ||
1726 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, | ||
1727 | 16, 2, buf, 4096, 1); | ||
1728 | kfree(buf); | ||
1729 | break; | ||
1730 | case B43_DEBUGIRQ_DUMP_REGS: | ||
1731 | if (!B43_DEBUG) | ||
1732 | break; /* Only with driver debugging enabled. */ | ||
1733 | b43info(dev->wl, "Microcode register dump:\n"); | ||
1734 | for (i = 0, cnt = 0; i < 64; i++) { | ||
1735 | u16 tmp = b43_shm_read16(dev, B43_SHM_SCRATCH, i); | ||
1736 | if (cnt == 0) | ||
1737 | printk(KERN_INFO); | ||
1738 | printk("r%02u: 0x%04X ", i, tmp); | ||
1739 | cnt++; | ||
1740 | if (cnt == 6) { | ||
1741 | printk("\n"); | ||
1742 | cnt = 0; | ||
1743 | } | ||
1744 | } | ||
1745 | printk("\n"); | ||
1746 | break; | ||
1747 | case B43_DEBUGIRQ_MARKER: | ||
1748 | if (!B43_DEBUG) | ||
1749 | break; /* Only with driver debugging enabled. */ | ||
1750 | marker_id = b43_shm_read16(dev, B43_SHM_SCRATCH, | ||
1751 | B43_MARKER_ID_REG); | ||
1752 | marker_line = b43_shm_read16(dev, B43_SHM_SCRATCH, | ||
1753 | B43_MARKER_LINE_REG); | ||
1754 | b43info(dev->wl, "The firmware just executed the MARKER(%u) " | ||
1755 | "at line number %u\n", | ||
1756 | marker_id, marker_line); | ||
1757 | break; | ||
1758 | default: | ||
1759 | b43dbg(dev->wl, "Debug-IRQ triggered for unknown reason: %u\n", | ||
1760 | reason); | ||
1761 | } | ||
1762 | out: | ||
1763 | /* Acknowledge the debug-IRQ, so the firmware can continue. */ | ||
1764 | b43_shm_write16(dev, B43_SHM_SCRATCH, | ||
1765 | B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK); | ||
1670 | } | 1766 | } |
1671 | 1767 | ||
1672 | /* Interrupt handler bottom-half */ | 1768 | /* Interrupt handler bottom-half */ |
@@ -1853,7 +1949,8 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
1853 | 1949 | ||
1854 | static int do_request_fw(struct b43_wldev *dev, | 1950 | static int do_request_fw(struct b43_wldev *dev, |
1855 | const char *name, | 1951 | const char *name, |
1856 | struct b43_firmware_file *fw) | 1952 | struct b43_firmware_file *fw, |
1953 | bool silent) | ||
1857 | { | 1954 | { |
1858 | char path[sizeof(modparam_fwpostfix) + 32]; | 1955 | char path[sizeof(modparam_fwpostfix) + 32]; |
1859 | const struct firmware *blob; | 1956 | const struct firmware *blob; |
@@ -1877,9 +1974,15 @@ static int do_request_fw(struct b43_wldev *dev, | |||
1877 | "b43%s/%s.fw", | 1974 | "b43%s/%s.fw", |
1878 | modparam_fwpostfix, name); | 1975 | modparam_fwpostfix, name); |
1879 | err = request_firmware(&blob, path, dev->dev->dev); | 1976 | err = request_firmware(&blob, path, dev->dev->dev); |
1880 | if (err) { | 1977 | if (err == -ENOENT) { |
1881 | b43err(dev->wl, "Firmware file \"%s\" not found " | 1978 | if (!silent) { |
1882 | "or load failed.\n", path); | 1979 | b43err(dev->wl, "Firmware file \"%s\" not found\n", |
1980 | path); | ||
1981 | } | ||
1982 | return err; | ||
1983 | } else if (err) { | ||
1984 | b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n", | ||
1985 | path, err); | ||
1883 | return err; | 1986 | return err; |
1884 | } | 1987 | } |
1885 | if (blob->size < sizeof(struct b43_fw_header)) | 1988 | if (blob->size < sizeof(struct b43_fw_header)) |
@@ -1930,7 +2033,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
1930 | filename = "ucode13"; | 2033 | filename = "ucode13"; |
1931 | else | 2034 | else |
1932 | goto err_no_ucode; | 2035 | goto err_no_ucode; |
1933 | err = do_request_fw(dev, filename, &fw->ucode); | 2036 | err = do_request_fw(dev, filename, &fw->ucode, 0); |
1934 | if (err) | 2037 | if (err) |
1935 | goto err_load; | 2038 | goto err_load; |
1936 | 2039 | ||
@@ -1941,8 +2044,13 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
1941 | filename = NULL; | 2044 | filename = NULL; |
1942 | else | 2045 | else |
1943 | goto err_no_pcm; | 2046 | goto err_no_pcm; |
1944 | err = do_request_fw(dev, filename, &fw->pcm); | 2047 | fw->pcm_request_failed = 0; |
1945 | if (err) | 2048 | err = do_request_fw(dev, filename, &fw->pcm, 1); |
2049 | if (err == -ENOENT) { | ||
2050 | /* We did not find a PCM file? Not fatal, but | ||
2051 | * core rev <= 10 must do without hwcrypto then. */ | ||
2052 | fw->pcm_request_failed = 1; | ||
2053 | } else if (err) | ||
1946 | goto err_load; | 2054 | goto err_load; |
1947 | 2055 | ||
1948 | /* Get initvals */ | 2056 | /* Get initvals */ |
@@ -1960,7 +2068,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
1960 | if ((rev >= 5) && (rev <= 10)) | 2068 | if ((rev >= 5) && (rev <= 10)) |
1961 | filename = "b0g0initvals5"; | 2069 | filename = "b0g0initvals5"; |
1962 | else if (rev >= 13) | 2070 | else if (rev >= 13) |
1963 | filename = "lp0initvals13"; | 2071 | filename = "b0g0initvals13"; |
1964 | else | 2072 | else |
1965 | goto err_no_initvals; | 2073 | goto err_no_initvals; |
1966 | break; | 2074 | break; |
@@ -1973,7 +2081,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
1973 | default: | 2081 | default: |
1974 | goto err_no_initvals; | 2082 | goto err_no_initvals; |
1975 | } | 2083 | } |
1976 | err = do_request_fw(dev, filename, &fw->initvals); | 2084 | err = do_request_fw(dev, filename, &fw->initvals, 0); |
1977 | if (err) | 2085 | if (err) |
1978 | goto err_load; | 2086 | goto err_load; |
1979 | 2087 | ||
@@ -2007,7 +2115,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2007 | default: | 2115 | default: |
2008 | goto err_no_initvals; | 2116 | goto err_no_initvals; |
2009 | } | 2117 | } |
2010 | err = do_request_fw(dev, filename, &fw->initvals_band); | 2118 | err = do_request_fw(dev, filename, &fw->initvals_band, 0); |
2011 | if (err) | 2119 | if (err) |
2012 | goto err_load; | 2120 | goto err_load; |
2013 | 2121 | ||
@@ -2124,14 +2232,28 @@ static int b43_upload_microcode(struct b43_wldev *dev) | |||
2124 | err = -EOPNOTSUPP; | 2232 | err = -EOPNOTSUPP; |
2125 | goto error; | 2233 | goto error; |
2126 | } | 2234 | } |
2127 | b43info(dev->wl, "Loading firmware version %u.%u " | ||
2128 | "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", | ||
2129 | fwrev, fwpatch, | ||
2130 | (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, | ||
2131 | (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); | ||
2132 | |||
2133 | dev->fw.rev = fwrev; | 2235 | dev->fw.rev = fwrev; |
2134 | dev->fw.patch = fwpatch; | 2236 | dev->fw.patch = fwpatch; |
2237 | dev->fw.opensource = (fwdate == 0xFFFF); | ||
2238 | |||
2239 | if (dev->fw.opensource) { | ||
2240 | /* Patchlevel info is encoded in the "time" field. */ | ||
2241 | dev->fw.patch = fwtime; | ||
2242 | b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n", | ||
2243 | dev->fw.rev, dev->fw.patch, | ||
2244 | dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : ""); | ||
2245 | } else { | ||
2246 | b43info(dev->wl, "Loading firmware version %u.%u " | ||
2247 | "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", | ||
2248 | fwrev, fwpatch, | ||
2249 | (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, | ||
2250 | (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); | ||
2251 | if (dev->fw.pcm_request_failed) { | ||
2252 | b43warn(dev->wl, "No \"pcm5.fw\" firmware file found. " | ||
2253 | "Hardware accelerated cryptography is disabled.\n"); | ||
2254 | b43_print_fw_helptext(dev->wl, 0); | ||
2255 | } | ||
2256 | } | ||
2135 | 2257 | ||
2136 | if (b43_is_old_txhdr_format(dev)) { | 2258 | if (b43_is_old_txhdr_format(dev)) { |
2137 | b43warn(dev->wl, "You are using an old firmware image. " | 2259 | b43warn(dev->wl, "You are using an old firmware image. " |
@@ -2376,7 +2498,8 @@ static void b43_adjust_opmode(struct b43_wldev *dev) | |||
2376 | ctl &= ~B43_MACCTL_BEACPROMISC; | 2498 | ctl &= ~B43_MACCTL_BEACPROMISC; |
2377 | ctl |= B43_MACCTL_INFRA; | 2499 | ctl |= B43_MACCTL_INFRA; |
2378 | 2500 | ||
2379 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) | 2501 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || |
2502 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | ||
2380 | ctl |= B43_MACCTL_AP; | 2503 | ctl |= B43_MACCTL_AP; |
2381 | else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) | 2504 | else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) |
2382 | ctl &= ~B43_MACCTL_INFRA; | 2505 | ctl &= ~B43_MACCTL_INFRA; |
@@ -2813,8 +2936,7 @@ static int b43_rng_init(struct b43_wl *wl) | |||
2813 | } | 2936 | } |
2814 | 2937 | ||
2815 | static int b43_op_tx(struct ieee80211_hw *hw, | 2938 | static int b43_op_tx(struct ieee80211_hw *hw, |
2816 | struct sk_buff *skb, | 2939 | struct sk_buff *skb) |
2817 | struct ieee80211_tx_control *ctl) | ||
2818 | { | 2940 | { |
2819 | struct b43_wl *wl = hw_to_b43_wl(hw); | 2941 | struct b43_wl *wl = hw_to_b43_wl(hw); |
2820 | struct b43_wldev *dev = wl->current_dev; | 2942 | struct b43_wldev *dev = wl->current_dev; |
@@ -2836,9 +2958,9 @@ static int b43_op_tx(struct ieee80211_hw *hw, | |||
2836 | err = -ENODEV; | 2958 | err = -ENODEV; |
2837 | if (likely(b43_status(dev) >= B43_STAT_STARTED)) { | 2959 | if (likely(b43_status(dev) >= B43_STAT_STARTED)) { |
2838 | if (b43_using_pio_transfers(dev)) | 2960 | if (b43_using_pio_transfers(dev)) |
2839 | err = b43_pio_tx(dev, skb, ctl); | 2961 | err = b43_pio_tx(dev, skb); |
2840 | else | 2962 | else |
2841 | err = b43_dma_tx(dev, skb, ctl); | 2963 | err = b43_dma_tx(dev, skb); |
2842 | } | 2964 | } |
2843 | 2965 | ||
2844 | read_unlock_irqrestore(&wl->tx_lock, flags); | 2966 | read_unlock_irqrestore(&wl->tx_lock, flags); |
@@ -3244,8 +3366,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3244 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); | 3366 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); |
3245 | b43_set_rx_antenna(dev, antenna); | 3367 | b43_set_rx_antenna(dev, antenna); |
3246 | 3368 | ||
3247 | /* Update templates for AP mode. */ | 3369 | /* Update templates for AP/mesh mode. */ |
3248 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) | 3370 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || |
3371 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) | ||
3249 | b43_set_beacon_int(dev, conf->beacon_int); | 3372 | b43_set_beacon_int(dev, conf->beacon_int); |
3250 | 3373 | ||
3251 | if (!!conf->radio_enabled != phy->radio_on) { | 3374 | if (!!conf->radio_enabled != phy->radio_on) { |
@@ -3296,6 +3419,13 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3296 | if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) | 3419 | if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) |
3297 | goto out_unlock; | 3420 | goto out_unlock; |
3298 | 3421 | ||
3422 | if (dev->fw.pcm_request_failed) { | ||
3423 | /* We don't have firmware for the crypto engine. | ||
3424 | * Must use software-crypto. */ | ||
3425 | err = -EOPNOTSUPP; | ||
3426 | goto out_unlock; | ||
3427 | } | ||
3428 | |||
3299 | err = -EINVAL; | 3429 | err = -EINVAL; |
3300 | switch (key->alg) { | 3430 | switch (key->alg) { |
3301 | case ALG_WEP: | 3431 | case ALG_WEP: |
@@ -3426,13 +3556,12 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, | |||
3426 | else | 3556 | else |
3427 | memset(wl->bssid, 0, ETH_ALEN); | 3557 | memset(wl->bssid, 0, ETH_ALEN); |
3428 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { | 3558 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { |
3429 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { | 3559 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || |
3430 | B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); | 3560 | b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { |
3561 | B43_WARN_ON(conf->type != wl->if_type); | ||
3431 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); | 3562 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); |
3432 | if (conf->beacon) { | 3563 | if (conf->beacon) |
3433 | b43_update_templates(wl, conf->beacon, | 3564 | b43_update_templates(wl, conf->beacon); |
3434 | conf->beacon_control); | ||
3435 | } | ||
3436 | } | 3565 | } |
3437 | b43_write_mac_bssid_templates(dev); | 3566 | b43_write_mac_bssid_templates(dev); |
3438 | } | 3567 | } |
@@ -3497,7 +3626,6 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
3497 | /* Start data flow (TX/RX). */ | 3626 | /* Start data flow (TX/RX). */ |
3498 | b43_mac_enable(dev); | 3627 | b43_mac_enable(dev); |
3499 | b43_interrupt_enable(dev, dev->irq_savedstate); | 3628 | b43_interrupt_enable(dev, dev->irq_savedstate); |
3500 | ieee80211_start_queues(dev->wl->hw); | ||
3501 | 3629 | ||
3502 | /* Start maintainance work */ | 3630 | /* Start maintainance work */ |
3503 | b43_periodic_tasks_setup(dev); | 3631 | b43_periodic_tasks_setup(dev); |
@@ -3970,6 +4098,7 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
3970 | /* TODO: allow WDS/AP devices to coexist */ | 4098 | /* TODO: allow WDS/AP devices to coexist */ |
3971 | 4099 | ||
3972 | if (conf->type != IEEE80211_IF_TYPE_AP && | 4100 | if (conf->type != IEEE80211_IF_TYPE_AP && |
4101 | conf->type != IEEE80211_IF_TYPE_MESH_POINT && | ||
3973 | conf->type != IEEE80211_IF_TYPE_STA && | 4102 | conf->type != IEEE80211_IF_TYPE_STA && |
3974 | conf->type != IEEE80211_IF_TYPE_WDS && | 4103 | conf->type != IEEE80211_IF_TYPE_WDS && |
3975 | conf->type != IEEE80211_IF_TYPE_IBSS) | 4104 | conf->type != IEEE80211_IF_TYPE_IBSS) |
@@ -4119,31 +4248,29 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) | |||
4119 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4248 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4120 | struct sk_buff *beacon; | 4249 | struct sk_buff *beacon; |
4121 | unsigned long flags; | 4250 | unsigned long flags; |
4122 | struct ieee80211_tx_control txctl; | ||
4123 | 4251 | ||
4124 | /* We could modify the existing beacon and set the aid bit in | 4252 | /* We could modify the existing beacon and set the aid bit in |
4125 | * the TIM field, but that would probably require resizing and | 4253 | * the TIM field, but that would probably require resizing and |
4126 | * moving of data within the beacon template. | 4254 | * moving of data within the beacon template. |
4127 | * Simply request a new beacon and let mac80211 do the hard work. */ | 4255 | * Simply request a new beacon and let mac80211 do the hard work. */ |
4128 | beacon = ieee80211_beacon_get(hw, wl->vif, &txctl); | 4256 | beacon = ieee80211_beacon_get(hw, wl->vif); |
4129 | if (unlikely(!beacon)) | 4257 | if (unlikely(!beacon)) |
4130 | return -ENOMEM; | 4258 | return -ENOMEM; |
4131 | spin_lock_irqsave(&wl->irq_lock, flags); | 4259 | spin_lock_irqsave(&wl->irq_lock, flags); |
4132 | b43_update_templates(wl, beacon, &txctl); | 4260 | b43_update_templates(wl, beacon); |
4133 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 4261 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
4134 | 4262 | ||
4135 | return 0; | 4263 | return 0; |
4136 | } | 4264 | } |
4137 | 4265 | ||
4138 | static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, | 4266 | static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, |
4139 | struct sk_buff *beacon, | 4267 | struct sk_buff *beacon) |
4140 | struct ieee80211_tx_control *ctl) | ||
4141 | { | 4268 | { |
4142 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4269 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4143 | unsigned long flags; | 4270 | unsigned long flags; |
4144 | 4271 | ||
4145 | spin_lock_irqsave(&wl->irq_lock, flags); | 4272 | spin_lock_irqsave(&wl->irq_lock, flags); |
4146 | b43_update_templates(wl, beacon, ctl); | 4273 | b43_update_templates(wl, beacon); |
4147 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 4274 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
4148 | 4275 | ||
4149 | return 0; | 4276 | return 0; |