Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

Conflicts:
	drivers/net/wireless/rt2x00/rt2x00pci.c
	net/mac80211/sta_info.c
	net/wireless/core.h
This commit is contained in:
John W. Linville 2013-04-10 10:39:27 -04:00
commit d3641409a0
258 changed files with 23464 additions and 3976 deletions

View file

@ -437,7 +437,7 @@
</section>
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
!Finclude/net/mac80211.h ieee80211_beacon_get
!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
!Finclude/net/mac80211.h ieee80211_sta_eosp
!Finclude/net/mac80211.h ieee80211_frame_release_type
!Finclude/net/mac80211.h ieee80211_sta_ps_transition
!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni

View file

@ -25,13 +25,14 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
return value;
}
static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
{
if (cc->capabilities & BCMA_CC_CAP_PMU)
return bcma_pmu_get_alp_clock(cc);
return 20000000;
}
EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
{
@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
return res;
}
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
return res;
}
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
/*
* If the bit is set to 0, chipcommon controlls this GPIO,

View file

@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
struct bcma_bus *bus = cc->core->bus;
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM4716:
case BCMA_CHIP_ID_BCM4748:
case BCMA_CHIP_ID_BCM47162:
case BCMA_CHIP_ID_BCM4313:
case BCMA_CHIP_ID_BCM5357:
case BCMA_CHIP_ID_BCM43224:
case BCMA_CHIP_ID_BCM43225:
case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM4331:
case BCMA_CHIP_ID_BCM43421:
case BCMA_CHIP_ID_BCM43428:
case BCMA_CHIP_ID_BCM43431:
case BCMA_CHIP_ID_BCM4716:
case BCMA_CHIP_ID_BCM47162:
case BCMA_CHIP_ID_BCM4748:
case BCMA_CHIP_ID_BCM4749:
case BCMA_CHIP_ID_BCM5357:
case BCMA_CHIP_ID_BCM53572:
case BCMA_CHIP_ID_BCM6362:
/* always 20Mhz */
return 20000 * 1000;
case BCMA_CHIP_ID_BCM5356:
case BCMA_CHIP_ID_BCM4706:
case BCMA_CHIP_ID_BCM5356:
/* always 25Mhz */
return 25000 * 1000;
case BCMA_CHIP_ID_BCM43460:
case BCMA_CHIP_ID_BCM4352:
case BCMA_CHIP_ID_BCM4360:
if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
return 40000 * 1000;
else
return 20000 * 1000;
default:
bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
@ -373,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
tmp = 1 << 10;
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
break;
case BCMA_CHIP_ID_BCM4331:
@ -394,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
0x03000a08);
}
tmp = 1 << 10;
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
break;
case BCMA_CHIP_ID_BCM43224:
@ -427,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
0x88888815);
}
tmp = 1 << 10;
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
break;
case BCMA_CHIP_ID_BCM4716:
@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
0x88888815);
}
tmp = 3 << 9;
tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
break;
case BCMA_CHIP_ID_BCM43227:
@ -497,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
0x88888815);
}
tmp = 1 << 10;
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
break;
default:
bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",

View file

@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
addr);
}
static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent = readl(*eromptr);
(*eromptr)++;
return ent;
}
static void bcma_erom_push_ent(u32 **eromptr)
static void bcma_erom_push_ent(u32 __iomem **eromptr)
{
(*eromptr)--;
}
static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent = bcma_erom_get_ent(bus, eromptr);
if (!(ent & SCAN_ER_VALID))
@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
return ent;
}
static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent = bcma_erom_get_ent(bus, eromptr);
bcma_erom_push_ent(eromptr);
return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
}
static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent = bcma_erom_get_ent(bus, eromptr);
bcma_erom_push_ent(eromptr);
@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
}
static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent;
while (1) {
@ -189,7 +189,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
bcma_erom_push_ent(eromptr);
}
static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
{
u32 ent = bcma_erom_get_ent(bus, eromptr);
if (!(ent & SCAN_ER_VALID))
@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
return ent;
}
static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
u32 type, u8 port)
{
u32 addrl, addrh, sizel, sizeh = 0;

View file

@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
}
SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
SSB_SPROM4_TXPID2G0_SHIFT);

View file

@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "sd8688_helper.bin",
.firmware = "sd8688.bin",
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
.reg = &btmrvl_reg_8688,
.sd_blksz_fw_dl = 64,
};
@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE("sd8688_helper.bin");
MODULE_FIRMWARE("sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");

View file

@ -1091,7 +1091,7 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static void ar5523_flush(struct ieee80211_hw *hw, bool drop)
static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct ar5523 *ar = hw->priv;

View file

@ -731,7 +731,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in 1ms; noisy environment?\n");
"offset calibration failed to complete in %d ms; noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false;
}
REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
@ -745,7 +746,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in 1ms; noisy environment?\n");
"offset calibration failed to complete in %d ms; noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false;
}
@ -841,7 +843,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in 1ms; noisy environment?\n");
"offset calibration failed to complete in %d ms; noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false;
}

View file

@ -1126,7 +1126,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
ar9003_hw_rtt_disable(ah);
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in 1ms; noisy environment?\n");
"offset calibration failed to complete in %d ms; noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false;
}

View file

@ -2072,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_modal_eeprom);
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
sc->debug.debugfs_phy,
262144, 4, &rfs_spec_scan_cb,
1024, 256, &rfs_spec_scan_cb,
NULL);
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,

View file

@ -193,9 +193,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
DFS_STAT_INC(sc, pulses_processed);
if (pd != NULL && pd->add_pulse(pd, &pe)) {
DFS_STAT_INC(sc, radar_detected);
/*
* TODO: forward radar event to DFS management layer
*/
ieee80211_radar_detected(sc->hw);
}
}
}

View file

@ -105,6 +105,24 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf,
return count;
}
static ssize_t write_file_simulate_radar(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
ieee80211_radar_detected(sc->hw);
return count;
}
static const struct file_operations fops_simulate_radar = {
.write = write_file_simulate_radar,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static const struct file_operations fops_dfs_stats = {
.read = read_file_dfs,
.write = write_file_dfs,
@ -117,4 +135,6 @@ void ath9k_dfs_init_debug(struct ath_softc *sc)
{
debugfs_create_file("dfs_stats", S_IRUSR,
sc->debug.debugfs_phy, sc, &fops_dfs_stats);
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_simulate_radar);
}

View file

@ -2380,8 +2380,11 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
{
switch (ah->hw_version.macVersion) {
/* for temporary testing DFS with 9280 */
case AR_SREV_VERSION_9280:
/* AR9580 will likely be our first target to get testing on */
case AR_SREV_VERSION_9580:
return true;
default:
return false;
}

View file

@ -319,6 +319,10 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
ath9k_ps_wakeup(sc);
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
/* synchronize DFS detector if regulatory domain changed */
if (sc->dfs_detector != NULL)
sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
request->dfs_region);
ath9k_ps_restore(sc);
}
}
@ -727,12 +731,28 @@ static const struct ieee80211_iface_limit if_limits[] = {
BIT(NL80211_IFTYPE_P2P_GO) },
};
static const struct ieee80211_iface_combination if_comb = {
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = 2048,
.num_different_channels = 1,
.beacon_int_infra_match = true,
static const struct ieee80211_iface_limit if_dfs_limits[] = {
{ .max = 1, .types = BIT(NL80211_IFTYPE_AP) },
};
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = 2048,
.num_different_channels = 1,
.beacon_int_infra_match = true,
},
{
.limits = if_dfs_limits,
.n_limits = ARRAY_SIZE(if_dfs_limits),
.max_interfaces = 1,
.num_different_channels = 1,
.beacon_int_infra_match = true,
.radar_detect_widths = BIT(NL80211_CHAN_NO_HT) |
BIT(NL80211_CHAN_HT20),
}
};
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
@ -763,8 +783,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
hw->wiphy->iface_combinations = &if_comb;
hw->wiphy->n_iface_combinations = 1;
hw->wiphy->iface_combinations = if_comb;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
if (AR_SREV_5416(sc->sc_ah))
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;

View file

@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
if (r) {
ath_err(common,
"Unable to reset channel, reset status %d\n", r);
ath9k_hw_enable_interrupts(ah);
ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);
goto out;
}
@ -1245,10 +1249,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (old_pos >= 0)
ath_update_survey_nf(sc, old_pos);
/* perform spectral scan if requested. */
if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN)
ath9k_spectral_scan_trigger(hw);
/*
* Enable radar pulse detection if on a DFS channel. Spectral
* scanning and radar detection can not be used concurrently.
*/
if (hw->conf.radar_enabled) {
u32 rxfilter;
/* set HW specific DFS configuration */
ath9k_hw_set_radar_params(ah);
rxfilter = ath9k_hw_getrxfilter(ah);
rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
ATH9K_RX_FILTER_PHYERR;
ath9k_hw_setrxfilter(ah, rxfilter);
ath_dbg(common, DFS, "DFS enabled at freq %d\n",
curchan->center_freq);
} else {
/* perform spectral scan if requested. */
if (sc->scanning &&
sc->spectral_mode == SPECTRAL_CHANSCAN)
ath9k_spectral_scan_trigger(hw);
}
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
@ -1745,7 +1766,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
mutex_unlock(&sc->mutex);
}
static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;

View file

@ -381,6 +381,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
/* if operating on a DFS channel, enable radar pulse detection */
if (sc->hw->conf.radar_enabled)
rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR;
if (sc->rx.rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
@ -1228,6 +1232,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
rxs->mactime += 0x100000000ULL;
if (rs.rs_phyerr == ATH9K_PHYERR_RADAR)
ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
if (rs.rs_status & ATH9K_RXERR_PHY) {
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
RX_STAT_INC(rx_spectral);

View file

@ -70,12 +70,6 @@
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
enum carl9170_rf_init_mode {
CARL9170_RFI_NONE,
CARL9170_RFI_WARM,
CARL9170_RFI_COLD,
};
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
enum carl9170_device_state {
@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
/* PHY / RF */
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
enum nl80211_channel_type bw);
int carl9170_get_noisefloor(struct ar9170 *ar);
/* FW */

View file

@ -655,7 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
case 'P':
err = carl9170_set_channel(ar, ar->hw->conf.channel,
ar->hw->conf.channel_type, CARL9170_RFI_COLD);
ar->hw->conf.channel_type);
if (err < 0)
count = err;

View file

@ -939,7 +939,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
goto out;
err = carl9170_set_channel(ar, hw->conf.channel,
hw->conf.channel_type, CARL9170_RFI_NONE);
hw->conf.channel_type);
if (err)
goto out;
@ -1703,7 +1703,7 @@ static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
return 0;
}
static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop)
static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct ar9170 *ar = hw->priv;
unsigned int vid;

View file

@ -1569,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
}
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
enum nl80211_channel_type _bw,
enum carl9170_rf_init_mode rfi)
enum nl80211_channel_type _bw)
{
const struct carl9170_phy_freq_params *freqpar;
struct carl9170_rf_init_result rf_res;
struct carl9170_rf_init rf;
u32 cmd, tmp, offs = 0, new_ht = 0;
u32 tmp, offs = 0, new_ht = 0;
int err;
enum carl9170_bw bw;
bool warm_reset;
struct ieee80211_channel *old_channel = NULL;
bw = nl80211_to_carl(_bw);
@ -1592,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
/* may be NULL at first setup */
if (ar->channel) {
old_channel = ar->channel;
warm_reset = (old_channel->band != channel->band) ||
(old_channel->center_freq ==
channel->center_freq) ||
(ar->ht_settings != new_ht);
ar->channel = NULL;
} else {
warm_reset = true;
}
/* HW workaround */
if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
channel->center_freq <= 2417)
warm_reset = true;
/* cold reset BB/ADDA */
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
AR9170_PWR_RESET_BB_COLD_RESET);
if (err)
return err;
if (rfi != CARL9170_RFI_NONE || warm_reset) {
u32 val;
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
if (err)
return err;
if (rfi == CARL9170_RFI_COLD)
val = AR9170_PWR_RESET_BB_COLD_RESET;
else
val = AR9170_PWR_RESET_BB_WARM_RESET;
err = carl9170_init_phy(ar, channel->band);
if (err)
return err;
/* warm/cold reset BB/ADDA */
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
if (err)
return err;
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
if (err)
return err;
err = carl9170_init_phy(ar, channel->band);
if (err)
return err;
err = carl9170_init_rf_banks_0_7(ar,
channel->band == IEEE80211_BAND_5GHZ);
if (err)
return err;
cmd = CARL9170_CMD_RF_INIT;
} else {
cmd = CARL9170_CMD_FREQUENCY;
}
err = carl9170_init_rf_banks_0_7(ar,
channel->band == IEEE80211_BAND_5GHZ);
if (err)
return err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
if (err)
@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return err;
err = carl9170_init_rf_bank4_pwr(ar,
channel->band == IEEE80211_BAND_5GHZ,
channel->center_freq, bw);
channel->band == IEEE80211_BAND_5GHZ,
channel->center_freq, bw);
if (err)
return err;
@ -1703,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
if (rfi != CARL9170_RFI_NONE)
rf.finiteLoopCount = cpu_to_le32(2000);
else
rf.finiteLoopCount = cpu_to_le32(1000);
err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
rf.finiteLoopCount = cpu_to_le32(2000);
err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf,
sizeof(rf_res), &rf_res);
if (err)
return err;
@ -1724,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
old_channel->center_freq : -1, channel->center_freq,
err);
if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
/*
* We have tried very hard to change to _another_
if (ar->chan_fail > 3) {
/* We have tried very hard to change to _another_
* channel and we've failed to do so!
* Chances are that the PHY/RF is no longer
* operable (due to corruptions/fatal events/bugs?)
@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return 0;
}
err = carl9170_set_channel(ar, channel, _bw,
CARL9170_RFI_COLD);
err = carl9170_set_channel(ar, channel, _bw);
if (err)
return err;
} else {

View file

@ -45,7 +45,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
void *ah = common->ah;
if (entry >= common->keymax) {
ath_err(common, "keycache entry %u out of range\n", entry);
ath_err(common, "keyreset: keycache entry %u out of range\n",
entry);
return false;
}
@ -91,7 +92,8 @@ static bool ath_hw_keysetmac(struct ath_common *common,
void *ah = common->ah;
if (entry >= common->keymax) {
ath_err(common, "keycache entry %u out of range\n", entry);
ath_err(common, "keysetmac: keycache entry %u out of range\n",
entry);
return false;
}
@ -133,7 +135,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
u32 keyType;
if (entry >= common->keymax) {
ath_err(common, "keycache entry %u out of range\n", entry);
ath_err(common, "set-entry: keycache entry %u out of range\n",
entry);
return false;
}

View file

@ -285,7 +285,9 @@ enum {
#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
/* SHM_SHARED beacon/AP variables */
#define B43_SHM_SH_BT_BASE0 0x0068 /* Beacon template base 0 */
#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
#define B43_SHM_SH_BT_BASE1 0x0468 /* Beacon template base 1 */
#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */

View file

@ -1310,17 +1310,19 @@ static u32 b43_jssi_read(struct b43_wldev *dev)
{
u32 val = 0;
val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A);
val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1);
val <<= 16;
val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);
val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0);
return val;
}
static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
{
b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF));
b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0,
(jssi & 0x0000FFFF));
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1,
(jssi & 0xFFFF0000) >> 16);
}
static void b43_generate_noise_sample(struct b43_wldev *dev)
@ -1623,7 +1625,7 @@ static void b43_upload_beacon0(struct b43_wldev *dev)
if (wl->beacon0_uploaded)
return;
b43_write_beacon_template(dev, 0x68, 0x18);
b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0);
wl->beacon0_uploaded = true;
}
@ -1633,7 +1635,7 @@ static void b43_upload_beacon1(struct b43_wldev *dev)
if (wl->beacon1_uploaded)
return;
b43_write_beacon_template(dev, 0x468, 0x1A);
b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1);
wl->beacon1_uploaded = true;
}
@ -2780,9 +2782,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
BCMA_CC_GPIOCTL) & ~mask) | set);
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set);
break;
#endif
#ifdef CONFIG_B43_SSB
@ -2807,8 +2807,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
0);
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0);
break;
#endif
#ifdef CONFIG_B43_SSB
@ -3116,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev)
/* Probe Response Timeout value */
/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 0);
/* Initially set the wireless operation mode. */
b43_adjust_opmode(dev);

View file

