mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
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:
commit
d3641409a0
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1126,8 @@ skip_tx_iqcal:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 @@ found:
|
||||
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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 @@ done:
|
||||
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 @@ fail:
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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_ */
|
||||
|
@ -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
@ -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_ */
|
||||
|
@ -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 @@ exit:
|
||||
* 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 @@ exit:
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
¶ms_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 @@ exit:
|
||||
|
||||
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 @@ scan_out:
|
||||
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 @@ dongle_scantime_out:
|
||||
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)
|
||||
|
@ -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_ */
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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, ðer_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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
|
@ -4701,8 +4701,7 @@ out:
|
||||
}
|
||||
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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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])");
|
||||
|
@ -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__ */
|
||||
|
@ -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__ */
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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 |
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(¤t_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",
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 @@ check_next_scan:
|
||||
/* 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;
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user