示例#1
0
static int
wl_ops_ampdu_action(struct ieee80211_hw *hw,
		    struct ieee80211_vif *vif,
		    enum ieee80211_ampdu_mlme_action action,
		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
		    u8 buf_size)
{
#if defined(BCMDBG)
	struct scb *scb = (struct scb *)sta->drv_priv;
#endif
	struct wl_info *wl = hw->priv;
	int status;

	ASSERT(scb->magic == SCB_MAGIC);
	switch (action) {
	case IEEE80211_AMPDU_RX_START:
		WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
		break;
	case IEEE80211_AMPDU_RX_STOP:
		WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
		break;
	case IEEE80211_AMPDU_TX_START:
		WL_LOCK(wl);
		status = wlc_aggregatable(wl->wlc, tid);
		WL_UNLOCK(wl);
		if (!status) {
			/* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
			return -1;
		}
		/* XXX: Use the starting sequence number provided ... */
		*ssn = 0;
		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
		break;

	case IEEE80211_AMPDU_TX_STOP:
		WL_LOCK(wl);
		wlc_ampdu_flush(wl->wlc, sta, tid);
		WL_UNLOCK(wl);
		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
		break;
	case IEEE80211_AMPDU_TX_OPERATIONAL:
		/* Not sure what to do here */
		/* Power save wakeup */
		WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
			__func__);
		break;
	default:
		WL_ERROR("%s: Invalid command, ignoring\n", __func__);
	}

	return 0;
}
示例#2
0
static int
wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
	       const struct ieee80211_tx_queue_params *params)
{
	struct wl_info *wl = hw->priv;

	WL_NONE("%s: Enter (WME config)\n", __func__);
	WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
		 params->txop, params->cw_min, params->cw_max, params->aifs);

	WL_LOCK(wl);
	wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
	WL_UNLOCK(wl);

	return 0;
}
示例#3
0
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;

	changed_flags &= MAC_FILTERS;
	*total_flags &= MAC_FILTERS;
	if (changed_flags & FIF_PROMISC_IN_BSS)
		WL_ERROR("FIF_PROMISC_IN_BSS\n");
	if (changed_flags & FIF_ALLMULTI)
		WL_ERROR("FIF_ALLMULTI\n");
	if (changed_flags & FIF_FCSFAIL)
		WL_ERROR("FIF_FCSFAIL\n");
	if (changed_flags & FIF_PLCPFAIL)
		WL_ERROR("FIF_PLCPFAIL\n");
	if (changed_flags & FIF_CONTROL)
		WL_ERROR("FIF_CONTROL\n");
	if (changed_flags & FIF_OTHER_BSS)
		WL_ERROR("FIF_OTHER_BSS\n");
	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
		WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
		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;
}
示例#4
0
static int
wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		  struct ieee80211_sta *sta)
{
	WL_NONE("%s: Enter\n", __func__);
	return 0;
}
示例#5
0
static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
{
	struct wl_info *wl = hw->priv;
	WL_NONE("Scan Complete\n");
	WL_LOCK(wl);
	wlc_scan_stop(wl->wlc);
	WL_UNLOCK(wl);
	return;
}
示例#6
0
/*
 * is called in wl_pci_probe() context, therefore no locking required.
 */