@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
maxpwr = sprom->maxpwr_bg;
lpphy->max_tx_pwr_med_band = maxpwr;
cckpo = sprom->cck2gpo;
/*
* We don't read SPROM's opo as specs say. On rev8 SPROMs
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
* and SPROM rev below 8.
*/
B43_WARN_ON(sprom->revision < 8);
ofdmpo = sprom->ofdm2gpo;
if (cckpo) {
ofdmpo = sprom->ofdm2gpo;
for (i = 0; i < 4; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
ofdmpo >>= 4;
}
} else {
ofdmpo &= 0xFF;
u8 opo = sprom->opo;
for (i = 0; i < 4; i++)
lpphy->tx_max_rate[i] = maxpwr;
for (i = 4; i < 15; i++)
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
lpphy->tx_max_rate[i] = maxpwr - opo;
}
} else { /* 5GHz */
lpphy->tx_isolation_low_band = sprom->tri5gl;

View file

@ -2789,10 +2789,6 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
* Tx and Rx
**************************************************/
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
}
static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
{//TODO
}
@ -4892,7 +4888,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
int b43_phy_initn(struct b43_wldev *dev)
static int b43_phy_initn(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;

View file

@ -2980,7 +2980,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
.rx = prefix##_rx, \
.rx_length = ARRAY_SIZE(prefix##_rx)
struct b2056_inittabs_pts b2056_inittabs[] = {
static const struct b2056_inittabs_pts b2056_inittabs[] = {
[3] = { INITTABSPTS(b2056_inittab_rev3) },
[4] = { INITTABSPTS(b2056_inittab_rev4) },
[5] = { INITTABSPTS(b2056_inittab_rev5) },
@ -9035,7 +9035,7 @@ static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag)
{
struct b2056_inittabs_pts *pts;
const struct b2056_inittabs_pts *pts;
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
B43_WARN_ON(1);
@ -9057,7 +9057,7 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5)
{
struct b2056_inittabs_pts *pts;
const struct b2056_inittabs_pts *pts;
const struct b2056_inittab_entry *e;
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {

View file

@ -25,12 +25,12 @@ void b43_sdio_exit(void);
#else /* CONFIG_B43_SDIO */
int b43_sdio_request_irq(struct b43_wldev *dev,
static inline int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
return -ENODEV;
}
void b43_sdio_free_irq(struct b43_wldev *dev)
static inline void b43_sdio_free_irq(struct b43_wldev *dev)
{
}
static inline int b43_sdio_init(void)

View file

@ -2800,7 +2800,7 @@ static const struct nphy_rf_control_override_rev7
{ 0x0010, 0x344, 0x345, 0x0010, 4 },
};
struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
{ 10, 14, 19, 27 },
{ -5, 6, 10, 15 },
{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
@ -2811,7 +2811,7 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
0x18, 0x18, 0x18,
0x01D0, 0x5,
};
struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = {
static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = {
{ /* 2GHz */
{ /* PHY rev 3 */
{ 7, 11, 16, 23 },

View file

@ -313,7 +313,7 @@ static const u32 b43_lcntab_0x18[] = {
* TX gain.
**************************************************/
const struct b43_lcntab_tx_gain_tbl_entry
static const struct b43_lcntab_tx_gain_tbl_entry
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
@ -449,7 +449,7 @@ const struct b43_lcntab_tx_gain_tbl_entry
* SW control.
**************************************************/
const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
@ -631,7 +631,7 @@ static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
}
void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
{
u32 i;

View file

@ -65,7 +65,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
u8 data;
unsigned long flags;
brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq);
brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
sdiodev->irq_flags, "brcmf_oob_intr",
@ -102,7 +102,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
brcmf_dbg(SDIO, "Entering\n");
sdio_claim_host(sdiodev->func[1]);
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
@ -136,7 +136,7 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
brcmf_dbg(SDIO, "Entering\n");
sdio_claim_host(sdiodev->func[1]);
sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
@ -148,7 +148,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
brcmf_dbg(SDIO, "Entering\n");
sdio_claim_host(sdiodev->func[1]);
sdio_release_irq(sdiodev->func[2]);
@ -253,9 +253,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
u8 data;
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
brcmf_dbg(INFO, "data:0x%02x\n", data);
brcmf_dbg(SDIO, "data:0x%02x\n", data);
if (ret)
*ret = retval;
@ -268,9 +268,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
u32 data;
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
brcmf_dbg(INFO, "data:0x%08x\n", data);
brcmf_dbg(SDIO, "data:0x%08x\n", data);
if (ret)
*ret = retval;
@ -283,7 +283,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
{
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
if (ret)
@ -295,7 +295,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
{
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
if (ret)
@ -358,7 +358,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint width;
int err = 0;
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
@ -381,7 +381,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint width;
int err = 0;
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
@ -428,7 +428,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
/* Async not implemented yet */
@ -492,13 +492,13 @@ int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
{
char t_func = (char)fn;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
/* issue abort cmd52 command through F0 */
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
SDIO_CCCR_ABORT, &t_func);
brcmf_dbg(TRACE, "Exit\n");
brcmf_dbg(SDIO, "Exit\n");
return 0;
}

View file

@ -139,7 +139,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
{
int err_ret;
brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
if (brcmf_pm_resume_error(sdiodev))
@ -179,7 +179,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
return -EINVAL;
}
brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
rw, func, addr, nbytes);
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
@ -252,7 +252,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
struct sk_buff *pkt;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
if (brcmf_pm_resume_error(sdiodev))
@ -270,7 +270,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
write ? "TX" : "RX", pkt, SGCount, addr,
pkt_len, err_ret);
} else {
brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
write ? "TX" : "RX", pkt, SGCount, addr,
pkt_len);
}
@ -280,7 +280,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
SGCount++;
}
brcmf_dbg(TRACE, "Exit\n");
brcmf_dbg(SDIO, "Exit\n");
return err_ret;
}
@ -295,7 +295,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
uint pkt_len;
bool fifo = (fix_inc == SDIOH_DATA_FIX);
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
if (pkt == NULL)
return -EINVAL;
@ -314,7 +314,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
write ? "TX" : "RX", pkt, addr, pkt_len, status);
} else {
brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n",
brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n",
write ? "TX" : "RX", pkt, addr, pkt_len);
}
@ -350,12 +350,12 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
u32 fbraddr;
u8 func;
brcmf_dbg(TRACE, "\n");
brcmf_dbg(SDIO, "\n");
/* Get the Card's common CIS address */
sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
SDIO_CCCR_CIS);
brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n",
sdiodev->func_cis_ptr[0]);
/* Get the Card's function CIS (for each function) */
@ -363,7 +363,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
sdiodev->func_cis_ptr[func] =
brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n",
func, sdiodev->func_cis_ptr[func]);
}
@ -382,7 +382,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
{
int err_ret = 0;
brcmf_dbg(TRACE, "\n");
brcmf_dbg(SDIO, "\n");
sdiodev->num_funcs = 2;
@ -404,13 +404,13 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
out:
sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Done\n");
brcmf_dbg(SDIO, "Done\n");
return err_ret;
}
void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "\n");
brcmf_dbg(SDIO, "\n");
/* Disable Function 2 */
sdio_claim_host(sdiodev->func[2]);
@ -458,11 +458,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(TRACE, "Class=%x\n", func->class);
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(TRACE, "Function#: %d\n", func->num);
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "Class=%x\n", func->class);
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
/* Consume func num 1 but dont do anything with it. */
if (func->num == 1)
@ -501,13 +501,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
if (err)
goto fail;
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
err = brcmf_sdio_probe(sdiodev);
if (err) {
brcmf_err("F2 error, probe failed %d...\n", err);
goto fail;
}
brcmf_dbg(TRACE, "F2 init completed...\n");
brcmf_dbg(SDIO, "F2 init completed...\n");
return 0;
fail:
@ -523,10 +523,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
struct brcmf_bus *bus_if;
struct brcmf_sdio_dev *sdiodev;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(TRACE, "Function: %d\n", func->num);
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(SDIO, "Function: %d\n", func->num);
if (func->num != 1 && func->num != 2)
return;
@ -543,7 +543,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
kfree(sdiodev);
}
brcmf_dbg(TRACE, "Exit\n");
brcmf_dbg(SDIO, "Exit\n");
}
#ifdef CONFIG_PM_SLEEP
@ -554,7 +554,7 @@ static int brcmf_sdio_suspend(struct device *dev)
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
int ret = 0;
brcmf_dbg(TRACE, "\n");
brcmf_dbg(SDIO, "\n");
atomic_set(&sdiodev->suspend, true);
@ -645,7 +645,7 @@ static struct platform_driver brcmf_sdio_pd = {
void brcmf_sdio_exit(void)
{
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
sdio_unregister_driver(&brcmf_sdmmc_driver);
@ -656,7 +656,7 @@ void brcmf_sdio_init(void)
{
int ret;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
ret = platform_driver_register(&brcmf_sdio_pd);
@ -666,7 +666,7 @@ void brcmf_sdio_init(void)
#else
void brcmf_sdio_exit(void)
{
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
sdio_unregister_driver(&brcmf_sdmmc_driver);
}
@ -675,7 +675,7 @@ void brcmf_sdio_init(void)
{
int ret;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
ret = sdio_register_driver(&brcmf_sdmmc_driver);

View file

@ -72,6 +72,7 @@
#define BRCMF_C_SET_WSEC 134
#define BRCMF_C_GET_PHY_NOISE 135
#define BRCMF_C_GET_BSS_INFO 136
#define BRCMF_C_GET_BANDLIST 140
#define BRCMF_C_SET_SCB_TIMEOUT 158
#define BRCMF_C_GET_PHYLIST 180
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
@ -475,6 +476,11 @@ struct brcmf_sta_info_le {
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
};
struct brcmf_chanspec_list {
__le32 count; /* # of entries */
__le32 element[1]; /* variable length uint32 list */
};
/*
* WLC_E_PROBRESP_MSG
* WLC_E_P2P_PROBREQ_MSG
@ -542,10 +548,25 @@ struct brcmf_if_event {
u8 action;
u8 flags;
u8 bssidx;
u8 role;
};
/* forward declaration */
/* forward declarations */
struct brcmf_cfg80211_vif;
struct brcmf_fws_mac_descriptor;
/**
* enum brcmf_netif_stop_reason - reason for stopping netif queue.
*
* @BRCMF_NETIF_STOP_REASON_FWS_FC:
* netif stopped due to firmware signalling flow control.
* @BRCMF_NETIF_STOP_REASON_BLOCK_BUS:
* netif stopped due to bus blocking.
*/
enum brcmf_netif_stop_reason {
BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2
};
/**
* struct brcmf_if - interface control information.
@ -554,9 +575,13 @@ struct brcmf_cfg80211_vif;
* @vif: points to cfg80211 specific interface information.
* @ndev: associated network device.
* @stats: interface specific network statistics.
* @setmacaddr_work: worker object for setting mac address.
* @multicast_work: worker object for multicast provisioning.
* @fws_desc: interface specific firmware-signalling descriptor.
* @ifidx: interface index in device firmware.
* @bssidx: index of bss associated with this interface.
* @mac_addr: assigned mac address.
* @netif_stop: bitmap indicates reason why netif queues are stopped.
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
* @pend_8021x_wait: used for signalling change in count.
*/
@ -567,9 +592,11 @@ struct brcmf_if {
struct net_device_stats stats;
struct work_struct setmacaddr_work;
struct work_struct multicast_work;
struct brcmf_fws_mac_descriptor *fws_desc;
int ifidx;
s32 bssidx;
u8 mac_addr[ETH_ALEN];
u8 netif_stop;
atomic_t pend_8021x_cnt;
wait_queue_head_t pend_8021x_wait;
};
@ -594,6 +621,10 @@ extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
s32 ifidx, char *name, u8 *mac_addr);
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
bool success);
#endif /* _BRCMF_H_ */

View file

@ -39,10 +39,12 @@ struct brcmf_bus_dcmd {
* @txdata: send a data frame to the dongle (callee disposes skb).
* @txctl: transmit a control request message to dongle.
* @rxctl: receive a control response message from dongle.
* @gettxq: obtain a reference of bus transmit queue (optional).
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
* will assure there is only one active transaction.
* will assure there is only one active transaction. Unless
* indicated otherwise these callbacks are mandatory.
*/
struct brcmf_bus_ops {
int (*init)(struct device *dev);
@ -50,6 +52,7 @@ struct brcmf_bus_ops {
int (*txdata)(struct device *dev, struct sk_buff *skb);
int (*txctl)(struct device *dev, unsigned char *msg, uint len);
int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
struct pktq * (*gettxq)(struct device *dev);
};
/**
@ -115,6 +118,14 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
return bus->ops->rxctl(bus->dev, msg, len);
}
static inline
struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
{
if (!bus->ops->gettxq)
return ERR_PTR(-ENOENT);
return bus->ops->gettxq(bus->dev);
}
/*
* interface functions from common layer
*/

View file

@ -303,8 +303,8 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
brcmf_err("rx data too short (%d < %d)\n",
if (pktbuf->len <= BDC_HEADER_LEN) {
brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
pktbuf->len, BDC_HEADER_LEN);
return -EBADE;
}

View file

@ -130,7 +130,7 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
{
struct brcmf_fws_stats *fwstats = f->private_data;
char buf[100];
char buf[650];
int res;
/* only allow read from start */
@ -138,14 +138,52 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
return 0;
res = scnprintf(buf, sizeof(buf),
"header_pulls: %u\n"
"header_only_pkt: %u\n"
"tlv_parse_failed: %u\n"
"tlv_invalid_type: %u\n",
"header_pulls: %u\n"
"header_only_pkt: %u\n"
"tlv_parse_failed: %u\n"
"tlv_invalid_type: %u\n"
"mac_update_fails: %u\n"
"ps_update_fails: %u\n"
"if_update_fails: %u\n"
"pkt2bus: %u\n"
"generic_error: %u\n"
"rollback_success: %u\n"
"rollback_failed: %u\n"
"delayq_full: %u\n"
"supprq_full: %u\n"
"txs_indicate: %u\n"
"txs_discard: %u\n"
"txs_suppr_core: %u\n"
"txs_suppr_ps: %u\n"
"txs_tossed: %u\n"
"send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
"fifo_credits_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
fwstats->header_pulls,
fwstats->header_only_pkt,
fwstats->tlv_parse_failed,
fwstats->tlv_invalid_type);
fwstats->tlv_invalid_type,
fwstats->mac_update_failed,
fwstats->mac_ps_update_failed,
fwstats->if_update_failed,
fwstats->pkt2bus,
fwstats->generic_error,
fwstats->rollback_success,
fwstats->rollback_failed,
fwstats->delayq_full_error,
fwstats->supprq_full_error,
fwstats->txs_indicate,
fwstats->txs_discard,
fwstats->txs_supp_core,
fwstats->txs_supp_ps,
fwstats->txs_tossed,
fwstats->send_pkts[0], fwstats->send_pkts[1],
fwstats->send_pkts[2], fwstats->send_pkts[3],
fwstats->send_pkts[4],
fwstats->fifo_credits_sent[0],
fwstats->fifo_credits_sent[1],
fwstats->fifo_credits_sent[2],
fwstats->fifo_credits_sent[3],
fwstats->fifo_credits_sent[4]);
return simple_read_from_buffer(data, count, ppos, buf, res);
}

View file

@ -34,6 +34,7 @@
#define BRCMF_SCAN_VAL 0x00004000
#define BRCMF_CONN_VAL 0x00008000
#define BRCMF_CDC_VAL 0x00010000
#define BRCMF_SDIO_VAL 0x00020000
/* set default print format */
#undef pr_fmt
@ -92,6 +93,7 @@ do { \
#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \
do { \
trace_brcmf_hexdump((void *)data, len); \
if (test) \
brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \
} while (0)
@ -137,6 +139,25 @@ struct brcmf_fws_stats {
u32 tlv_invalid_type;
u32 header_only_pkt;
u32 header_pulls;
u32 pkt2bus;
u32 send_pkts[5];
u32 fifo_credits_sent[5];
u32 fifo_credits_back[6];
u32 generic_error;
u32 mac_update_failed;
u32 mac_ps_update_failed;
u32 if_update_failed;
u32 packet_request_failed;
u32 credit_request_failed;
u32 rollback_success;
u32 rollback_failed;
u32 delayq_full_error;
u32 supprq_full_error;
u32 txs_indicate;
u32 txs_discard;
u32 txs_supp_core;
u32 txs_supp_ps;
u32 txs_tossed;
};
struct brcmf_pub;

View file

@ -223,18 +223,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}
/* handle ethernet header */
eh = (struct ethhdr *)(skb->data);
if (is_multicast_ether_addr(eh->h_dest))
drvr->tx_multicast++;
if (ntohs(eh->h_proto) == ETH_P_PAE)
atomic_inc(&ifp->pend_8021x_cnt);
/* If the protocol uses a data header, apply it */
brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
/* Use bus module to send data frame */
ret = brcmf_bus_txdata(drvr->bus_if, skb);
ret = brcmf_fws_process_skb(ifp, skb);
done:
if (ret) {
@ -248,9 +237,27 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state)
{
if (!ifp)
return;
brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
ifp->bssidx, ifp->netif_stop, reason, state);
if (state) {
if (!ifp->netif_stop)
netif_stop_queue(ifp->ndev);
ifp->netif_stop |= reason;
} else {
ifp->netif_stop &= ~reason;
if (!ifp->netif_stop)
netif_wake_queue(ifp->ndev);
}
}
void brcmf_txflowblock(struct device *dev, bool state)
{
struct net_device *ndev;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
int i;
@ -258,13 +265,8 @@ void brcmf_txflowblock(struct device *dev, bool state)
brcmf_dbg(TRACE, "Enter\n");
for (i = 0; i < BRCMF_MAX_IFS; i++)
if (drvr->iflist[i]) {
ndev = drvr->iflist[i]->ndev;
if (state)
netif_stop_queue(ndev);
else
netif_wake_queue(ndev);
}
brcmf_txflowblock_if(drvr->iflist[i],
BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
}
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
@ -321,13 +323,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
/* Strip header, count, deliver upward */
skb_pull(skb, ETH_HLEN);
/* Process special event packets and then discard them */
brcmf_fweh_process_skb(drvr, skb, &ifidx);
if (drvr->iflist[ifidx]) {
ifp = drvr->iflist[ifidx];
ifp->ndev->last_rx = jiffies;
}
/* Process special event packets */
brcmf_fweh_process_skb(drvr, skb);
if (!(ifp->ndev->flags & IFF_UP)) {
brcmu_pkt_buf_free_skb(skb);
@ -350,14 +347,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
}
}
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
bool success)
{
u8 ifidx;
struct ethhdr *eh;
u16 type;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
struct brcmf_if *ifp;
struct ethhdr *eh;
u8 ifidx;
u16 type;
int res;
res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
@ -378,11 +374,24 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
}
if (!success)
ifp->stats.tx_errors++;
done:
brcmu_pkt_buf_free_skb(txp);
}
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
/* await txstatus signal for firmware if active */
if (brcmf_fws_fc_active(drvr->fws)) {
if (!success)
brcmf_fws_bustxfail(drvr->fws, txp);
} else {
brcmf_txfinalize(drvr, txp, success);
}
}
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
@ -741,28 +750,35 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
}
}
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
if (!ndev) {
brcmf_err("OOM - alloc_netdev\n");
return ERR_PTR(-ENOMEM);
if (!brcmf_p2p_enable && bssidx == 1) {
/* this is P2P_DEVICE interface */
brcmf_dbg(INFO, "allocate non-netdev interface\n");
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
} else {
brcmf_dbg(INFO, "allocate netdev interface\n");
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
if (!ndev) {
brcmf_err("OOM - alloc_netdev\n");
return ERR_PTR(-ENOMEM);
}
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
}
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
ifp->drvr = drvr;
drvr->iflist[bssidx] = ifp;
ifp->ifidx = ifidx;
ifp->bssidx = bssidx;
init_waitqueue_head(&ifp->pend_8021x_wait);
if (mac_addr != NULL)
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
current->pid, ifp->ndev->name, ifp->mac_addr);
current->pid, name, ifp->mac_addr);
return ifp;
}
@ -794,11 +810,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
}
unregister_netdev(ifp->ndev);
drvr->iflist[bssidx] = NULL;
if (bssidx == 0)
brcmf_cfg80211_detach(drvr->config);
free_netdev(ifp->ndev);
} else {
kfree(ifp);
}
drvr->iflist[bssidx] = NULL;
}
int brcmf_attach(uint bus_hdrlen, struct device *dev)
@ -882,6 +900,7 @@ int brcmf_bus_start(struct device *dev)
drvr->fw_signals = true;
(void)brcmf_fws_init(drvr);
brcmf_fws_add_interface(ifp);
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
if (drvr->config == NULL) {
@ -899,8 +918,10 @@ int brcmf_bus_start(struct device *dev)
brcmf_err("failed: %d\n", ret);
if (drvr->config)
brcmf_cfg80211_detach(drvr->config);
if (drvr->fws)
if (drvr->fws) {
brcmf_fws_del_interface(ifp);
brcmf_fws_deinit(drvr);
}
free_netdev(ifp->ndev);
drvr->iflist[0] = NULL;
if (p2p_ifp) {
@ -956,16 +977,17 @@ void brcmf_detach(struct device *dev)
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
if (drvr->iflist[i])
if (drvr->iflist[i]) {
brcmf_fws_del_interface(drvr->iflist[i]);
brcmf_del_if(drvr, i);
}
brcmf_bus_detach(drvr);
if (drvr->prot)
brcmf_proto_detach(drvr);
if (drvr->fws)
brcmf_fws_deinit(drvr);
brcmf_fws_deinit(drvr);
brcmf_debugfs_detach(drvr);
bus_if->drvr = NULL;

View file

@ -94,6 +94,7 @@ struct rte_console {
#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "tracepoint.h"
#define TXQLEN 2048 /* bulk tx queue length */
#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
@ -675,7 +676,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
u8 clkctl, clkreq, devctl;
unsigned long timeout;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
clkctl = 0;
@ -713,7 +714,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
devctl, &err);
brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
bus->clkstate = CLK_PENDING;
return 0;
@ -750,7 +751,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
/* Mark clock available */
bus->clkstate = CLK_AVAIL;
brcmf_dbg(INFO, "CLKCTL: turned ON\n");
brcmf_dbg(SDIO, "CLKCTL: turned ON\n");
#if defined(DEBUG)
if (!bus->alp_only) {
@ -775,7 +776,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
bus->clkstate = CLK_SDONLY;
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
clkreq, &err);
brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
if (err) {
brcmf_err("Failed access turning clock off: %d\n",
err);
@ -788,7 +789,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
/* Change idle/active SD state */
static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
{
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
if (on)
bus->clkstate = CLK_SDONLY;
@ -805,7 +806,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
uint oldstate = bus->clkstate;
#endif /* DEBUG */
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
/* Early exit if we're already there */
if (bus->clkstate == target) {
@ -849,7 +850,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
break;
}
#ifdef DEBUG
brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate);
#endif /* DEBUG */
return 0;
@ -862,7 +863,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
u8 fcbits;
int ret;
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(SDIO, "Enter\n");
/* Read mailbox data and ack that we did so */
ret = r_sdreg32(bus, &hmb_data,
@ -875,7 +876,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
/* Dongle recomposed rx frames, accept them again */
if (hmb_data & HMB_DATA_NAKHANDLED) {
brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
bus->rx_seq);
if (!bus->rxskip)
brcmf_err("unexpected NAKHANDLED!\n");
@ -896,7 +897,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
"expecting %d\n",
bus->sdpcm_ver, SDPCM_PROT_VERSION);
else
brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
bus->sdpcm_ver);
}
@ -970,7 +971,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
if (!retries)
brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
else
brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries);
if (rtx) {
bus->sdcnt.rxrtx++;
@ -1173,7 +1174,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
/* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */
brcmf_dbg(TRACE, "start: glomd %p glom %p\n",
brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
bus->glomd, skb_peek(&bus->glom));
/* If there's a descriptor, generate the packet chain */
@ -1781,7 +1782,6 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
u8 *frame;
u16 len, pad = 0;
u32 swheader;
struct sk_buff *new;
int i;
brcmf_dbg(TRACE, "Enter\n");
@ -1795,27 +1795,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
skb_headroom(pkt), pad);
bus->sdiodev->bus_if->tx_realloc++;
new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
if (!new) {
brcmf_err("couldn't allocate new %d-byte packet\n",
pkt->len + BRCMF_SDALIGN);
ret = -ENOMEM;
ret = skb_cow(pkt, BRCMF_SDALIGN);
if (ret)
goto done;
}
pkt_align(new, pkt->len, BRCMF_SDALIGN);
memcpy(new->data, pkt->data, pkt->len);
brcmu_pkt_buf_free_skb(pkt);
pkt = new;
frame = (u8 *) (pkt->data);
/* precondition: (frame % BRCMF_SDALIGN) == 0) */
pad = 0;
} else {
skb_push(pkt, pad);
frame = (u8 *) (pkt->data);
/* precondition: pad + SDPCM_HDRLEN <= pkt->len */
memset(frame, 0, pad + SDPCM_HDRLEN);
pad = ((unsigned long)frame % BRCMF_SDALIGN);
}
skb_push(pkt, pad);
frame = (u8 *) (pkt->data);
memset(frame, 0, pad + SDPCM_HDRLEN);
}
/* precondition: pad < BRCMF_SDALIGN */
@ -1830,8 +1817,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
(((pad +
SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
*(((__le32 *) frame) + 1) = cpu_to_le32(swheader);
*(((__le32 *) frame) + 2) = 0;
#ifdef DEBUG
tx_packets[pkt->priority]++;
@ -1897,7 +1884,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
done:
/* restore pkt buffer pointer before calling tx complete routine */
skb_pull(pkt, SDPCM_HDRLEN + pad);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
return ret;
}
@ -2131,7 +2118,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
devctl, clkctl);
if (SBSDIO_HTAV(clkctl)) {
@ -2307,6 +2294,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
}
static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
return &bus->txq;
}
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
{
int ret = -EBADE;
@ -2392,7 +2388,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
/* Do the transfer(s) */
while (size) {
brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
write ? "write" : "read", dsize,
sdaddr, address & SBSDIO_SBWINDOW_MASK);
bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
@ -2625,10 +2621,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
msecs_to_jiffies(2000));
if (!bus->ctrl_frame_stat) {
brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
ret = 0;
} else {
brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
ret = -1;
}
}
@ -2699,7 +2695,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
addr = le32_to_cpu(addr_le);
brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
/*
* Check if addr is valid.
@ -2726,8 +2722,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
sh->console_addr = le32_to_cpu(sh_le.console_addr);
sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n",
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
SDPCM_SHARED_VERSION,
sh->flags & SDPCM_SHARED_VERSION_MASK);
return -EPROTO;
@ -2809,21 +2805,18 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
int error, res;
char buf[350];
struct brcmf_trap_info tr;
int nbytes;
loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
brcmf_dbg(INFO, "no trap in firmware\n");
return 0;
}
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
if (nbytes < 0)
return nbytes;
res = scnprintf(buf, sizeof(buf),
"dongle trap info: type 0x%x @ epc 0x%08x\n"
" cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
@ -2839,12 +2832,7 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res);
if (error < 0)
return error;
nbytes += error;
return nbytes;
return simple_read_from_buffer(data, count, &pos, buf, res);
}
static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
@ -2926,14 +2914,20 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
error = brcmf_sdio_assert_info(bus, &sh, data, count);
if (error < 0)
goto done;
nbytes = error;
error = brcmf_sdio_trap_info(bus, &sh, data, count);
error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
if (error < 0)
goto done;
nbytes += error;
error += nbytes;
*ppos += error;
error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
if (error < 0)
goto done;
nbytes += error;
error = nbytes;
*ppos += nbytes;
done:
return error;
}
@ -3309,15 +3303,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
goto err;
}
/* External image takes precedence if specified */
if (brcmf_sdbrcm_download_code_file(bus)) {
brcmf_err("dongle image file download failed\n");
goto err;
}
/* External nvram takes precedence if specified */
if (brcmf_sdbrcm_download_nvram(bus))
if (brcmf_sdbrcm_download_nvram(bus)) {
brcmf_err("dongle nvram file download failed\n");
goto err;
}
/* Take arm out of reset */
if (brcmf_sdbrcm_download_state(bus, false)) {
@ -3848,6 +3842,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.txdata = brcmf_sdbrcm_bus_txdata,
.txctl = brcmf_sdbrcm_bus_txctl,
.rxctl = brcmf_sdbrcm_bus_rxctl,
.gettxq = brcmf_sdbrcm_bus_gettxq,
};
void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)

