static void _rtl_init_mac80211(struct ieee80211_hw *hw) { struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); /* * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ /*IEEE80211_HW_SUPPORTS_PS | */ /*IEEE80211_HW_PS_NULLFUNC_STACK | */ /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; hw->queues = AC_MAX; hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; hw->max_listen_interval = 5; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; get_random_bytes((rtlmac + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac); } }
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); if (AR_SREV_5416(sc->sc_ah)) hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); #ifdef CONFIG_ATH9K_RATE_CONTROL hw->rate_control_algorithm = "ath9k_rate_control"; #endif if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } SET_IEEE80211_PERM_ADDR(hw, common->macaddr); }
static int wl1251_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct wl1251 *wl = hw->priv; int ret = 0; wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", conf->type, conf->mac_addr); mutex_lock(&wl->mutex); switch (conf->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: wl->bss_type = BSS_TYPE_IBSS; break; default: ret = -EOPNOTSUPP; goto out; } if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = wl1251_acx_station_id(wl); if (ret < 0) goto out; } out: mutex_unlock(&wl->mutex); return ret; }
int mt7601u_register_device(struct mt7601u_dev *dev) { struct ieee80211_hw *hw = dev->hw; struct wiphy *wiphy = hw->wiphy; int ret; /* Reserve WCID 0 for mcast - thanks to this APs WCID will go to * entry no. 1 like it does in the vendor driver. */ dev->wcid_mask[0] |= 1; /* init fake wcid for monitor interfaces */ dev->mon_wcid = devm_kmalloc(dev->dev, sizeof(*dev->mon_wcid), GFP_KERNEL); if (!dev->mon_wcid) return -ENOMEM; dev->mon_wcid->idx = 0xff; dev->mon_wcid->hw_key_idx = -1; SET_IEEE80211_DEV(hw, dev->dev); hw->queues = 4; ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); ieee80211_hw_set(hw, AMPDU_AGGREGATION); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); hw->max_rates = 1; hw->max_report_rates = 7; hw->max_rate_tries = 1; hw->sta_data_size = sizeof(struct mt76_sta); hw->vif_data_size = sizeof(struct mt76_vif); SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); ret = mt76_init_sband_2g(dev); if (ret) return ret; INIT_DELAYED_WORK(&dev->mac_work, mt7601u_mac_work); INIT_DELAYED_WORK(&dev->stat_work, mt7601u_tx_stat); ret = ieee80211_register_hw(hw); if (ret) return ret; mt7601u_init_debugfs(dev); return 0; }
int zd_mac_preinit_hw(struct ieee80211_hw *hw) { int r; u8 addr[ETH_ALEN]; struct zd_mac *mac = zd_hw_mac(hw); r = zd_chip_read_mac_addr_fw(&mac->chip, addr); if (r) return r; SET_IEEE80211_PERM_ADDR(hw, addr); return 0; }
static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; char *tx_power; unsigned int i; /* * Initialize all hw fields. */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); /* * Initialize hw_mode information. */ spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK; spec->num_channels = ARRAY_SIZE(rf_vals_b); spec->channels = rf_vals_b; /* * Create channel information array */ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; spec->channels_info = info; tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); for (i = 0; i < 14; i++) { info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER); info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); } return 0; }
static int wl1251_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; int ret = 0; vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_UAPSD | IEEE80211_VIF_SUPPORTS_CQM_RSSI; wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { ret = -EBUSY; goto out; } wl->vif = vif; switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: wl->bss_type = BSS_TYPE_IBSS; break; default: ret = -EOPNOTSUPP; goto out; } if (!ether_addr_equal_unaligned(wl->mac_addr, vif->addr)) { memcpy(wl->mac_addr, vif->addr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = wl1251_acx_station_id(wl); if (ret < 0) goto out; } out: mutex_unlock(&wl->mutex); return ret; }
static int wl1271_register_hw(struct wl1271 *wl) { int ret; if (wl->mac80211_registered) return 0; SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = ieee80211_register_hw(wl->hw); if (ret < 0) { wl1271_error("unable to register mac80211 hw: %d", ret); return ret; } wl->mac80211_registered = true; wl1271_notice("loaded"); return 0; }
static int ar5523_get_devstatus(struct ar5523 *ar) { u8 macaddr[ETH_ALEN]; int error; /* retrieve MAC address */ error = ar5523_get_status(ar, ST_MAC_ADDR, macaddr, ETH_ALEN); if (error) { ar5523_err(ar, "could not read MAC address\n"); return error; } SET_IEEE80211_PERM_ADDR(ar->hw, macaddr); error = ar5523_get_status(ar, ST_SERIAL_NUMBER, &ar->serial[0], sizeof(ar->serial)); if (error) { ar5523_err(ar, "could not read device serial number\n"); return error; } return 0; }
static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; unsigned int i; /* * Initialize all hw fields. */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = 0; rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; rt2x00dev->hw->queues = 2; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. */ txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); for (i = 0; i < 14; i++) txpower[i] = TXPOWER_FROM_DEV(txpower[i]); /* * Initialize hw_mode information. */ spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; spec->num_channels = ARRAY_SIZE(rf_vals_bg); spec->channels = rf_vals_bg; }
static int __devinit p54u_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct ieee80211_hw *dev; struct p54u_priv *priv; int err; unsigned int i, recognized_pipes; DECLARE_MAC_BUF(mac); dev = p54_init_common(sizeof(*priv)); if (!dev) { printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n"); return -ENOMEM; } priv = dev->priv; SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); priv->udev = udev; usb_get_dev(udev); /* really lazy and simple way of figuring out if we're a 3887 */ /* TODO: should just stick the identification in the device table */ i = intf->altsetting->desc.bNumEndpoints; recognized_pipes = 0; while (i--) { switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) { case P54U_PIPE_DATA: case P54U_PIPE_MGMT: case P54U_PIPE_BRG: case P54U_PIPE_DEV: case P54U_PIPE_DATA | USB_DIR_IN: case P54U_PIPE_MGMT | USB_DIR_IN: case P54U_PIPE_BRG | USB_DIR_IN: case P54U_PIPE_DEV | USB_DIR_IN: case P54U_PIPE_INT | USB_DIR_IN: recognized_pipes++; } } priv->common.open = p54u_open; if (recognized_pipes < P54U_PIPE_NUMBER) { priv->hw_type = P54U_3887; priv->common.tx = p54u_tx_3887; } else { dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); priv->common.tx = p54u_tx_net2280; } priv->common.stop = p54u_stop; if (priv->hw_type) err = p54u_upload_firmware_3887(dev); else err = p54u_upload_firmware_net2280(dev); if (err) goto err_free_dev; err = p54u_read_eeprom(dev); if (err) goto err_free_dev; if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { u8 perm_addr[ETH_ALEN]; printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n"); random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } skb_queue_head_init(&priv->rx_queue); err = ieee80211_register_hw(dev); if (err) { printk(KERN_ERR "prism54usb: Cannot register netdevice\n"); goto err_free_dev; } printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), priv->common.version); return 0; err_free_dev: ieee80211_free_hw(dev); usb_set_intfdata(intf, NULL); usb_put_dev(udev); return err; }
static int __devinit agnx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct ieee80211_hw *dev; struct agnx_priv *priv; int err; err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "can't enable pci device\n"); return err; } err = pci_request_regions(pdev, "agnx-pci"); if (err) { dev_err(&pdev->dev, "can't reserve PCI resources\n"); return err; } if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "no suitable DMA available\n"); err = -EIO; goto err_free_reg; } pci_set_master(pdev); dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops); if (!dev) { dev_err(&pdev->dev, "ieee80211 alloc failed\n"); err = -ENOMEM; goto err_free_reg; } priv = dev->priv; memset(priv, 0, sizeof(*priv)); priv->mode = NL80211_IFTYPE_MONITOR; priv->pdev = pdev; priv->hw = dev; spin_lock_init(&priv->lock); priv->init_status = AGNX_UNINIT; priv->ctl = pci_iomap(pdev, 0, 0); /* dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */ if (!priv->ctl) { dev_err(&pdev->dev, "can't map device memory\n"); err = -ENOMEM; goto err_free_dev; } priv->data = pci_iomap(pdev, 1, 0); if (!priv->data) { dev_err(&pdev->dev, "can't map device memory\n"); err = -ENOMEM; goto err_iounmap2; } pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid); priv->band.channels = (struct ieee80211_channel *)agnx_channels; priv->band.n_channels = ARRAY_SIZE(agnx_channels); priv->band.bitrates = (struct ieee80211_rate *)agnx_rates_80211g; priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g); /* Init ieee802.11 dev */ SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); dev->extra_tx_headroom = sizeof(struct agnx_hdr); /* FIXME It only include FCS in promious mode but not manage mode */ /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */ dev->channel_change_time = 5000; dev->max_signal = 100; /* FIXME */ dev->queues = 1; agnx_get_mac_address(priv); SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr); /* /\* FIXME *\/ */ /* for (i = 1; i < NUM_DRIVE_MODES; i++) { */ /* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */ /* if (err) { */ /* printk(KERN_ERR PFX "Can't register hwmode\n"); */ /* goto err_iounmap; */ /* } */ /* } */ priv->channel = 1; dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; err = ieee80211_register_hw(dev); if (err) { dev_err(&pdev->dev, "can't register hardware\n"); goto err_iounmap; } agnx_hw_reset(priv); dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n", wiphy_name(dev->wiphy), dev->wiphy->perm_addr, priv->revid); return 0; err_iounmap: pci_iounmap(pdev, priv->data); err_iounmap2: pci_iounmap(pdev, priv->ctl); err_free_dev: pci_set_drvdata(pdev, NULL); ieee80211_free_hw(dev); err_free_reg: pci_release_regions(pdev); pci_disable_device(pdev); return err; } /* agnx_pci_probe*/
/** * attach to the WL device. * * Attach to the WL device identified by vendor and device parameters. * regs is a host accessible memory address pointing to WL device registers. * * brcms_attach is not defined as static because in the case where no bus * is defined, wl_attach will never be called, and thus, gcc will issue * a warning that this function is defined but not used if we declare * it as static. * * * is called in brcms_pci_probe() context, therefore no locking required. */ static struct brcms_info *brcms_attach(u16 vendor, u16 device, resource_size_t regs, struct pci_dev *btparam, uint irq) { struct brcms_info *wl = NULL; int unit, err; struct ieee80211_hw *hw; u8 perm[ETH_ALEN]; unit = n_adapters_found; err = 0; if (unit < 0) return NULL; /* allocate private info */ hw = pci_get_drvdata(btparam); /* btparam == pdev */ if (hw != NULL) wl = hw->priv; if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) return NULL; wl->wiphy = hw->wiphy; atomic_set(&wl->callbacks, 0); /* setup the bottom half handler */ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ); if (wl->regsva == NULL) { wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); goto fail; } spin_lock_init(&wl->lock); spin_lock_init(&wl->isr_lock); /* prepare ucode */ if (brcms_request_fw(wl, btparam) < 0) { wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); brcms_release_fw(wl); brcms_remove(btparam); return NULL; } /* common load-time initialization */ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, wl->regsva, btparam, &err); brcms_release_fw(wl); if (!wl->wlc) { wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", KBUILD_MODNAME, err); goto fail; } wl->pub = brcms_c_pub(wl->wlc); wl->pub->ieee_hw = hw; /* disable mpc */ brcms_c_set_radio_mpc(wl->wlc, false); /* register our interrupt handler */ if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); goto fail; } wl->irq = irq; /* register module */ brcms_c_module_register(wl->pub, "linux", wl, NULL); if (ieee_hw_init(hw)) { wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, __func__); goto fail; } memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); if (WARN_ON(!is_valid_ether_addr(perm))) goto fail; SET_IEEE80211_PERM_ADDR(hw, perm); err = ieee80211_register_hw(hw); if (err) wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); if (wl->pub->srom_ccode[0]) err = brcms_set_hint(wl, wl->pub->srom_ccode); else err = brcms_set_hint(wl, "US"); if (err) wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", __func__, err); n_adapters_found++; return wl; fail: brcms_free(wl); return NULL; }
int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates) { struct ieee80211_hw *hw = dev->hw; struct wiphy *wiphy = hw->wiphy; int ret; dev_set_drvdata(dev->dev, dev); INIT_LIST_HEAD(&dev->txwi_cache); SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy->available_antennas_tx = dev->antenna_mask; wiphy->available_antennas_rx = dev->antenna_mask; hw->txq_data_size = sizeof(struct mt76_txq); hw->max_tx_fragments = 16; ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, AMPDU_AGGREGATION); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, TX_FRAG_LIST); ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, AP_LINK_PS); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); wiphy->flags |= WIPHY_FLAG_IBSS_RSN; if (dev->cap.has_2ghz) { ret = mt76_init_sband_2g(dev, rates, n_rates); if (ret) return ret; } if (dev->cap.has_5ghz) { ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht); if (ret) return ret; } wiphy_read_of_freq_limits(dev->hw->wiphy); mt76_check_sband(dev, NL80211_BAND_2GHZ); mt76_check_sband(dev, NL80211_BAND_5GHZ); if (IS_ENABLED(CONFIG_MT76_LEDS)) { ret = mt76_led_init(dev); if (ret) return ret; } return ieee80211_register_hw(hw); }
int mt76_register_device(struct mt76_dev *dev) { struct ieee80211_hw *hw = dev->hw; struct wiphy *wiphy = hw->wiphy; void *status_fifo; int fifo_size; int i, ret; fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76_tx_status)); status_fifo = devm_kzalloc(dev->dev, fifo_size, GFP_KERNEL); if (!status_fifo) return -ENOMEM; kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); ret = mt76_init_hardware(dev); if (ret) return ret; SET_IEEE80211_DEV(hw, dev->dev); hw->queues = 4; hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SUPPORTS_HT_CCK_RATES | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SUPPORTS_RC_TABLE; hw->max_rates = 1; hw->max_report_rates = 7; hw->max_rate_tries = 1; hw->sta_data_size = sizeof(struct mt76_sta); hw->vif_data_size = sizeof(struct mt76_vif); hw->txq_data_size = sizeof(struct mt76_txq); dev->macaddr[0] &= ~BIT(1); SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) { u8 *addr = dev->macaddr_list[i].addr; memcpy(addr, dev->macaddr, ETH_ALEN); if (!i) continue; addr[0] |= BIT(1); addr[0] ^= ((i - 1) << 2); } wiphy->addresses = dev->macaddr_list; wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | #ifdef CONFIG_MAC80211_MESH BIT(NL80211_IFTYPE_MESH_POINT) | #endif BIT(NL80211_IFTYPE_ADHOC); wiphy->iface_combinations = if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); ret = mt76_init_sband_2g(dev); if (ret) goto fail; ret = mt76_init_sband_5g(dev); if (ret) goto fail; INIT_LIST_HEAD(&dev->txwi_cache); INIT_DELAYED_WORK(&dev->cal_work, mt76_phy_calibrate); INIT_DELAYED_WORK(&dev->mac_work, mt76_mac_work); ret = ieee80211_register_hw(hw); if (ret) goto fail; mt76_init_debugfs(dev); return 0; fail: mt76_stop_hardware(dev); return ret; }
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_RC_TABLE | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; if (ath9k_ps_enable) hw->flags |= IEEE80211_HW_SUPPORTS_PS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; if (AR_SREV_9280_20_OR_LATER(ah)) hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_STBC; } if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; if (!config_enabled(CONFIG_ATH9K_TX99)) { hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); hw->wiphy->iface_combinations = if_comb; hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); } hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; #ifdef CONFIG_PM_SLEEP if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && (sc->driver_data & ATH9K_PCI_WOW) && device_can_wakeup(sc->dev)) hw->wiphy->wowlan = &ath9k_wowlan_support; atomic_set(&sc->wow_sleep_proc_intr, -1); atomic_set(&sc->wow_got_bmiss_intr, -1); #endif hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 1; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); hw->extra_tx_headroom = 4; hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; /* single chain devices with rx diversity */ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; ath9k_reload_chainmask_settings(sc); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); }
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); if (AR_SREV_5416(sc->sc_ah)) hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 1; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; /* single chain devices with rx diversity */ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; #ifdef CONFIG_ATH9K_RATE_CONTROL hw->rate_control_algorithm = "ath9k_rate_control"; #endif if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; ath9k_reload_chainmask_settings(sc); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); }
static void _rtl_init_mac80211(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == BAND_ON_BOTH) { sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; } else if (rtlhal->current_bandtype == BAND_ON_5G) { sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); _rtl_init_hw_ht_capab(hw, &sband->ht_cap); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", rtlhal->current_bandtype); } } hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; if (rtlpriv->psc.swctrl_lps) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | 0; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; hw->queues = AC_MAX; hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; hw->channel_change_time = 100; hw->max_listen_interval = 10; hw->max_rate_tries = 4; hw->sta_data_size = sizeof(struct rtl_sta_info); if (is_valid_ether_addr(rtlefuse->dev_addr)) { SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac1); } }
int ath9k_wiphy_add(struct ath_softc *sc) { int i, error; struct ath_wiphy *aphy; struct ieee80211_hw *hw; u8 addr[ETH_ALEN]; hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); if (hw == NULL) return -ENOMEM; spin_lock_bh(&sc->wiphy_lock); for (i = 0; i < sc->num_sec_wiphy; i++) { if (sc->sec_wiphy[i] == NULL) break; } if (i == sc->num_sec_wiphy) { /* No empty slot available; increase array length */ struct ath_wiphy **n; n = krealloc(sc->sec_wiphy, (sc->num_sec_wiphy + 1) * sizeof(struct ath_wiphy *), GFP_ATOMIC); if (n == NULL) { spin_unlock_bh(&sc->wiphy_lock); ieee80211_free_hw(hw); return -ENOMEM; } n[i] = NULL; sc->sec_wiphy = n; sc->num_sec_wiphy++; } SET_IEEE80211_DEV(hw, sc->dev); aphy = hw->priv; aphy->sc = sc; aphy->hw = hw; sc->sec_wiphy[i] = aphy; spin_unlock_bh(&sc->wiphy_lock); memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); addr[0] |= 0x02; /* Locally managed address */ /* * XOR virtual wiphy index into the least significant bits to generate * a different MAC address for each virtual wiphy. */ addr[5] ^= i & 0xff; addr[4] ^= (i & 0xff00) >> 8; addr[3] ^= (i & 0xff0000) >> 16; SET_IEEE80211_PERM_ADDR(hw, addr); ath_set_hw_capab(sc, hw); error = ieee80211_register_hw(hw); if (error == 0) { /* Make sure wiphy scheduler is started (if enabled) */ ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); } return error; }
static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(hw, SPECTRUM_MGMT); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, RX_INCLUDES_FCS); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); if (ath9k_ps_enable) ieee80211_hw_set(hw, SUPPORTS_PS); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { ieee80211_hw_set(hw, AMPDU_AGGREGATION); if (AR_SREV_9280_20_OR_LATER(ah)) hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_STBC; } if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) ieee80211_hw_set(hw, MFP_CAPABLE); hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | NL80211_FEATURE_P2P_GO_CTWIN; if (!IS_ENABLED(CONFIG_ATH9K_TX99)) { hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT) | #ifdef CONFIG_WIRELESS_WDS BIT(NL80211_IFTYPE_WDS) | #endif BIT(NL80211_IFTYPE_OCB); if (ath9k_is_chanctx_enabled()) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); hw->wiphy->iface_combinations = if_comb; hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); } hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->queues = 4; hw->max_rates = 4; hw->max_listen_interval = 10; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); hw->txq_data_size = sizeof(struct ath_atx_tid); hw->extra_tx_headroom = 4; hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; /* single chain devices with rx diversity */ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[NL80211_BAND_2GHZ] = &common->sbands[NL80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[NL80211_BAND_5GHZ] = &common->sbands[NL80211_BAND_5GHZ]; #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT ath9k_set_mcc_capab(sc, hw); #endif ath9k_init_wow(hw); ath9k_cmn_reload_chainmask(ah); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); }
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); hw->wiphy->iface_combinations = &if_comb; hw->wiphy->n_iface_combinations = 1; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; #ifdef CONFIG_PM_SLEEP if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && device_can_wakeup(sc->dev)) { hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT; hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN; hw->wiphy->wowlan.pattern_min_len = 1; hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE; } atomic_set(&sc->wow_sleep_proc_intr, -1); atomic_set(&sc->wow_got_bmiss_intr, -1); #endif hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 1; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; /* single chain devices with rx diversity */ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; ath9k_reload_chainmask_settings(sc); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); }
static void _rtl_init_mac80211(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == BAND_ON_BOTH) { /* 1: 2.4 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; /* 2: 5 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; } else if (rtlhal->current_bandtype == BAND_ON_5G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] * to default value(1T1R) */ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", rtlhal->current_bandtype); } } /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_CONNECTION_MONITOR | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; /* swlps or hwlps has been set in diff chip in init_sw_vars */ if (rtlpriv->psc.swctrl_lps) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ 0; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; hw->queues = AC_MAX; hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; hw->max_listen_interval = 10; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ hw->sta_data_size = sizeof(struct rtl_sta_info); /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac1); } }
/** * attach to the WL device. * * Attach to the WL device identified by vendor and device parameters. * regs is a host accessible memory address pointing to WL device registers. * * wl_attach is not defined as static because in the case where no bus * is defined, wl_attach will never be called, and thus, gcc will issue * a warning that this function is defined but not used if we declare * it as static. * * * is called in wl_pci_probe() context, therefore no locking required. */ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs, uint bustype, void *btparam, uint irq) { struct wl_info *wl = NULL; int unit, err; unsigned long base_addr; struct ieee80211_hw *hw; u8 perm[ETH_ALEN]; unit = wl_found; err = 0; if (unit < 0) { return NULL; } /* allocate private info */ hw = pci_get_drvdata(btparam); /* btparam == pdev */ if (hw != NULL) wl = hw->priv; if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) return NULL; wl->wiphy = hw->wiphy; atomic_set(&wl->callbacks, 0); /* setup the bottom half handler */ tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl); base_addr = regs; if (bustype == PCI_BUS) { wl->piomode = false; } else if (bustype == RPC_BUS) { /* Do nothing */ } else { bustype = PCI_BUS; BCMMSG(wl->wiphy, "force to PCI\n"); } wl->bcm_bustype = bustype; wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ); if (wl->regsva == NULL) { wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); goto fail; } spin_lock_init(&wl->lock); spin_lock_init(&wl->isr_lock); /* prepare ucode */ if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) { wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); wl_release_fw(wl); wl_remove((struct pci_dev *)btparam); return NULL; } /* common load-time initialization */ wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, wl->regsva, wl->bcm_bustype, btparam, &err); wl_release_fw(wl); if (!wl->wlc) { wiphy_err(wl->wiphy, "%s: wlc_attach() failed with code %d\n", KBUILD_MODNAME, err); goto fail; } wl->pub = wlc_pub(wl->wlc); wl->pub->ieee_hw = hw; if (wlc_iovar_setint(wl->wlc, "mpc", 0)) { wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n", unit); } /* register our interrupt handler */ if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); goto fail; } wl->irq = irq; /* register module */ wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL); if (ieee_hw_init(hw)) { wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, __func__); goto fail; } memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); if (WARN_ON(!is_valid_ether_addr(perm))) goto fail; SET_IEEE80211_PERM_ADDR(hw, perm); err = ieee80211_register_hw(hw); if (err) { wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); } if (wl->pub->srom_ccode[0]) err = wl_set_hint(wl, wl->pub->srom_ccode); else err = wl_set_hint(wl, "US"); if (err) { wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", __func__, err); } wl_found++; return wl; fail: wl_free(wl); return NULL; }
struct ieee80211_hw *cw1200_init_common(size_t priv_data_len, u8 *mac_addr) { int i; struct ieee80211_hw *hw; struct cw1200_common *priv; struct ieee80211_supported_band *sband; int band; hw = ieee80211_alloc_hw(priv_data_len, &cw1200_ops); if (!hw) return NULL; priv = hw->priv; priv->hw = hw; priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->rates = cw1200_rates; /* TODO: fetch from FW */ priv->mcs_rates = cw1200_n_rates; /* Enable block ACK for every TID but voice. */ priv->ba_tid_mask = 0x3F; hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_SUPPORTS_CQM_RSSI | /* Aggregation is fully controlled by firmware. * Do not need any support from the mac80211 stack */ /* IEEE80211_HW_AMPDU_AGGREGATION | */ #if defined(CONFIG_CW1200_USE_STE_EXTENSIONS) IEEE80211_HW_SUPPORTS_P2P_PS | IEEE80211_HW_SUPPORTS_CQM_BEACON_MISS | IEEE80211_HW_SUPPORTS_CQM_TX_FAIL | #endif /* CONFIG_CW1200_USE_STE_EXTENSIONS */ IEEE80211_HW_BEACON_FILTER; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); /* Support only for limited wowlan functionalities */ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT; hw->wiphy->wowlan.n_patterns = 0; #if defined(CONFIG_CW1200_USE_STE_EXTENSIONS) hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; #endif /* CONFIG_CW1200_USE_STE_EXTENSIONS */ #if defined(CONFIG_CW1200_DISABLE_BEACON_HINTS) hw->wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; #endif hw->channel_change_time = 1000; /* TODO: find actual value */ /* priv->beacon_req_id = cpu_to_le32(0); */ hw->queues = 4; priv->noise = -94; hw->max_rates = 8; hw->max_rate_tries = 15; hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM + 8 /* TKIP IV */ + 12 /* TKIP ICV and MIC */; hw->sta_data_size = sizeof(struct cw1200_sta_priv); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz; #ifdef CONFIG_CW1200_5GHZ_SUPPORT hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz; #endif /* CONFIG_CW1200_5GHZ_SUPPORT */ /* Channel params have to be cleared before registering wiphy again */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { sband = hw->wiphy->bands[band]; if (!sband) continue; for (i = 0; i < sband->n_channels; i++) { sband->channels[i].flags = 0; sband->channels[i].max_antenna_gain = 0; sband->channels[i].max_power = 30; } } hw->wiphy->max_scan_ssids = 2; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; SET_IEEE80211_PERM_ADDR(hw, mac_addr); if (hw->wiphy->perm_addr[3] == 0 && hw->wiphy->perm_addr[4] == 0 && hw->wiphy->perm_addr[5] == 0) { get_random_bytes(&hw->wiphy->perm_addr[3], 3); } mutex_init(&priv->wsm_cmd_mux); mutex_init(&priv->conf_mutex); priv->workqueue = create_singlethread_workqueue("cw1200_wq"); sema_init(&priv->scan.lock, 1); INIT_WORK(&priv->scan.work, cw1200_scan_work); INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work); INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout); INIT_DELAYED_WORK(&priv->clear_recent_scan_work, cw1200_clear_recent_scan_work); INIT_WORK(&priv->join_work, cw1200_join_work); INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout); INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work); INIT_WORK(&priv->offchannel_work, cw1200_offchannel_work); INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work); INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work); spin_lock_init(&priv->event_queue_lock); INIT_LIST_HEAD(&priv->event_queue); INIT_WORK(&priv->event_handler, cw1200_event_handler); INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work); INIT_DELAYED_WORK(&priv->connection_loss_work, cw1200_connection_loss_work); spin_lock_init(&priv->bss_loss_lock); INIT_WORK(&priv->tx_failure_work, cw1200_tx_failure_work); spin_lock_init(&priv->ps_state_lock); INIT_DELAYED_WORK(&priv->set_cts_work, cw1200_set_cts_work); INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work); INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work); INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work); INIT_WORK(&priv->link_id_work, cw1200_link_id_work); INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work); #if defined(CONFIG_CW1200_USE_STE_EXTENSIONS) INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset); #endif INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work); INIT_WORK(&priv->set_beacon_wakeup_period_work, cw1200_set_beacon_wakeup_period_work); INIT_WORK(&priv->ba_work, cw1200_ba_work); init_timer(&priv->mcast_timeout); priv->mcast_timeout.data = (unsigned long)priv; priv->mcast_timeout.function = cw1200_mcast_timeout; spin_lock_init(&priv->ba_lock); init_timer(&priv->ba_timer); priv->ba_timer.data = (unsigned long)priv; priv->ba_timer.function = cw1200_ba_timer; if (unlikely(cw1200_queue_stats_init(&priv->tx_queue_stats, CW1200_LINK_ID_MAX, cw1200_skb_dtor, priv))) { ieee80211_free_hw(hw); return NULL; } for (i = 0; i < 4; ++i) { if (unlikely(cw1200_queue_init(&priv->tx_queue[i], &priv->tx_queue_stats, i, 16, cw1200_ttl[i]))) { for (; i > 0; i--) cw1200_queue_deinit(&priv->tx_queue[i - 1]); cw1200_queue_stats_deinit(&priv->tx_queue_stats); ieee80211_free_hw(hw); return NULL; } } init_waitqueue_head(&priv->channel_switch_done); init_waitqueue_head(&priv->wsm_cmd_wq); init_waitqueue_head(&priv->wsm_startup_done); wsm_buf_init(&priv->wsm_cmd_buf); spin_lock_init(&priv->wsm_cmd.lock); tx_policy_init(priv); #if defined(CONFIG_CW1200_WSM_DUMPS_SHORT) priv->wsm_dump_max_size = 20; #endif /* CONFIG_CW1200_WSM_DUMPS_SHORT */ return hw; }
static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, const bool have_5ghz) { int i, band; struct ieee80211_hw *hw; struct cw1200_common *priv; hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops); if (!hw) return NULL; priv = hw->priv; priv->hw = hw; priv->hw_type = -1; priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->rates = cw1200_rates; /* TODO: fetch from FW */ priv->mcs_rates = cw1200_n_rates; if (cw1200_ba_rx_tids != -1) priv->ba_rx_tid_mask = cw1200_ba_rx_tids; else priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */ if (cw1200_ba_tx_tids != -1) priv->ba_tx_tid_mask = cw1200_ba_tx_tids; else priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); #ifdef CONFIG_PM hw->wiphy->wowlan = &cw1200_wowlan_support; #endif hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->queues = 4; priv->rts_threshold = -1; hw->max_rates = 8; hw->max_rate_tries = 15; hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM + 8; /* TKIP IV */ hw->sta_data_size = sizeof(struct cw1200_sta_priv); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz; if (have_5ghz) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz; /* Channel params have to be cleared before registering wiphy again */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; if (!sband) continue; for (i = 0; i < sband->n_channels; i++) { sband->channels[i].flags = 0; sband->channels[i].max_antenna_gain = 0; sband->channels[i].max_power = 30; } } hw->wiphy->max_scan_ssids = 2; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; if (macaddr) SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr); else SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template); /* Fix up mac address if necessary */ if (hw->wiphy->perm_addr[3] == 0 && hw->wiphy->perm_addr[4] == 0 && hw->wiphy->perm_addr[5] == 0) { get_random_bytes(&hw->wiphy->perm_addr[3], 3); } mutex_init(&priv->wsm_cmd_mux); mutex_init(&priv->conf_mutex); priv->workqueue = create_singlethread_workqueue("cw1200_wq"); sema_init(&priv->scan.lock, 1); INIT_WORK(&priv->scan.work, cw1200_scan_work); INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work); INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout); INIT_DELAYED_WORK(&priv->clear_recent_scan_work, cw1200_clear_recent_scan_work); INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout); INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work); INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work); INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work); INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work); spin_lock_init(&priv->event_queue_lock); INIT_LIST_HEAD(&priv->event_queue); INIT_WORK(&priv->event_handler, cw1200_event_handler); INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work); INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work); spin_lock_init(&priv->bss_loss_lock); spin_lock_init(&priv->ps_state_lock); INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work); INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work); INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work); INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work); INIT_WORK(&priv->link_id_work, cw1200_link_id_work); INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work); INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset); INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work); INIT_WORK(&priv->set_beacon_wakeup_period_work, cw1200_set_beacon_wakeup_period_work); init_timer(&priv->mcast_timeout); priv->mcast_timeout.data = (unsigned long)priv; priv->mcast_timeout.function = cw1200_mcast_timeout; if (cw1200_queue_stats_init(&priv->tx_queue_stats, CW1200_LINK_ID_MAX, cw1200_skb_dtor, priv)) { ieee80211_free_hw(hw); return NULL; } for (i = 0; i < 4; ++i) { if (cw1200_queue_init(&priv->tx_queue[i], &priv->tx_queue_stats, i, 16, cw1200_ttl[i])) { for (; i > 0; i--) cw1200_queue_deinit(&priv->tx_queue[i - 1]); cw1200_queue_stats_deinit(&priv->tx_queue_stats); ieee80211_free_hw(hw); return NULL; } } init_waitqueue_head(&priv->channel_switch_done); init_waitqueue_head(&priv->wsm_cmd_wq); init_waitqueue_head(&priv->wsm_startup_done); init_waitqueue_head(&priv->ps_mode_switch_done); wsm_buf_init(&priv->wsm_cmd_buf); spin_lock_init(&priv->wsm_cmd.lock); priv->wsm_cmd.done = 1; tx_policy_init(priv); return hw; }
int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; struct eeprom_pda_wrap *wrap; struct pda_entry *entry; unsigned int data_len, entry_len; void *tmp; int err; u8 *end = (u8 *)eeprom + len; u16 synth = 0; u16 crc16 = ~0; wrap = (struct eeprom_pda_wrap *) eeprom; entry = (void *)wrap->data + le16_to_cpu(wrap->len); /* verify that at least the entry length/code fits */ while ((u8 *)entry <= end - sizeof(*entry)) { entry_len = le16_to_cpu(entry->len); data_len = ((entry_len - 1) << 1); /* abort if entry exceeds whole structure */ if ((u8 *)entry + sizeof(*entry) + data_len > end) break; switch (le16_to_cpu(entry->code)) { case PDR_MAC_ADDRESS: if (data_len != ETH_ALEN) break; SET_IEEE80211_PERM_ADDR(dev, entry->data); break; case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: if (priv->output_limit) break; err = p54_convert_output_limits(dev, entry->data, data_len); if (err) goto err; break; case PDR_PRISM_PA_CAL_CURVE_DATA: { struct pda_pa_curve_data *curve_data = (struct pda_pa_curve_data *)entry->data; if (data_len < sizeof(*curve_data)) { err = -EINVAL; goto err; } switch (curve_data->cal_method_rev) { case 0: err = p54_convert_rev0(dev, curve_data); break; case 1: err = p54_convert_rev1(dev, curve_data); break; default: wiphy_err(dev->wiphy, "unknown curve data revision %d\n", curve_data->cal_method_rev); err = -ENODEV; break; } if (err) goto err; } break; case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: priv->iq_autocal = kmemdup(entry->data, data_len, GFP_KERNEL); if (!priv->iq_autocal) { err = -ENOMEM; goto err; } priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); break; case PDR_DEFAULT_COUNTRY: p54_parse_default_country(dev, entry->data, data_len); break; case PDR_INTERFACE_LIST: tmp = entry->data; while ((u8 *)tmp < entry->data + data_len) { struct exp_if *exp_if = tmp; if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000)) synth = le16_to_cpu(exp_if->variant); tmp += sizeof(*exp_if); } break; case PDR_HARDWARE_PLATFORM_COMPONENT_ID: if (data_len < 2) break; priv->version = *(u8 *)(entry->data + 1); break; case PDR_RSSI_LINEAR_APPROXIMATION: case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: err = p54_parse_rssical(dev, entry->data, data_len, le16_to_cpu(entry->code)); if (err) goto err; break; case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: { struct pda_custom_wrapper *pda = (void *) entry->data; __le16 *src; u16 *dst; int i; if (priv->rssi_db || data_len < sizeof(*pda)) break; priv->rssi_db = p54_convert_db(pda, data_len); if (!priv->rssi_db) break; src = (void *) priv->rssi_db->data; dst = (void *) priv->rssi_db->data; for (i = 0; i < priv->rssi_db->entries; i++) *(dst++) = (s16) le16_to_cpu(*(src++)); } break; case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: { struct pda_custom_wrapper *pda = (void *) entry->data; if (priv->output_limit || data_len < sizeof(*pda)) break; priv->output_limit = p54_convert_db(pda, data_len); } break; case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: { struct pda_custom_wrapper *pda = (void *) entry->data; if (priv->curve_data || data_len < sizeof(*pda)) break; priv->curve_data = p54_convert_db(pda, data_len); } break; case PDR_END: crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry)); if (crc16 != le16_to_cpup((__le16 *)entry->data)) { wiphy_err(dev->wiphy, "eeprom failed checksum " "test!\n"); err = -ENOMSG; goto err; } else { goto good_eeprom; } break; default: break; } crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2); entry = (void *)entry + (entry_len + 1) * 2; } wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n"); err = -ENODATA; goto err; good_eeprom: if (!synth || !priv->iq_autocal || !priv->output_limit || !priv->curve_data) { wiphy_err(dev->wiphy, "not all required entries found in eeprom!\n"); err = -EINVAL; goto err; } err = p54_generate_channel_lists(dev); if (err) goto err; priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_2GHZ] = priv->band_table[IEEE80211_BAND_2GHZ]; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_5GHZ] = priv->band_table[IEEE80211_BAND_5GHZ]; if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) priv->rx_diversity_mask = 3; if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) priv->tx_diversity_mask = 3; if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { u8 perm_addr[ETH_ALEN]; wiphy_warn(dev->wiphy, "Invalid hwaddr! Using randomly generated MAC addr\n"); random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } priv->cur_rssi = &p54_rssi_default; wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n", dev->wiphy->perm_addr, priv->version, p54_rf_chips[priv->rxhw]); return 0; err: kfree(priv->iq_autocal); kfree(priv->output_limit); kfree(priv->curve_data); kfree(priv->rssi_db); priv->iq_autocal = NULL; priv->output_limit = NULL; priv->curve_data = NULL; priv->rssi_db = NULL; wiphy_err(dev->wiphy, "eeprom parse failed!\n"); return err; }
static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_RC_TABLE | IEEE80211_HW_QUEUE_CONTROL | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; if (ath9k_ps_enable) hw->flags |= IEEE80211_HW_SUPPORTS_PS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; if (AR_SREV_9280_20_OR_LATER(ah)) hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_STBC; } if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->wiphy->features |= (NL80211_FEATURE_ACTIVE_MONITOR | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE); if (!config_enabled(CONFIG_ATH9K_TX99)) { hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); if (!ath9k_use_chanctx) { hw->wiphy->iface_combinations = if_comb; hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS); } else { hw->wiphy->iface_combinations = if_comb_multi; hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi); hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; hw->wiphy->max_remain_on_channel_duration = 10000; hw->chanctx_data_size = sizeof(void *); hw->extra_beacon_tailroom = sizeof(struct ieee80211_p2p_noa_attr) + 9; } } hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; /* allow 4 queues per channel context + * 1 cab queue + 1 offchannel tx queue */ hw->queues = 10; /* last queue for offchannel */ hw->offchannel_tx_hw_queue = hw->queues - 1; hw->max_rates = 4; hw->max_listen_interval = 10; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; /* single chain devices with rx diversity */ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &common->sbands[IEEE80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &common->sbands[IEEE80211_BAND_5GHZ]; ath9k_init_wow(hw); ath9k_cmn_reload_chainmask(ah); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); }
/** * attach to the WL device. * * Attach to the WL device identified by vendor and device parameters. * regs is a host accessible memory address pointing to WL device registers. * * is called in brcms_bcma_probe() context, therefore no locking required. */ static struct brcms_info *brcms_attach(struct bcma_device *pdev) { struct brcms_info *wl = NULL; int unit, err; struct ieee80211_hw *hw; u8 perm[ETH_ALEN]; unit = n_adapters_found; err = 0; if (unit < 0) return NULL; /* allocate private info */ hw = bcma_get_drvdata(pdev); if (hw != NULL) wl = hw->priv; if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) return NULL; wl->wiphy = hw->wiphy; atomic_set(&wl->callbacks, 0); init_waitqueue_head(&wl->tx_flush_wq); /* setup the bottom half handler */ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); spin_lock_init(&wl->lock); spin_lock_init(&wl->isr_lock); /* common load-time initialization */ wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); if (!wl->wlc) { wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", KBUILD_MODNAME, err); goto fail; } wl->pub = brcms_c_pub(wl->wlc); wl->pub->ieee_hw = hw; /* register our interrupt handler */ if (request_irq(pdev->irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); goto fail; } wl->irq = pdev->irq; /* register module */ brcms_c_module_register(wl->pub, "linux", wl, NULL); if (ieee_hw_init(hw)) { wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, __func__); goto fail; } brcms_c_regd_init(wl->wlc); memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); if (WARN_ON(!is_valid_ether_addr(perm))) goto fail; SET_IEEE80211_PERM_ADDR(hw, perm); err = ieee80211_register_hw(hw); if (err) wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); if (wl->pub->srom_ccode[0] && regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); brcms_debugfs_attach(wl->pub); brcms_debugfs_create_files(wl->pub); n_adapters_found++; return wl; fail: brcms_free(wl); return NULL; }
static int __init init_mac80211_hwsim(void) { int i, err = 0; u8 addr[ETH_ALEN]; struct mac80211_hwsim_data *data; struct ieee80211_hw *hw; DECLARE_MAC_BUF(mac); if (radios < 1 || radios > 65535) return -EINVAL; hwsim_radio_count = radios; hwsim_radios = kcalloc(hwsim_radio_count, sizeof(struct ieee80211_hw *), GFP_KERNEL); if (hwsim_radios == NULL) return -ENOMEM; hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); if (IS_ERR(hwsim_class)) { kfree(hwsim_radios); return PTR_ERR(hwsim_class); } memset(addr, 0, ETH_ALEN); addr[0] = 0x02; for (i = 0; i < hwsim_radio_count; i++) { printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", i); hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); if (hw == NULL) { printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " "failed\n"); err = -ENOMEM; goto failed; } hwsim_radios[i] = hw; data = hw->priv; data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, "hwsim%d", i); if (IS_ERR(data->dev)) { printk(KERN_DEBUG "mac80211_hwsim: device_create_drvdata " "failed (%ld)\n", PTR_ERR(data->dev)); err = -ENOMEM; goto failed_drvdata; } data->dev->driver = &mac80211_hwsim_driver; SET_IEEE80211_DEV(hw, data->dev); addr[3] = i >> 8; addr[4] = i; SET_IEEE80211_PERM_ADDR(hw, addr); hw->channel_change_time = 1; hw->queues = 1; memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); data->band.channels = data->channels; data->band.n_channels = ARRAY_SIZE(hwsim_channels); data->band.bitrates = data->rates; data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; err = ieee80211_register_hw(hw); if (err < 0) { printk(KERN_DEBUG "mac80211_hwsim: " "ieee80211_register_hw failed (%d)\n", err); goto failed_hw; } printk(KERN_DEBUG "%s: hwaddr %s registered\n", wiphy_name(hw->wiphy), print_mac(mac, hw->wiphy->perm_addr)); setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, (unsigned long) hw); } hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); if (hwsim_mon == NULL) goto failed; rtnl_lock(); err = dev_alloc_name(hwsim_mon, hwsim_mon->name); if (err < 0) goto failed_mon; err = register_netdevice(hwsim_mon); if (err < 0) goto failed_mon; rtnl_unlock(); return 0; failed_mon: rtnl_unlock(); free_netdev(hwsim_mon); mac80211_hwsim_free(); return err; failed_hw: device_unregister(data->dev); failed_drvdata: ieee80211_free_hw(hw); hwsim_radios[i] = NULL; failed: mac80211_hwsim_free(); return err; }