static int ieee_hw_rate_init(struct ieee80211_hw *hw)
{
	struct wl_info *wl = HW_TO_WL(hw);
	int has_5g;
	char phy_list[4];

	has_5g = 0;

	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
	hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;

	if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
		WL_ERROR("Phy list failed\n");
	}
	WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);

	if (phy_list[0] == 'n' || phy_list[0] == 'c') {
		if (phy_list[0] == 'c') {
			/* Single stream */
			wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
			wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
		}
		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
	} else {
		BUG();
		return -1;
	}

	/* Assume all bands use the same phy.  True for 11n devices. */
	if (NBANDS_PUB(wl->pub) > 1) {
		has_5g++;
		if (phy_list[0] == 'n' || phy_list[0] == 'c') {
			hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
			    &wl_band_5GHz_nphy;
		} else {
			return -1;
		}
	}

	WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);

	return 0;
}
示例#7
0
static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
{
	struct wl_info *wl = HW_TO_WL(hw);
	bool blocked;

	WL_LOCK(wl);
	blocked = wlc_check_radio_disabled(wl->wlc);
	WL_UNLOCK(wl);

	WL_NONE("wl: rfkill_poll: %d\n", blocked);
	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
}
示例#8
0
static void
wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
{
	WL_NONE("%s: Enter\n", __func__);
	switch (cmd) {
	default:
		WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
		break;
	}
	return;
}
示例#9
0
/* totally bogus -- d11 hdr only + tx hdrs */
static void *
wlc_olpc_get_pkt(wlc_info_t *wlc, uint ac, uint* fifo)
{
    int buflen = (TXOFF + WL_OLPC_PKT_LEN);
    void* p = NULL;
    osl_t *osh = wlc->osh;
    const char* macaddr = NULL;
    struct dot11_header *hdr = NULL;

    if ((p = PKTGET(osh, buflen, TRUE)) == NULL) {
        WL_ERROR(("wl%d: %s: pktget error for len %d \n",
                  wlc->pub->unit, __FUNCTION__, buflen));
        goto fatal;
    }
    macaddr = WLC_MACADDR(wlc);

    WL_NONE(("pkt manip\n"));
    /* reserve TXOFF bytes of headroom */
    PKTPULL(osh, p, TXOFF);
    PKTSETLEN(osh, p, WL_OLPC_PKT_LEN);

    WL_NONE(("d11_hdr\n"));
    hdr = (struct dot11_header*)PKTDATA(osh, p);
    bzero((char*)hdr, WL_OLPC_PKT_LEN);
    hdr->fc = htol16(FC_DATA);
    hdr->durid = 0;
    bcopy((const char*)macaddr, (char*)&(hdr->a1.octet), ETHER_ADDR_LEN);
    bcopy((const char*)macaddr, (char*)&(hdr->a2.octet), ETHER_ADDR_LEN);
    bcopy((const char*)macaddr, (char*)&(hdr->a3.octet), ETHER_ADDR_LEN);
    hdr->seq = 0;
    WL_NONE(("prep raw 80211\n"));
    wlc->olpc_info->tx_cal_pkts = TRUE;
    /* frameid returned here -- ignore for now -- may speed up using this */
    (void)wlc_prep80211_raw(wlc, NULL, ac, TRUE, p, fifo);
    wlc->olpc_info->tx_cal_pkts = FALSE;

    return p;
fatal:
    return (NULL);
}
示例#10
0
/*
 * precondition: perimeter lock has been acquired
 */
bool wl_rfkill_set_hw_state(struct wl_info *wl)
{
	bool blocked = wlc_check_radio_disabled(wl->wlc);

	WL_NONE("%s: update hw state: blocked=%s\n", __func__,
		blocked ? "true" : "false");
	WL_UNLOCK(wl);
	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
	if (blocked)
		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
	WL_LOCK(wl);
	return blocked;
}
示例#11
0
/*
 * Precondition: Since this function is called in wl_pci_probe() context,
 * no locking is required.
 */