View file

@ -20,6 +20,8 @@
#include "dhd.h"
#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwsignal.h"
#include "fweh.h"
#include "fwil.h"
@ -154,7 +156,7 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
fweh = &ifp->drvr->fweh;
/* handle the event if valid interface and handler */
if (ifp->ndev && fweh->evt_handler[code])
if (fweh->evt_handler[code])
err = fweh->evt_handler[code](ifp, emsg, data);
else
brcmf_err("unhandled event %d ignored\n", code);
@ -179,9 +181,9 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
struct brcmf_if *ifp;
int err = 0;
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n",
ifevent->action, ifevent->ifidx,
ifevent->bssidx, ifevent->flags);
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
ifevent->action, ifevent->ifidx, ifevent->bssidx,
ifevent->flags, ifevent->role);
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
brcmf_err("invalid interface index: %u\n",
@ -198,15 +200,20 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
emsg->ifname, emsg->addr);
if (IS_ERR(ifp))
return;
brcmf_fws_add_interface(ifp);
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
err = brcmf_net_attach(ifp, false);
}
if (ifevent->action == BRCMF_E_IF_CHANGE)
brcmf_fws_reset_interface(ifp);
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
if (ifevent->action == BRCMF_E_IF_DEL)
if (ifevent->action == BRCMF_E_IF_DEL) {
brcmf_fws_del_interface(ifp);
brcmf_del_if(drvr, ifevent->bssidx);
}
}
/**
@ -400,13 +407,12 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
*
* @drvr: driver information object.
* @event_packet: event packet to process.
* @ifidx: index of the firmware interface (may change).
*
* If the packet buffer contains a firmware event message it will
* dispatch the event to a registered handler (using worker).
*/
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
struct brcmf_event *event_packet, u8 *ifidx)
struct brcmf_event *event_packet)
{
enum brcmf_fweh_event_code code;
struct brcmf_fweh_info *fweh = &drvr->fweh;
@ -418,7 +424,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
/* get event info */
code = get_unaligned_be32(&event_packet->msg.event_type);
datalen = get_unaligned_be32(&event_packet->msg.datalen);
*ifidx = event_packet->msg.ifidx;
data = &event_packet[1];
if (code >= BRCMF_E_LAST)
@ -435,7 +440,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
return;
event->code = code;
event->ifidx = *ifidx;
event->ifidx = event_packet->msg.ifidx;
/* use memcpy to get aligned event message */
memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));

View file

@ -187,10 +187,10 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr,
enum brcmf_fweh_event_code code);
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
struct brcmf_event *event_packet, u8 *ifidx);
struct brcmf_event *event_packet);
static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
struct sk_buff *skb, u8 *ifidx)
struct sk_buff *skb)
{
struct brcmf_event *event_packet;
u8 *data;
@ -213,7 +213,7 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
return;
brcmf_fweh_process_event(drvr, event_packet, ifidx);
brcmf_fweh_process_event(drvr, event_packet);
}
#endif /* FWEH_H_ */

View file

@ -25,6 +25,7 @@
#include "dhd.h"
#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwil.h"

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,14 @@
int brcmf_fws_init(struct brcmf_pub *drvr);
void brcmf_fws_deinit(struct brcmf_pub *drvr);
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
struct sk_buff *skb);
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_fws_reset_interface(struct brcmf_if *ifp);
void brcmf_fws_add_interface(struct brcmf_if *ifp);
void brcmf_fws_del_interface(struct brcmf_if *ifp);
void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
#endif /* FWSIGNAL_H_ */

View file

@ -15,6 +15,7 @@
*/
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/cfg80211.h>
#include <brcmu_wifi.h>
@ -455,7 +456,9 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
{
s32 ret = 0;
brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
brcmf_fil_iovar_int_set(ifp, "apsta", 1);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
/* In case of COB type, firmware has default mac address
* After Initializing firmware, we have to set current mac address to
@ -473,28 +476,35 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
* brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P.
*
* @p2p: P2P specific data.
* @dev_addr: optional device address.
*
* P2P needs mac addresses for P2P device and interface. These are
* derived from the primary net device, ie. the permanent ethernet
* address of the device.
* P2P needs mac addresses for P2P device and interface. If no device
* address it specified, these are derived from the primary net device, ie.
* the permanent ethernet address of the device.
*/
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p)
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
{
struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp;
bool local_admin = false;
if (!dev_addr || is_zero_ether_addr(dev_addr)) {
dev_addr = pri_ifp->mac_addr;
local_admin = true;
}
/* Generate the P2P Device Address. This consists of the device's
* primary MAC address with the locally administered bit set.
*/
memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN);
p2p->dev_addr[0] |= 0x02;
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
if (local_admin)
p2p->dev_addr[0] |= 0x02;
/* Generate the P2P Interface Address. If the discovery and connection
* BSSCFGs need to simultaneously co-exist, then this address must be
* different from the P2P Device Address, but also locally administered.
*/
memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
p2p->int_addr[0] |= 0x02;
p2p->int_addr[4] ^= 0x80;
}
@ -773,7 +783,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
* validates the channels in the request.
*/
static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
struct brcmf_if *ifp,
struct cfg80211_scan_request *request,
u16 action)
{
@ -1261,7 +1271,7 @@ static void
brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct net_device *ndev = cfg->escan_info.ndev;
struct brcmf_if *ifp = cfg->escan_info.ifp;
if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
(test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) ||
@ -1271,12 +1281,12 @@ brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
* So abort scan for off channel completion.
*/
if (p2p->af_sent_channel)
brcmf_notify_escan_complete(cfg, ndev, true, true);
brcmf_notify_escan_complete(cfg, ifp, true, true);
} else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
&p2p->status)) {
brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n");
/* So abort scan to cancel listen */
brcmf_notify_escan_complete(cfg, ndev, true, true);
brcmf_notify_escan_complete(cfg, ifp, true, true);
}
}
@ -1384,7 +1394,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
/* After complete GO Negotiation, roll back to mpc mode */
if ((action == P2P_PAF_GON_CONF) ||
(action == P2P_PAF_PROVDIS_RSP))
brcmf_set_mpc(ifp->ndev, 1);
brcmf_set_mpc(ifp, 1);
if (action == P2P_PAF_GON_CONF) {
brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n");
clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
@ -1421,7 +1431,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
CHSPEC_IS2G(chanspec) ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
wdev = ifp->ndev->ieee80211_ptr;
wdev = &ifp->vif->wdev;
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
GFP_ATOMIC);
@ -1637,6 +1648,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
struct brcmf_fil_af_params_le *af_params)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_fil_action_frame_le *action_frame;
struct brcmf_config_af_params config_af_params;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
@ -1725,7 +1737,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
/* To make sure to send successfully action frame, turn off mpc */
if (config_af_params.mpc_onoff == 0)
brcmf_set_mpc(ndev, 0);
brcmf_set_mpc(ifp, 0);
/* set status and destination address before sending af */
if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
@ -1753,7 +1765,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
* care of current piggback algo, lets abort the scan here
* itself.
*/
brcmf_notify_escan_complete(cfg, ndev, true, true);
brcmf_notify_escan_complete(cfg, ifp, true, true);
/* update channel */
af_params->channel = cpu_to_le32(afx_hdl->peer_chan);
@ -1820,7 +1832,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status);
/* if all done, turn mpc on again */
if (config_af_params.mpc_onoff == 1)
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
return ack;
}
@ -1839,7 +1851,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct wireless_dev *wdev;
struct brcmf_cfg80211_vif *vif = ifp->vif;
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u16 chanspec = be16_to_cpu(rxframe->chanspec);
@ -1882,8 +1893,9 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
CHSPEC_IS2G(chanspec) ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
wdev = ifp->ndev->ieee80211_ptr;
cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len,
GFP_ATOMIC);
brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
mgmt_frame_len, e->datalen, chanspec, freq);
@ -1934,7 +1946,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
brcmf_p2p_generate_bss_mac(p2p);
brcmf_p2p_generate_bss_mac(p2p, NULL);
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
/* Initialize P2P Discovery in the firmware */
@ -2040,13 +2053,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
return -EPERM;
}
brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true);
brcmf_notify_escan_complete(cfg, vif->ifp, true, true);
vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
if (!vif) {
brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
return -EPERM;
}
brcmf_set_mpc(vif->ifp->ndev, 0);
brcmf_set_mpc(vif->ifp, 0);
/* In concurrency case, STA may be already associated in a particular */
/* channel. so retrieve the current channel of primary interface and */
@ -2123,14 +2136,106 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
}
/**
* brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface.
*
* @p2p: P2P specific data.
* @wiphy: wiphy device of new interface.
* @addr: mac address for this new interface.
*/
static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
struct wiphy *wiphy,
u8 *addr)
{
struct brcmf_cfg80211_vif *p2p_vif;
struct brcmf_if *p2p_ifp;
struct brcmf_if *pri_ifp;
int err;
u32 bssidx;
if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
return ERR_PTR(-ENOSPC);
p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE,
false);
if (IS_ERR(p2p_vif)) {
brcmf_err("could not create discovery vif\n");
return (struct wireless_dev *)p2p_vif;
}
pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
brcmf_p2p_generate_bss_mac(p2p, addr);
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif);
/* Initialize P2P Discovery in the firmware */
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
if (err < 0) {
brcmf_err("set p2p_disc error\n");
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
goto fail;
}
/* wait for firmware event */
err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD,
msecs_to_jiffies(1500));
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
if (!err) {
brcmf_err("timeout occurred\n");
err = -EIO;
goto fail;
}
/* discovery interface created */
p2p_ifp = p2p_vif->ifp;
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
/* verify bsscfg index for P2P discovery */
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
if (err < 0) {
brcmf_err("retrieving discover bsscfg index failed\n");
goto fail;
}
WARN_ON(p2p_ifp->bssidx != bssidx);
init_completion(&p2p->send_af_done);
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
init_completion(&p2p->afx_hdl.act_frm_scan);
init_completion(&p2p->wait_next_af);
return &p2p_vif->wdev;
fail:
brcmf_free_vif(p2p_vif);
return ERR_PTR(err);
}
/**
* brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface.
*
* @vif: virtual interface object to delete.
*/
static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif)
{
struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p;
cfg80211_unregister_wdev(&vif->wdev);
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
brcmf_free_vif(vif);
}
/**
* brcmf_p2p_add_vif() - create a new P2P virtual interface.
*
* @wiphy: wiphy device of new interface.
* @name: name of the new interface.
* @type: nl80211 interface type.
* @flags: TBD
* @params: TBD
* @flags: not used.
* @params: contains mac address for P2P device.
*/
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
enum nl80211_iftype type, u32 *flags,
@ -2157,6 +2262,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
iftype = BRCMF_FIL_P2P_IF_GO;
mode = WL_MODE_AP;
break;
case NL80211_IFTYPE_P2P_DEVICE:
return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy,
params->macaddr);
default:
return ERR_PTR(-EOPNOTSUPP);
}
@ -2244,6 +2352,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
break;
case NL80211_IFTYPE_P2P_DEVICE:
brcmf_p2p_delete_p2pdev(vif);
return 0;
default:
return -ENOTSUPP;
break;
@ -2275,3 +2385,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
return err;
}
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct brcmf_cfg80211_vif *vif;
int err;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
mutex_lock(&cfg->usr_sync);
err = brcmf_p2p_enable_discovery(p2p);
if (!err)
set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
mutex_unlock(&cfg->usr_sync);
return err;
}
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct brcmf_cfg80211_vif *vif;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
mutex_lock(&cfg->usr_sync);
(void)brcmf_p2p_deinit_discovery(p2p);
brcmf_abort_scanning(cfg);
clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
mutex_unlock(&cfg->usr_sync);
}

