static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name, char *trigger) { int err; snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name); ar->leds[i].ar = ar; ar->leds[i].l.name = ar->leds[i].name; ar->leds[i].l.brightness_set = carl9170_led_set_brightness; ar->leds[i].l.brightness = 0; ar->leds[i].l.default_trigger = trigger; err = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds[i].l); if (err) { wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", ar->leds[i].name, err); } else { ar->leds[i].registered = true; } return err; }
static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; struct sta_info *sta; int ret; might_sleep(); if (!key || !key->local->ops->set_key) return; assert_key_lock(key->local); if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) return; sta = key->sta; sdata = key->sdata; if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) increment_tailroom_need_count(sdata); ret = drv_set_key(key->local, DISABLE_KEY, sdata, sta ? &sta->sta : NULL, &key->conf); if (ret) wiphy_err(key->local->hw.wiphy, "failed to remove key (%d, %pM) from hardware (%d)\n", key->conf.keyidx, sta ? sta->sta.addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; }
/* * precondition: perimeter lock has been acquired */ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) { int i, entry; const u8 *pdata; struct firmware_hdr *hdr; for (i = 0; i < wl->fw.fw_cnt; i++) { hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; for (entry = 0; entry < wl->fw.hdr_num_entries[i]; entry++, hdr++) { u32 len = le32_to_cpu(hdr->len); if (le32_to_cpu(hdr->idx) == idx) { pdata = wl->fw.fw_bin[i]->data + le32_to_cpu(hdr->offset); *pbuf = kmalloc(len, GFP_ATOMIC); if (*pbuf == NULL) goto fail; memcpy(*pbuf, pdata, len); return 0; } } } wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n", idx); *pbuf = NULL; fail: return -ENODATA; }
/* * CFG802.11 operation handler to join an IBSS. * * This function does not work in any mode other than Ad-Hoc, or if * a join operation is already in progress. */ static int mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); int ret = 0; if (priv->ibss_join_request) return -EBUSY; if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { wiphy_err(wiphy, "request to join ibss received " "when station is not in ibss mode\n"); goto done; } priv->ibss_join_request = -EINPROGRESS; wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", (char *) params->ssid, params->bssid); ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, params->bssid, priv->bss_mode, params->channel, NULL, params->privacy); priv->ibss_join_request = 1; done: priv->ibss_join_result = ret; queue_work(priv->workqueue, &priv->cfg_workqueue); return ret; }
/* * CFG802.11 operation handler for association request. * * This function does not work when the current mode is set to Ad-Hoc, or * when there is already an association procedure going on. The given BSS * information is used to associate. */ static int mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int ret = 0; if (priv->assoc_request) return -EBUSY; if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { wiphy_err(wiphy, "received infra assoc request " "when station is in ibss mode\n"); goto done; } priv->assoc_request = -EINPROGRESS; wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", (char *) sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); priv->assoc_request = 1; done: priv->assoc_result = ret; queue_work(priv->workqueue, &priv->cfg_workqueue); return ret; }
int carl9170_read_mreg(struct ar9170 *ar, const int nregs, const u32 *regs, u32 *out) { int i, err; __le32 *offs, *res; /* abuse "out" for the register offsets, must be same length */ offs = (__le32 *)out; for (i = 0; i < nregs; i++) offs[i] = cpu_to_le32(regs[i]); /* also use the same buffer for the input */ res = (__le32 *)out; err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, 4 * nregs, (u8 *)offs, 4 * nregs, (u8 *)res); if (err) { if (net_ratelimit()) { wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n", err); } return err; } /* convert result to cpu endian */ for (i = 0; i < nregs; i++) out[i] = le32_to_cpu(res[i]); return 0; }
static const struct country_info * brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, char *mapped_ccode, uint *mapped_regrev) { struct brcms_c_info *wlc = wlc_cm->wlc; const struct country_info *country; uint srom_regrev = wlc_cm->srom_regrev; const char *srom_ccode = wlc_cm->srom_ccode; int mapped; /* check for currently supported ccode size */ if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " "match\n", wlc->pub->unit, __func__, ccode); return NULL; } /* default mapping is the given ccode and regrev 0 */ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); *mapped_regrev = 0; /* If the desired country code matches the srom country code, * then the mapped country is the srom regulatory rev. * Otherwise look for an aggregate mapping. */ if (!strcmp(srom_ccode, ccode)) { *mapped_regrev = srom_regrev; mapped = 0; wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); } else { mapped = brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, mapped_regrev); } /* find the matching built-in country definition */ country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); /* if there is not an exact rev match, default to rev zero */ if (country == NULL && *mapped_regrev != 0) { *mapped_regrev = 0; country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); } return country; }
static int p54p_open(struct ieee80211_hw *dev) { struct p54p_priv *priv = dev->priv; int err; init_completion(&priv->boot_comp); err = request_irq(priv->pdev->irq, p54p_interrupt, IRQF_SHARED, "p54pci", dev); if (err) { dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); return err; } memset(priv->ring_control, 0, sizeof(*priv->ring_control)); err = p54p_upload_firmware(dev); if (err) { free_irq(priv->pdev->irq, dev); return err; } priv->rx_idx_data = priv->tx_idx_data = 0; priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data, 0); p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt, 0); P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); P54P_READ(ring_control_base); wmb(); udelay(10); P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); P54P_READ(int_enable); wmb(); udelay(10); P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); P54P_READ(dev_int); if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { wiphy_err(dev->wiphy, "Cannot boot firmware!\n"); p54p_stop(dev); return -ETIMEDOUT; } P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); P54P_READ(int_enable); wmb(); udelay(10); P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); P54P_READ(dev_int); wmb(); udelay(10); return 0; }
static int mwifiex_process_country_ie(struct mwifiex_private *priv, struct cfg80211_bss *bss) { const u8 *country_ie; u8 country_ie_len; struct mwifiex_802_11d_domain_reg *domain_info = &priv->adapter->domain_reg; rcu_read_lock(); country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); if (!country_ie) { rcu_read_unlock(); return 0; } country_ie_len = country_ie[1]; if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { rcu_read_unlock(); return 0; } if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { rcu_read_unlock(); wiphy_dbg(priv->wdev->wiphy, "11D: skip setting domain info in FW\n"); return 0; } memcpy(priv->adapter->country_code, &country_ie[2], 2); domain_info->country_code[0] = country_ie[2]; domain_info->country_code[1] = country_ie[3]; domain_info->country_code[2] = ' '; country_ie_len -= IEEE80211_COUNTRY_STRING_LEN; domain_info->no_of_triplet = country_ie_len / sizeof(struct ieee80211_country_ie_triplet); memcpy((u8 *)domain_info->triplet, &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); rcu_read_unlock(); if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, HostCmd_ACT_GEN_SET, 0, NULL, false)) { wiphy_err(priv->adapter->wiphy, "11D: setting domain info in FW\n"); return -1; } mwifiex_dnld_txpwr_table(priv); return 0; }
static void wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { switch (cmd) { default: wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__, cmd); break; } return; }
/* Update the radio state (enable/disable) and tx power targets * based on a new set of channel/regulatory information */ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) { struct brcms_c_info *wlc = wlc_cm->wlc; uint chan; struct txpwr_limits txpwr; /* search for the existence of any valid channel */ for (chan = 0; chan < MAXCHANNEL; chan++) { if (brcms_c_valid_channel20_db(wlc->cmi, chan)) break; } if (chan == MAXCHANNEL) chan = INVCHANNEL; /* * based on the channel search above, set or * clear WL_RADIO_COUNTRY_DISABLE. */ if (chan == INVCHANNEL) { /* * country/locale with no valid channels, set * the radio disable bit */ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " "nbands %d bandlocked %d\n", wlc->pub->unit, __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, wlc->bandlocked); } else if (mboolisset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE)) { /* * country/locale with valid channel, clear * the radio disable bit */ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); } /* * Now that the country abbreviation is set, if the radio supports 2G, * then set channel 14 restrictions based on the new locale. */ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, brcms_c_japan(wlc) ? true : false); if (wlc->pub->up && chan != INVCHANNEL) { brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr, BRCMS_TXPWR_MAX); wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); } }
static void wl_ops_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast) { struct wl_info *wl = hw->priv; struct wiphy *wiphy = hw->wiphy; changed_flags &= MAC_FILTERS; *total_flags &= MAC_FILTERS; if (changed_flags & FIF_PROMISC_IN_BSS) wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n"); if (changed_flags & FIF_ALLMULTI) wiphy_err(wiphy, "FIF_ALLMULTI\n"); if (changed_flags & FIF_FCSFAIL) wiphy_err(wiphy, "FIF_FCSFAIL\n"); if (changed_flags & FIF_PLCPFAIL) wiphy_err(wiphy, "FIF_PLCPFAIL\n"); if (changed_flags & FIF_CONTROL) wiphy_err(wiphy, "FIF_CONTROL\n"); if (changed_flags & FIF_OTHER_BSS) wiphy_err(wiphy, "FIF_OTHER_BSS\n"); if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { WL_LOCK(wl); if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS; wlc_mac_bcn_promisc_change(wl->wlc, 1); } else { wlc_mac_bcn_promisc_change(wl->wlc, 0); wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS; } WL_UNLOCK(wl); } return; }
/* * CFG802.11 operation handler for association request. * * This function does not work when the current mode is set to Ad-Hoc, or * when there is already an association procedure going on. The given BSS * information is used to associate. */ static int mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int ret = 0; if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { wiphy_err(wiphy, "received infra assoc request " "when station is in ibss mode\n"); goto done; } if (priv->bss_mode == NL80211_IFTYPE_AP) { wiphy_err(wiphy, "skip association request for AP interface\n"); goto done; } wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", (char *) sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); done: if (!ret) { cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, NULL, 0, WLAN_STATUS_SUCCESS, GFP_KERNEL); dev_dbg(priv->adapter->dev, "info: associated to bssid %pM successfully\n", priv->cfg_bssid); } else { dev_dbg(priv->adapter->dev, "info: association to bssid %pM failed\n", priv->cfg_bssid); memset(priv->cfg_bssid, 0, ETH_ALEN); } return ret; }
/* * CFG802.11 operation handler to delete a network key. */ static int mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { wiphy_err(wiphy, "deleting the crypto keys\n"); return -EFAULT; } wiphy_dbg(wiphy, "info: crypto keys deleted\n"); return 0; }
static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct brcms_info *wl = hw->priv; spin_lock_bh(&wl->lock); if (!wl->pub->up) { wiphy_err(wl->wiphy, "ops->tx called while down\n"); kfree_skb(skb); goto done; } brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); done: spin_unlock_bh(&wl->lock); }
static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl_info *wl = hw->priv; WL_LOCK(wl); if (!wl->pub->up) { wiphy_err(wl->wiphy, "ops->tx called while down\n"); kfree_skb(skb); goto done; } wlc_sendpkt_mac80211(wl->wlc, skb, hw); done: WL_UNLOCK(wl); }
/* * CFG802.11 operation handler to set channel. * * This function can only be used when station is not connected. */ static int mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); if (priv->media_connected) { wiphy_err(wiphy, "This setting is valid only when station " "is not connected\n"); return -EINVAL; } return mwifiex_set_rf_channel(priv, chan, channel_type); }
/* * CFG802.11 operation handler to add a network key. */ static int mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); if (mwifiex_set_encode(priv, params->key, params->key_len, key_index, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; } return 0; }
/* * Precondition: Since this function is called in wl_pci_probe() context, * no locking is required. */ int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx) { int i, entry; const u8 *pdata; struct wl_fw_hdr *hdr; for (i = 0; i < wl->fw.fw_cnt; i++) { hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data; for (entry = 0; entry < wl->fw.hdr_num_entries[i]; entry++, hdr++) { if (hdr->idx == idx) { pdata = wl->fw.fw_bin[i]->data + hdr->offset; if (hdr->len != 4) { wiphy_err(wl->wiphy, "ERROR: fw hdr len\n"); return -ENOMSG; } *data = *((u32 *) pdata); return 0; } } } wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx); return -ENOMSG; }
/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate * as well as it's easier to make it periodic * * precondition: perimeter lock has been acquired */ void wl_add_timer(struct wl_info *wl, struct wl_timer *t, uint ms, int periodic) { #ifdef BCMDBG if (t->set) { wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n", __func__, t->name, periodic); } #endif t->ms = ms; t->periodic = (bool) periodic; t->set = true; t->timer.expires = jiffies + ms * HZ / 1000; atomic_inc(&wl->callbacks); add_timer(&t->timer); }
struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, void *wl, void *wlc) { struct phy_shim_info *physhim = NULL; physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC); if (!physhim) { wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_phy_shim_attach: out of mem\n", wlc_hw->unit); return NULL; } physhim->wlc_hw = wlc_hw; physhim->wlc = wlc; physhim->wl = wl; return physhim; }
static int brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct brcms_info *wl = hw->priv; /* Just STA for now */ if (vif->type != NL80211_IFTYPE_STATION) { wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only" " STA for now\n", __func__, vif->type); return -EOPNOTSUPP; } wl->mute_tx = false; brcms_c_mute(wl->wlc, false); return 0; }
static int pcie_tx_ring_alloc_ndp(struct mwl_priv *priv) { struct pcie_priv *pcie_priv = priv->hif.priv; struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp; u8 *mem; mem = dma_alloc_coherent(priv->dev, MAX_NUM_TX_RING_BYTES, &desc->pphys_tx_ring, GFP_KERNEL); if (!mem) goto err_no_mem; desc->ptx_ring = (struct pcie_tx_desc_ndp *)mem; memset(desc->ptx_ring, 0x00, MAX_NUM_TX_RING_BYTES); mem = dma_alloc_coherent(priv->dev, MAX_NUM_TX_RING_DONE_BYTES, &desc->pphys_tx_ring_done, GFP_KERNEL); if (!mem) goto err_no_mem; desc->ptx_ring_done = (struct tx_ring_done *)mem; memset(desc->ptx_ring_done, 0x00, MAX_NUM_TX_RING_DONE_BYTES); mem = dma_alloc_coherent(priv->dev, DEFAULT_ACNT_RING_SIZE, &desc->pphys_acnt_ring, GFP_KERNEL); if (!mem) goto err_no_mem; desc->pacnt_ring = (u8 *)mem; memset(desc->pacnt_ring, 0x00, DEFAULT_ACNT_RING_SIZE); desc->pacnt_buf = kzalloc(DEFAULT_ACNT_RING_SIZE, GFP_KERNEL); if (!desc->pacnt_buf) goto err_no_mem; desc->acnt_ring_size = DEFAULT_ACNT_RING_SIZE; return 0; err_no_mem: wiphy_err(priv->hw->wiphy, "cannot alloc mem\n"); return -ENOMEM; }
/* * adds only the kernel timer since it's going to be more accurate * as well as it's easier to make it periodic * * precondition: perimeter lock has been acquired */ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) { struct ieee80211_hw *hw = t->wl->pub->ieee_hw; #ifdef DEBUG if (t->set) wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", __func__, t->name, periodic); #endif t->ms = ms; t->periodic = (bool) periodic; t->set = true; atomic_inc(&t->wl->callbacks); ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); }
/* * CFG802.11 operation handler to add a network key. */ static int mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const u8 *peer_mac = pairwise ? mac_addr : bc_mac; if (mwifiex_set_encode(priv, params->key, params->key_len, key_index, peer_mac, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; } return 0; }
int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) { const __le32 buf[2] = { cpu_to_le32(reg), cpu_to_le32(val), }; int err; err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf), (u8 *) buf, 0, NULL); if (err) { if (net_ratelimit()) { wiphy_err(ar->hw->wiphy, "writing reg %#x " "(val %#x) failed (%d)\n", reg, val, err); } } return err; }
static void brcms_ops_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { struct brcms_info *wl = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); spin_lock_bh(&wl->lock); if (!wl->pub->up) { wiphy_err(wl->wiphy, "ops->tx called while down\n"); kfree_skb(skb); goto done; } if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw)) tx_info->rate_driver_data[0] = control->sta; done: spin_unlock_bh(&wl->lock); }
/* * CFG802.11 operation handler to set the default network key. */ static int mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool unicast, bool multicast) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); /* Return if WEP key not configured */ if (!priv->sec_info.wep_enabled) return 0; if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { wiphy_err(wiphy, "set default Tx key index\n"); return -EFAULT; } return 0; }
/* * CFG802.11 operation handler to change interface type. */ static int mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { int ret; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); if (priv->bss_mode == type) { wiphy_warn(wiphy, "already set to required type\n"); return 0; } priv->bss_mode = type; switch (type) { case NL80211_IFTYPE_ADHOC: dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); break; case NL80211_IFTYPE_STATION: dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; wiphy_dbg(wiphy, "info: setting interface type to managed\n"); break; case NL80211_IFTYPE_UNSPECIFIED: dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; wiphy_dbg(wiphy, "info: setting interface type to auto\n"); return 0; default: wiphy_err(wiphy, "unknown interface type: %d\n", type); return -EINVAL; } mwifiex_deauthenticate(priv, NULL); priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, HostCmd_ACT_GEN_SET, 0, NULL); return ret; }
static int mwl_tx_ring_init(struct mwl_priv *priv) { int num, i; struct mwl_desc_data *desc; for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { skb_queue_head_init(&priv->txq[num]); priv->fw_desc_cnt[num] = 0; desc = &priv->desc_data[num]; if (desc->ptx_ring) { for (i = 0; i < SYSADPT_MAX_NUM_TX_DESC; i++) { desc->ptx_ring[i].status = cpu_to_le32(EAGLE_TXD_STATUS_IDLE); desc->ptx_ring[i].pphys_next = cpu_to_le32((u32)desc->pphys_tx_ring + ((i + 1) * sizeof(struct mwl_tx_desc))); desc->tx_hndl[i].pdesc = &desc->ptx_ring[i]; if (i < SYSADPT_MAX_NUM_TX_DESC - 1) desc->tx_hndl[i].pnext = &desc->tx_hndl[i + 1]; } desc->ptx_ring[SYSADPT_MAX_NUM_TX_DESC - 1].pphys_next = cpu_to_le32((u32)desc->pphys_tx_ring); desc->tx_hndl[SYSADPT_MAX_NUM_TX_DESC - 1].pnext = &desc->tx_hndl[0]; desc->pstale_tx_hndl = &desc->tx_hndl[0]; desc->pnext_tx_hndl = &desc->tx_hndl[0]; } else { wiphy_err(priv->hw->wiphy, "no valid TX mem\n"); return -ENOMEM; } } return 0; }