static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
{
	int status;
	struct device *device = &pdev->dev;
	char fw_name[100];
	int i;

	memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
	for (i = 0; i < WL_MAX_FW; i++) {
		if (wl_firmwares[i] == NULL)
			break;
		sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
			UCODE_LOADER_API_VER);
		WL_NONE("request fw %s\n", fw_name);
		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
		if (status) {
			WL_ERROR("%s: fail to load firmware %s\n",
				 KBUILD_MODNAME, fw_name);
			return status;
		}
		WL_NONE("request fw %s\n", fw_name);
		sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
			UCODE_LOADER_API_VER);
		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
		if (status) {
			WL_ERROR("%s: fail to load firmware %s\n",
				 KBUILD_MODNAME, fw_name);
			return status;
		}
		wl->fw.hdr_num_entries[i] =
		    wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
		WL_NONE("request fw %s find: %d entries\n",
			fw_name, wl->fw.hdr_num_entries[i]);
	}
	wl->fw.fw_cnt = i;
	return wl_ucode_data_init(wl);
}
示例#12
0
static int
wlc_olpc_eng_recal_ex(wlc_info_t *wlc, uint8 npkts)
{
    int err = BCME_OK;
    wlc_olpc_eng_chan_t* chan_info = wlc->olpc_info->cur_chan;
    if (chan_info) {
        WL_OLPC(wlc->olpc_info, ("%s - send dummies\n", __FUNCTION__));
        err = wlc_olpc_send_dummy_pkts(wlc, chan_info, npkts);
    } else {
        WL_OLPC(wlc->olpc_info,
                ("%s: chan info NULL - no cal\n", __FUNCTION__));
    }
    WL_NONE(("%s - end\n", __FUNCTION__));

    return err;
}
示例#13
0
wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc)
{
	wlc_cm_info_t *wlc_cm;
	char country_abbrev[WLC_CNTRY_BUF_SZ];
	const country_info_t *country;
	struct wlc_pub *pub = wlc->pub;
	char *ccode;

	WL_TRACE("wl%d: wlc_channel_mgr_attach\n", wlc->pub->unit);

	wlc_cm = kzalloc(sizeof(wlc_cm_info_t), GFP_ATOMIC);
	if (wlc_cm == NULL) {
		WL_ERROR("wl%d: %s: out of memory", pub->unit, __func__);
		return NULL;
	}
	wlc_cm->pub = pub;
	wlc_cm->wlc = wlc;
	wlc->cmi = wlc_cm;

	/* store the country code for passing up as a regulatory hint */
	ccode = getvar(wlc->pub->vars, "ccode");
	if (ccode) {
		strncpy(wlc->pub->srom_ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
		WL_NONE("%s: SROM country code is %c%c\n",
			__func__,
			wlc->pub->srom_ccode[0], wlc->pub->srom_ccode[1]);
	}

	/* internal country information which must match regulatory constraints in firmware */
	memset(country_abbrev, 0, WLC_CNTRY_BUF_SZ);
	strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
	country = wlc_country_lookup(wlc, country_abbrev);

	ASSERT(country != NULL);

	/* save default country for exiting 11d regulatory mode */
	strncpy(wlc->country_default, country_abbrev, WLC_CNTRY_BUF_SZ - 1);

	/* initialize autocountry_default to driver default */
	strncpy(wlc->autocountry_default, "X2", WLC_CNTRY_BUF_SZ - 1);

	wlc_set_countrycode(wlc_cm, country_abbrev);

	return wlc_cm;
}
示例#14
0
int
wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
			const char *country_abbrev,
			const char *ccode, int regrev)
{
	const country_info_t *country;
	char mapped_ccode[WLC_CNTRY_BUF_SZ];
	uint mapped_regrev;

	WL_NONE("%s: (country_abbrev \"%s\", ccode \"%s\", regrev %d) SPROM \"%s\"/%u\n",
		__func__, country_abbrev, ccode, regrev,
		wlc_cm->srom_ccode, wlc_cm->srom_regrev);

	/* if regrev is -1, lookup the mapped country code,
	 * otherwise use the ccode and regrev directly
	 */
	if (regrev == -1) {
		/* map the country code to a built-in country code, regrev, and country_info */
		country =
		    wlc_countrycode_map(wlc_cm, ccode, mapped_ccode,
					&mapped_regrev);
	} else {
		/* find the matching built-in country definition */
		ASSERT(0);
		country = wlc_country_lookup_direct(ccode, regrev);
		strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
		mapped_regrev = regrev;
	}

	if (country == NULL)
		return BCME_BADARG;

	/* set the driver state for the country */
	wlc_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
			       mapped_regrev, country);

	return 0;
}
示例#15
0
/* use ppr to find min tgt power (2ss/3ss sdm) in .25dBm units */
static int
wlc_olpc_get_min_tgt_pwr(wlc_olpc_eng_info_t *olpc, chanspec_t channel)
{
    wlc_info_t* wlc = olpc->wlc;
    int cur_min = 0xFFFF;
    wlc_phy_t *pi = wlc->band->pi;
    ppr_t *txpwr;
    ppr_t *srommax;
    int8 min_srom;
    if ((txpwr = ppr_create(wlc->pub->osh, PPR_CHSPEC_BW(channel))) == NULL) {
        return WL_RATE_DISABLED;
    }
    if ((srommax = ppr_create(wlc->pub->osh, PPR_CHSPEC_BW(channel))) == NULL) {
        ppr_delete(wlc->pub->osh, txpwr);
        return WL_RATE_DISABLED;
    }
    /* use the control channel to get the regulatory limits and srom max/min */
    wlc_channel_reg_limits(wlc->cmi, channel, txpwr);

    wlc_phy_txpower_sromlimit(pi, channel, (uint8*)&min_srom, srommax, 0);

    /* bound the regulatory limit by srom min/max */
    ppr_apply_vector_ceiling(txpwr, srommax);

    /* apply min and  then disable powers below min */
    ppr_apply_min(txpwr, min_srom);
    ppr_force_disabled(txpwr, min_srom);

    WL_NONE(("min_srom %d\n", min_srom));

    cur_min = wlc_olpc_get_min_2ss3ss_sdm_pwr(olpc, txpwr, channel);

    ppr_delete(wlc->pub->osh, srommax);
    ppr_delete(wlc->pub->osh, txpwr);

    return (int)(cur_min);
}
示例#16
0
/*
* called from both kernel as from wl_*()
* precondition: perimeter lock is not acquired.
*/
static void wl_remove(struct pci_dev *pdev)
{
	struct wl_info *wl;
	struct ieee80211_hw *hw;
	int status;

	hw = pci_get_drvdata(pdev);
	wl = HW_TO_WL(hw);
	if (!wl) {
		WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
		return;
	}

	WL_LOCK(wl);
	status = wlc_chipmatch(pdev->vendor, pdev->device);
	WL_UNLOCK(wl);
	if (!status) {
		WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
		return;
	}
	if (wl->wlc) {
		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
		ieee80211_unregister_hw(hw);
		WL_LOCK(wl);
		wl_down(wl);
		WL_UNLOCK(wl);
		WL_NONE("%s: Down\n", __func__);
	}
	pci_disable_device(pdev);

	wl_free(wl);

	pci_set_drvdata(pdev, NULL);
	ieee80211_free_hw(hw);
}
示例#17
0
/* process one pkt send complete */
static void
wlc_olpc_eng_pkt_complete(wlc_info_t *wlc, void *pkt, uint txs)
{
    chanspec_t chanspec;

    wlc_olpc_eng_chan_t* olpc_chan = NULL;
    wlc_txh_info_t tx_info;
    int err;
    uint8 coreMask;
    uint8 cidx = 0;

    wlc_get_txh_info(wlc, pkt, &tx_info);

    /* one calibration packet was finished */
    /* look at packet header to find - channel, antenna, etc. */
    chanspec = wlc_txh_get_chanspec(wlc, &tx_info);
    olpc_chan = wlc_olpc_get_chan_ex(wlc, chanspec, &err, FALSE);
    WL_OLPC_ENTRY(wlc->olpc_info, ("%s\n", __FUNCTION__));

    if (!olpc_chan || err != BCME_OK) {
        WL_OLPC_DBG(wlc->olpc_info, ("%s: err: NO-OP chanspec=%x\n",
                                     __FUNCTION__, chanspec));
        return;
    }
    if (olpc_chan->cal_pkts_outstanding) {
        olpc_chan->cal_pkts_outstanding--;
    }
    if (olpc_chan->cores_cal_active == 0) {
        WL_OLPC_DBG(wlc->olpc_info, ("%s: NO-OP (no cal was active) chanspec=%x\n",
                                     __FUNCTION__, chanspec));
        goto pkt_complete_done;
    }

    WL_OLPC_DBG(wlc->olpc_info, ("%s: entry status=%d\n", __FUNCTION__, txs));

    /* get core number */
    coreMask = (tx_info.PhyTxControlWord0 & D11AC_PHY_TXC_CORE_MASK) >>
               (D11AC_PHY_TXC_CORE_SHIFT);
    cidx = WL_OLPC_ANT_TO_CIDX(coreMask);

    WL_OLPC_DBG(wlc->olpc_info, ("%s: coreNum=%x\n", __FUNCTION__, coreMask));

    /* decrement counters */
    if (olpc_chan->pkts_sent[cidx]) {
        olpc_chan->pkts_sent[cidx]--;
    } else {
        WL_NONE(("wl%d: %s: tried decrementing counter of 0, idx=%d\n",
                 wlc->pub->unit, __FUNCTION__, WL_OLPC_ANT_TO_CIDX(coreMask)));
    }
    /* if done on core, update info */
    if (olpc_chan->pkts_sent[cidx] == 0) {
        olpc_chan->cores_cal_active &= ~coreMask;
        olpc_chan->cores_cal |= coreMask;
        olpc_chan->cores_cal_to_cmplt |= coreMask;
#if WL_OLPC_IOVARS_ENAB
        olpc_chan->cores_cal_pkts_sent |= coreMask;
#endif /* WL_OLPC_IOVARS_ENAB */

        WL_OLPC(wlc->olpc_info, ("%s: exit: open loop phy CAL done mask=%x!\n",
                                 __FUNCTION__, coreMask));
        WL_OLPC(wlc->olpc_info, ("%s: exit: open loop phy CAL done done=%x active=%x!\n",
                                 __FUNCTION__, olpc_chan->cores_cal, olpc_chan->cores_cal_active));
    }
#if WL_OLPC_IOVARS_ENAB
    if (olpc_chan->cores_cal == wlc->stf->hw_txchain) {
        WL_OLPC(wlc->olpc_info, ("%s: exit: open loop phy CAL done for all chains!\n",
                                 __FUNCTION__));
    }
#endif /* WLTEST || BCMDBG */
    if (olpc_chan->cores_cal_active == 0) {
        WL_OLPC(wlc->olpc_info, ("%s: no more cores w/ cal active!\n", __FUNCTION__));
        /* cache calibration results so following ops don't mess it up */
#if (defined(PHYCAL_CACHING) || defined(WLMCHAN))
#ifndef WLC_HIGH_ONLY
        if (!wlc_phy_get_chanctx((phy_info_t *)wlc->band->pi, wlc->chanspec))
            wlc_phy_create_chanctx(wlc->band->pi, wlc->chanspec);
#endif /* WLC_HIGH_ONLY */
        wlc_phy_cal_cache((wlc_phy_t *)wlc->band->pi);
#endif /* PHYCAL_CACHING || WLMCHAN */

        /* execute these for now, coz cal is over */
        wlc_olpc_stf_override_revert(wlc);

#ifdef WLTXPWR_CACHE
        wlc_phy_txpwr_cache_invalidate(wlc_phy_get_txpwr_cache(wlc->band->pi));
#endif	/* WLTXPWR_CACHE */
#ifdef WLC_HIGH_ONLY
        wlc_bmac_phy_txpwr_cache_invalidate(wlc->hw);
#endif		/* restore cal cache to what it was prior to doing txpwr limit */
#if (defined(PHYCAL_CACHING) || defined(WLMCHAN))
        if ((err = wlc_phy_cal_cache_return((wlc_phy_t *)wlc->band->pi)) != BCME_OK) {
            WL_ERROR(("wl%d:%s: error from wlc_phy_cal_cache_restore=%d\n",
                      wlc->pub->unit, __FUNCTION__, err));
            /* mark as not calibrated - calibration values hosed */
            olpc_chan->cores_cal = 0;
        }
        if (err == BCME_OK ||
#if WL_OLPC_IOVARS_ENAB
                olpc_chan->dbg_mode ||
#endif /* WL_OLPC_IOVARS_ENAB */
                FALSE) {
            /* inform the phy we are calibrated */
            /* if dbg mode is set, we ignore cal cache errors and tell the phy */
            /* to use dbg storage for cal result */
            wlc_phy_update_olpc_cal((wlc_phy_t *)wlc->band->pi, TRUE,
#if WL_OLPC_IOVARS_ENAB
                                    olpc_chan->dbg_mode);
#else
                                    FALSE);
#endif /* WL_OLPC_IOVARS_ENAB */
        }
示例#18
0
static void
wl_ops_bss_info_changed(struct ieee80211_hw *hw,
			struct ieee80211_vif *vif,
			struct ieee80211_bss_conf *info, u32 changed)
{
	struct wl_info *wl = HW_TO_WL(hw);
	int val;

	if (changed & BSS_CHANGED_ASSOC) {
		/* association status changed (associated/disassociated)
		 * also implies a change in the AID.
		 */
		WL_ERROR("%s: %s: %sassociated\n", KBUILD_MODNAME, __func__,
			 info->assoc ? "" : "dis");
		wlc_associate_upd(wl->wlc, info->assoc);
	}
	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
		/* CTS protection changed */
		WL_ERROR("%s: use_cts_prot: %s (implement)\n", __func__,
			info->use_cts_prot ? "true" : "false");
	}
	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
		/* preamble changed */
		WL_ERROR("%s: short preamble: %s (implement)\n", __func__,
			info->use_short_preamble ? "true" : "false");
	}
	if (changed & BSS_CHANGED_ERP_SLOT) {
		/* slot timing changed */
		if (info->use_short_slot)
			val = 1;
		else
			val = 0;
		WL_LOCK(wl);
		wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
		WL_UNLOCK(wl);
	}

	if (changed & BSS_CHANGED_HT) {
		/* 802.11n parameters changed */
		u16 mode = info->ht_operation_mode;
		WL_NONE("%s: HT mode: 0x%04X\n", __func__, mode);
		wlc_protection_upd(wl->wlc, WLC_PROT_N_CFG,
			mode & IEEE80211_HT_OP_MODE_PROTECTION);
		wlc_protection_upd(wl->wlc, WLC_PROT_N_NONGF,
			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
		wlc_protection_upd(wl->wlc, WLC_PROT_N_OBSS,
			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
	}
	if (changed & BSS_CHANGED_BASIC_RATES) {
		/* Basic rateset changed */
		WL_ERROR("%s: Need to change Basic Rates: 0x%x (implement)\n",
			 __func__, (u32) info->basic_rates);
	}
	if (changed & BSS_CHANGED_BEACON_INT) {
		/* Beacon interval changed */
		WL_NONE("%s: Beacon Interval: %d\n",
			__func__, info->beacon_int);
		wlc_set(wl->wlc, WLC_SET_BCNPRD, info->beacon_int);
	}
	if (changed & BSS_CHANGED_BSSID) {
		/* BSSID changed, for whatever reason (IBSS and managed mode) */
		WL_NONE("%s: new BSSID: aid %d  bss:%pM\n", __func__,
			info->aid, info->bssid);
		WL_LOCK(wl);
		wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
				  info->bssid);
		WL_UNLOCK(wl);
	}
	if (changed & BSS_CHANGED_BEACON) {
		/* Beacon data changed, retrieve new beacon (beaconing modes) */
		WL_ERROR("%s: beacon changed\n", __func__);
	}
	if (changed & BSS_CHANGED_BEACON_ENABLED) {
		/* Beaconing should be enabled/disabled (beaconing modes) */
		WL_ERROR("%s: Beacon enabled: %s\n", __func__,
			 info->enable_beacon ? "true" : "false");
	}
	if (changed & BSS_CHANGED_CQM) {
		/* Connection quality monitor config changed */
		WL_ERROR("%s: cqm change: threshold %d, hys %d (implement)\n",
			__func__, info->cqm_rssi_thold, info->cqm_rssi_hyst);
	}
	if (changed & BSS_CHANGED_IBSS) {
		/* IBSS join status changed */
		WL_ERROR("%s: IBSS joined: %s (implement)\n", __func__,
			info->ibss_joined ? "true" : "false");
	}
	if (changed & BSS_CHANGED_ARP_FILTER) {
		/* Hardware ARP filter address list or state changed */
		WL_ERROR("%s: arp filtering: enabled %s, count %d (implement)\n",
			__func__, info->arp_filter_enabled ? "true" : "false",
			info->arp_addr_cnt);
	}
	if (changed & BSS_CHANGED_QOS) {
		/*
		 * QoS for this association was enabled/disabled.
		 * Note that it is only ever disabled for station mode.
		 */
		WL_ERROR("%s: qos enabled: %s (implement)\n", __func__,
			info->qos ? "true" : "false");
	}
	if (changed & BSS_CHANGED_IDLE) {
		/* Idle changed for this BSS/interface */
		WL_ERROR("%s: BSS idle: %s (implement)\n", __func__,
			info->idle ? "true" : "false");
	}
	return;
}
示例#19
0
/* kick-off open loop phy cal */
static int
wlc_olpc_eng_hdl_chan_update_ex(wlc_info_t *wlc, uint8 npkts, bool force_cal)
{
    int err = BCME_OK;
    chanspec_t cspec = WLC_TO_CHANSPEC(wlc);
    bool olpc_chan = FALSE;
    wlc_olpc_eng_chan_t* chan_info = NULL;
    wlc_olpc_eng_info_t* olpc_info = wlc->olpc_info;

    if (!wlc_olpc_eng_ready(olpc_info)) {
        WL_NONE(("wl%d:%s: olpc module not up\n", wlc->pub->unit, __FUNCTION__));
        return BCME_ERROR;
    }
    WL_OLPC_ENTRY(olpc_info, ("%s\n", __FUNCTION__));

    /* check for any condition that may cause us to terminate our current calibration */
    /* and terminate it if needed */
    wlc_olpc_eng_terminate_cal(wlc);

    /* do nothing if scan or rm is running */
    if (wlc_olpc_in_cal_prohibit_state(wlc)) {
        olpc_info->cur_chan = NULL;
        goto exit;
    }

    olpc_chan = wlc_olpc_chan_needs_olpc(olpc_info, wlc->chanspec);
    WL_OLPC_DBG(olpc_info, ("%s: chan=%x home=%x olpc_chan=%d\n", __FUNCTION__, wlc->chanspec,
                            wlc->home_chanspec, olpc_chan));

    if (olpc_chan) {
        /* phytx ctl word power offset needs to be set */
        chan_info = wlc_olpc_get_chan(wlc, cspec, &err);
        olpc_info->cur_chan = chan_info;

        /* pretend not calibrated */
        if (chan_info && force_cal) {
            olpc_info->cur_chan->cores_cal = 0;
#if WL_OLPC_IOVARS_ENAB
            olpc_info->cur_chan->cores_cal_pkts_sent = 0;
#endif /* WL_OLPC_IOVARS_ENAB */
        }


        /* if null here, there was an out of mem condition */
        if (!chan_info) {
            err = BCME_NOMEM;
            WL_OLPC(olpc_info, ("%s: chan info not found\n", __FUNCTION__));

            goto exit;
        } else if (!wlc_olpc_chan_needs_cal(olpc_info, chan_info)) {
            /* no cal needed */
            WL_OLPC_DBG(olpc_info, ("%s: no cal needed at chan update notify\n",
                                    __FUNCTION__));
            goto exit;
        } else {
            /* cal needed -- limit all rates for now; force implies cfg up on channel */
            if (!force_cal && !wlc_olpc_find_other_up_on_chan(wlc, NULL)) {
                WL_OLPC_DBG(olpc_info, ("%s: NO BSS FOUND UP - exitting\n",
                                        __FUNCTION__));
                /* avoid calibrations when no cfg up, as cal caching not avail */
                goto exit;
            }

            WL_OLPC_DBG(olpc_info, ("%s: calibration needed\n",
                                    __FUNCTION__));
        }
        /* now kick off cal/recal */
        WL_OLPC_DBG(olpc_info, ("%s: calibration needed, starting recal\n", __FUNCTION__));
        err = wlc_olpc_eng_recal_ex(wlc, npkts);
    } else {
        if (olpc_info->cur_chan) {
            wlc_olpc_stf_override_revert(wlc);
            olpc_info->cur_chan = NULL;
        }
    }

exit:
    return err;
}
示例#20
0
/*
 * is called in wl_pci_probe() context, therefore no locking required.
 */
static int wl_set_hint(struct wl_info *wl, char *abbrev)
{
	WL_NONE("%s: Sending country code %c%c to MAC80211\n",
		 __func__, abbrev[0], abbrev[1]);
	return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
}
示例#21
0
static int
wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
{
	WL_NONE("%s: Enter\n", __func__);
	return 0;
}