View file

@ -73,6 +73,20 @@ TRACE_EVENT(brcmf_dbg,
TP_printk("%s: %s", __get_str(func), __get_str(msg))
);
TRACE_EVENT(brcmf_hexdump,
TP_PROTO(void *data, size_t len),
TP_ARGS(data, len),
TP_STRUCT__entry(
__field(unsigned long, len)
__dynamic_array(u8, hdata, len)
),
TP_fast_assign(
__entry->len = len;
memcpy(__get_dynamic_array(hdata), data, len);
),
TP_printk("hexdump [length=%lu]", __entry->len)
);
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH

View file

@ -26,6 +26,7 @@
#include <brcmu_wifi.h>
#include "dhd.h"
#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwil_types.h"
#include "p2p.h"
#include "wl_cfg80211.h"
@ -182,64 +183,6 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = {
CHAN5G(216, 0),
};
static struct ieee80211_channel __wl_5ghz_n_channels[] = {
CHAN5G(32, 0), CHAN5G(34, 0),
CHAN5G(36, 0), CHAN5G(38, 0),
CHAN5G(40, 0), CHAN5G(42, 0),
CHAN5G(44, 0), CHAN5G(46, 0),
CHAN5G(48, 0), CHAN5G(50, 0),
CHAN5G(52, 0), CHAN5G(54, 0),
CHAN5G(56, 0), CHAN5G(58, 0),
CHAN5G(60, 0), CHAN5G(62, 0),
CHAN5G(64, 0), CHAN5G(66, 0),
CHAN5G(68, 0), CHAN5G(70, 0),
CHAN5G(72, 0), CHAN5G(74, 0),
CHAN5G(76, 0), CHAN5G(78, 0),
CHAN5G(80, 0), CHAN5G(82, 0),
CHAN5G(84, 0), CHAN5G(86, 0),
CHAN5G(88, 0), CHAN5G(90, 0),
CHAN5G(92, 0), CHAN5G(94, 0),
CHAN5G(96, 0), CHAN5G(98, 0),
CHAN5G(100, 0), CHAN5G(102, 0),
CHAN5G(104, 0), CHAN5G(106, 0),
CHAN5G(108, 0), CHAN5G(110, 0),
CHAN5G(112, 0), CHAN5G(114, 0),
CHAN5G(116, 0), CHAN5G(118, 0),
CHAN5G(120, 0), CHAN5G(122, 0),
CHAN5G(124, 0), CHAN5G(126, 0),
CHAN5G(128, 0), CHAN5G(130, 0),
CHAN5G(132, 0), CHAN5G(134, 0),
CHAN5G(136, 0), CHAN5G(138, 0),
CHAN5G(140, 0), CHAN5G(142, 0),
CHAN5G(144, 0), CHAN5G(145, 0),
CHAN5G(146, 0), CHAN5G(147, 0),
CHAN5G(148, 0), CHAN5G(149, 0),
CHAN5G(150, 0), CHAN5G(151, 0),
CHAN5G(152, 0), CHAN5G(153, 0),
CHAN5G(154, 0), CHAN5G(155, 0),
CHAN5G(156, 0), CHAN5G(157, 0),
CHAN5G(158, 0), CHAN5G(159, 0),
CHAN5G(160, 0), CHAN5G(161, 0),
CHAN5G(162, 0), CHAN5G(163, 0),
CHAN5G(164, 0), CHAN5G(165, 0),
CHAN5G(166, 0), CHAN5G(168, 0),
CHAN5G(170, 0), CHAN5G(172, 0),
CHAN5G(174, 0), CHAN5G(176, 0),
CHAN5G(178, 0), CHAN5G(180, 0),
CHAN5G(182, 0), CHAN5G(184, 0),
CHAN5G(186, 0), CHAN5G(188, 0),
CHAN5G(190, 0), CHAN5G(192, 0),
CHAN5G(194, 0), CHAN5G(196, 0),
CHAN5G(198, 0), CHAN5G(200, 0),
CHAN5G(202, 0), CHAN5G(204, 0),
CHAN5G(206, 0), CHAN5G(208, 0),
CHAN5G(210, 0), CHAN5G(212, 0),
CHAN5G(214, 0), CHAN5G(216, 0),
CHAN5G(218, 0), CHAN5G(220, 0),
CHAN5G(222, 0), CHAN5G(224, 0),
CHAN5G(226, 0), CHAN5G(228, 0),
};
static struct ieee80211_supported_band __wl_band_2ghz = {
.band = IEEE80211_BAND_2GHZ,
.channels = __wl_2ghz_channels,
@ -256,12 +199,28 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
.n_bitrates = wl_a_rates_size,
};
static struct ieee80211_supported_band __wl_band_5ghz_n = {
.band = IEEE80211_BAND_5GHZ,
.channels = __wl_5ghz_n_channels,
.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
.bitrates = wl_a_rates,
.n_bitrates = wl_a_rates_size,
/* This is to override regulatory domains defined in cfg80211 module (reg.c)
* By default world regulatory domain defined in reg.c puts the flags
* NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
* 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
* start p2p operations on 5GHz channels. All the changes in world regulatory
* domain are to be done here.
*/
static const struct ieee80211_regdomain brcmf_regdom = {
.n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
/* If any */
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only
*/
REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
/* IEEE 802.11a, channel 36..64 */
REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
/* IEEE 802.11a, channel 100..165 */
REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
};
static const u32 __wl_cipher_suites[] = {
@ -523,17 +482,16 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
return ERR_PTR(-EOPNOTSUPP);
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_P2P_DEVICE:
default:
return ERR_PTR(-EINVAL);
}
}
void brcmf_set_mpc(struct net_device *ndev, int mpc)
void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
{
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
if (check_vif_up(ifp->vif)) {
@ -546,10 +504,9 @@ void brcmf_set_mpc(struct net_device *ndev, int mpc)
}
}
s32
brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
bool aborted, bool fw_abort)
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp, bool aborted,
bool fw_abort)
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
@ -580,7 +537,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
/* Scan is aborted by setting channel_list[0] to -1 */
params_le.channel_list[0] = cpu_to_le16(-1);
/* E-Scan (or anyother type) can be aborted by SCAN */
err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
brcmf_err("Scan abort failed\n");
@ -594,12 +551,12 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
cfg->sched_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
} else if (scan_request) {
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
}
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
@ -619,9 +576,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
if (ndev) {
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
cfg->escan_info.ndev == ndev)
brcmf_notify_escan_complete(cfg, ndev, true,
true);
cfg->escan_info.ifp == netdev_priv(ndev))
brcmf_notify_escan_complete(cfg, netdev_priv(ndev),
true, true);
brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
}
@ -637,9 +594,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
return -EOPNOTSUPP;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
return brcmf_p2p_del_vif(wiphy, wdev);
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_P2P_DEVICE:
default:
return -EINVAL;
}
@ -803,7 +760,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
}
static s32
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
struct cfg80211_scan_request *request, u16 action)
{
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
@ -832,8 +789,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
params->action = cpu_to_le16(action);
params->sync_id = cpu_to_le16(0x1234);
err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
params, params_size);
err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);
if (err) {
if (err == -EBUSY)
brcmf_dbg(INFO, "system busy : escan canceled\n");
@ -848,7 +804,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
static s32
brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
struct net_device *ndev, struct cfg80211_scan_request *request)
struct brcmf_if *ifp, struct cfg80211_scan_request *request)
{
s32 err;
u32 passive_scan;
@ -856,35 +812,35 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
struct escan_info *escan = &cfg->escan_info;
brcmf_dbg(SCAN, "Enter\n");
escan->ndev = ndev;
escan->ifp = ifp;
escan->wiphy = wiphy;
escan->escan_state = WL_ESCAN_STATE_SCANNING;
passive_scan = cfg->active_scan ? 0 : 1;
err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
passive_scan);
if (err) {
brcmf_err("error (%d)\n", err);
return err;
}
brcmf_set_mpc(ndev, 0);
brcmf_set_mpc(ifp, 0);
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
results->version = 0;
results->count = 0;
results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
err = escan->run(cfg, ndev, request, WL_ESCAN_ACTION_START);
err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START);
if (err)
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
return err;
}
static s32
brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
struct brcmf_if *ifp = vif->ifp;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct cfg80211_ssid *ssids;
struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
u32 passive_scan;
@ -910,10 +866,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
}
/* If scan req comes for p2p0, send it over primary I/F */
if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) {
ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
ndev = ifp->ndev;
}
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
/* Arm scan timeout timer */
mod_timer(&cfg->escan_timeout, jiffies +
@ -934,11 +888,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
if (escan_req) {
cfg->escan_info.run = brcmf_run_escan;
err = brcmf_p2p_scan_prep(wiphy, request, ifp->vif);
err = brcmf_p2p_scan_prep(wiphy, request, vif);
if (err)
goto scan_out;
err = brcmf_do_escan(cfg, wiphy, ndev, request);
err = brcmf_do_escan(cfg, wiphy, vif->ifp, request);
if (err)
goto scan_out;
} else {
@ -962,7 +916,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
brcmf_set_mpc(ndev, 0);
brcmf_set_mpc(ifp, 0);
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&sr->ssid_le, sizeof(sr->ssid_le));
if (err) {
@ -972,7 +926,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
else
brcmf_err("WLC_SCAN error (%d)\n", err);
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
goto scan_out;
}
}
@ -990,16 +944,15 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
static s32
brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct net_device *ndev = request->wdev->netdev;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(container_of(request->wdev,
struct brcmf_cfg80211_vif, wdev)))
vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
if (!check_vif_up(vif))
return -EIO;
err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
err = brcmf_cfg80211_escan(wiphy, vif, request, NULL);
if (err)
brcmf_err("scan error (%d)\n", err);
@ -1891,8 +1844,10 @@ static s32
brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_wsec_key key;
s32 err = 0;
u8 keybuf[8];
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
@ -1916,8 +1871,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
memcpy(key.data, params->key, key.len);
if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
u8 keybuf[8];
if ((ifp->vif->mode != WL_MODE_AP) &&
(params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
@ -2013,7 +1969,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
break;
case WLAN_CIPHER_SUITE_TKIP:
if (ifp->vif->mode != WL_MODE_AP) {
brcmf_dbg(CONN, "Swapping key\n");
brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
@ -2118,8 +2074,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
err = -EAGAIN;
goto done;
}
switch (wsec & ~SES_OW_ENABLED) {
case WEP_ENABLED:
if (wsec & WEP_ENABLED) {
sec = &profile->sec;
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
params.cipher = WLAN_CIPHER_SUITE_WEP40;
@ -2128,16 +2083,13 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
params.cipher = WLAN_CIPHER_SUITE_WEP104;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
}
break;
case TKIP_ENABLED:
} else if (wsec & TKIP_ENABLED) {
params.cipher = WLAN_CIPHER_SUITE_TKIP;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
break;
case AES_ENABLED:
} else if (wsec & AES_ENABLED) {
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
break;
default:
} else {
brcmf_err("Invalid algo (0x%x)\n", wsec);
err = -EINVAL;
goto done;
@ -2511,7 +2463,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
if (cfg->scan_request) {
escan->escan_state = WL_ESCAN_STATE_IDLE;
brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
}
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
@ -2523,7 +2475,7 @@ static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
container_of(work, struct brcmf_cfg80211_info,
escan_timeout_work);
brcmf_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true);
}
static void brcmf_escan_timeout(unsigned long data)
@ -2574,7 +2526,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
struct net_device *ndev = ifp->ndev;
s32 status;
s32 err = 0;
struct brcmf_escan_result_le *escan_result_le;
@ -2587,9 +2538,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
status = e->status;
if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("scan not ready ndev %p drv_status %x\n", ndev,
!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx);
return -EPERM;
}
@ -2660,7 +2610,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
cfg->escan_info.escan_buf;
brcmf_inform_bss(cfg);
aborted = status != BRCMF_E_STATUS_SUCCESS;
brcmf_notify_escan_complete(cfg, ndev, aborted,
brcmf_notify_escan_complete(cfg, ifp, aborted,
false);
} else
brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n",
@ -2738,7 +2688,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
brcmf_abort_scanning(cfg);
/* Turn off watchdog timer */
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(netdev_priv(ndev), 1);
exit:
brcmf_dbg(TRACE, "Exit\n");
@ -2896,7 +2846,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
struct net_device *ndev = ifp->ndev;
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
struct cfg80211_scan_request *request = NULL;
struct cfg80211_ssid *ssid = NULL;
@ -2980,7 +2929,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
}
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
err = brcmf_do_escan(cfg, wiphy, ndev, request);
err = brcmf_do_escan(cfg, wiphy, ifp, request);
if (err) {
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
goto out_err;
@ -3137,7 +3086,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
brcmf_dbg(SCAN, "enter\n");
brcmf_dev_pno_clean(ndev);
if (cfg->sched_escan)
brcmf_notify_escan_complete(cfg, ndev, true, true);
brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true);
return 0;
}
@ -3709,7 +3658,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
}
brcmf_set_mpc(ndev, 0);
brcmf_set_mpc(ifp, 0);
/* find the RSN_IE */
rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
@ -3817,15 +3766,16 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
exit:
if (err)
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
return err;
}
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = -EPERM;
s32 err;
struct brcmf_fil_bss_enable_le bss_enable;
struct brcmf_join_params join_params;
brcmf_dbg(TRACE, "Enter\n");
@ -3833,16 +3783,21 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
/* Due to most likely deauths outstanding we sleep */
/* first to make sure they get processed by fw. */
msleep(400);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0) {
brcmf_err("setting AP mode failed %d\n", err);
goto exit;
}
memset(&join_params, 0, sizeof(join_params));
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, sizeof(join_params));
if (err < 0)
brcmf_err("SET SSID error (%d)\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
if (err < 0) {
if (err < 0)
brcmf_err("BRCMF_C_UP error %d\n", err);
goto exit;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0)
brcmf_err("setting AP mode failed %d\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
if (err < 0)
brcmf_err("setting INFRA mode failed %d\n", err);
} else {
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
bss_enable.enable = cpu_to_le32(0);
@ -3851,11 +3806,10 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
if (err < 0)
brcmf_err("bss_enable config failed %d\n", err);
}
brcmf_set_mpc(ndev, 1);
brcmf_set_mpc(ifp, 1);
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
exit:
return err;
}
@ -3909,13 +3863,13 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
struct wireless_dev *wdev,
u16 frame_type, bool reg)
{
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
struct brcmf_cfg80211_vif *vif = ifp->vif;
struct brcmf_cfg80211_vif *vif;
u16 mgmt_type;
brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
if (reg)
vif->mgmt_rx_reg |= BIT(mgmt_type);
else
@ -3931,7 +3885,6 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
const struct ieee80211_mgmt *mgmt;
struct brcmf_if *ifp;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
s32 ie_offset;
@ -3967,8 +3920,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
ie_offset = DOT11_MGMT_HDR_LEN +
DOT11_BCN_PRB_FIXED_LEN;
ie_len = len - ie_offset;
ifp = netdev_priv(wdev->netdev);
vif = ifp->vif;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
err = brcmf_vif_set_mgmt_ie(vif,
@ -4003,7 +3955,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
*cookie, le16_to_cpu(action_frame->len),
chan->center_freq);
ack = brcmf_p2p_send_action_frame(cfg, wdev->netdev,
ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),
af_params);
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
@ -4075,6 +4027,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
.remain_on_channel = brcmf_p2p_remain_on_channel,
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
.start_p2p_device = brcmf_p2p_start_device,
.stop_p2p_device = brcmf_p2p_stop_device,
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode
#endif
@ -4162,6 +4116,11 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_DEAUTH >> 4) |
BIT(IEEE80211_STYPE_ACTION >> 4)
},
[NL80211_IFTYPE_P2P_DEVICE] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
}
};
@ -4188,13 +4147,6 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
wiphy->iface_combinations = brcmf_iface_combos;
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
* it as 11a by default.
* This will be updated with
* 11n phy tables in
* "ifconfig up"
* if phy has 11n capability
*/
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->cipher_suites = __wl_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
@ -4204,6 +4156,9 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
brcmf_wiphy_pno_params(wiphy);
brcmf_dbg(INFO, "Registering custom regulatory\n");
wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
err = wiphy_register(wiphy);
if (err < 0) {
brcmf_err("Could not register wiphy device (%d)\n", err);
@ -4622,9 +4577,11 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
ifp->vif = vif;
vif->ifp = ifp;
vif->wdev.netdev = ifp->ndev;
ifp->ndev->ieee80211_ptr = &vif->wdev;
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
if (ifp->ndev) {
vif->wdev.netdev = ifp->ndev;
ifp->ndev->ieee80211_ptr = &vif->wdev;
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
}
mutex_unlock(&event->vif_event_lock);
wake_up(&event->vif_wq);
return 0;
@ -4927,34 +4884,248 @@ brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
return err;
}
static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
{
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct ieee80211_channel *band_chan_arr;
struct brcmf_chanspec_list *list;
s32 err;
u8 *pbuf;
u32 i, j;
u32 total;
u16 chanspec;
enum ieee80211_band band;
u32 channel;
u32 *n_cnt;
bool ht40_allowed;
u32 index;
u32 ht40_flag;
bool update;
u32 array_size;
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
if (pbuf == NULL)
return -ENOMEM;
list = (struct brcmf_chanspec_list *)pbuf;
err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
BRCMF_DCMD_MEDLEN);
if (err) {
brcmf_err("get chanspecs error (%d)\n", err);
goto exit;
}
__wl_band_2ghz.n_channels = 0;
__wl_band_5ghz_a.n_channels = 0;
total = le32_to_cpu(list->count);
for (i = 0; i < total; i++) {
chanspec = (u16)le32_to_cpu(list->element[i]);
channel = CHSPEC_CHANNEL(chanspec);
if (CHSPEC_IS40(chanspec)) {
if (CHSPEC_SB_UPPER(chanspec))
channel += CH_10MHZ_APART;
else
channel -= CH_10MHZ_APART;
} else if (CHSPEC_IS80(chanspec)) {
brcmf_dbg(INFO, "HT80 center channel : %d\n",
channel);
continue;
}
if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
(channel <= CH_MAX_2G_CHANNEL)) {
band_chan_arr = __wl_2ghz_channels;
array_size = ARRAY_SIZE(__wl_2ghz_channels);
n_cnt = &__wl_band_2ghz.n_channels;
band = IEEE80211_BAND_2GHZ;
ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
} else if (CHSPEC_IS5G(chanspec) &&
channel >= CH_MIN_5G_CHANNEL) {
band_chan_arr = __wl_5ghz_a_channels;
array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
n_cnt = &__wl_band_5ghz_a.n_channels;
band = IEEE80211_BAND_5GHZ;
ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
} else {
brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
continue;
}
if (!ht40_allowed && CHSPEC_IS40(chanspec))
continue;
update = false;
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
if (band_chan_arr[j].hw_value == channel) {
update = true;
break;
}
}
if (update)
index = j;
else
index = *n_cnt;
if (index < array_size) {
band_chan_arr[index].center_freq =
ieee80211_channel_to_frequency(channel, band);
band_chan_arr[index].hw_value = channel;
if (CHSPEC_IS40(chanspec) && ht40_allowed) {
/* assuming the order is HT20, HT40 Upper,
* HT40 lower from chanspecs
*/
ht40_flag = band_chan_arr[index].flags &
IEEE80211_CHAN_NO_HT40;
if (CHSPEC_SB_UPPER(chanspec)) {
if (ht40_flag == IEEE80211_CHAN_NO_HT40)
band_chan_arr[index].flags &=
~IEEE80211_CHAN_NO_HT40;
band_chan_arr[index].flags |=
IEEE80211_CHAN_NO_HT40PLUS;
} else {
/* It should be one of
* IEEE80211_CHAN_NO_HT40 or
* IEEE80211_CHAN_NO_HT40PLUS
*/
band_chan_arr[index].flags &=
~IEEE80211_CHAN_NO_HT40;
if (ht40_flag == IEEE80211_CHAN_NO_HT40)
band_chan_arr[index].flags |=
IEEE80211_CHAN_NO_HT40MINUS;
}
} else {
band_chan_arr[index].flags =
IEEE80211_CHAN_NO_HT40;
if (band == IEEE80211_BAND_2GHZ)
channel |= WL_CHANSPEC_BAND_2G;
else
channel |= WL_CHANSPEC_BAND_5G;
channel |= WL_CHANSPEC_BW_20;
err = brcmf_fil_bsscfg_int_get(ifp,
"per_chan_info",
&channel);
if (!err) {
if (channel & WL_CHAN_RADAR)
band_chan_arr[index].flags |=
(IEEE80211_CHAN_RADAR |
IEEE80211_CHAN_NO_IBSS);
if (channel & WL_CHAN_PASSIVE)
band_chan_arr[index].flags |=
IEEE80211_CHAN_PASSIVE_SCAN;
}
}
if (!update)
(*n_cnt)++;
}
}
exit:
kfree(pbuf);
return err;
}
static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
{
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct wiphy *wiphy;
s32 phy_list;
u32 band_list[3];
u32 nmode;
u32 bw_cap = 0;
s8 phy;
s32 err = 0;
s32 err;
u32 nband;
s32 i;
struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
s32 index;
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
&phy_list, sizeof(phy_list));
if (err) {
brcmf_err("error (%d)\n", err);
brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
return err;
}
phy = ((char *)&phy_list)[0];
brcmf_dbg(INFO, "%c phy\n", phy);
if (phy == 'n' || phy == 'a') {
wiphy = cfg_to_wiphy(cfg);
wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
&band_list, sizeof(band_list));
if (err) {
brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
return err;
}
brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
band_list[0], band_list[1], band_list[2]);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
if (err) {
brcmf_err("nmode error (%d)\n", err);
} else {
err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap);
if (err)
brcmf_err("mimo_bw_cap error (%d)\n", err);
}
brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap);
err = brcmf_construct_reginfo(cfg, bw_cap);
if (err) {
brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
return err;
}
nband = band_list[0];
memset(bands, 0, sizeof(bands));
for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
index = -1;
if ((band_list[i] == WLC_BAND_5G) &&
(__wl_band_5ghz_a.n_channels > 0)) {
index = IEEE80211_BAND_5GHZ;
bands[index] = &__wl_band_5ghz_a;
if ((bw_cap == WLC_N_BW_40ALL) ||
(bw_cap == WLC_N_BW_20IN2G_40IN5G))
bands[index]->ht_cap.cap |=
IEEE80211_HT_CAP_SGI_40;
} else if ((band_list[i] == WLC_BAND_2G) &&
(__wl_band_2ghz.n_channels > 0)) {
index = IEEE80211_BAND_2GHZ;
bands[index] = &__wl_band_2ghz;
if (bw_cap == WLC_N_BW_40ALL)
bands[index]->ht_cap.cap |=
IEEE80211_HT_CAP_SGI_40;
}
if ((index >= 0) && nmode) {
bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
bands[index]->ht_cap.ht_supported = true;
bands[index]->ht_cap.ampdu_factor =
IEEE80211_HT_MAX_AMPDU_64K;
bands[index]->ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_16;
/* An HT shall support all EQM rates for one spatial
* stream
*/
bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
}
}
wiphy = cfg_to_wiphy(cfg);
wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
return err;
}
static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
{
return wl_update_wiphybands(cfg);
return brcmf_update_wiphybands(cfg);
}
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)

View file

@ -238,9 +238,8 @@ struct escan_info {
u32 escan_state;
u8 escan_buf[WL_ESCAN_BUF_SIZE];
struct wiphy *wiphy;
struct net_device *ndev;
s32 (*run)(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
struct brcmf_if *ifp;
s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
struct cfg80211_scan_request *request, u16 action);
};
@ -493,9 +492,9 @@ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
u8 action, ulong timeout);
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
bool aborted, bool fw_abort);
void brcmf_set_mpc(struct net_device *ndev, int mpc);
struct brcmf_if *ifp, bool aborted,
bool fw_abort);
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
#endif /* _wl_cfg80211_h_ */

View file

@ -318,12 +318,6 @@
#define IS_SIM(chippkg) \
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
#ifdef DEBUG
#define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
#else
#define SI_MSG(fmt, ...) no_printk(fmt, ##__VA_ARGS__)
#endif /* DEBUG */
#define GOODCOREADDR(x, b) \
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
IS_ALIGNED((x), SI_CORE_SIZE))

View file

@ -457,6 +457,7 @@ struct d11regs {
/*== maccontrol register ==*/
#define MCTL_GMODE (1U << 31)
#define MCTL_DISCARD_PMQ (1 << 30)
#define MCTL_TBTTHOLD (1 << 28)
#define MCTL_WAKE (1 << 26)
#define MCTL_HPS (1 << 25)
#define MCTL_PROMISC (1 << 24)

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Broadcom Corporation
* Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -356,18 +357,26 @@ 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) {
/* Just STA, AP and ADHOC for now */
if (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC) {
brcms_err(wl->wlc->hw->d11core,
"%s: Attempt to add type %d, only STA for now\n",
"%s: Attempt to add type %d, only STA, AP and AdHoc for now\n",
__func__, vif->type);
return -EOPNOTSUPP;
}
spin_lock_bh(&wl->lock);
memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
wl->mute_tx = false;
brcms_c_mute(wl->wlc, false);
if (vif->type == NL80211_IFTYPE_STATION)
brcms_c_start_station(wl->wlc, vif->addr);
else if (vif->type == NL80211_IFTYPE_AP)
brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid,
vif->bss_conf.ssid, vif->bss_conf.ssid_len);
else if (vif->type == NL80211_IFTYPE_ADHOC)
brcms_c_start_adhoc(wl->wlc, vif->addr);
spin_unlock_bh(&wl->lock);
return 0;
@ -519,14 +528,43 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BEACON)
if (changed & BSS_CHANGED_SSID) {
/* BSSID changed, for whatever reason (IBSS and managed mode) */
spin_lock_bh(&wl->lock);
brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len);
spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BEACON) {
/* Beacon data changed, retrieve new beacon (beaconing modes) */
brcms_err(core, "%s: beacon changed\n", __func__);
struct sk_buff *beacon;
u16 tim_offset = 0;
spin_lock_bh(&wl->lock);
beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,
info->dtim_period);
spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_AP_PROBE_RESP) {
struct sk_buff *probe_resp;
spin_lock_bh(&wl->lock);
probe_resp = ieee80211_proberesp_get(hw, vif);
brcms_c_set_new_probe_resp(wl->wlc, probe_resp);
spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
/* Beaconing should be enabled/disabled (beaconing modes) */
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
info->enable_beacon ? "true" : "false");
if (info->enable_beacon &&
hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) {
brcms_c_enable_probe_resp(wl->wlc, true);
} else {
brcms_c_enable_probe_resp(wl->wlc, false);
}
}
if (changed & BSS_CHANGED_CQM) {
@ -724,7 +762,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
return result;
}
static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct brcms_info *wl = hw->priv;
int ret;
@ -739,6 +777,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
"ret=%d\n", jiffies_to_msecs(ret));
}
static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl = hw->priv;
u64 tsf;
spin_lock_bh(&wl->lock);
tsf = brcms_c_tsf_get(wl->wlc);
spin_unlock_bh(&wl->lock);
return tsf;
}
static void brcms_ops_set_tsf(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u64 tsf)
{
struct brcms_info *wl = hw->priv;
spin_lock_bh(&wl->lock);
brcms_c_tsf_set(wl->wlc, tsf);
spin_unlock_bh(&wl->lock);
}
static const struct ieee80211_ops brcms_ops = {
.tx = brcms_ops_tx,
.start = brcms_ops_start,
@ -755,6 +815,8 @@ static const struct ieee80211_ops brcms_ops = {
.ampdu_action = brcms_ops_ampdu_action,
.rfkill_poll = brcms_ops_rfkill_poll,
.flush = brcms_ops_flush,
.get_tsf = brcms_ops_get_tsf,
.set_tsf = brcms_ops_set_tsf,
};
void brcms_dpc(unsigned long data)
@ -996,7 +1058,16 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
/* channel change time is dependent on chip and band */
hw->channel_change_time = 7 * 1000;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_ADHOC);
/*
* deactivate sending probe responses by ucude, because this will
* cause problems when WPS is used.
*
* hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
*/
hw->rate_control_algorithm = "minstrel_ht";

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Broadcom Corporation
* Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -448,6 +449,10 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
kfree(wlc->corestate);
kfree(wlc->hw->bandstate[0]);
kfree(wlc->hw);
if (wlc->beacon)
dev_kfree_skb_any(wlc->beacon);
if (wlc->probe_resp)
dev_kfree_skb_any(wlc->probe_resp);
/* free the wlc */
kfree(wlc);
@ -1069,7 +1074,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
static void brcms_c_tbtt(struct brcms_c_info *wlc)
{
if (!wlc->bsscfg->BSS)
if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
/*
* DirFrmQ is now valid...defer setting until end
* of ATIM window
@ -2163,6 +2168,32 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
}
}
void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr)
{
memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
wlc->bsscfg->type = BRCMS_TYPE_STATION;
}
void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
u8 *ssid, size_t ssid_len)
{
brcms_c_set_ssid(wlc, ssid, ssid_len);
memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID));
wlc->bsscfg->type = BRCMS_TYPE_AP;
brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA);
}
void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr)
{
memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
wlc->bsscfg->type = BRCMS_TYPE_ADHOC;
brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0);
}
/* Initialize GPIOs that are controlled by D11 core */
static void brcms_c_gpio_init(struct brcms_c_info *wlc)
{
@ -3043,8 +3074,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
*/
static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
{
struct brcms_bss_cfg *cfg = wlc->bsscfg;
/* disallow PS when one of the following global conditions meets */
if (!wlc->pub->associated)
return false;
@ -3053,16 +3082,11 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
return false;
if (cfg->associated) {
/*
* disallow PS when one of the following
* bsscfg specific conditions meets
*/
if (!cfg->BSS)
return false;
if (wlc->bsscfg->type == BRCMS_TYPE_AP)
return false;
if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
return false;
}
return true;
}
@ -3771,7 +3795,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
struct brcms_c_info *wlc = bsscfg->wlc;
/* enter the MAC addr into the RXE match registers */
brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr);
brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr);
brcms_c_ampdu_macaddr_upd(wlc);
@ -3787,6 +3811,15 @@ static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
}
void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len)
{
u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len);
memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID));
memcpy(wlc->bsscfg->SSID, ssid, len);
wlc->bsscfg->SSID_len = len;
}
static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
{
wlc_hw->shortslot = shortslot;
@ -3821,7 +3854,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
if (wlc->home_chanspec != chanspec) {
wlc->home_chanspec = chanspec;
if (wlc->bsscfg->associated)
if (wlc->pub->associated)
wlc->bsscfg->current_bss->chanspec = chanspec;
}
}
@ -4091,10 +4124,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
*shm_entry++);
}
if (suspend) {
if (suspend)
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, false);
if (suspend)
brcms_c_enable_mac(wlc);
}
}
static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
@ -4332,7 +4369,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
/* WME QoS mode is Auto by default */
wlc->pub->_ampdu = AMPDU_AGG_HOST;
wlc->pub->bcmerror = 0;
}
static uint brcms_c_attach_module(struct brcms_c_info *wlc)
@ -5072,8 +5108,8 @@ int brcms_c_up(struct brcms_c_info *wlc)
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
mboolset(wlc->pub->radio_disabled,
WL_RADIO_HW_DISABLE);
if (bsscfg->enable && bsscfg->BSS)
if (bsscfg->type == BRCMS_TYPE_STATION ||
bsscfg->type == BRCMS_TYPE_ADHOC)
brcms_err(wlc->hw->d11core,
"wl%d: up: rfdisable -> "
"bsscfg_disable()\n",
@ -5434,7 +5470,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
u8 r;
bool war = false;
if (wlc->bsscfg->associated)
if (wlc->pub->associated)
r = wlc->bsscfg->current_bss->rateset.rates[0];
else
r = wlc->default_bss->rateset.rates[0];
@ -5528,7 +5564,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
/* merge rateset coming in with the current mcsset */
if (wlc->pub->_n_enab & SUPPORT_11N) {
struct brcms_bss_info *mcsset_bss;
if (wlc->bsscfg->associated)
if (wlc->pub->associated)
mcsset_bss = wlc->bsscfg->current_bss;
else
mcsset_bss = wlc->default_bss;
@ -5543,12 +5579,36 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
return bcmerror;
}
static void brcms_c_time_lock(struct brcms_c_info *wlc)
{
bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD);
/* Commit the write */
bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
}
static void brcms_c_time_unlock(struct brcms_c_info *wlc)
{
bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD);
/* Commit the write */
bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
}
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
{
u32 bcnint_us;
if (period == 0)
return -EINVAL;
wlc->default_bss->beacon_period = period;
bcnint_us = period << 10;
brcms_c_time_lock(wlc);
bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep),
(bcnint_us << CFPREP_CBI_SHIFT));
bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us);
brcms_c_time_unlock(wlc);
return 0;
}
@ -7291,74 +7351,112 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
}
}
/* Max buffering needed for beacon template/prb resp template is 142 bytes.
*
* PLCP header is 6 bytes.
* 802.11 A3 header is 24 bytes.
* Max beacon frame body template length is 112 bytes.
* Max probe resp frame body template length is 110 bytes.
*
* *len on input contains the max length of the packet available.
*
* The *len value is set to the number of bytes in buf used, and starts
* with the PLCP and included up to, but not including, the 4 byte FCS.
*/
static void
brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
u32 bcn_rspec,
struct brcms_bss_cfg *cfg, u16 *buf, int *len)
{
static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
struct cck_phy_hdr *plcp;
struct ieee80211_mgmt *h;
int hdr_len, body_len;
hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
/* calc buffer size provided for frame body */
body_len = *len - hdr_len;
/* return actual size */
*len = hdr_len + body_len;
/* format PHY and MAC headers */
memset(buf, 0, hdr_len);
plcp = (struct cck_phy_hdr *) buf;
/*
* PLCP for Probe Response frames are filled in from
* core's rate table
*/
if (type == IEEE80211_STYPE_BEACON)
/* fill in PLCP */
brcms_c_compute_plcp(wlc, bcn_rspec,
(DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
(u8 *) plcp);
/* "Regular" and 16 MBSS but not for 4 MBSS */
/* Update the phytxctl for the beacon based on the rspec */
brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
h = (struct ieee80211_mgmt *)&plcp[1];
/* fill in 802.11 header */
h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
/* A1 filled in by MAC for prb resp, broadcast for bcn */
if (type == IEEE80211_STYPE_BEACON)
memcpy(&h->da, &ether_bcast, ETH_ALEN);
memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
/* SEQ filled in by MAC */
}
int brcms_c_get_header_len(void)
{
return TXOFF;
}
static void brcms_c_beacon_write(struct brcms_c_info *wlc,
struct sk_buff *beacon, u16 tim_offset,
u16 dtim_period, bool bcn0, bool bcn1)
{
size_t len;
struct ieee80211_tx_info *tx_info;
struct brcms_hardware *wlc_hw = wlc->hw;
struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw;
/* Get tx_info */
tx_info = IEEE80211_SKB_CB(beacon);
len = min_t(size_t, beacon->len, BCN_TMPL_LEN);
wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value;
brcms_c_compute_plcp(wlc, wlc->bcn_rspec,
len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data);
/* "Regular" and 16 MBSS but not for 4 MBSS */
/* Update the phytxctl for the beacon based on the rspec */
brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
if (bcn0) {
/* write the probe response into the template region */
brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE,
(len + 3) & ~3, beacon->data);
/* write beacon length to SCR */
brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
}
if (bcn1) {
/* write the probe response into the template region */
brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE,
(len + 3) & ~3, beacon->data);
/* write beacon length to SCR */
brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
}
if (tim_offset != 0) {
brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
tim_offset + D11B_PHY_HDR_LEN);
brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period);
} else {
brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
len + D11B_PHY_HDR_LEN);
brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0);
}
}
static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc,
struct sk_buff *beacon, u16 tim_offset,
u16 dtim_period)
{
struct brcms_hardware *wlc_hw = wlc->hw;
struct bcma_device *core = wlc_hw->d11core;
/* Hardware beaconing for this config */
u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
/* Check if both templates are in use, if so sched. an interrupt
* that will call back into this routine
*/
if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid)
/* clear any previous status */
bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL);
if (wlc->beacon_template_virgin) {
wlc->beacon_template_virgin = false;
brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
true);
/* mark beacon0 valid */
bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
return;
}
/* Check that after scheduling the interrupt both of the
* templates are still busy. if not clear the int. & remask
*/
if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) {
wlc->defmacintmask |= MI_BCNTPL;
return;
}
if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) {
brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
false);
/* mark beacon0 valid */
bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
return;
}
if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) {
brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period,
false, true);
/* mark beacon0 valid */
bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD);
return;
}
return;
}
/*
* Update all beacons for the system.
*/
@ -7366,9 +7464,57 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
{
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
if (bsscfg->up && !bsscfg->BSS)
if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
bsscfg->type == BRCMS_TYPE_ADHOC)) {
/* Clear the soft intmask */
wlc->defmacintmask &= ~MI_BCNTPL;
if (!wlc->beacon)
return;
brcms_c_update_beacon_hw(wlc, wlc->beacon,
wlc->beacon_tim_offset,
wlc->beacon_dtim_period);
}
}
void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
u16 tim_offset, u16 dtim_period)
{
if (!beacon)
return;
if (wlc->beacon)
dev_kfree_skb_any(wlc->beacon);
wlc->beacon = beacon;
/* add PLCP */
skb_push(wlc->beacon, D11_PHY_HDR_LEN);
wlc->beacon_tim_offset = tim_offset;
wlc->beacon_dtim_period = dtim_period;
brcms_c_update_beacon(wlc);
}
void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
struct sk_buff *probe_resp)
{
if (!probe_resp)
return;
if (wlc->probe_resp)
dev_kfree_skb_any(wlc->probe_resp);
wlc->probe_resp = probe_resp;
/* add PLCP */
skb_push(wlc->probe_resp, D11_PHY_HDR_LEN);
brcms_c_update_probe_resp(wlc, false);
}
void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable)
{
/*
* prevent ucode from sending probe responses by setting the timeout
* to 1, it can not send it in that time frame.
*/
wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1;
brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
/* TODO: if (enable) => also deactivate receiving of probe request */
}
/* Write ssid into shared memory */
@ -7390,30 +7536,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
static void
brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
struct brcms_bss_cfg *cfg,
struct sk_buff *probe_resp,
bool suspend)
{
u16 *prb_resp;
int len = BCN_TMPL_LEN;
int len;
prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
if (!prb_resp)
return;
/*
* write the probe response to hardware, or save in
* the config structure
*/
/* create the probe response template */
brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
cfg, prb_resp, &len);
len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN);
if (suspend)
brcms_c_suspend_mac_and_wait(wlc);
/* write the probe response into the template region */
brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
(len + 3) & ~3, prb_resp);
(len + 3) & ~3, probe_resp->data);
/* write the length of the probe response frame (+PLCP/-FCS) */
brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
@ -7427,13 +7562,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
* PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
* by subtracting the PLCP len and adding the FCS.
*/
len += (-D11_PHY_HDR_LEN + FCS_LEN);
brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
brcms_c_mod_prb_rsp_rate_table(wlc,
(u16)len + FCS_LEN - D11_PHY_HDR_LEN);
if (suspend)
brcms_c_enable_mac(wlc);
kfree(prb_resp);
}
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
@ -7441,8 +7574,13 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
/* update AP or IBSS probe responses */
if (bsscfg->up && !bsscfg->BSS)
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
bsscfg->type == BRCMS_TYPE_ADHOC)) {
if (!wlc->probe_resp)
return;
brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp,
suspend);
}
}
int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
@ -7481,7 +7619,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
{
wlc->pub->associated = state;
wlc->bsscfg->associated = state;
}
/*
@ -7526,6 +7663,36 @@ void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
brcms_c_bcn_li_upd(wlc);
}
u64 brcms_c_tsf_get(struct brcms_c_info *wlc)
{
u32 tsf_h, tsf_l;
u64 tsf;
brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
tsf = tsf_h;
tsf <<= 32;
tsf |= tsf_l;
return tsf;
}
void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf)
{
u32 tsf_h, tsf_l;
brcms_c_time_lock(wlc);
tsf_l = tsf;
tsf_h = (tsf >> 32);
/* read the tsf timer low, then high to get an atomic read */
bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l);
bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h);
brcms_c_time_unlock(wlc);
}
int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
{
uint qdbm;
@ -7737,6 +7904,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
brcms_rfkill_set_hw_state(wlc->wl);
}
/* BCN template is available */
if (macintstatus & MI_BCNTPL)
brcms_c_update_beacon(wlc);
/* it isn't done and needs to be resched if macintstatus is non-zero */
return wlc->macintstatus != 0;
@ -7765,7 +7936,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
brcms_c_set_bssid(wlc->bsscfg);
/* Update tsf_cfprep if associated and up */
if (wlc->pub->associated && wlc->bsscfg->up) {
if (wlc->pub->associated && wlc->pub->up) {
u32 bi;
/* get beacon period and convert to uS */
@ -7873,6 +8044,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
pub->unit = unit;
pub->_piomode = piomode;
wlc->bandinit_pending = false;
wlc->beacon_template_virgin = true;
/* populate struct brcms_c_info with default values */
brcms_c_info_init(wlc, unit);

View file

@ -492,6 +492,8 @@ struct brcms_c_info {
bool radio_monitor;
bool going_down;
bool beacon_template_virgin;
struct brcms_timer *wdtimer;
struct brcms_timer *radio_timer;
@ -561,6 +563,11 @@ struct brcms_c_info {
struct wiphy *wiphy;
struct scb pri_scb;
struct sk_buff *beacon;
u16 beacon_tim_offset;
u16 beacon_dtim_period;
struct sk_buff *probe_resp;
};
/* antsel module specific state */
@ -576,14 +583,17 @@ struct antsel_info {
struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
};
enum brcms_bss_type {
BRCMS_TYPE_STATION,
BRCMS_TYPE_AP,
BRCMS_TYPE_ADHOC,
};
/*
* BSS configuration state
*
* wlc: wlc to which this bsscfg belongs to.
* up: is this configuration up operational
* enable: is this configuration enabled
* associated: is BSS in ASSOCIATED state
* BSS: infraustructure or adhoc
* type: interface type
* SSID_len: the length of SSID
* SSID: SSID string
*
@ -599,14 +609,10 @@ struct antsel_info {
*/
struct brcms_bss_cfg {
struct brcms_c_info *wlc;
bool up;
bool enable;
bool associated;
bool BSS;
enum brcms_bss_type type;
u8 SSID_len;
u8 SSID[IEEE80211_MAX_SSID_LEN];
u8 BSSID[ETH_ALEN];
u8 cur_etheraddr[ETH_ALEN];
struct brcms_bss_info *current_bss;
};
@ -631,7 +637,6 @@ extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
struct ieee80211_sta *sta,
void (*dma_callback_fn));
extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,

View file

@ -198,8 +198,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
if ((D11REV_GE(pi->sh->corerev, 24)) ||
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@ -211,7 +209,7 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
}
if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
(++pi->phy_wreg >= pi->phy_wreg_limit)) {
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
pi->phy_wreg = 0;
@ -297,10 +295,8 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
if (addr == 0x72)
(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
#else
struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
(++pi->phy_wreg >= pi->phy_wreg_limit)) {
pi->phy_wreg = 0;
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
@ -374,7 +370,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
if (sh == NULL)
return NULL;
sh->sih = shp->sih;
sh->physhim = shp->physhim;
sh->unit = shp->unit;
sh->corerev = shp->corerev;
@ -2911,29 +2906,24 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
}
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x0);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioout),
0x40, 0x40);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioouten),
0x40, 0x40);
bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
0x0, 0x0);
bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
~0x40, 0x40);
bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
~0x40, 0x40);
} else {
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioout),
0x40, 0x00);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioouten),
0x40, 0x0);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x40);
bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
~0x40, 0x00);
bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
~0x40, 0x00);
bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
0x0, 0x40);
}
}
}

View file

@ -488,7 +488,6 @@ struct lcnphy_cal_results {
struct shared_phy {
struct brcms_phy *phy_head;
uint unit;
struct si_pub *sih;
struct phy_shim_info *physhim;
uint corerev;
u32 machwcap;

View file

@ -1595,11 +1595,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
if (channel == 1 || channel == 2 || channel == 3 ||
channel == 4 || channel == 9 ||
channel == 10 || channel == 11 || channel == 12) {
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
0x03000c04);
bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
~0x00ffffff, 0x0);
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
0x200005c0);
si_pmu_pllupd(pi->sh->sih);
bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
BCMA_CC_PMU_CTL_PLL_UPD);
write_phy_reg(pi, 0x942, 0);
wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
pi_lcn->lcnphy_spurmod = false;
@ -1607,11 +1611,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
write_phy_reg(pi, 0x425, 0x5907);
} else {
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
0x03140c04);
bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
~0x00ffffff, 0x333333);
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
0x202c2820);
si_pmu_pllupd(pi->sh->sih);
bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
BCMA_CC_PMU_CTL_PLL_UPD);
write_phy_reg(pi, 0x942, 0);
wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
@ -4755,9 +4763,10 @@ void wlc_phy_init_lcnphy(struct brcms_phy *pi)
wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9);
si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0,
0x03CDDDDD);
if ((pi->sh->boardflags & BFL_FEM)
&& wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
@ -4968,7 +4977,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
pi->hwpwrctrl_capable = true;
}
pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih);
pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc);
pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
pi->pi_fptr.init = wlc_phy_init_lcnphy;

View file

@ -19321,14 +19321,13 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
(pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
if ((pi->sh->boardflags & BFL_EXTLNA) &&
(CHSPEC_IS2G(pi->radio_chanspec)))
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, chipcontrol),
0x40, 0x40);
bcma_cc_set32(&pi->d11core->bus->drv_cc,
BCMA_CC_CHIPCTL, 0x40);
}
if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
CCTRL5357_EXTPA);
bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1,
~CCTRL5357_EXTPA, CCTRL5357_EXTPA);
if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
CHSPEC_IS40(pi->radio_chanspec)) {
@ -21133,7 +21132,6 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
const struct nphy_sfo_cfg *ci)
{
u16 val;
struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
if (CHSPEC_IS5G(chanspec) && !val) {
@ -21221,11 +21219,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
(pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
spuravoid);
} else {
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
spuravoid);
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
}

View file

@ -115,60 +115,6 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
return (u16) delay;
}
/* Read/write a chipcontrol reg */
u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data),
mask, val);
}
/* Read/write a regcontrol reg */
u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data),
mask, val);
}
/* Read/write a pllcontrol reg */
u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data),
mask, val);
}
/* PMU PLL update */
void si_pmu_pllupd(struct si_pub *sih)
{
ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
}
/* query alp/xtal clock frequency */
u32 si_pmu_alp_clock(struct si_pub *sih)
{
u32 clock = ALP_CLOCK;
/* bail out with default */
if (!(ai_get_cccaps(sih) & CC_CAP_PMU))
return clock;
switch (ai_get_chip_id(sih)) {
case BCMA_CHIP_ID_BCM43224:
case BCMA_CHIP_ID_BCM43225:
case BCMA_CHIP_ID_BCM4313:
/* always 20Mhz */
clock = 20000 * 1000;
break;
default:
break;
}
return clock;
}
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
struct si_info *sii = container_of(sih, struct si_info, pub);

View file

@ -21,12 +21,6 @@
#include "types.h"
extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable);
extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */

View file

@ -164,8 +164,6 @@ struct brcms_pub {
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
int bcmerror; /* last bcm error */
u32 radio_disabled; /* bit vector for radio disabled reasons */
u16 boardrev; /* version # of particular board */
@ -326,10 +324,25 @@ extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
s8 sslot_override);
extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
u8 interval);
extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr,
const u8 *bssid, u8 *ssid, size_t ssid_len);
extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
struct sk_buff *beacon, u16 tim_offset,
u16 dtim_period);
extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
struct sk_buff *probe_resp);
extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
size_t ssid_len);
#endif /* _BRCM_PUB_H_ */

View file

@ -32,8 +32,9 @@
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
#define CH_MIN_2G_CHANNEL 1
#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */
#define CH_MIN_5G_CHANNEL 34
/* bandstate array indices */
#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
@ -60,6 +61,7 @@
#define WL_CHANSPEC_BW_10 0x0400
#define WL_CHANSPEC_BW_20 0x0800
#define WL_CHANSPEC_BW_40 0x0C00
#define WL_CHANSPEC_BW_80 0x2000
#define WL_CHANSPEC_BAND_MASK 0xf000
#define WL_CHANSPEC_BAND_SHIFT 12
@ -67,6 +69,25 @@
#define WL_CHANSPEC_BAND_2G 0x2000
#define INVCHANSPEC 255
#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */
#define WL_CHAN_VALID_SW (1 << 1) /* valid with country sett. */
#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */
#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */
#define WL_CHAN_INACTIVE (1 << 4) /* inactive due to radar */
#define WL_CHAN_PASSIVE (1 << 5) /* channel in passive mode */
#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */
/* values for band specific 40MHz capabilities */
#define WLC_N_BW_20ALL 0
#define WLC_N_BW_40ALL 1
#define WLC_N_BW_20IN2G_40IN5G 2
/* band types */
#define WLC_BAND_AUTO 0 /* auto-select */
#define WLC_BAND_5G 1 /* 5 Ghz */
#define WLC_BAND_2G 2 /* 2.4 Ghz */
#define WLC_BAND_ALL 3 /* all bands */
#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
@ -79,10 +100,11 @@
#define CHSPEC_IS20(chspec) \
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
#ifndef CHSPEC_IS40
#define CHSPEC_IS40(chspec) \
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
#endif
#define CHSPEC_IS80(chspec) \
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
#define CHSPEC_IS5G(chspec) \
(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)

View file

@ -4701,8 +4701,7 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
EXPORT_SYMBOL(il_mac_change_interface);
void
il_mac_flush(struct ieee80211_hw *hw, bool drop)
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct il_priv *il = hw->priv;
unsigned long timeout = jiffies + msecs_to_jiffies(500);

View file

@ -1720,7 +1720,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
void il_mac_flush(struct ieee80211_hw *hw, bool drop);
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
int il_alloc_txq_mem(struct il_priv *il);
void il_free_txq_mem(struct il_priv *il);

View file

@ -1100,7 +1100,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);

View file

@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
bool, S_IRUGO);
MODULE_PARM_DESC(auto_agg,
"enable agg w/o check traffic load (default: enable)");
module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz,
bool, S_IRUGO);
MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])");

View file

@ -154,6 +154,19 @@ struct iwl_tlv_calib_ctrl {
__le32 event_trigger;
} __packed;
enum iwl_fw_phy_cfg {
FW_PHY_CFG_RADIO_TYPE_POS = 0,
FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
FW_PHY_CFG_RADIO_STEP_POS = 2,
FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
FW_PHY_CFG_RADIO_DASH_POS = 4,
FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
FW_PHY_CFG_TX_CHAIN_POS = 16,
FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
FW_PHY_CFG_RX_CHAIN_POS = 20,
FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
};
/**
* struct iwl_fw - variables associated with the firmware
*
@ -190,4 +203,16 @@ struct iwl_fw {
bool mvm_fw;
};
static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
{
return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >>
FW_PHY_CFG_TX_CHAIN_POS;
}
static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
{
return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >>
FW_PHY_CFG_RX_CHAIN_POS;
}
#endif /* __iwl_fw_h__ */

View file

@ -103,7 +103,6 @@ enum iwl_power_level {
* @ant_coupling: antenna coupling in dB, default = 0
* @bt_ch_announce: BT channel inhibition, default = enable
* @auto_agg: enable agg. without check, default = true
* @disable_5ghz: disable 5GHz capability, default = false
*/
struct iwl_mod_params {
int sw_crypto;
@ -120,7 +119,6 @@ struct iwl_mod_params {
int ant_coupling;
bool bt_ch_announce;
bool auto_agg;
bool disable_5ghz;
};
#endif /* #__iwl_modparams_h__ */

View file

@ -272,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
skb = iwl_test_alloc_reply(tst, reply_len + 20);
reply_buf = kmalloc(reply_len, GFP_KERNEL);
reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL);
if (!skb || !reply_buf) {
kfree_skb(skb);
kfree(reply_buf);
@ -280,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
}
/* The reply is in a page, that we cannot send to user space. */
memcpy(reply_buf, &(pkt->hdr), reply_len);
iwl_free_resp(&cmd);
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,

View file

@ -125,15 +125,15 @@ enum iwl_bt_kill_msk {
};
static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
0xffffffff,
0xfffffc00,
0,
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
};
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
0xffffffff,
0xfffffc00,
0,
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
};
#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
@ -188,6 +188,8 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
/* BT Antenna Coupling Threshold (dB) */
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
{
@ -201,8 +203,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
BT_COEX_NW : BT_COEX_DISABLE;
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ?
BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0;
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
cmd.flags |= BT_SYNC_2_BT_DISABLE;
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
@ -275,7 +276,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (data->notif->bt_status)
smps_mode = IEEE80211_SMPS_DYNAMIC;
if (data->notif->bt_traffic_load)
if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD)
smps_mode = IEEE80211_SMPS_STATIC;
IWL_DEBUG_COEX(data->mvm,
@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
return 0;
IWL_DEBUG_COEX(mvm,
"Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n",
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
bt_kill_msk,
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",

View file

@ -866,17 +866,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
if (wowlan->rfkill_release)
d3_cfg_cmd.wakeup_flags |=
wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
if (wowlan->tcp) {
/*
* The firmware currently doesn't really look at these, only
* the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that
* reason bit since losing the connection to the AP implies
* losing the TCP connection.
* Set the flags anyway as long as they exist, in case this
* will be changed in the firmware.
* Set the "link change" (really "link lost") flag as well
* since that implies losing the TCP connection.
*/
wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |

View file

@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd {
struct ieee80211_hdr frame[0];
} __packed;
struct iwl_beacon_notif {
struct iwl_mvm_tx_resp beacon_notify_hdr;
__le64 tsf;
__le32 ibss_mgr_status;
} __packed;
/**
* enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty

View file

@ -151,6 +151,7 @@ enum {
SET_CALIB_DEFAULT_CMD = 0x8e,
BEACON_NOTIFICATION = 0x90,
BEACON_TEMPLATE_CMD = 0x91,
TX_ANT_CONFIGURATION_CMD = 0x98,
BT_CONFIG = 0x9b,
@ -278,38 +279,7 @@ enum {
NVM_ACCESS_TARGET_EEPROM = 2,
};
/**
* struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM.
* @op_code: 0 - read, 1 - write.
* @target: NVM_ACCESS_TARGET_*. should be 0 for read.
* @cache_refresh: 0 - None, 1- NVM.
* @offset: offset in the nvm data.
* @length: of the chunk.
* @data: empty on read, the NVM chunk on write
*/
struct iwl_nvm_access_cmd_ver1 {
u8 op_code;
u8 target;
u8 cache_refresh;
u8 reserved;
__le16 offset;
__le16 length;
u8 data[];
} __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */
/**
* struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD
* @offset: the offset in the nvm data
* @length: of the chunk
* @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write
*/
struct iwl_nvm_access_resp_ver1 {
__le16 offset;
__le16 length;
u8 data[];
} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */
/* Section types for NVM_ACCESS_CMD version 2 */
/* Section types for NVM_ACCESS_CMD */
enum {
NVM_SECTION_TYPE_HW = 0,
NVM_SECTION_TYPE_SW,
@ -330,7 +300,7 @@ enum {
* @length: in bytes, to read/write
* @data: if write operation, the data to write. On read its empty
*/
struct iwl_nvm_access_cmd_ver2 {
struct iwl_nvm_access_cmd {
u8 op_code;
u8 target;
__le16 type;
@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 {
* @status: 0 for success, fail otherwise
* @data: if read operation, the data returned. Empty on write.
*/
struct iwl_nvm_access_resp_ver2 {
struct iwl_nvm_access_resp {
__le16 offset;
__le16 length;
__le16 type;

View file

@ -114,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
.valid = cpu_to_le32(valid_tx_ant),
};
IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);
return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
sizeof(tx_ant_cmd), &tx_ant_cmd);
}
@ -134,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
IWL_DEBUG_FW(mvm,
"Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
le16_to_cpu(palive->status), palive->ver_type,
palive->ver_subtype);
palive->ver_subtype, palive->flags);
return true;
}
@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
WARN_ON(ret);
/* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
if (ret)
goto error;
/* WkP doesn't have all calibrations, need to set default values */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
ret = iwl_set_default_calibrations(mvm);
if (ret)
goto error;
}
/* need to set default values */
ret = iwl_set_default_calibrations(mvm);
if (ret)
goto error;
/*
* Send phy configurations command to init uCode
@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
if (ret)
goto error;
@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error;
}
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
if (ret)
goto error;

View file

@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
u32 qmask, ac;
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return BIT(IWL_OFFCHANNEL_QUEUE);
return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
BIT(vif->cab_queue) : 0;
@ -692,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
/* No other data to be filled */
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
MAC_FILTER_IN_BEACON |
MAC_FILTER_IN_PROBE_REQUEST);
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@ -798,7 +803,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
TX_CMD_FLG_TSF);
mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
mvm->mgmt_last_antenna_idx);
beacon_cmd.tx.rate_n_flags =
@ -1013,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->uploaded = false;
return 0;
}
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_beacon_notif *beacon = (void *)pkt->data;
u16 status __maybe_unused =
le16_to_cpu(beacon->beacon_notify_hdr.status.status);
u32 rate __maybe_unused =
le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
status & TX_STATUS_MSK,
beacon->beacon_notify_hdr.failure_frame,
le64_to_cpu(beacon->tsf),
rate);
return 0;
}

View file

@ -143,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_TIMING_BEACON_ONLY;
hw->queues = IWL_FIRST_AMPDU_QUEUE;
hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE;
hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
hw->rate_control_algorithm = "iwl-mvm-rs";
/*
@ -174,7 +174,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->n_iface_combinations =
ARRAY_SIZE(iwl_mvm_iface_combinations);
hw->wiphy->max_remain_on_channel_duration = 500;
hw->wiphy->max_remain_on_channel_duration = 10000;
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
/* Extract MAC address */
@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
goto drop;
}
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE &&
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
goto drop;
@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
if (vif->type == NL80211_IFTYPE_AP && !sta) {
/* GTK on AP interface is a TX-only key, return 0 */
ret = 0;
key->hw_key_idx = STA_KEY_IDX_INVALID;
break;
}
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
if (ret) {
@ -1095,11 +1102,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
* can't add key for RX, but we don't need it
* in the device for TX so still return 0
*/
key->hw_key_idx = STA_KEY_IDX_INVALID;
ret = 0;
}
break;
case DISABLE_KEY:
if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
ret = 0;
break;
}
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
break;
@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
&chandef, 1, 1);
/* Schedule the time events */
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration);
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
mutex_unlock(&mvm->mutex);
IWL_DEBUG_MAC80211(mvm, "leave\n");
@ -1252,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* will handle quota settings.
*/
if (vif->type == NL80211_IFTYPE_MONITOR) {
mvmvif->monitor_active = true;
ret = iwl_mvm_update_quotas(mvm, vif);
if (ret)
goto out_remove_binding;
@ -1282,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP)
goto out_unlock;
iwl_mvm_binding_remove_vif(mvm, vif);
switch (vif->type) {
case NL80211_IFTYPE_MONITOR:
iwl_mvm_update_quotas(mvm, vif);
mvmvif->monitor_active = false;
iwl_mvm_update_quotas(mvm, NULL);
break;
default:
break;
}
iwl_mvm_binding_remove_vif(mvm, vif);
out_unlock:
mvmvif->phy_ctxt = NULL;
mutex_unlock(&mvm->mutex);

View file

@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_VO,
};
/* Placeholder */
#define IWL_OFFCHANNEL_QUEUE 8
#define IWL_FIRST_AMPDU_QUEUE 11
extern struct ieee80211_ops iwl_mvm_hw_ops;
/**
* struct iwl_mvm_mod_params - module parameters for iwlmvm
@ -161,6 +157,8 @@ enum iwl_power_scheme {
* @uploaded: indicates the MAC context has been added to the device
* @ap_active: indicates that ap context is configured, and that the interface
* should get quota etc.
* @monitor_active: indicates that monitor context is configured, and that the
* interface should get quota etc.
* @queue_params: QoS params for this MAC
* @bcast_sta: station used for broadcast packets. Used by the following
* vifs: P2P_DEVICE, GO and AP.
@ -173,6 +171,7 @@ struct iwl_mvm_vif {
bool uploaded;
bool ap_active;
bool monitor_active;
u32 ap_beacon_time;
@ -281,10 +280,7 @@ struct iwl_mvm {
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
struct iwl_nvm_data *nvm_data;
/* eeprom blob for debugfs/testmode */
u8 *eeprom_blob;
size_t eeprom_blob_size;
/* NVM sections for 7000 family */
/* NVM sections */
struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
/* EEPROM MAC addresses */
@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

View file

@ -77,26 +77,8 @@ static const int nvm_to_read[] = {
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
/* used to simplify the shared operations on NCM_ACCESS_CMD versions */
union iwl_nvm_access_cmd {
struct iwl_nvm_access_cmd_ver1 ver1;
struct iwl_nvm_access_cmd_ver2 ver2;
};
union iwl_nvm_access_resp {
struct iwl_nvm_access_resp_ver1 ver1;
struct iwl_nvm_access_resp_ver2 ver2;
};
static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd,
u16 offset, u16 length)
{
cmd->offset = cpu_to_le16(offset);
cmd->length = cpu_to_le16(length);
cmd->cache_refresh = 1;
}
static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
u16 offset, u16 length, u16 section)
static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
u16 offset, u16 length, u16 section)
{
cmd->offset = cpu_to_le16(offset);
cmd->length = cpu_to_le16(length);
@ -106,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
u16 offset, u16 length, u8 *data)
{
union iwl_nvm_access_cmd nvm_access_cmd;
union iwl_nvm_access_resp *nvm_resp;
struct iwl_nvm_access_cmd nvm_access_cmd = {};
struct iwl_nvm_access_resp *nvm_resp;
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD,
@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
int ret, bytes_read, offset_read;
u8 *resp_data;
memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd));
/* TODO: not sure family should be the decider, maybe FW version? */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2),
offset, length, section);
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2);
} else {
iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1),
offset, length);
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1);
}
iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret)
@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
/* Extract NVM response */
nvm_resp = (void *)pkt->data;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
ret = le16_to_cpu(nvm_resp->ver2.status);
bytes_read = le16_to_cpu(nvm_resp->ver2.length);
offset_read = le16_to_cpu(nvm_resp->ver2.offset);
resp_data = nvm_resp->ver2.data;
} else {
ret = le16_to_cpu(nvm_resp->ver1.length) <= 0;
bytes_read = le16_to_cpu(nvm_resp->ver1.length);
offset_read = le16_to_cpu(nvm_resp->ver1.offset);
resp_data = nvm_resp->ver1.data;
}
ret = le16_to_cpu(nvm_resp->status);
bytes_read = le16_to_cpu(nvm_resp->length);
offset_read = le16_to_cpu(nvm_resp->offset);
resp_data = nvm_resp->data;
if (ret) {
IWL_ERR(mvm,
"NVM access command failed with status %d (device: %s)\n",
@ -194,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
{
u16 length, offset = 0;
int ret;
bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
/* Set nvm section read length */
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
/*
* if length is greater than EEPROM size, truncate it because uCode
* doesn't check it by itself, and exit the loop when reached.
*/
if (old_eeprom && length > mvm->cfg->base_params->eeprom_size)
length = mvm->cfg->base_params->eeprom_size;
ret = length;
/* Read the NVM until exhausted (reading less than requested) */
@ -217,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
return ret;
}
offset += ret;
if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size)
break;
}
IWL_INFO(mvm, "NVM section %d read completed\n", section);
@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
int ret, i, section;
u8 *nvm_buffer, *temp;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/* TODO: find correct NVM max size for a section */
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
section = nvm_to_read[i];
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
if (ret < 0)
break;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
break;
}
mvm->nvm_sections[section].data = temp;
mvm->nvm_sections[section].length = ret;
}
kfree(nvm_buffer);
/* TODO: find correct NVM max size for a section */
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
section = nvm_to_read[i];
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
if (ret < 0)
return ret;
} else {
/* allocate eeprom */
mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size;
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n",
mvm->eeprom_blob_size);
mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL);
if (!mvm->eeprom_blob)
return -ENOMEM;
ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob);
if (ret != mvm->eeprom_blob_size) {
IWL_ERR(mvm, "Read partial NVM %d/%zd\n",
ret, mvm->eeprom_blob_size);
kfree(mvm->eeprom_blob);
mvm->eeprom_blob = NULL;
return -EINVAL;
break;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
break;
}
mvm->nvm_sections[section].data = temp;
mvm->nvm_sections[section].length = ret;
}
kfree(nvm_buffer);
if (ret < 0)
return ret;
ret = 0;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
else
mvm->nvm_data =
iwl_parse_eeprom_data(mvm->trans->dev,
mvm->cfg,
mvm->eeprom_blob,
mvm->eeprom_blob_size);
if (!mvm->nvm_data) {
kfree(mvm->eeprom_blob);
mvm->eeprom_blob = NULL;
ret = -ENOMEM;
}
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
return ret;
}

View file

@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
u32 reg_val = 0;
/*
* We can't upload the correct value to the INIT image
* as we don't have nvm_data by that time.
*
* TODO: Figure out what we should do here
*/
if (mvm->nvm_data) {
radio_cfg_type = mvm->nvm_data->radio_cfg_type;
radio_cfg_step = mvm->nvm_data->radio_cfg_step;
radio_cfg_dash = mvm->nvm_data->radio_cfg_dash;
} else {
radio_cfg_type = 0;
radio_cfg_step = 0;
radio_cfg_dash = 0;
}
radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
FW_PHY_CFG_RADIO_TYPE_POS;
radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
FW_PHY_CFG_RADIO_STEP_POS;
radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
FW_PHY_CFG_RADIO_DASH_POS;
/* SKU control */
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
/* silicon bits */
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
@ -231,6 +221,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
@ -276,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(WEP_KEY),
CMD(REPLY_RX_PHY_CMD),
CMD(REPLY_RX_MPDU_CMD),
CMD(BEACON_NOTIFICATION),
CMD(BEACON_TEMPLATE_CMD),
CMD(STATISTICS_NOTIFICATION),
CMD(TX_ANT_CONFIGURATION_CMD),
@ -319,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
};
int err, scan_size;
switch (cfg->device_family) {
case IWL_DEVICE_FAMILY_6030:
case IWL_DEVICE_FAMILY_6005:
case IWL_DEVICE_FAMILY_7000:
break;
default:
IWL_ERR(trans, "Trying to load mvm on an unsupported device\n");
return NULL;
}
/********************************
* 1. Allocating and configuring HW data
********************************/
@ -444,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
out_free:
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
kfree(mvm->eeprom_blob);
iwl_trans_stop_hw(trans, true);
ieee80211_free_hw(mvm->hw);
return NULL;
@ -466,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_phy_db_free(mvm->phy_db);
mvm->phy_db = NULL;
kfree(mvm->eeprom_blob);
iwl_free_nvm_data(mvm->nvm_data);
for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
kfree(mvm->nvm_sections[i].data);

View file

@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
u8 valid_rx_chains, active_cnt, idle_cnt;
u8 active_cnt, idle_cnt;
/* Set the channel info data */
cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
@ -158,17 +158,16 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
* Need to add on chain noise calibration limitations, and
* BT coex considerations.
*/
valid_rx_chains = mvm->nvm_data->valid_rx_ant;
idle_cnt = chains_static;
active_cnt = chains_dynamic;
cmd->rxchain_info = cpu_to_le32(valid_rx_chains <<
cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) <<
PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = cpu_to_le32(mvm->nvm_data->valid_tx_ant);
cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw));
}
/*

View file

@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_MONITOR:
data->n_interfaces[id]++;
if (mvmvif->monitor_active)
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_P2P_DEVICE:
break;

View file

@ -74,7 +74,7 @@
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
{
u16 rx_chain;
u8 rx_ant = mvm->nvm_data->valid_rx_ant;
u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw);
rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
u32 tx_ant;
mvm->scan_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
mvm->scan_last_antenna_idx);
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;

View file

@ -76,14 +76,12 @@
#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/* For ROC use a TE type which has priority high enough to be scheduled when
* there is a concurrent BSS or GO/AP. Currently, use a TE type that has
* priority similar to the TE priority used for action scans by the FW.
* TODO: This needs to be changed, based on the reason for the ROC, i.e., use
* TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use
* TE_P2P_DEVICE_ACTION_SCAN
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
*/
#define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN
#define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE
#define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC
void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
struct iwl_mvm_time_event_data *te_data)
@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
iwl_mvm_flush_tx_path(mvm, BIT(IWL_OFFCHANNEL_QUEUE), false);
iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
@ -438,7 +436,7 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
}
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int duration)
int duration, enum ieee80211_roc_type type)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
@ -459,21 +457,29 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
time_cmd.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE);
switch (type) {
case IEEE80211_ROC_TYPE_NORMAL:
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL);
break;
case IEEE80211_ROC_TYPE_MGMT_TX:
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX);
break;
default:
WARN_ONCE(1, "Got an invalid ROC type\n");
return -EINVAL;
}
time_cmd.apply_time = cpu_to_le32(0);
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
time_cmd.is_present = cpu_to_le32(1);
time_cmd.interval = cpu_to_le32(1);
/*
* IWL_MVM_ROC_TE_TYPE can have lower priority than other events
* The P2P Device TEs can have lower priority than other events
* that are being scheduled by the driver/fw, and thus it might not be
* scheduled. To improve the chances of it being scheduled, allow it to
* be fragmented.
* In addition, for the same reasons, allow to delay the scheduling of
* the time event.
* scheduled. To improve the chances of it being scheduled, allow them
* to be fragmented, and in addition allow them to be delayed.
*/
time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));

View file

@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
* that the vif type is NL80211_IFTYPE_P2P_DEVICE
* @duration: the requested duration in millisecond for the fw to be on the
* channel that is bound to the vif.
* @type: the remain on channel request type
*
* This function can be used to issue a remain on channel session,
* which means that the fw will stay in the channel for the request %duration
@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
* another notification to the driver.
*/
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int duration);
int duration, enum ieee80211_roc_type type);
/**
* iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity

View file

@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
spin_unlock(&mvmsta->lock);
if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
txq_id < IWL_FIRST_AMPDU_QUEUE)
txq_id < IWL_MVM_FIRST_AGG_QUEUE)
atomic_inc(&mvmsta->pending_frames);
return 0;
@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info);
/* Single frame failure in an AMPDU queue => send BAR */
if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE &&
!(info->flags & IEEE80211_TX_STAT_ACK))
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
ieee80211_tx_status_ni(mvm->hw, skb);
}
if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) {
/* If this is an aggregation queue, we use the ssn since:
* ssn = wifi seq_num % 256.
* The seq_ctl is the sequence control of the packet to which
@ -681,7 +681,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
* If there are no pending frames for this STA, notify mac80211 that
* this station can go to sleep in its STA table.
*/
if (txq_id < IWL_FIRST_AMPDU_QUEUE && mvmsta &&
if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta &&
!WARN_ON(skb_freed > 1) &&
mvmsta->vif->type == NL80211_IFTYPE_AP &&
atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
@ -750,7 +750,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
struct ieee80211_sta *sta;
if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_FIRST_AMPDU_QUEUE))
if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE))
return;
if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS))

View file

@ -1564,8 +1564,11 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
return -EIO;
if (test_bit(STATUS_RFKILL, &trans_pcie->status))
if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
cmd->id);
return -ERFKILL;
}
if (cmd->flags & CMD_ASYNC)
return iwl_pcie_send_hcmd_async(trans, cmd);

View file

@ -964,6 +964,12 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
newtype, vif->addr);
hwsim_check_magic(vif);
/*
* interface may change from non-AP to AP in
* which case this needs to be set up again
*/
vif->cab_queue = 0;
return 0;
}
@ -1389,7 +1395,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
return 0;
}
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
/* Not implemented, queues only on kernel side */
}

View file

@ -259,3 +259,44 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
return ret_len;
}
int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, u16 cmd_action,
struct mwifiex_11ac_vht_cfg *cfg)
{
struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
S_DS_GEN);
vhtcfg->action = cpu_to_le16(cmd_action);
vhtcfg->band_config = cfg->band_config;
vhtcfg->misc_config = cfg->misc_config;
vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
return 0;
}
/* This function initializes the BlockACK setup information for given
* mwifiex_private structure for 11ac enabled networks.
*/
void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
{
priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
priv->add_ba_param.tx_win_size =
MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size =
MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
} else {
priv->add_ba_param.tx_win_size =
MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size =
MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
}
return;
}

View file

@ -20,7 +20,24 @@
#ifndef _MWIFIEX_11AC_H_
#define _MWIFIEX_11AC_H_
#define VHT_CFG_2GHZ BIT(0)
#define VHT_CFG_5GHZ BIT(1)
enum vht_cfg_misc_config {
VHT_CAP_TX_OPERATION = 1,
VHT_CAP_ASSOCIATION,
VHT_CAP_UAP_ONLY
};
#define DEFAULT_VHT_MCS_SET 0xfffa
#define DISABLE_VHT_MCS_SET 0xffff
#define VHT_BW_80_160_80P80 BIT(2)
int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc,
u8 **buffer);
int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd, u16 cmd_action,
struct mwifiex_11ac_vht_cfg *cfg);
#endif /* _MWIFIEX_11AC_H_ */

View file

@ -679,3 +679,25 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
return;
}
/* This function initializes the BlockACK setup information for given
* mwifiex_private structure.
*/
void mwifiex_set_ba_params(struct mwifiex_private *priv)
{
priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
priv->add_ba_param.tx_win_size =
MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size =
MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
} else {
priv->add_ba_param.tx_win_size =
MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size =
MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
}
return;
}

View file

@ -1374,6 +1374,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
}
mwifiex_set_ht_params(priv, bss_cfg, params);
if (priv->adapter->is_hw_11ac_capable) {
mwifiex_set_vht_params(priv, bss_cfg, params);
mwifiex_set_vht_width(priv, params->chandef.width,
priv->ap_11ac_enabled);
}
if (priv->ap_11ac_enabled)
mwifiex_set_11ac_ba_params(priv);
else
mwifiex_set_ba_params(priv);
mwifiex_set_wmm_params(priv, bss_cfg, params);
if (params->inactivity_timeout > 0) {

View file

@ -153,7 +153,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
" or cmd size is 0, not sending\n");
if (cmd_node->wait_q_enabled)
adapter->cmd_wait_q.status = -1;
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
mwifiex_recycle_cmd_node(adapter, cmd_node);
return -1;
}
@ -167,7 +167,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
"DNLD_CMD: FW in reset state, ignore cmd %#x\n",
cmd_code);
mwifiex_complete_cmd(adapter, cmd_node);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
mwifiex_recycle_cmd_node(adapter, cmd_node);
return -1;
}
@ -228,7 +228,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
adapter->cmd_sent = false;
if (cmd_node->wait_q_enabled)
adapter->cmd_wait_q.status = -1;
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->curr_cmd = NULL;
@ -632,6 +632,20 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
}
/* This function reuses a command node. */
void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_node)
{
struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
atomic_dec(&adapter->cmd_pending);
dev_dbg(adapter->dev, "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
le16_to_cpu(host_cmd->command),
atomic_read(&adapter->cmd_pending));
}
/*
* This function queues a command to the command pending queue.
*
@ -673,7 +687,9 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
list_add(&cmd_node->list, &adapter->cmd_pending_q);
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command);
atomic_inc(&adapter->cmd_pending);
dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
command, atomic_read(&adapter->cmd_pending));
}
/*
@ -783,7 +799,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n",
le16_to_cpu(resp->command));
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->curr_cmd = NULL;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
@ -833,7 +849,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd->wait_q_enabled)
adapter->cmd_wait_q.status = -1;
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->curr_cmd = NULL;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
@ -865,8 +881,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd->wait_q_enabled)
adapter->cmd_wait_q.status = ret;
/* Clean up and put current command back to cmd_free_q */
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->curr_cmd = NULL;
@ -993,7 +1008,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
mwifiex_complete_cmd(adapter, cmd_node);
cmd_node->wait_q_enabled = false;
}
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
mwifiex_recycle_cmd_node(adapter, cmd_node);
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
}
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
@ -1040,7 +1055,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
cmd_node = adapter->curr_cmd;
cmd_node->wait_q_enabled = false;
cmd_node->cmd_flag |= CMD_F_CANCELED;
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
mwifiex_recycle_cmd_node(adapter, cmd_node);
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
adapter->curr_cmd = NULL;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);

View file

@ -41,8 +41,15 @@
#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2
#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16
#define MWIFIEX_AMPDU_DEF_TXWINSIZE 32
#define MWIFIEX_AMPDU_DEF_RXWINSIZE 16
#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 16
#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 32
#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32
#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16
#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 32
#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 48
#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 48
#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 32
#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
#define MWIFIEX_RATE_BITMAP_MCS0 32

View file

@ -295,6 +295,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
#define HostCmd_CMD_11AC_CFG 0x0112
#define PROTOCOL_NO_SECURITY 0x01
#define PROTOCOL_STATIC_WEP 0x02
@ -1363,6 +1364,15 @@ struct host_cmd_ds_sys_config {
u8 tlv[0];
};
struct host_cmd_11ac_vht_cfg {
__le16 action;
u8 band_config;
u8 misc_config;
__le32 cap_info;
__le32 mcs_tx_set;
__le32 mcs_rx_set;
} __packed;
struct host_cmd_tlv_akmp {
struct host_cmd_tlv tlv;
__le16 key_mgmt;
@ -1620,6 +1630,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_802_11_eeprom_access eeprom;
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
struct host_cmd_ds_sys_config uap_sys_config;
struct host_cmd_11ac_vht_cfg vht_cfg;
} params;
} __packed;

View file

@ -533,10 +533,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
if (!adapter->priv[i])
continue;
priv = adapter->priv[i];
for (j = 0; j < MAX_NUM_TID; ++j) {
for (j = 0; j < MAX_NUM_TID; ++j)
INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock);
}
INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
INIT_LIST_HEAD(&priv->sta_list);
@ -713,7 +711,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
if (adapter->curr_cmd) {
dev_warn(adapter->dev, "curr_cmd is still in processing\n");
del_timer(&adapter->cmd_timer);
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
adapter->curr_cmd = NULL;
}

View file

@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg {
} param;
};
struct mwifiex_11ac_vht_cfg {
u8 band_config;
u8 misc_config;
u32 cap_info;
u32 mcs_tx_set;
u32 mcs_rx_set;
};
struct mwifiex_ds_11n_tx_cfg {
u16 tx_htcap;
u16 tx_htinfo;

View file

@ -1295,6 +1295,14 @@ int mwifiex_associate(struct mwifiex_private *priv,
(bss_desc->bss_mode != NL80211_IFTYPE_STATION))
return -1;
if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
!bss_desc->disable_11n && !bss_desc->disable_11ac &&
(priv->adapter->config_bands & BAND_GAC ||
priv->adapter->config_bands & BAND_AAC))
mwifiex_set_11ac_ba_params(priv);
else
mwifiex_set_ba_params(priv);
memcpy(&current_bssid,
&priv->curr_bss_params.bss_descriptor.mac_address,
sizeof(current_bssid));
@ -1323,6 +1331,13 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
priv->curr_bss_params.band);
if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
(priv->adapter->config_bands & BAND_GAC ||
priv->adapter->config_bands & BAND_AAC))
mwifiex_set_11ac_ba_params(priv);
else
mwifiex_set_ba_params(priv);
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START,
HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
}
@ -1356,6 +1371,14 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
return -1;
}
if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
!bss_desc->disable_11n && !bss_desc->disable_11ac &&
(priv->adapter->config_bands & BAND_GAC ||
priv->adapter->config_bands & BAND_AAC))
mwifiex_set_11ac_ba_params(priv);
else
mwifiex_set_ba_params(priv);
dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
priv->curr_bss_params.bss_descriptor.channel);
dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",

View file

@ -213,15 +213,12 @@ struct mwifiex_ra_list_tbl {
struct mwifiex_tid_tbl {
struct list_head ra_list;
/* spin lock for tid table */
spinlock_t tid_tbl_lock;
struct mwifiex_ra_list_tbl *ra_list_curr;
};
#define WMM_HIGHEST_PRIORITY 7
#define HIGH_PRIO_TID 7
#define LOW_PRIO_TID 0
#define NO_PKT_PRIO_TID (-1)
struct mwifiex_wmm_desc {
struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
@ -798,6 +795,8 @@ void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_node);
void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_node);
void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_node,
@ -912,12 +911,20 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
void mwifiex_set_ht_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
void mwifiex_set_vht_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
void mwifiex_set_vht_width(struct mwifiex_private *priv,
enum nl80211_chan_width width,
bool ap_11ac_disable);
void
mwifiex_set_wmm_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_cfg,
struct cfg80211_ap_settings *params);
void mwifiex_set_ba_params(struct mwifiex_private *priv);
void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
/*
* This function checks if the queuing is RA based or not.

View file

@ -287,18 +287,13 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
}
/*
* This function wakes up the card.
*
* A host power up command is written to the card configuration
* register to wake up the card.
* This function adds delay loop to ensure FW is awake before proceeding.
*/
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
{
int i = 0;
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
while (reg->sleep_cookie && mwifiex_pcie_ok_to_access_hw(adapter)) {
while (mwifiex_pcie_ok_to_access_hw(adapter)) {
i++;
usleep_range(10, 20);
/* 50ms max wait */
@ -306,16 +301,32 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
break;
}
return;
}
/* This function wakes up the card by reading fw_status register. */
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
{
u32 fw_status;
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
dev_dbg(adapter->dev, "event: Wakeup device...\n");
/* Enable interrupts or any chip access will wakeup device */
if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) {
dev_warn(adapter->dev, "Enable host interrupt failed\n");
if (reg->sleep_cookie)
mwifiex_pcie_dev_wakeup_delay(adapter);
/* Reading fw_status register will wakeup device */
if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
dev_warn(adapter->dev, "Reading fw_status register failed\n");
return -1;
}
dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
adapter->ps_state = PS_STATE_AWAKE;
if (reg->sleep_cookie) {
mwifiex_pcie_dev_wakeup_delay(adapter);
dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
adapter->ps_state = PS_STATE_AWAKE;
}
return 0;
}
@ -1984,12 +1995,13 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
}
}
} else if (!adapter->pps_uapsd_mode &&
adapter->ps_state == PS_STATE_SLEEP) {
adapter->ps_state == PS_STATE_SLEEP &&
mwifiex_pcie_ok_to_access_hw(adapter)) {
/* Potentially for PCIe we could get other
* interrupts like shared. Don't change power
* state until cookie is set */
if (mwifiex_pcie_ok_to_access_hw(adapter))
adapter->ps_state = PS_STATE_AWAKE;
adapter->ps_state = PS_STATE_AWAKE;
adapter->pm_wakeup_fw_try = false;
}
}
}
@ -2112,7 +2124,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
}
dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
adapter->cmd_sent, adapter->data_sent);
mwifiex_pcie_enable_host_int(adapter);
if (adapter->ps_state != PS_STATE_SLEEP)
mwifiex_pcie_enable_host_int(adapter);
return 0;
}

View file

@ -1393,8 +1393,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
queue_work(adapter->workqueue, &adapter->main_work);
/* Perform internal scan synchronously */
if (!priv->scan_request)
if (!priv->scan_request) {
dev_dbg(adapter->dev, "wait internal scan\n");
mwifiex_wait_queue_complete(adapter, cmd_node);
}
} else {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
@ -1793,7 +1795,12 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
/* Need to indicate IOCTL complete */
if (adapter->curr_cmd->wait_q_enabled) {
adapter->cmd_wait_q.status = 0;
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
if (!priv->scan_request) {
dev_dbg(adapter->dev,
"complete internal scan\n");
mwifiex_complete_cmd(adapter,
adapter->curr_cmd);
}
}
if (priv->report_scan_result)
priv->report_scan_result = false;

View file

@ -24,6 +24,7 @@
#include "main.h"
#include "wmm.h"
#include "11n.h"
#include "11ac.h"
/*
* This function prepares command to set/get RSSI information.
@ -1258,6 +1259,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
S_DS_GEN);
break;
case HostCmd_CMD_11AC_CFG:
ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
break;
case HostCmd_CMD_P2P_MODE_CFG:
cmd_ptr->command = cpu_to_le16(cmd_no);
cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);

View file

@ -95,7 +95,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
break;
}
/* Handling errors here */
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->curr_cmd = NULL;
@ -907,6 +907,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_REMAIN_ON_CHAN:
ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
break;
case HostCmd_CMD_11AC_CFG:
break;
case HostCmd_CMD_P2P_MODE_CFG:
ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
break;

Some files were not shown because too many files have changed in this diff Show more