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>
|
</section>
|
||||||
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
|
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
|
||||||
!Finclude/net/mac80211.h ieee80211_beacon_get
|
!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_frame_release_type
|
||||||
!Finclude/net/mac80211.h ieee80211_sta_ps_transition
|
!Finclude/net/mac80211.h ieee80211_sta_ps_transition
|
||||||
!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
|
!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;
|
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)
|
if (cc->capabilities & BCMA_CC_CAP_PMU)
|
||||||
return bcma_pmu_get_alp_clock(cc);
|
return bcma_pmu_get_alp_clock(cc);
|
||||||
|
|
||||||
return 20000000;
|
return 20000000;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
|
||||||
|
|
||||||
static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
|
||||||
|
|
||||||
u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the bit is set to 0, chipcommon controlls this GPIO,
|
* 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;
|
struct bcma_bus *bus = cc->core->bus;
|
||||||
|
|
||||||
switch (bus->chipinfo.id) {
|
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_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_BCM4749:
|
||||||
|
case BCMA_CHIP_ID_BCM5357:
|
||||||
case BCMA_CHIP_ID_BCM53572:
|
case BCMA_CHIP_ID_BCM53572:
|
||||||
|
case BCMA_CHIP_ID_BCM6362:
|
||||||
/* always 20Mhz */
|
/* always 20Mhz */
|
||||||
return 20000 * 1000;
|
return 20000 * 1000;
|
||||||
case BCMA_CHIP_ID_BCM5356:
|
|
||||||
case BCMA_CHIP_ID_BCM4706:
|
case BCMA_CHIP_ID_BCM4706:
|
||||||
|
case BCMA_CHIP_ID_BCM5356:
|
||||||
/* always 25Mhz */
|
/* always 25Mhz */
|
||||||
return 25000 * 1000;
|
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:
|
default:
|
||||||
bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
|
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);
|
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;
|
tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
|
||||||
bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
|
bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
|
||||||
|
|
||||||
tmp = 1 << 10;
|
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCMA_CHIP_ID_BCM4331:
|
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,
|
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
|
||||||
0x03000a08);
|
0x03000a08);
|
||||||
}
|
}
|
||||||
tmp = 1 << 10;
|
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCMA_CHIP_ID_BCM43224:
|
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,
|
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
|
||||||
0x88888815);
|
0x88888815);
|
||||||
}
|
}
|
||||||
tmp = 1 << 10;
|
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCMA_CHIP_ID_BCM4716:
|
case BCMA_CHIP_ID_BCM4716:
|
||||||
|
@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
|
||||||
0x88888815);
|
0x88888815);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = 3 << 9;
|
tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCMA_CHIP_ID_BCM43227:
|
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,
|
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
|
||||||
0x88888815);
|
0x88888815);
|
||||||
}
|
}
|
||||||
tmp = 1 << 10;
|
tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
|
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);
|
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);
|
u32 ent = readl(*eromptr);
|
||||||
(*eromptr)++;
|
(*eromptr)++;
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bcma_erom_push_ent(u32 **eromptr)
|
static void bcma_erom_push_ent(u32 __iomem **eromptr)
|
||||||
{
|
{
|
||||||
(*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);
|
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||||
if (!(ent & SCAN_ER_VALID))
|
if (!(ent & SCAN_ER_VALID))
|
||||||
|
@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
|
||||||
return ent;
|
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);
|
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||||
bcma_erom_push_ent(eromptr);
|
bcma_erom_push_ent(eromptr);
|
||||||
return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
|
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);
|
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||||
bcma_erom_push_ent(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));
|
((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;
|
u32 ent;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -189,7 +189,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
|
||||||
bcma_erom_push_ent(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);
|
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||||
if (!(ent & SCAN_ER_VALID))
|
if (!(ent & SCAN_ER_VALID))
|
||||||
|
@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
|
||||||
return ent;
|
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 type, u8 port)
|
||||||
{
|
{
|
||||||
u32 addrl, addrh, sizel, sizeh = 0;
|
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_rev, SSB_SPROM8_BOARDREV, ~0, 0);
|
||||||
|
SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
|
||||||
|
|
||||||
SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
|
SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
|
||||||
SSB_SPROM4_TXPID2G0_SHIFT);
|
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 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||||
.helper = "sd8688_helper.bin",
|
.helper = "mrvl/sd8688_helper.bin",
|
||||||
.firmware = "sd8688.bin",
|
.firmware = "mrvl/sd8688.bin",
|
||||||
.reg = &btmrvl_reg_8688,
|
.reg = &btmrvl_reg_8688,
|
||||||
.sd_blksz_fw_dl = 64,
|
.sd_blksz_fw_dl = 64,
|
||||||
};
|
};
|
||||||
|
@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
||||||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
|
||||||
MODULE_FIRMWARE("sd8688.bin");
|
MODULE_FIRMWARE("mrvl/sd8688.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8797_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;
|
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;
|
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,
|
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||||
AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
|
AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
|
||||||
ath_dbg(common, CALIBRATE,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
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,
|
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
|
||||||
0, AH_WAIT_TIMEOUT)) {
|
0, AH_WAIT_TIMEOUT)) {
|
||||||
ath_dbg(common, CALIBRATE,
|
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;
|
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,
|
AR_PHY_AGC_CONTROL_CAL,
|
||||||
0, AH_WAIT_TIMEOUT)) {
|
0, AH_WAIT_TIMEOUT)) {
|
||||||
ath_dbg(common, CALIBRATE,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1126,7 +1126,8 @@ skip_tx_iqcal:
|
||||||
ar9003_hw_rtt_disable(ah);
|
ar9003_hw_rtt_disable(ah);
|
||||||
|
|
||||||
ath_dbg(common, CALIBRATE,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2072,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||||
&fops_modal_eeprom);
|
&fops_modal_eeprom);
|
||||||
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
|
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
|
||||||
sc->debug.debugfs_phy,
|
sc->debug.debugfs_phy,
|
||||||
262144, 4, &rfs_spec_scan_cb,
|
1024, 256, &rfs_spec_scan_cb,
|
||||||
NULL);
|
NULL);
|
||||||
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
|
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
|
||||||
sc->debug.debugfs_phy, sc,
|
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);
|
DFS_STAT_INC(sc, pulses_processed);
|
||||||
if (pd != NULL && pd->add_pulse(pd, &pe)) {
|
if (pd != NULL && pd->add_pulse(pd, &pe)) {
|
||||||
DFS_STAT_INC(sc, radar_detected);
|
DFS_STAT_INC(sc, radar_detected);
|
||||||
/*
|
ieee80211_radar_detected(sc->hw);
|
||||||
* TODO: forward radar event to DFS management layer
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,24 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf,
|
||||||
return count;
|
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 = {
|
static const struct file_operations fops_dfs_stats = {
|
||||||
.read = read_file_dfs,
|
.read = read_file_dfs,
|
||||||
.write = write_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,
|
debugfs_create_file("dfs_stats", S_IRUSR,
|
||||||
sc->debug.debugfs_phy, sc, &fops_dfs_stats);
|
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) {
|
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 */
|
/* AR9580 will likely be our first target to get testing on */
|
||||||
case AR_SREV_VERSION_9580:
|
case AR_SREV_VERSION_9580:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,6 +319,10 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
|
||||||
ath9k_ps_wakeup(sc);
|
ath9k_ps_wakeup(sc);
|
||||||
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
|
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
|
||||||
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
|
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);
|
ath9k_ps_restore(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,12 +731,28 @@ static const struct ieee80211_iface_limit if_limits[] = {
|
||||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ieee80211_iface_combination if_comb = {
|
|
||||||
.limits = if_limits,
|
static const struct ieee80211_iface_limit if_dfs_limits[] = {
|
||||||
.n_limits = ARRAY_SIZE(if_limits),
|
{ .max = 1, .types = BIT(NL80211_IFTYPE_AP) },
|
||||||
.max_interfaces = 2048,
|
};
|
||||||
.num_different_channels = 1,
|
|
||||||
.beacon_int_infra_match = true,
|
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)
|
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_ADHOC) |
|
||||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||||
|
|
||||||
hw->wiphy->iface_combinations = &if_comb;
|
hw->wiphy->iface_combinations = if_comb;
|
||||||
hw->wiphy->n_iface_combinations = 1;
|
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||||
|
|
||||||
if (AR_SREV_5416(sc->sc_ah))
|
if (AR_SREV_5416(sc->sc_ah))
|
||||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
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) {
|
if (r) {
|
||||||
ath_err(common,
|
ath_err(common,
|
||||||
"Unable to reset channel, reset status %d\n", r);
|
"Unable to reset channel, reset status %d\n", r);
|
||||||
|
|
||||||
|
ath9k_hw_enable_interrupts(ah);
|
||||||
|
ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,10 +1249,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
if (old_pos >= 0)
|
if (old_pos >= 0)
|
||||||
ath_update_survey_nf(sc, old_pos);
|
ath_update_survey_nf(sc, old_pos);
|
||||||
|
|
||||||
/* perform spectral scan if requested. */
|
/*
|
||||||
if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN)
|
* Enable radar pulse detection if on a DFS channel. Spectral
|
||||||
ath9k_spectral_scan_trigger(hw);
|
* 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) {
|
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);
|
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_softc *sc = hw->priv;
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
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
|
rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
|
||||||
| ATH9K_RX_FILTER_MCAST;
|
| 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)
|
if (sc->rx.rxfilter & FIF_PROBE_REQ)
|
||||||
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
|
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))
|
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
|
||||||
rxs->mactime += 0x100000000ULL;
|
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 (rs.rs_status & ATH9K_RXERR_PHY) {
|
||||||
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
|
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
|
||||||
RX_STAT_INC(rx_spectral);
|
RX_STAT_INC(rx_spectral);
|
||||||
|
|
|
@ -70,12 +70,6 @@
|
||||||
|
|
||||||
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
|
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
|
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
|
||||||
|
|
||||||
enum carl9170_device_state {
|
enum carl9170_device_state {
|
||||||
|
@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
|
||||||
|
|
||||||
/* PHY / RF */
|
/* PHY / RF */
|
||||||
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
|
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);
|
int carl9170_get_noisefloor(struct ar9170 *ar);
|
||||||
|
|
||||||
/* FW */
|
/* FW */
|
||||||
|
|
|
@ -655,7 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
err = carl9170_set_channel(ar, ar->hw->conf.channel,
|
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)
|
if (err < 0)
|
||||||
count = err;
|
count = err;
|
||||||
|
|
||||||
|
|
|
@ -939,7 +939,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = carl9170_set_channel(ar, hw->conf.channel,
|
err = carl9170_set_channel(ar, hw->conf.channel,
|
||||||
hw->conf.channel_type, CARL9170_RFI_NONE);
|
hw->conf.channel_type);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1703,7 +1703,7 @@ found:
|
||||||
return 0;
|
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;
|
struct ar9170 *ar = hw->priv;
|
||||||
unsigned int vid;
|
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,
|
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
|
||||||
enum nl80211_channel_type _bw,
|
enum nl80211_channel_type _bw)
|
||||||
enum carl9170_rf_init_mode rfi)
|
|
||||||
{
|
{
|
||||||
const struct carl9170_phy_freq_params *freqpar;
|
const struct carl9170_phy_freq_params *freqpar;
|
||||||
struct carl9170_rf_init_result rf_res;
|
struct carl9170_rf_init_result rf_res;
|
||||||
struct carl9170_rf_init rf;
|
struct carl9170_rf_init rf;
|
||||||
u32 cmd, tmp, offs = 0, new_ht = 0;
|
u32 tmp, offs = 0, new_ht = 0;
|
||||||
int err;
|
int err;
|
||||||
enum carl9170_bw bw;
|
enum carl9170_bw bw;
|
||||||
bool warm_reset;
|
|
||||||
struct ieee80211_channel *old_channel = NULL;
|
struct ieee80211_channel *old_channel = NULL;
|
||||||
|
|
||||||
bw = nl80211_to_carl(_bw);
|
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 */
|
/* may be NULL at first setup */
|
||||||
if (ar->channel) {
|
if (ar->channel) {
|
||||||
old_channel = 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;
|
ar->channel = NULL;
|
||||||
} else {
|
|
||||||
warm_reset = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HW workaround */
|
/* cold reset BB/ADDA */
|
||||||
if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
|
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
|
||||||
channel->center_freq <= 2417)
|
AR9170_PWR_RESET_BB_COLD_RESET);
|
||||||
warm_reset = true;
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (rfi != CARL9170_RFI_NONE || warm_reset) {
|
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
|
||||||
u32 val;
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (rfi == CARL9170_RFI_COLD)
|
err = carl9170_init_phy(ar, channel->band);
|
||||||
val = AR9170_PWR_RESET_BB_COLD_RESET;
|
if (err)
|
||||||
else
|
return err;
|
||||||
val = AR9170_PWR_RESET_BB_WARM_RESET;
|
|
||||||
|
|
||||||
/* warm/cold reset BB/ADDA */
|
err = carl9170_init_rf_banks_0_7(ar,
|
||||||
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
|
channel->band == IEEE80211_BAND_5GHZ);
|
||||||
if (err)
|
if (err)
|
||||||
return 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_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
|
err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = carl9170_init_rf_bank4_pwr(ar,
|
err = carl9170_init_rf_bank4_pwr(ar,
|
||||||
channel->band == IEEE80211_BAND_5GHZ,
|
channel->band == IEEE80211_BAND_5GHZ,
|
||||||
channel->center_freq, bw);
|
channel->center_freq, bw);
|
||||||
if (err)
|
if (err)
|
||||||
return 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_man = cpu_to_le32(freqpar->coeff_man);
|
||||||
rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
|
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);
|
rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
|
||||||
|
rf.finiteLoopCount = cpu_to_le32(2000);
|
||||||
if (rfi != CARL9170_RFI_NONE)
|
err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf,
|
||||||
rf.finiteLoopCount = cpu_to_le32(2000);
|
|
||||||
else
|
|
||||||
rf.finiteLoopCount = cpu_to_le32(1000);
|
|
||||||
|
|
||||||
err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
|
|
||||||
sizeof(rf_res), &rf_res);
|
sizeof(rf_res), &rf_res);
|
||||||
if (err)
|
if (err)
|
||||||
return 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,
|
old_channel->center_freq : -1, channel->center_freq,
|
||||||
err);
|
err);
|
||||||
|
|
||||||
if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
|
if (ar->chan_fail > 3) {
|
||||||
/*
|
/* We have tried very hard to change to _another_
|
||||||
* We have tried very hard to change to _another_
|
|
||||||
* channel and we've failed to do so!
|
* channel and we've failed to do so!
|
||||||
* Chances are that the PHY/RF is no longer
|
* Chances are that the PHY/RF is no longer
|
||||||
* operable (due to corruptions/fatal events/bugs?)
|
* operable (due to corruptions/fatal events/bugs?)
|
||||||
|
@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = carl9170_set_channel(ar, channel, _bw,
|
err = carl9170_set_channel(ar, channel, _bw);
|
||||||
CARL9170_RFI_COLD);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -45,7 +45,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
|
||||||
void *ah = common->ah;
|
void *ah = common->ah;
|
||||||
|
|
||||||
if (entry >= common->keymax) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +92,8 @@ static bool ath_hw_keysetmac(struct ath_common *common,
|
||||||
void *ah = common->ah;
|
void *ah = common->ah;
|
||||||
|
|
||||||
if (entry >= common->keymax) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +135,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
|
||||||
u32 keyType;
|
u32 keyType;
|
||||||
|
|
||||||
if (entry >= common->keymax) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,9 @@ enum {
|
||||||
#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
|
#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
|
||||||
#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
|
#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
|
||||||
/* SHM_SHARED beacon/AP variables */
|
/* 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_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_BTL1 0x001A /* Beacon template length 1 */
|
||||||
#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
|
#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
|
||||||
#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */
|
#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;
|
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 <<= 16;
|
||||||
val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);
|
val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0);
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
|
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, B43_SHM_SH_JSSI0,
|
||||||
b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);
|
(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)
|
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)
|
if (wl->beacon0_uploaded)
|
||||||
return;
|
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;
|
wl->beacon0_uploaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1633,7 +1635,7 @@ static void b43_upload_beacon1(struct b43_wldev *dev)
|
||||||
|
|
||||||
if (wl->beacon1_uploaded)
|
if (wl->beacon1_uploaded)
|
||||||
return;
|
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;
|
wl->beacon1_uploaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2780,9 +2782,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
|
||||||
switch (dev->dev->bus_type) {
|
switch (dev->dev->bus_type) {
|
||||||
#ifdef CONFIG_B43_BCMA
|
#ifdef CONFIG_B43_BCMA
|
||||||
case B43_BUS_BCMA:
|
case B43_BUS_BCMA:
|
||||||
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
|
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set);
|
||||||
(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
|
|
||||||
BCMA_CC_GPIOCTL) & ~mask) | set);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_B43_SSB
|
#ifdef CONFIG_B43_SSB
|
||||||
|
@ -2807,8 +2807,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
|
||||||
switch (dev->dev->bus_type) {
|
switch (dev->dev->bus_type) {
|
||||||
#ifdef CONFIG_B43_BCMA
|
#ifdef CONFIG_B43_BCMA
|
||||||
case B43_BUS_BCMA:
|
case B43_BUS_BCMA:
|
||||||
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
|
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0);
|
||||||
0);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_B43_SSB
|
#ifdef CONFIG_B43_SSB
|
||||||
|
@ -3116,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev)
|
||||||
|
|
||||||
/* Probe Response Timeout value */
|
/* Probe Response Timeout value */
|
||||||
/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
|
/* 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. */
|
/* Initially set the wireless operation mode. */
|
||||||
b43_adjust_opmode(dev);
|
b43_adjust_opmode(dev);
|
||||||
|
|
|
@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
|
||||||
maxpwr = sprom->maxpwr_bg;
|
maxpwr = sprom->maxpwr_bg;
|
||||||
lpphy->max_tx_pwr_med_band = maxpwr;
|
lpphy->max_tx_pwr_med_band = maxpwr;
|
||||||
cckpo = sprom->cck2gpo;
|
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) {
|
if (cckpo) {
|
||||||
|
ofdmpo = sprom->ofdm2gpo;
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
lpphy->tx_max_rate[i] =
|
lpphy->tx_max_rate[i] =
|
||||||
maxpwr - (ofdmpo & 0xF) * 2;
|
maxpwr - (ofdmpo & 0xF) * 2;
|
||||||
|
@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
|
||||||
ofdmpo >>= 4;
|
ofdmpo >>= 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ofdmpo &= 0xFF;
|
u8 opo = sprom->opo;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
lpphy->tx_max_rate[i] = maxpwr;
|
lpphy->tx_max_rate[i] = maxpwr;
|
||||||
for (i = 4; i < 15; i++)
|
for (i = 4; i < 15; i++)
|
||||||
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
|
lpphy->tx_max_rate[i] = maxpwr - opo;
|
||||||
}
|
}
|
||||||
} else { /* 5GHz */
|
} else { /* 5GHz */
|
||||||
lpphy->tx_isolation_low_band = sprom->tri5gl;
|
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
|
* 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)
|
static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
|
||||||
{//TODO
|
{//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 */
|
/* 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 ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||||
struct b43_phy *phy = &dev->phy;
|
struct b43_phy *phy = &dev->phy;
|
||||||
|
|
|
@ -2980,7 +2980,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
|
||||||
.rx = prefix##_rx, \
|
.rx = prefix##_rx, \
|
||||||
.rx_length = ARRAY_SIZE(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) },
|
[3] = { INITTABSPTS(b2056_inittab_rev3) },
|
||||||
[4] = { INITTABSPTS(b2056_inittab_rev4) },
|
[4] = { INITTABSPTS(b2056_inittab_rev4) },
|
||||||
[5] = { INITTABSPTS(b2056_inittab_rev5) },
|
[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,
|
void b2056_upload_inittabs(struct b43_wldev *dev,
|
||||||
bool ghz5, bool ignore_uploadflag)
|
bool ghz5, bool ignore_uploadflag)
|
||||||
{
|
{
|
||||||
struct b2056_inittabs_pts *pts;
|
const struct b2056_inittabs_pts *pts;
|
||||||
|
|
||||||
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
|
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
|
||||||
B43_WARN_ON(1);
|
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)
|
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;
|
const struct b2056_inittab_entry *e;
|
||||||
|
|
||||||
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
|
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
|
||||||
|
|
|
@ -25,12 +25,12 @@ void b43_sdio_exit(void);
|
||||||
#else /* CONFIG_B43_SDIO */
|
#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))
|
void (*handler)(struct b43_wldev *dev))
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
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)
|
static inline int b43_sdio_init(void)
|
||||||
|
|
|
@ -2800,7 +2800,7 @@ static const struct nphy_rf_control_override_rev7
|
||||||
{ 0x0010, 0x344, 0x345, 0x0010, 4 },
|
{ 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 },
|
{ 10, 14, 19, 27 },
|
||||||
{ -5, 6, 10, 15 },
|
{ -5, 6, 10, 15 },
|
||||||
{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
|
{ 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,
|
0x18, 0x18, 0x18,
|
||||||
0x01D0, 0x5,
|
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 */
|
{ /* 2GHz */
|
||||||
{ /* PHY rev 3 */
|
{ /* PHY rev 3 */
|
||||||
{ 7, 11, 16, 23 },
|
{ 7, 11, 16, 23 },
|
||||||
|
|
|
@ -313,7 +313,7 @@ static const u32 b43_lcntab_0x18[] = {
|
||||||
* TX gain.
|
* 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] = {
|
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
|
||||||
{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
|
{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
|
||||||
{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
|
{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
|
||||||
|
@ -449,7 +449,7 @@ const struct b43_lcntab_tx_gain_tbl_entry
|
||||||
* SW control.
|
* 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,
|
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
|
||||||
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
|
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
|
||||||
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
|
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);
|
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)
|
const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
|
@ -65,7 +65,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
||||||
u8 data;
|
u8 data;
|
||||||
unsigned long flags;
|
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,
|
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
|
||||||
sdiodev->irq_flags, "brcmf_oob_intr",
|
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)
|
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_claim_host(sdiodev->func[1]);
|
||||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
|
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)
|
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_host(sdiodev->func[1]);
|
||||||
sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
|
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)
|
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_claim_host(sdiodev->func[1]);
|
||||||
sdio_release_irq(sdiodev->func[2]);
|
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;
|
u8 data;
|
||||||
int retval;
|
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);
|
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)
|
if (ret)
|
||||||
*ret = retval;
|
*ret = retval;
|
||||||
|
@ -268,9 +268,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
||||||
u32 data;
|
u32 data;
|
||||||
int retval;
|
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);
|
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)
|
if (ret)
|
||||||
*ret = retval;
|
*ret = retval;
|
||||||
|
@ -283,7 +283,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||||
{
|
{
|
||||||
int retval;
|
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);
|
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -295,7 +295,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||||
{
|
{
|
||||||
int retval;
|
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);
|
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -358,7 +358,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
||||||
uint width;
|
uint width;
|
||||||
int err = 0;
|
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);
|
fn, addr, pkt->len);
|
||||||
|
|
||||||
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
|
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;
|
uint width;
|
||||||
int err = 0;
|
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);
|
fn, addr, pktq->qlen);
|
||||||
|
|
||||||
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
|
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;
|
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
|
||||||
int err = 0;
|
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);
|
fn, addr, pkt->len);
|
||||||
|
|
||||||
/* Async not implemented yet */
|
/* 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)
|
int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
|
||||||
{
|
{
|
||||||
char t_func = (char)fn;
|
char t_func = (char)fn;
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
/* issue abort cmd52 command through F0 */
|
/* issue abort cmd52 command through F0 */
|
||||||
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
|
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
|
||||||
SDIO_CCCR_ABORT, &t_func);
|
SDIO_CCCR_ABORT, &t_func);
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Exit\n");
|
brcmf_dbg(SDIO, "Exit\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
|
||||||
{
|
{
|
||||||
int err_ret;
|
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);
|
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
|
||||||
if (brcmf_pm_resume_error(sdiodev))
|
if (brcmf_pm_resume_error(sdiodev))
|
||||||
|
@ -179,7 +179,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
|
||||||
return -EINVAL;
|
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);
|
rw, func, addr, nbytes);
|
||||||
|
|
||||||
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
|
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;
|
struct sk_buff *pkt;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
|
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
|
||||||
if (brcmf_pm_resume_error(sdiodev))
|
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,
|
write ? "TX" : "RX", pkt, SGCount, addr,
|
||||||
pkt_len, err_ret);
|
pkt_len, err_ret);
|
||||||
} else {
|
} 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,
|
write ? "TX" : "RX", pkt, SGCount, addr,
|
||||||
pkt_len);
|
pkt_len);
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
|
||||||
SGCount++;
|
SGCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Exit\n");
|
brcmf_dbg(SDIO, "Exit\n");
|
||||||
return err_ret;
|
return err_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
|
||||||
uint pkt_len;
|
uint pkt_len;
|
||||||
bool fifo = (fix_inc == SDIOH_DATA_FIX);
|
bool fifo = (fix_inc == SDIOH_DATA_FIX);
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
if (pkt == NULL)
|
if (pkt == NULL)
|
||||||
return -EINVAL;
|
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",
|
brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
|
||||||
write ? "TX" : "RX", pkt, addr, pkt_len, status);
|
write ? "TX" : "RX", pkt, addr, pkt_len, status);
|
||||||
} else {
|
} 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);
|
write ? "TX" : "RX", pkt, addr, pkt_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,12 +350,12 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
|
||||||
u32 fbraddr;
|
u32 fbraddr;
|
||||||
u8 func;
|
u8 func;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "\n");
|
brcmf_dbg(SDIO, "\n");
|
||||||
|
|
||||||
/* Get the Card's common CIS address */
|
/* Get the Card's common CIS address */
|
||||||
sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
|
sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
|
||||||
SDIO_CCCR_CIS);
|
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]);
|
sdiodev->func_cis_ptr[0]);
|
||||||
|
|
||||||
/* Get the Card's function CIS (for each function) */
|
/* 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) {
|
func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
|
||||||
sdiodev->func_cis_ptr[func] =
|
sdiodev->func_cis_ptr[func] =
|
||||||
brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
|
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]);
|
func, sdiodev->func_cis_ptr[func]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
||||||
{
|
{
|
||||||
int err_ret = 0;
|
int err_ret = 0;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "\n");
|
brcmf_dbg(SDIO, "\n");
|
||||||
|
|
||||||
sdiodev->num_funcs = 2;
|
sdiodev->num_funcs = 2;
|
||||||
|
|
||||||
|
@ -404,13 +404,13 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sdio_release_host(sdiodev->func[1]);
|
sdio_release_host(sdiodev->func[1]);
|
||||||
brcmf_dbg(TRACE, "Done\n");
|
brcmf_dbg(SDIO, "Done\n");
|
||||||
return err_ret;
|
return err_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
||||||
{
|
{
|
||||||
brcmf_dbg(TRACE, "\n");
|
brcmf_dbg(SDIO, "\n");
|
||||||
|
|
||||||
/* Disable Function 2 */
|
/* Disable Function 2 */
|
||||||
sdio_claim_host(sdiodev->func[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_sdio_dev *sdiodev;
|
||||||
struct brcmf_bus *bus_if;
|
struct brcmf_bus *bus_if;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
brcmf_dbg(TRACE, "Class=%x\n", func->class);
|
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
||||||
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
|
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
|
||||||
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
|
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||||
brcmf_dbg(TRACE, "Function#: %d\n", func->num);
|
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
||||||
|
|
||||||
/* Consume func num 1 but dont do anything with it. */
|
/* Consume func num 1 but dont do anything with it. */
|
||||||
if (func->num == 1)
|
if (func->num == 1)
|
||||||
|
@ -501,13 +501,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
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);
|
err = brcmf_sdio_probe(sdiodev);
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_err("F2 error, probe failed %d...\n", err);
|
brcmf_err("F2 error, probe failed %d...\n", err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
brcmf_dbg(TRACE, "F2 init completed...\n");
|
brcmf_dbg(SDIO, "F2 init completed...\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -523,10 +523,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
||||||
struct brcmf_bus *bus_if;
|
struct brcmf_bus *bus_if;
|
||||||
struct brcmf_sdio_dev *sdiodev;
|
struct brcmf_sdio_dev *sdiodev;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
|
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
|
||||||
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
|
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||||
brcmf_dbg(TRACE, "Function: %d\n", func->num);
|
brcmf_dbg(SDIO, "Function: %d\n", func->num);
|
||||||
|
|
||||||
if (func->num != 1 && func->num != 2)
|
if (func->num != 1 && func->num != 2)
|
||||||
return;
|
return;
|
||||||
|
@ -543,7 +543,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
||||||
kfree(sdiodev);
|
kfree(sdiodev);
|
||||||
}
|
}
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Exit\n");
|
brcmf_dbg(SDIO, "Exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#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;
|
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "\n");
|
brcmf_dbg(SDIO, "\n");
|
||||||
|
|
||||||
atomic_set(&sdiodev->suspend, true);
|
atomic_set(&sdiodev->suspend, true);
|
||||||
|
|
||||||
|
@ -645,7 +645,7 @@ static struct platform_driver brcmf_sdio_pd = {
|
||||||
|
|
||||||
void brcmf_sdio_exit(void)
|
void brcmf_sdio_exit(void)
|
||||||
{
|
{
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||||
|
|
||||||
|
@ -656,7 +656,7 @@ void brcmf_sdio_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
ret = platform_driver_register(&brcmf_sdio_pd);
|
ret = platform_driver_register(&brcmf_sdio_pd);
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ void brcmf_sdio_init(void)
|
||||||
#else
|
#else
|
||||||
void brcmf_sdio_exit(void)
|
void brcmf_sdio_exit(void)
|
||||||
{
|
{
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ void brcmf_sdio_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
#define BRCMF_C_SET_WSEC 134
|
#define BRCMF_C_SET_WSEC 134
|
||||||
#define BRCMF_C_GET_PHY_NOISE 135
|
#define BRCMF_C_GET_PHY_NOISE 135
|
||||||
#define BRCMF_C_GET_BSS_INFO 136
|
#define BRCMF_C_GET_BSS_INFO 136
|
||||||
|
#define BRCMF_C_GET_BANDLIST 140
|
||||||
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
||||||
#define BRCMF_C_GET_PHYLIST 180
|
#define BRCMF_C_GET_PHYLIST 180
|
||||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
#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 */
|
__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_PROBRESP_MSG
|
||||||
* WLC_E_P2P_PROBREQ_MSG
|
* WLC_E_P2P_PROBREQ_MSG
|
||||||
|
@ -542,10 +548,25 @@ struct brcmf_if_event {
|
||||||
u8 action;
|
u8 action;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 bssidx;
|
u8 bssidx;
|
||||||
|
u8 role;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* forward declaration */
|
/* forward declarations */
|
||||||
struct brcmf_cfg80211_vif;
|
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.
|
* struct brcmf_if - interface control information.
|
||||||
|
@ -554,9 +575,13 @@ struct brcmf_cfg80211_vif;
|
||||||
* @vif: points to cfg80211 specific interface information.
|
* @vif: points to cfg80211 specific interface information.
|
||||||
* @ndev: associated network device.
|
* @ndev: associated network device.
|
||||||
* @stats: interface specific network statistics.
|
* @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.
|
* @ifidx: interface index in device firmware.
|
||||||
* @bssidx: index of bss associated with this interface.
|
* @bssidx: index of bss associated with this interface.
|
||||||
* @mac_addr: assigned mac address.
|
* @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_cnt: tracks outstanding number of 802.1x frames.
|
||||||
* @pend_8021x_wait: used for signalling change in count.
|
* @pend_8021x_wait: used for signalling change in count.
|
||||||
*/
|
*/
|
||||||
|
@ -567,9 +592,11 @@ struct brcmf_if {
|
||||||
struct net_device_stats stats;
|
struct net_device_stats stats;
|
||||||
struct work_struct setmacaddr_work;
|
struct work_struct setmacaddr_work;
|
||||||
struct work_struct multicast_work;
|
struct work_struct multicast_work;
|
||||||
|
struct brcmf_fws_mac_descriptor *fws_desc;
|
||||||
int ifidx;
|
int ifidx;
|
||||||
s32 bssidx;
|
s32 bssidx;
|
||||||
u8 mac_addr[ETH_ALEN];
|
u8 mac_addr[ETH_ALEN];
|
||||||
|
u8 netif_stop;
|
||||||
atomic_t pend_8021x_cnt;
|
atomic_t pend_8021x_cnt;
|
||||||
wait_queue_head_t pend_8021x_wait;
|
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,
|
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
|
||||||
s32 ifidx, char *name, u8 *mac_addr);
|
s32 ifidx, char *name, u8 *mac_addr);
|
||||||
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
|
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 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_ */
|
#endif /* _BRCMF_H_ */
|
||||||
|
|
|
@ -39,10 +39,12 @@ struct brcmf_bus_dcmd {
|
||||||
* @txdata: send a data frame to the dongle (callee disposes skb).
|
* @txdata: send a data frame to the dongle (callee disposes skb).
|
||||||
* @txctl: transmit a control request message to dongle.
|
* @txctl: transmit a control request message to dongle.
|
||||||
* @rxctl: receive a control response message from 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
|
* This structure provides an abstract interface towards the
|
||||||
* bus specific driver. For control messages to common driver
|
* 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 {
|
struct brcmf_bus_ops {
|
||||||
int (*init)(struct device *dev);
|
int (*init)(struct device *dev);
|
||||||
|
@ -50,6 +52,7 @@ struct brcmf_bus_ops {
|
||||||
int (*txdata)(struct device *dev, struct sk_buff *skb);
|
int (*txdata)(struct device *dev, struct sk_buff *skb);
|
||||||
int (*txctl)(struct device *dev, unsigned char *msg, uint len);
|
int (*txctl)(struct device *dev, unsigned char *msg, uint len);
|
||||||
int (*rxctl)(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);
|
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
|
* 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 */
|
/* Pop BDC header used to convey priority for buses that don't */
|
||||||
|
|
||||||
if (pktbuf->len < BDC_HEADER_LEN) {
|
if (pktbuf->len <= BDC_HEADER_LEN) {
|
||||||
brcmf_err("rx data too short (%d < %d)\n",
|
brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
|
||||||
pktbuf->len, BDC_HEADER_LEN);
|
pktbuf->len, BDC_HEADER_LEN);
|
||||||
return -EBADE;
|
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)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct brcmf_fws_stats *fwstats = f->private_data;
|
struct brcmf_fws_stats *fwstats = f->private_data;
|
||||||
char buf[100];
|
char buf[650];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* only allow read from start */
|
/* only allow read from start */
|
||||||
|
@ -138,14 +138,52 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
res = scnprintf(buf, sizeof(buf),
|
res = scnprintf(buf, sizeof(buf),
|
||||||
"header_pulls: %u\n"
|
"header_pulls: %u\n"
|
||||||
"header_only_pkt: %u\n"
|
"header_only_pkt: %u\n"
|
||||||
"tlv_parse_failed: %u\n"
|
"tlv_parse_failed: %u\n"
|
||||||
"tlv_invalid_type: %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_pulls,
|
||||||
fwstats->header_only_pkt,
|
fwstats->header_only_pkt,
|
||||||
fwstats->tlv_parse_failed,
|
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);
|
return simple_read_from_buffer(data, count, ppos, buf, res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define BRCMF_SCAN_VAL 0x00004000
|
#define BRCMF_SCAN_VAL 0x00004000
|
||||||
#define BRCMF_CONN_VAL 0x00008000
|
#define BRCMF_CONN_VAL 0x00008000
|
||||||
#define BRCMF_CDC_VAL 0x00010000
|
#define BRCMF_CDC_VAL 0x00010000
|
||||||
|
#define BRCMF_SDIO_VAL 0x00020000
|
||||||
|
|
||||||
/* set default print format */
|
/* set default print format */
|
||||||
#undef pr_fmt
|
#undef pr_fmt
|
||||||
|
@ -92,6 +93,7 @@ do { \
|
||||||
|
|
||||||
#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \
|
#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
|
trace_brcmf_hexdump((void *)data, len); \
|
||||||
if (test) \
|
if (test) \
|
||||||
brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \
|
brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -137,6 +139,25 @@ struct brcmf_fws_stats {
|
||||||
u32 tlv_invalid_type;
|
u32 tlv_invalid_type;
|
||||||
u32 header_only_pkt;
|
u32 header_only_pkt;
|
||||||
u32 header_pulls;
|
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;
|
struct brcmf_pub;
|
||||||
|
|
|
@ -223,18 +223,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle ethernet header */
|
ret = brcmf_fws_process_skb(ifp, skb);
|
||||||
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);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -248,9 +237,27 @@ done:
|
||||||
return NETDEV_TX_OK;
|
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)
|
void brcmf_txflowblock(struct device *dev, bool state)
|
||||||
{
|
{
|
||||||
struct net_device *ndev;
|
|
||||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||||
struct brcmf_pub *drvr = bus_if->drvr;
|
struct brcmf_pub *drvr = bus_if->drvr;
|
||||||
int i;
|
int i;
|
||||||
|
@ -258,13 +265,8 @@ void brcmf_txflowblock(struct device *dev, bool state)
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(TRACE, "Enter\n");
|
||||||
|
|
||||||
for (i = 0; i < BRCMF_MAX_IFS; i++)
|
for (i = 0; i < BRCMF_MAX_IFS; i++)
|
||||||
if (drvr->iflist[i]) {
|
brcmf_txflowblock_if(drvr->iflist[i],
|
||||||
ndev = drvr->iflist[i]->ndev;
|
BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
|
||||||
if (state)
|
|
||||||
netif_stop_queue(ndev);
|
|
||||||
else
|
|
||||||
netif_wake_queue(ndev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
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 */
|
/* Strip header, count, deliver upward */
|
||||||
skb_pull(skb, ETH_HLEN);
|
skb_pull(skb, ETH_HLEN);
|
||||||
|
|
||||||
/* Process special event packets and then discard them */
|
/* Process special event packets */
|
||||||
brcmf_fweh_process_skb(drvr, skb, &ifidx);
|
brcmf_fweh_process_skb(drvr, skb);
|
||||||
|
|
||||||
if (drvr->iflist[ifidx]) {
|
|
||||||
ifp = drvr->iflist[ifidx];
|
|
||||||
ifp->ndev->last_rx = jiffies;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||||
brcmu_pkt_buf_free_skb(skb);
|
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 brcmf_if *ifp;
|
||||||
|
struct ethhdr *eh;
|
||||||
|
u8 ifidx;
|
||||||
|
u16 type;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
|
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)
|
if (!success)
|
||||||
ifp->stats.tx_errors++;
|
ifp->stats.tx_errors++;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
brcmu_pkt_buf_free_skb(txp);
|
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)
|
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp = netdev_priv(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 */
|
if (!brcmf_p2p_enable && bssidx == 1) {
|
||||||
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
|
/* this is P2P_DEVICE interface */
|
||||||
if (!ndev) {
|
brcmf_dbg(INFO, "allocate non-netdev interface\n");
|
||||||
brcmf_err("OOM - alloc_netdev\n");
|
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
|
||||||
return ERR_PTR(-ENOMEM);
|
} 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;
|
ifp->drvr = drvr;
|
||||||
drvr->iflist[bssidx] = ifp;
|
drvr->iflist[bssidx] = ifp;
|
||||||
ifp->ifidx = ifidx;
|
ifp->ifidx = ifidx;
|
||||||
ifp->bssidx = bssidx;
|
ifp->bssidx = bssidx;
|
||||||
|
|
||||||
|
|
||||||
init_waitqueue_head(&ifp->pend_8021x_wait);
|
init_waitqueue_head(&ifp->pend_8021x_wait);
|
||||||
|
|
||||||
if (mac_addr != NULL)
|
if (mac_addr != NULL)
|
||||||
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||||
|
|
||||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
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;
|
return ifp;
|
||||||
}
|
}
|
||||||
|
@ -794,11 +810,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||||
}
|
}
|
||||||
|
|
||||||
unregister_netdev(ifp->ndev);
|
unregister_netdev(ifp->ndev);
|
||||||
drvr->iflist[bssidx] = NULL;
|
|
||||||
if (bssidx == 0)
|
if (bssidx == 0)
|
||||||
brcmf_cfg80211_detach(drvr->config);
|
brcmf_cfg80211_detach(drvr->config);
|
||||||
free_netdev(ifp->ndev);
|
free_netdev(ifp->ndev);
|
||||||
|
} else {
|
||||||
|
kfree(ifp);
|
||||||
}
|
}
|
||||||
|
drvr->iflist[bssidx] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||||
|
@ -882,6 +900,7 @@ int brcmf_bus_start(struct device *dev)
|
||||||
|
|
||||||
drvr->fw_signals = true;
|
drvr->fw_signals = true;
|
||||||
(void)brcmf_fws_init(drvr);
|
(void)brcmf_fws_init(drvr);
|
||||||
|
brcmf_fws_add_interface(ifp);
|
||||||
|
|
||||||
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
|
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
|
||||||
if (drvr->config == NULL) {
|
if (drvr->config == NULL) {
|
||||||
|
@ -899,8 +918,10 @@ fail:
|
||||||
brcmf_err("failed: %d\n", ret);
|
brcmf_err("failed: %d\n", ret);
|
||||||
if (drvr->config)
|
if (drvr->config)
|
||||||
brcmf_cfg80211_detach(drvr->config);
|
brcmf_cfg80211_detach(drvr->config);
|
||||||
if (drvr->fws)
|
if (drvr->fws) {
|
||||||
|
brcmf_fws_del_interface(ifp);
|
||||||
brcmf_fws_deinit(drvr);
|
brcmf_fws_deinit(drvr);
|
||||||
|
}
|
||||||
free_netdev(ifp->ndev);
|
free_netdev(ifp->ndev);
|
||||||
drvr->iflist[0] = NULL;
|
drvr->iflist[0] = NULL;
|
||||||
if (p2p_ifp) {
|
if (p2p_ifp) {
|
||||||
|
@ -956,16 +977,17 @@ void brcmf_detach(struct device *dev)
|
||||||
|
|
||||||
/* make sure primary interface removed last */
|
/* make sure primary interface removed last */
|
||||||
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
|
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_del_if(drvr, i);
|
||||||
|
}
|
||||||
|
|
||||||
brcmf_bus_detach(drvr);
|
brcmf_bus_detach(drvr);
|
||||||
|
|
||||||
if (drvr->prot)
|
if (drvr->prot)
|
||||||
brcmf_proto_detach(drvr);
|
brcmf_proto_detach(drvr);
|
||||||
|
|
||||||
if (drvr->fws)
|
brcmf_fws_deinit(drvr);
|
||||||
brcmf_fws_deinit(drvr);
|
|
||||||
|
|
||||||
brcmf_debugfs_detach(drvr);
|
brcmf_debugfs_detach(drvr);
|
||||||
bus_if->drvr = NULL;
|
bus_if->drvr = NULL;
|
||||||
|
|
|
@ -94,6 +94,7 @@ struct rte_console {
|
||||||
|
|
||||||
#include "dhd_bus.h"
|
#include "dhd_bus.h"
|
||||||
#include "dhd_dbg.h"
|
#include "dhd_dbg.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
|
|
||||||
#define TXQLEN 2048 /* bulk tx queue length */
|
#define TXQLEN 2048 /* bulk tx queue length */
|
||||||
#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
|
#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;
|
u8 clkctl, clkreq, devctl;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
clkctl = 0;
|
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;
|
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
|
||||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||||
devctl, &err);
|
devctl, &err);
|
||||||
brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
|
brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
|
||||||
bus->clkstate = CLK_PENDING;
|
bus->clkstate = CLK_PENDING;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -750,7 +751,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
||||||
|
|
||||||
/* Mark clock available */
|
/* Mark clock available */
|
||||||
bus->clkstate = CLK_AVAIL;
|
bus->clkstate = CLK_AVAIL;
|
||||||
brcmf_dbg(INFO, "CLKCTL: turned ON\n");
|
brcmf_dbg(SDIO, "CLKCTL: turned ON\n");
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
if (!bus->alp_only) {
|
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;
|
bus->clkstate = CLK_SDONLY;
|
||||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||||
clkreq, &err);
|
clkreq, &err);
|
||||||
brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
|
brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_err("Failed access turning clock off: %d\n",
|
brcmf_err("Failed access turning clock off: %d\n",
|
||||||
err);
|
err);
|
||||||
|
@ -788,7 +789,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
||||||
/* Change idle/active SD state */
|
/* Change idle/active SD state */
|
||||||
static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
|
static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
|
||||||
{
|
{
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
bus->clkstate = CLK_SDONLY;
|
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;
|
uint oldstate = bus->clkstate;
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
/* Early exit if we're already there */
|
/* Early exit if we're already there */
|
||||||
if (bus->clkstate == target) {
|
if (bus->clkstate == target) {
|
||||||
|
@ -849,7 +850,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
|
brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -862,7 +863,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
|
||||||
u8 fcbits;
|
u8 fcbits;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
|
|
||||||
/* Read mailbox data and ack that we did so */
|
/* Read mailbox data and ack that we did so */
|
||||||
ret = r_sdreg32(bus, &hmb_data,
|
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 */
|
/* Dongle recomposed rx frames, accept them again */
|
||||||
if (hmb_data & HMB_DATA_NAKHANDLED) {
|
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);
|
bus->rx_seq);
|
||||||
if (!bus->rxskip)
|
if (!bus->rxskip)
|
||||||
brcmf_err("unexpected NAKHANDLED!\n");
|
brcmf_err("unexpected NAKHANDLED!\n");
|
||||||
|
@ -896,7 +897,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
|
||||||
"expecting %d\n",
|
"expecting %d\n",
|
||||||
bus->sdpcm_ver, SDPCM_PROT_VERSION);
|
bus->sdpcm_ver, SDPCM_PROT_VERSION);
|
||||||
else
|
else
|
||||||
brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
|
brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
|
||||||
bus->sdpcm_ver);
|
bus->sdpcm_ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,7 +971,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
|
||||||
if (!retries)
|
if (!retries)
|
||||||
brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
|
brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
|
||||||
else
|
else
|
||||||
brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
|
brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries);
|
||||||
|
|
||||||
if (rtx) {
|
if (rtx) {
|
||||||
bus->sdcnt.rxrtx++;
|
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 */
|
/* If packets, issue read(s) and send up packet chain */
|
||||||
/* Return sequence numbers consumed? */
|
/* 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));
|
bus->glomd, skb_peek(&bus->glom));
|
||||||
|
|
||||||
/* If there's a descriptor, generate the packet chain */
|
/* 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;
|
u8 *frame;
|
||||||
u16 len, pad = 0;
|
u16 len, pad = 0;
|
||||||
u32 swheader;
|
u32 swheader;
|
||||||
struct sk_buff *new;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
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",
|
brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
|
||||||
skb_headroom(pkt), pad);
|
skb_headroom(pkt), pad);
|
||||||
bus->sdiodev->bus_if->tx_realloc++;
|
bus->sdiodev->bus_if->tx_realloc++;
|
||||||
new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
|
ret = skb_cow(pkt, BRCMF_SDALIGN);
|
||||||
if (!new) {
|
if (ret)
|
||||||
brcmf_err("couldn't allocate new %d-byte packet\n",
|
|
||||||
pkt->len + BRCMF_SDALIGN);
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
pad = ((unsigned long)frame % BRCMF_SDALIGN);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
skb_push(pkt, pad);
|
||||||
|
frame = (u8 *) (pkt->data);
|
||||||
|
memset(frame, 0, pad + SDPCM_HDRLEN);
|
||||||
}
|
}
|
||||||
/* precondition: pad < BRCMF_SDALIGN */
|
/* precondition: pad < BRCMF_SDALIGN */
|
||||||
|
|
||||||
|
@ -1830,8 +1817,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
|
||||||
(((pad +
|
(((pad +
|
||||||
SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
|
SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
|
||||||
|
|
||||||
put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
|
*(((__le32 *) frame) + 1) = cpu_to_le32(swheader);
|
||||||
put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
|
*(((__le32 *) frame) + 2) = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
tx_packets[pkt->priority]++;
|
tx_packets[pkt->priority]++;
|
||||||
|
@ -1897,7 +1884,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
|
||||||
done:
|
done:
|
||||||
/* restore pkt buffer pointer before calling tx complete routine */
|
/* restore pkt buffer pointer before calling tx complete routine */
|
||||||
skb_pull(pkt, SDPCM_HDRLEN + pad);
|
skb_pull(pkt, SDPCM_HDRLEN + pad);
|
||||||
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
|
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2131,7 +2118,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
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);
|
devctl, clkctl);
|
||||||
|
|
||||||
if (SBSDIO_HTAV(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)
|
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
||||||
{
|
{
|
||||||
int ret = -EBADE;
|
int ret = -EBADE;
|
||||||
|
@ -2392,7 +2388,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
|
||||||
|
|
||||||
/* Do the transfer(s) */
|
/* Do the transfer(s) */
|
||||||
while (size) {
|
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,
|
write ? "write" : "read", dsize,
|
||||||
sdaddr, address & SBSDIO_SBWINDOW_MASK);
|
sdaddr, address & SBSDIO_SBWINDOW_MASK);
|
||||||
bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
|
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));
|
msecs_to_jiffies(2000));
|
||||||
|
|
||||||
if (!bus->ctrl_frame_stat) {
|
if (!bus->ctrl_frame_stat) {
|
||||||
brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
|
brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
|
brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2699,7 +2695,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||||
|
|
||||||
addr = le32_to_cpu(addr_le);
|
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.
|
* 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->console_addr = le32_to_cpu(sh_le.console_addr);
|
||||||
sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
|
sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
|
||||||
|
|
||||||
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
|
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
|
||||||
brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n",
|
brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
|
||||||
SDPCM_SHARED_VERSION,
|
SDPCM_SHARED_VERSION,
|
||||||
sh->flags & SDPCM_SHARED_VERSION_MASK);
|
sh->flags & SDPCM_SHARED_VERSION_MASK);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
@ -2809,21 +2805,18 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
||||||
int error, res;
|
int error, res;
|
||||||
char buf[350];
|
char buf[350];
|
||||||
struct brcmf_trap_info tr;
|
struct brcmf_trap_info tr;
|
||||||
int nbytes;
|
|
||||||
loff_t pos = 0;
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||||
sizeof(struct brcmf_trap_info));
|
sizeof(struct brcmf_trap_info));
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
|
|
||||||
if (nbytes < 0)
|
|
||||||
return nbytes;
|
|
||||||
|
|
||||||
res = scnprintf(buf, sizeof(buf),
|
res = scnprintf(buf, sizeof(buf),
|
||||||
"dongle trap info: type 0x%x @ epc 0x%08x\n"
|
"dongle trap info: type 0x%x @ epc 0x%08x\n"
|
||||||
" cpsr 0x%08x spsr 0x%08x sp 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.r4), le32_to_cpu(tr.r5),
|
||||||
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
|
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
|
||||||
|
|
||||||
error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res);
|
return simple_read_from_buffer(data, count, &pos, buf, res);
|
||||||
if (error < 0)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
nbytes += error;
|
|
||||||
return nbytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
|
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);
|
error = brcmf_sdio_assert_info(bus, &sh, data, count);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
nbytes = error;
|
nbytes = error;
|
||||||
error = brcmf_sdio_trap_info(bus, &sh, data, count);
|
|
||||||
|
error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
nbytes += error;
|
||||||
|
|
||||||
error += nbytes;
|
error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
|
||||||
*ppos += error;
|
if (error < 0)
|
||||||
|
goto done;
|
||||||
|
nbytes += error;
|
||||||
|
|
||||||
|
error = nbytes;
|
||||||
|
*ppos += nbytes;
|
||||||
done:
|
done:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -3309,15 +3303,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* External image takes precedence if specified */
|
|
||||||
if (brcmf_sdbrcm_download_code_file(bus)) {
|
if (brcmf_sdbrcm_download_code_file(bus)) {
|
||||||
brcmf_err("dongle image file download failed\n");
|
brcmf_err("dongle image file download failed\n");
|
||||||
goto err;
|
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");
|
brcmf_err("dongle nvram file download failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take arm out of reset */
|
/* Take arm out of reset */
|
||||||
if (brcmf_sdbrcm_download_state(bus, false)) {
|
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,
|
.txdata = brcmf_sdbrcm_bus_txdata,
|
||||||
.txctl = brcmf_sdbrcm_bus_txctl,
|
.txctl = brcmf_sdbrcm_bus_txctl,
|
||||||
.rxctl = brcmf_sdbrcm_bus_rxctl,
|
.rxctl = brcmf_sdbrcm_bus_rxctl,
|
||||||
|
.gettxq = brcmf_sdbrcm_bus_gettxq,
|
||||||
};
|
};
|
||||||
|
|
||||||
void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include "dhd.h"
|
#include "dhd.h"
|
||||||
#include "dhd_dbg.h"
|
#include "dhd_dbg.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
|
#include "fwsignal.h"
|
||||||
#include "fweh.h"
|
#include "fweh.h"
|
||||||
#include "fwil.h"
|
#include "fwil.h"
|
||||||
|
|
||||||
|
@ -154,7 +156,7 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
|
||||||
fweh = &ifp->drvr->fweh;
|
fweh = &ifp->drvr->fweh;
|
||||||
|
|
||||||
/* handle the event if valid interface and handler */
|
/* 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);
|
err = fweh->evt_handler[code](ifp, emsg, data);
|
||||||
else
|
else
|
||||||
brcmf_err("unhandled event %d ignored\n", code);
|
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;
|
struct brcmf_if *ifp;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n",
|
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
|
||||||
ifevent->action, ifevent->ifidx,
|
ifevent->action, ifevent->ifidx, ifevent->bssidx,
|
||||||
ifevent->bssidx, ifevent->flags);
|
ifevent->flags, ifevent->role);
|
||||||
|
|
||||||
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
||||||
brcmf_err("invalid interface index: %u\n",
|
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);
|
emsg->ifname, emsg->addr);
|
||||||
if (IS_ERR(ifp))
|
if (IS_ERR(ifp))
|
||||||
return;
|
return;
|
||||||
|
brcmf_fws_add_interface(ifp);
|
||||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||||
err = brcmf_net_attach(ifp, false);
|
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);
|
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);
|
brcmf_del_if(drvr, ifevent->bssidx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -400,13 +407,12 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
|
||||||
*
|
*
|
||||||
* @drvr: driver information object.
|
* @drvr: driver information object.
|
||||||
* @event_packet: event packet to process.
|
* @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
|
* If the packet buffer contains a firmware event message it will
|
||||||
* dispatch the event to a registered handler (using worker).
|
* dispatch the event to a registered handler (using worker).
|
||||||
*/
|
*/
|
||||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
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;
|
enum brcmf_fweh_event_code code;
|
||||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||||
|
@ -418,7 +424,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||||
/* get event info */
|
/* get event info */
|
||||||
code = get_unaligned_be32(&event_packet->msg.event_type);
|
code = get_unaligned_be32(&event_packet->msg.event_type);
|
||||||
datalen = get_unaligned_be32(&event_packet->msg.datalen);
|
datalen = get_unaligned_be32(&event_packet->msg.datalen);
|
||||||
*ifidx = event_packet->msg.ifidx;
|
|
||||||
data = &event_packet[1];
|
data = &event_packet[1];
|
||||||
|
|
||||||
if (code >= BRCMF_E_LAST)
|
if (code >= BRCMF_E_LAST)
|
||||||
|
@ -435,7 +440,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event->code = code;
|
event->code = code;
|
||||||
event->ifidx = *ifidx;
|
event->ifidx = event_packet->msg.ifidx;
|
||||||
|
|
||||||
/* use memcpy to get aligned event message */
|
/* use memcpy to get aligned event message */
|
||||||
memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
|
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);
|
enum brcmf_fweh_event_code code);
|
||||||
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
|
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
|
||||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
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,
|
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;
|
struct brcmf_event *event_packet;
|
||||||
u8 *data;
|
u8 *data;
|
||||||
|
@ -213,7 +213,7 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
|
||||||
if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
|
if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
brcmf_fweh_process_event(drvr, event_packet, ifidx);
|
brcmf_fweh_process_event(drvr, event_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FWEH_H_ */
|
#endif /* FWEH_H_ */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "dhd.h"
|
#include "dhd.h"
|
||||||
#include "dhd_bus.h"
|
#include "dhd_bus.h"
|
||||||
#include "dhd_dbg.h"
|
#include "dhd_dbg.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
#include "fwil.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);
|
int brcmf_fws_init(struct brcmf_pub *drvr);
|
||||||
void brcmf_fws_deinit(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,
|
int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||||
struct sk_buff *skb);
|
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_ */
|
#endif /* FWSIGNAL_H_ */
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
#include <net/cfg80211.h>
|
#include <net/cfg80211.h>
|
||||||
|
|
||||||
#include <brcmu_wifi.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;
|
s32 ret = 0;
|
||||||
|
|
||||||
|
brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
|
||||||
brcmf_fil_iovar_int_set(ifp, "apsta", 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
|
/* In case of COB type, firmware has default mac address
|
||||||
* After Initializing firmware, we have to set current mac address to
|
* 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.
|
* brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P.
|
||||||
*
|
*
|
||||||
* @p2p: P2P specific data.
|
* @p2p: P2P specific data.
|
||||||
|
* @dev_addr: optional device address.
|
||||||
*
|
*
|
||||||
* P2P needs mac addresses for P2P device and interface. These are
|
* P2P needs mac addresses for P2P device and interface. If no device
|
||||||
* derived from the primary net device, ie. the permanent ethernet
|
* address it specified, these are derived from the primary net device, ie.
|
||||||
* address of the device.
|
* 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 *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
|
/* Generate the P2P Device Address. This consists of the device's
|
||||||
* primary MAC address with the locally administered bit set.
|
* primary MAC address with the locally administered bit set.
|
||||||
*/
|
*/
|
||||||
memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN);
|
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
|
||||||
p2p->dev_addr[0] |= 0x02;
|
if (local_admin)
|
||||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
p2p->dev_addr[0] |= 0x02;
|
||||||
|
|
||||||
/* Generate the P2P Interface Address. If the discovery and connection
|
/* Generate the P2P Interface Address. If the discovery and connection
|
||||||
* BSSCFGs need to simultaneously co-exist, then this address must be
|
* BSSCFGs need to simultaneously co-exist, then this address must be
|
||||||
* different from the P2P Device Address, but also locally administered.
|
* different from the P2P Device Address, but also locally administered.
|
||||||
*/
|
*/
|
||||||
memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
|
memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
|
||||||
|
p2p->int_addr[0] |= 0x02;
|
||||||
p2p->int_addr[4] ^= 0x80;
|
p2p->int_addr[4] ^= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +783,7 @@ exit:
|
||||||
* validates the channels in the request.
|
* validates the channels in the request.
|
||||||
*/
|
*/
|
||||||
static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
|
static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
|
||||||
struct net_device *ndev,
|
struct brcmf_if *ifp,
|
||||||
struct cfg80211_scan_request *request,
|
struct cfg80211_scan_request *request,
|
||||||
u16 action)
|
u16 action)
|
||||||
{
|
{
|
||||||
|
@ -1261,7 +1271,7 @@ static void
|
||||||
brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
|
brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
|
||||||
{
|
{
|
||||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
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) &&
|
if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
|
||||||
(test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &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.
|
* So abort scan for off channel completion.
|
||||||
*/
|
*/
|
||||||
if (p2p->af_sent_channel)
|
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,
|
} else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
|
||||||
&p2p->status)) {
|
&p2p->status)) {
|
||||||
brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n");
|
brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n");
|
||||||
/* So abort scan to cancel listen */
|
/* 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 */
|
/* After complete GO Negotiation, roll back to mpc mode */
|
||||||
if ((action == P2P_PAF_GON_CONF) ||
|
if ((action == P2P_PAF_GON_CONF) ||
|
||||||
(action == P2P_PAF_PROVDIS_RSP))
|
(action == P2P_PAF_PROVDIS_RSP))
|
||||||
brcmf_set_mpc(ifp->ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
if (action == P2P_PAF_GON_CONF) {
|
if (action == P2P_PAF_GON_CONF) {
|
||||||
brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n");
|
brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n");
|
||||||
clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
|
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) ?
|
CHSPEC_IS2G(chanspec) ?
|
||||||
IEEE80211_BAND_2GHZ :
|
IEEE80211_BAND_2GHZ :
|
||||||
IEEE80211_BAND_5GHZ);
|
IEEE80211_BAND_5GHZ);
|
||||||
wdev = ifp->ndev->ieee80211_ptr;
|
|
||||||
|
wdev = &ifp->vif->wdev;
|
||||||
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
|
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
|
||||||
GFP_ATOMIC);
|
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_fil_af_params_le *af_params)
|
||||||
{
|
{
|
||||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||||
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
struct brcmf_fil_action_frame_le *action_frame;
|
struct brcmf_fil_action_frame_le *action_frame;
|
||||||
struct brcmf_config_af_params config_af_params;
|
struct brcmf_config_af_params config_af_params;
|
||||||
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
|
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 */
|
/* To make sure to send successfully action frame, turn off mpc */
|
||||||
if (config_af_params.mpc_onoff == 0)
|
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 */
|
/* set status and destination address before sending af */
|
||||||
if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
|
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
|
* care of current piggback algo, lets abort the scan here
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
brcmf_notify_escan_complete(cfg, ndev, true, true);
|
brcmf_notify_escan_complete(cfg, ifp, true, true);
|
||||||
|
|
||||||
/* update channel */
|
/* update channel */
|
||||||
af_params->channel = cpu_to_le32(afx_hdl->peer_chan);
|
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);
|
clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status);
|
||||||
/* if all done, turn mpc on again */
|
/* if all done, turn mpc on again */
|
||||||
if (config_af_params.mpc_onoff == 1)
|
if (config_af_params.mpc_onoff == 1)
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
|
|
||||||
return ack;
|
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_cfg80211_info *cfg = ifp->drvr->config;
|
||||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||||
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
|
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
|
||||||
struct wireless_dev *wdev;
|
|
||||||
struct brcmf_cfg80211_vif *vif = ifp->vif;
|
struct brcmf_cfg80211_vif *vif = ifp->vif;
|
||||||
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
|
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
|
||||||
u16 chanspec = be16_to_cpu(rxframe->chanspec);
|
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) ?
|
CHSPEC_IS2G(chanspec) ?
|
||||||
IEEE80211_BAND_2GHZ :
|
IEEE80211_BAND_2GHZ :
|
||||||
IEEE80211_BAND_5GHZ);
|
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",
|
brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
|
||||||
mgmt_frame_len, e->datalen, chanspec, freq);
|
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;
|
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);
|
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||||
|
|
||||||
/* Initialize P2P Discovery in the firmware */
|
/* 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");
|
brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
|
||||||
return -EPERM;
|
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;
|
vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
|
||||||
if (!vif) {
|
if (!vif) {
|
||||||
brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
|
brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
|
||||||
return -EPERM;
|
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 */
|
/* In concurrency case, STA may be already associated in a particular */
|
||||||
/* channel. so retrieve the current channel of primary interface and */
|
/* 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);
|
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.
|
* brcmf_p2p_add_vif() - create a new P2P virtual interface.
|
||||||
*
|
*
|
||||||
* @wiphy: wiphy device of new interface.
|
* @wiphy: wiphy device of new interface.
|
||||||
* @name: name of the new interface.
|
* @name: name of the new interface.
|
||||||
* @type: nl80211 interface type.
|
* @type: nl80211 interface type.
|
||||||
* @flags: TBD
|
* @flags: not used.
|
||||||
* @params: TBD
|
* @params: contains mac address for P2P device.
|
||||||
*/
|
*/
|
||||||
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
||||||
enum nl80211_iftype type, u32 *flags,
|
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;
|
iftype = BRCMF_FIL_P2P_IF_GO;
|
||||||
mode = WL_MODE_AP;
|
mode = WL_MODE_AP;
|
||||||
break;
|
break;
|
||||||
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
|
return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy,
|
||||||
|
params->macaddr);
|
||||||
default:
|
default:
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
@ -2244,6 +2352,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
|
brcmf_p2p_delete_p2pdev(vif);
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
break;
|
break;
|
||||||
|
@ -2275,3 +2385,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||||
|
|
||||||
return err;
|
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))
|
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
|
#ifdef CONFIG_BRCM_TRACING
|
||||||
|
|
||||||
#undef TRACE_INCLUDE_PATH
|
#undef TRACE_INCLUDE_PATH
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <brcmu_wifi.h>
|
#include <brcmu_wifi.h>
|
||||||
#include "dhd.h"
|
#include "dhd.h"
|
||||||
#include "dhd_dbg.h"
|
#include "dhd_dbg.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
#include "fwil_types.h"
|
#include "fwil_types.h"
|
||||||
#include "p2p.h"
|
#include "p2p.h"
|
||||||
#include "wl_cfg80211.h"
|
#include "wl_cfg80211.h"
|
||||||
|
@ -182,64 +183,6 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = {
|
||||||
CHAN5G(216, 0),
|
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 = {
|
static struct ieee80211_supported_band __wl_band_2ghz = {
|
||||||
.band = IEEE80211_BAND_2GHZ,
|
.band = IEEE80211_BAND_2GHZ,
|
||||||
.channels = __wl_2ghz_channels,
|
.channels = __wl_2ghz_channels,
|
||||||
|
@ -256,12 +199,28 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
|
||||||
.n_bitrates = wl_a_rates_size,
|
.n_bitrates = wl_a_rates_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ieee80211_supported_band __wl_band_5ghz_n = {
|
/* This is to override regulatory domains defined in cfg80211 module (reg.c)
|
||||||
.band = IEEE80211_BAND_5GHZ,
|
* By default world regulatory domain defined in reg.c puts the flags
|
||||||
.channels = __wl_5ghz_n_channels,
|
* NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
|
||||||
.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
|
* 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
|
||||||
.bitrates = wl_a_rates,
|
* start p2p operations on 5GHz channels. All the changes in world regulatory
|
||||||
.n_bitrates = wl_a_rates_size,
|
* 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[] = {
|
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);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
case NL80211_IFTYPE_P2P_CLIENT:
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
case NL80211_IFTYPE_P2P_GO:
|
case NL80211_IFTYPE_P2P_GO:
|
||||||
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
|
return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
|
||||||
case NL80211_IFTYPE_UNSPECIFIED:
|
case NL80211_IFTYPE_UNSPECIFIED:
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
|
||||||
default:
|
default:
|
||||||
return ERR_PTR(-EINVAL);
|
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;
|
s32 err = 0;
|
||||||
|
|
||||||
if (check_vif_up(ifp->vif)) {
|
if (check_vif_up(ifp->vif)) {
|
||||||
|
@ -546,10 +504,9 @@ void brcmf_set_mpc(struct net_device *ndev, int mpc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32
|
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||||
brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
struct brcmf_if *ifp, bool aborted,
|
||||||
struct net_device *ndev,
|
bool fw_abort)
|
||||||
bool aborted, bool fw_abort)
|
|
||||||
{
|
{
|
||||||
struct brcmf_scan_params_le params_le;
|
struct brcmf_scan_params_le params_le;
|
||||||
struct cfg80211_scan_request *scan_request;
|
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 */
|
/* Scan is aborted by setting channel_list[0] to -1 */
|
||||||
params_le.channel_list[0] = cpu_to_le16(-1);
|
params_le.channel_list[0] = cpu_to_le16(-1);
|
||||||
/* E-Scan (or anyother type) can be aborted by SCAN */
|
/* 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));
|
¶ms_le, sizeof(params_le));
|
||||||
if (err)
|
if (err)
|
||||||
brcmf_err("Scan abort failed\n");
|
brcmf_err("Scan abort failed\n");
|
||||||
|
@ -594,12 +551,12 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||||
cfg->sched_escan = false;
|
cfg->sched_escan = false;
|
||||||
if (!aborted)
|
if (!aborted)
|
||||||
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
|
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
} else if (scan_request) {
|
} else if (scan_request) {
|
||||||
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
|
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
|
||||||
aborted ? "Aborted" : "Done");
|
aborted ? "Aborted" : "Done");
|
||||||
cfg80211_scan_done(scan_request, aborted);
|
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))
|
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
|
||||||
brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
|
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 (ndev) {
|
||||||
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
|
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
|
||||||
cfg->escan_info.ndev == ndev)
|
cfg->escan_info.ifp == netdev_priv(ndev))
|
||||||
brcmf_notify_escan_complete(cfg, ndev, true,
|
brcmf_notify_escan_complete(cfg, netdev_priv(ndev),
|
||||||
true);
|
true, true);
|
||||||
|
|
||||||
brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
|
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;
|
return -EOPNOTSUPP;
|
||||||
case NL80211_IFTYPE_P2P_CLIENT:
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
case NL80211_IFTYPE_P2P_GO:
|
case NL80211_IFTYPE_P2P_GO:
|
||||||
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
return brcmf_p2p_del_vif(wiphy, wdev);
|
return brcmf_p2p_del_vif(wiphy, wdev);
|
||||||
case NL80211_IFTYPE_UNSPECIFIED:
|
case NL80211_IFTYPE_UNSPECIFIED:
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -803,7 +760,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32
|
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)
|
struct cfg80211_scan_request *request, u16 action)
|
||||||
{
|
{
|
||||||
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
|
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->action = cpu_to_le16(action);
|
||||||
params->sync_id = cpu_to_le16(0x1234);
|
params->sync_id = cpu_to_le16(0x1234);
|
||||||
|
|
||||||
err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
|
err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);
|
||||||
params, params_size);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == -EBUSY)
|
if (err == -EBUSY)
|
||||||
brcmf_dbg(INFO, "system busy : escan canceled\n");
|
brcmf_dbg(INFO, "system busy : escan canceled\n");
|
||||||
|
@ -848,7 +804,7 @@ exit:
|
||||||
|
|
||||||
static s32
|
static s32
|
||||||
brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
|
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;
|
s32 err;
|
||||||
u32 passive_scan;
|
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;
|
struct escan_info *escan = &cfg->escan_info;
|
||||||
|
|
||||||
brcmf_dbg(SCAN, "Enter\n");
|
brcmf_dbg(SCAN, "Enter\n");
|
||||||
escan->ndev = ndev;
|
escan->ifp = ifp;
|
||||||
escan->wiphy = wiphy;
|
escan->wiphy = wiphy;
|
||||||
escan->escan_state = WL_ESCAN_STATE_SCANNING;
|
escan->escan_state = WL_ESCAN_STATE_SCANNING;
|
||||||
passive_scan = cfg->active_scan ? 0 : 1;
|
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);
|
passive_scan);
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_err("error (%d)\n", err);
|
brcmf_err("error (%d)\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
brcmf_set_mpc(ndev, 0);
|
brcmf_set_mpc(ifp, 0);
|
||||||
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
|
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
|
||||||
results->version = 0;
|
results->version = 0;
|
||||||
results->count = 0;
|
results->count = 0;
|
||||||
results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
|
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)
|
if (err)
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32
|
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_scan_request *request,
|
||||||
struct cfg80211_ssid *this_ssid)
|
struct cfg80211_ssid *this_ssid)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
struct brcmf_if *ifp = vif->ifp;
|
||||||
struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
|
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||||
struct cfg80211_ssid *ssids;
|
struct cfg80211_ssid *ssids;
|
||||||
struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
|
struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
|
||||||
u32 passive_scan;
|
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 scan req comes for p2p0, send it over primary I/F */
|
||||||
if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) {
|
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
|
||||||
ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
|
||||||
ndev = ifp->ndev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Arm scan timeout timer */
|
/* Arm scan timeout timer */
|
||||||
mod_timer(&cfg->escan_timeout, jiffies +
|
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);
|
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||||
if (escan_req) {
|
if (escan_req) {
|
||||||
cfg->escan_info.run = brcmf_run_escan;
|
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)
|
if (err)
|
||||||
goto scan_out;
|
goto scan_out;
|
||||||
|
|
||||||
err = brcmf_do_escan(cfg, wiphy, ndev, request);
|
err = brcmf_do_escan(cfg, wiphy, vif->ifp, request);
|
||||||
if (err)
|
if (err)
|
||||||
goto scan_out;
|
goto scan_out;
|
||||||
} else {
|
} 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);
|
brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
|
||||||
goto scan_out;
|
goto scan_out;
|
||||||
}
|
}
|
||||||
brcmf_set_mpc(ndev, 0);
|
brcmf_set_mpc(ifp, 0);
|
||||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
||||||
&sr->ssid_le, sizeof(sr->ssid_le));
|
&sr->ssid_le, sizeof(sr->ssid_le));
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -972,7 +926,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
else
|
else
|
||||||
brcmf_err("WLC_SCAN error (%d)\n", err);
|
brcmf_err("WLC_SCAN error (%d)\n", err);
|
||||||
|
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
goto scan_out;
|
goto scan_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -990,16 +944,15 @@ scan_out:
|
||||||
static s32
|
static s32
|
||||||
brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
|
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;
|
s32 err = 0;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(TRACE, "Enter\n");
|
||||||
|
vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
|
||||||
if (!check_vif_up(container_of(request->wdev,
|
if (!check_vif_up(vif))
|
||||||
struct brcmf_cfg80211_vif, wdev)))
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
|
err = brcmf_cfg80211_escan(wiphy, vif, request, NULL);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
brcmf_err("scan error (%d)\n", err);
|
brcmf_err("scan error (%d)\n", err);
|
||||||
|
@ -1891,8 +1844,10 @@ static s32
|
||||||
brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
|
brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
u8 key_idx, const u8 *mac_addr, struct key_params *params)
|
u8 key_idx, const u8 *mac_addr, struct key_params *params)
|
||||||
{
|
{
|
||||||
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
struct brcmf_wsec_key key;
|
struct brcmf_wsec_key key;
|
||||||
s32 err = 0;
|
s32 err = 0;
|
||||||
|
u8 keybuf[8];
|
||||||
|
|
||||||
memset(&key, 0, sizeof(key));
|
memset(&key, 0, sizeof(key));
|
||||||
key.index = (u32) key_idx;
|
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);
|
brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
|
||||||
memcpy(key.data, params->key, key.len);
|
memcpy(key.data, params->key, key.len);
|
||||||
|
|
||||||
if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
if ((ifp->vif->mode != WL_MODE_AP) &&
|
||||||
u8 keybuf[8];
|
(params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
|
||||||
|
brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
|
||||||
memcpy(keybuf, &key.data[24], sizeof(keybuf));
|
memcpy(keybuf, &key.data[24], sizeof(keybuf));
|
||||||
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
|
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
|
||||||
memcpy(&key.data[16], keybuf, 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;
|
break;
|
||||||
case WLAN_CIPHER_SUITE_TKIP:
|
case WLAN_CIPHER_SUITE_TKIP:
|
||||||
if (ifp->vif->mode != WL_MODE_AP) {
|
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(keybuf, &key.data[24], sizeof(keybuf));
|
||||||
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
|
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
|
||||||
memcpy(&key.data[16], keybuf, 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;
|
err = -EAGAIN;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
switch (wsec & ~SES_OW_ENABLED) {
|
if (wsec & WEP_ENABLED) {
|
||||||
case WEP_ENABLED:
|
|
||||||
sec = &profile->sec;
|
sec = &profile->sec;
|
||||||
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
|
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
|
||||||
params.cipher = 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;
|
params.cipher = WLAN_CIPHER_SUITE_WEP104;
|
||||||
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
|
||||||
}
|
}
|
||||||
break;
|
} else if (wsec & TKIP_ENABLED) {
|
||||||
case TKIP_ENABLED:
|
|
||||||
params.cipher = WLAN_CIPHER_SUITE_TKIP;
|
params.cipher = WLAN_CIPHER_SUITE_TKIP;
|
||||||
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
|
||||||
break;
|
} else if (wsec & AES_ENABLED) {
|
||||||
case AES_ENABLED:
|
|
||||||
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
|
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
|
||||||
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
brcmf_err("Invalid algo (0x%x)\n", wsec);
|
brcmf_err("Invalid algo (0x%x)\n", wsec);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -2511,7 +2463,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
|
||||||
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
|
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
|
||||||
if (cfg->scan_request) {
|
if (cfg->scan_request) {
|
||||||
escan->escan_state = WL_ESCAN_STATE_IDLE;
|
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_BUSY, &cfg->scan_status);
|
||||||
clear_bit(BRCMF_SCAN_STATUS_ABORT, &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,
|
container_of(work, struct brcmf_cfg80211_info,
|
||||||
escan_timeout_work);
|
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)
|
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)
|
const struct brcmf_event_msg *e, void *data)
|
||||||
{
|
{
|
||||||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||||
struct net_device *ndev = ifp->ndev;
|
|
||||||
s32 status;
|
s32 status;
|
||||||
s32 err = 0;
|
s32 err = 0;
|
||||||
struct brcmf_escan_result_le *escan_result_le;
|
struct brcmf_escan_result_le *escan_result_le;
|
||||||
|
@ -2587,9 +2538,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
|
||||||
|
|
||||||
status = e->status;
|
status = e->status;
|
||||||
|
|
||||||
if (!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 ndev %p drv_status %x\n", ndev,
|
brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx);
|
||||||
!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
|
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2660,7 +2610,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
|
||||||
cfg->escan_info.escan_buf;
|
cfg->escan_info.escan_buf;
|
||||||
brcmf_inform_bss(cfg);
|
brcmf_inform_bss(cfg);
|
||||||
aborted = status != BRCMF_E_STATUS_SUCCESS;
|
aborted = status != BRCMF_E_STATUS_SUCCESS;
|
||||||
brcmf_notify_escan_complete(cfg, ndev, aborted,
|
brcmf_notify_escan_complete(cfg, ifp, aborted,
|
||||||
false);
|
false);
|
||||||
} else
|
} else
|
||||||
brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n",
|
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);
|
brcmf_abort_scanning(cfg);
|
||||||
|
|
||||||
/* Turn off watchdog timer */
|
/* Turn off watchdog timer */
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(netdev_priv(ndev), 1);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
brcmf_dbg(TRACE, "Exit\n");
|
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)
|
const struct brcmf_event_msg *e, void *data)
|
||||||
{
|
{
|
||||||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||||
struct net_device *ndev = ifp->ndev;
|
|
||||||
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
|
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
|
||||||
struct cfg80211_scan_request *request = NULL;
|
struct cfg80211_scan_request *request = NULL;
|
||||||
struct cfg80211_ssid *ssid = 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);
|
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) {
|
if (err) {
|
||||||
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
@ -3137,7 +3086,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
|
||||||
brcmf_dbg(SCAN, "enter\n");
|
brcmf_dbg(SCAN, "enter\n");
|
||||||
brcmf_dev_pno_clean(ndev);
|
brcmf_dev_pno_clean(ndev);
|
||||||
if (cfg->sched_escan)
|
if (cfg->sched_escan)
|
||||||
brcmf_notify_escan_complete(cfg, ndev, true, true);
|
brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true);
|
||||||
return 0;
|
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);
|
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 */
|
/* find the RSN_IE */
|
||||||
rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
|
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:
|
exit:
|
||||||
if (err)
|
if (err)
|
||||||
brcmf_set_mpc(ndev, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
|
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
s32 err = -EPERM;
|
s32 err;
|
||||||
struct brcmf_fil_bss_enable_le bss_enable;
|
struct brcmf_fil_bss_enable_le bss_enable;
|
||||||
|
struct brcmf_join_params join_params;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
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 */
|
/* Due to most likely deauths outstanding we sleep */
|
||||||
/* first to make sure they get processed by fw. */
|
/* first to make sure they get processed by fw. */
|
||||||
msleep(400);
|
msleep(400);
|
||||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
|
|
||||||
if (err < 0) {
|
memset(&join_params, 0, sizeof(join_params));
|
||||||
brcmf_err("setting AP mode failed %d\n", err);
|
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
|
||||||
goto exit;
|
&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);
|
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);
|
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 {
|
} else {
|
||||||
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
|
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
|
||||||
bss_enable.enable = cpu_to_le32(0);
|
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)
|
if (err < 0)
|
||||||
brcmf_err("bss_enable config failed %d\n", err);
|
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);
|
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
|
||||||
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
||||||
|
|
||||||
exit:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3909,13 +3863,13 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg)
|
u16 frame_type, bool reg)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
struct brcmf_cfg80211_vif *vif;
|
||||||
struct brcmf_cfg80211_vif *vif = ifp->vif;
|
|
||||||
u16 mgmt_type;
|
u16 mgmt_type;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
|
brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
|
||||||
|
|
||||||
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
||||||
|
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||||
if (reg)
|
if (reg)
|
||||||
vif->mgmt_rx_reg |= BIT(mgmt_type);
|
vif->mgmt_rx_reg |= BIT(mgmt_type);
|
||||||
else
|
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);
|
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
struct brcmf_if *ifp;
|
|
||||||
struct brcmf_cfg80211_vif *vif;
|
struct brcmf_cfg80211_vif *vif;
|
||||||
s32 err = 0;
|
s32 err = 0;
|
||||||
s32 ie_offset;
|
s32 ie_offset;
|
||||||
|
@ -3967,8 +3920,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
ie_offset = DOT11_MGMT_HDR_LEN +
|
ie_offset = DOT11_MGMT_HDR_LEN +
|
||||||
DOT11_BCN_PRB_FIXED_LEN;
|
DOT11_BCN_PRB_FIXED_LEN;
|
||||||
ie_len = len - ie_offset;
|
ie_len = len - ie_offset;
|
||||||
ifp = netdev_priv(wdev->netdev);
|
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||||
vif = ifp->vif;
|
|
||||||
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
|
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
|
||||||
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||||
err = brcmf_vif_set_mgmt_ie(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),
|
*cookie, le16_to_cpu(action_frame->len),
|
||||||
chan->center_freq);
|
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);
|
af_params);
|
||||||
|
|
||||||
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
|
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,
|
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
|
||||||
.remain_on_channel = brcmf_p2p_remain_on_channel,
|
.remain_on_channel = brcmf_p2p_remain_on_channel,
|
||||||
.cancel_remain_on_channel = brcmf_cfg80211_cancel_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
|
#ifdef CONFIG_NL80211_TESTMODE
|
||||||
.testmode_cmd = brcmf_cfg80211_testmode
|
.testmode_cmd = brcmf_cfg80211_testmode
|
||||||
#endif
|
#endif
|
||||||
|
@ -4162,6 +4116,11 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
||||||
BIT(IEEE80211_STYPE_AUTH >> 4) |
|
BIT(IEEE80211_STYPE_AUTH >> 4) |
|
||||||
BIT(IEEE80211_STYPE_DEAUTH >> 4) |
|
BIT(IEEE80211_STYPE_DEAUTH >> 4) |
|
||||||
BIT(IEEE80211_STYPE_ACTION >> 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->iface_combinations = brcmf_iface_combos;
|
||||||
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
||||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
|
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->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||||
wiphy->cipher_suites = __wl_cipher_suites;
|
wiphy->cipher_suites = __wl_cipher_suites;
|
||||||
wiphy->n_cipher_suites = ARRAY_SIZE(__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->mgmt_stypes = brcmf_txrx_stypes;
|
||||||
wiphy->max_remain_on_channel_duration = 5000;
|
wiphy->max_remain_on_channel_duration = 5000;
|
||||||
brcmf_wiphy_pno_params(wiphy);
|
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);
|
err = wiphy_register(wiphy);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
brcmf_err("Could not register wiphy device (%d)\n", err);
|
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;
|
ifp->vif = vif;
|
||||||
vif->ifp = ifp;
|
vif->ifp = ifp;
|
||||||
vif->wdev.netdev = ifp->ndev;
|
if (ifp->ndev) {
|
||||||
ifp->ndev->ieee80211_ptr = &vif->wdev;
|
vif->wdev.netdev = ifp->ndev;
|
||||||
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
|
ifp->ndev->ieee80211_ptr = &vif->wdev;
|
||||||
|
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||||
|
}
|
||||||
mutex_unlock(&event->vif_event_lock);
|
mutex_unlock(&event->vif_event_lock);
|
||||||
wake_up(&event->vif_wq);
|
wake_up(&event->vif_wq);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4927,34 +4884,248 @@ dongle_scantime_out:
|
||||||
return err;
|
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 brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
s32 phy_list;
|
s32 phy_list;
|
||||||
|
u32 band_list[3];
|
||||||
|
u32 nmode;
|
||||||
|
u32 bw_cap = 0;
|
||||||
s8 phy;
|
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,
|
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
|
||||||
&phy_list, sizeof(phy_list));
|
&phy_list, sizeof(phy_list));
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_err("error (%d)\n", err);
|
brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
phy = ((char *)&phy_list)[0];
|
phy = ((char *)&phy_list)[0];
|
||||||
brcmf_dbg(INFO, "%c phy\n", phy);
|
brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
|
||||||
if (phy == 'n' || phy == 'a') {
|
|
||||||
wiphy = cfg_to_wiphy(cfg);
|
|
||||||
wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
|
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)
|
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
||||||
|
|
|
@ -238,9 +238,8 @@ struct escan_info {
|
||||||
u32 escan_state;
|
u32 escan_state;
|
||||||
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct net_device *ndev;
|
struct brcmf_if *ifp;
|
||||||
s32 (*run)(struct brcmf_cfg80211_info *cfg,
|
s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
||||||
struct net_device *ndev,
|
|
||||||
struct cfg80211_scan_request *request, u16 action);
|
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,
|
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
|
||||||
u8 action, ulong timeout);
|
u8 action, ulong timeout);
|
||||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||||
struct net_device *ndev,
|
struct brcmf_if *ifp, bool aborted,
|
||||||
bool aborted, bool fw_abort);
|
bool fw_abort);
|
||||||
void brcmf_set_mpc(struct net_device *ndev, int mpc);
|
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
|
||||||
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
||||||
|
|
||||||
#endif /* _wl_cfg80211_h_ */
|
#endif /* _wl_cfg80211_h_ */
|
||||||
|
|
|
@ -318,12 +318,6 @@
|
||||||
#define IS_SIM(chippkg) \
|
#define IS_SIM(chippkg) \
|
||||||
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
|
((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) \
|
#define GOODCOREADDR(x, b) \
|
||||||
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
|
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
|
||||||
IS_ALIGNED((x), SI_CORE_SIZE))
|
IS_ALIGNED((x), SI_CORE_SIZE))
|
||||||
|
|
|
@ -457,6 +457,7 @@ struct d11regs {
|
||||||
/*== maccontrol register ==*/
|
/*== maccontrol register ==*/
|
||||||
#define MCTL_GMODE (1U << 31)
|
#define MCTL_GMODE (1U << 31)
|
||||||
#define MCTL_DISCARD_PMQ (1 << 30)
|
#define MCTL_DISCARD_PMQ (1 << 30)
|
||||||
|
#define MCTL_TBTTHOLD (1 << 28)
|
||||||
#define MCTL_WAKE (1 << 26)
|
#define MCTL_WAKE (1 << 26)
|
||||||
#define MCTL_HPS (1 << 25)
|
#define MCTL_HPS (1 << 25)
|
||||||
#define MCTL_PROMISC (1 << 24)
|
#define MCTL_PROMISC (1 << 24)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Broadcom Corporation
|
* 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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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;
|
struct brcms_info *wl = hw->priv;
|
||||||
|
|
||||||
/* Just STA for now */
|
/* Just STA, AP and ADHOC for now */
|
||||||
if (vif->type != NL80211_IFTYPE_STATION) {
|
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||||
|
vif->type != NL80211_IFTYPE_AP &&
|
||||||
|
vif->type != NL80211_IFTYPE_ADHOC) {
|
||||||
brcms_err(wl->wlc->hw->d11core,
|
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);
|
__func__, vif->type);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_bh(&wl->lock);
|
spin_lock_bh(&wl->lock);
|
||||||
memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
|
|
||||||
wl->mute_tx = false;
|
wl->mute_tx = false;
|
||||||
brcms_c_mute(wl->wlc, 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);
|
spin_unlock_bh(&wl->lock);
|
||||||
|
|
||||||
return 0;
|
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);
|
brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
|
||||||
spin_unlock_bh(&wl->lock);
|
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) */
|
/* 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) {
|
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||||
/* Beaconing should be enabled/disabled (beaconing modes) */
|
/* Beaconing should be enabled/disabled (beaconing modes) */
|
||||||
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
|
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
|
||||||
info->enable_beacon ? "true" : "false");
|
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) {
|
if (changed & BSS_CHANGED_CQM) {
|
||||||
|
@ -724,7 +762,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
|
||||||
return result;
|
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;
|
struct brcms_info *wl = hw->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -739,6 +777,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
|
||||||
"ret=%d\n", jiffies_to_msecs(ret));
|
"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 = {
|
static const struct ieee80211_ops brcms_ops = {
|
||||||
.tx = brcms_ops_tx,
|
.tx = brcms_ops_tx,
|
||||||
.start = brcms_ops_start,
|
.start = brcms_ops_start,
|
||||||
|
@ -755,6 +815,8 @@ static const struct ieee80211_ops brcms_ops = {
|
||||||
.ampdu_action = brcms_ops_ampdu_action,
|
.ampdu_action = brcms_ops_ampdu_action,
|
||||||
.rfkill_poll = brcms_ops_rfkill_poll,
|
.rfkill_poll = brcms_ops_rfkill_poll,
|
||||||
.flush = brcms_ops_flush,
|
.flush = brcms_ops_flush,
|
||||||
|
.get_tsf = brcms_ops_get_tsf,
|
||||||
|
.set_tsf = brcms_ops_set_tsf,
|
||||||
};
|
};
|
||||||
|
|
||||||
void brcms_dpc(unsigned long data)
|
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 */
|
/* channel change time is dependent on chip and band */
|
||||||
hw->channel_change_time = 7 * 1000;
|
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";
|
hw->rate_control_algorithm = "minstrel_ht";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Broadcom Corporation
|
* 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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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->corestate);
|
||||||
kfree(wlc->hw->bandstate[0]);
|
kfree(wlc->hw->bandstate[0]);
|
||||||
kfree(wlc->hw);
|
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 */
|
/* free the wlc */
|
||||||
kfree(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)
|
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
|
* DirFrmQ is now valid...defer setting until end
|
||||||
* of ATIM window
|
* 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 */
|
/* Initialize GPIOs that are controlled by D11 core */
|
||||||
static void brcms_c_gpio_init(struct brcms_c_info *wlc)
|
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)
|
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 */
|
/* disallow PS when one of the following global conditions meets */
|
||||||
if (!wlc->pub->associated)
|
if (!wlc->pub->associated)
|
||||||
return false;
|
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)
|
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (cfg->associated) {
|
if (wlc->bsscfg->type == BRCMS_TYPE_AP)
|
||||||
/*
|
return false;
|
||||||
* disallow PS when one of the following
|
|
||||||
* bsscfg specific conditions meets
|
if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
|
||||||
*/
|
|
||||||
if (!cfg->BSS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3771,7 +3795,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
|
||||||
struct brcms_c_info *wlc = bsscfg->wlc;
|
struct brcms_c_info *wlc = bsscfg->wlc;
|
||||||
|
|
||||||
/* enter the MAC addr into the RXE match registers */
|
/* 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);
|
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);
|
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)
|
static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
|
||||||
{
|
{
|
||||||
wlc_hw->shortslot = 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) {
|
if (wlc->home_chanspec != chanspec) {
|
||||||
wlc->home_chanspec = chanspec;
|
wlc->home_chanspec = chanspec;
|
||||||
|
|
||||||
if (wlc->bsscfg->associated)
|
if (wlc->pub->associated)
|
||||||
wlc->bsscfg->current_bss->chanspec = chanspec;
|
wlc->bsscfg->current_bss->chanspec = chanspec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4091,10 +4124,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
|
||||||
*shm_entry++);
|
*shm_entry++);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suspend) {
|
if (suspend)
|
||||||
brcms_c_suspend_mac_and_wait(wlc);
|
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);
|
brcms_c_enable_mac(wlc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
|
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 */
|
/* WME QoS mode is Auto by default */
|
||||||
wlc->pub->_ampdu = AMPDU_AGG_HOST;
|
wlc->pub->_ampdu = AMPDU_AGG_HOST;
|
||||||
wlc->pub->bcmerror = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint brcms_c_attach_module(struct brcms_c_info *wlc)
|
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;
|
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||||
mboolset(wlc->pub->radio_disabled,
|
mboolset(wlc->pub->radio_disabled,
|
||||||
WL_RADIO_HW_DISABLE);
|
WL_RADIO_HW_DISABLE);
|
||||||
|
if (bsscfg->type == BRCMS_TYPE_STATION ||
|
||||||
if (bsscfg->enable && bsscfg->BSS)
|
bsscfg->type == BRCMS_TYPE_ADHOC)
|
||||||
brcms_err(wlc->hw->d11core,
|
brcms_err(wlc->hw->d11core,
|
||||||
"wl%d: up: rfdisable -> "
|
"wl%d: up: rfdisable -> "
|
||||||
"bsscfg_disable()\n",
|
"bsscfg_disable()\n",
|
||||||
|
@ -5434,7 +5470,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
|
||||||
u8 r;
|
u8 r;
|
||||||
bool war = false;
|
bool war = false;
|
||||||
|
|
||||||
if (wlc->bsscfg->associated)
|
if (wlc->pub->associated)
|
||||||
r = wlc->bsscfg->current_bss->rateset.rates[0];
|
r = wlc->bsscfg->current_bss->rateset.rates[0];
|
||||||
else
|
else
|
||||||
r = wlc->default_bss->rateset.rates[0];
|
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 */
|
/* merge rateset coming in with the current mcsset */
|
||||||
if (wlc->pub->_n_enab & SUPPORT_11N) {
|
if (wlc->pub->_n_enab & SUPPORT_11N) {
|
||||||
struct brcms_bss_info *mcsset_bss;
|
struct brcms_bss_info *mcsset_bss;
|
||||||
if (wlc->bsscfg->associated)
|
if (wlc->pub->associated)
|
||||||
mcsset_bss = wlc->bsscfg->current_bss;
|
mcsset_bss = wlc->bsscfg->current_bss;
|
||||||
else
|
else
|
||||||
mcsset_bss = wlc->default_bss;
|
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;
|
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)
|
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||||
{
|
{
|
||||||
|
u32 bcnint_us;
|
||||||
|
|
||||||
if (period == 0)
|
if (period == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
wlc->default_bss->beacon_period = period;
|
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;
|
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)
|
int brcms_c_get_header_len(void)
|
||||||
{
|
{
|
||||||
return TXOFF;
|
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.
|
* 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;
|
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 */
|
/* Clear the soft intmask */
|
||||||
wlc->defmacintmask &= ~MI_BCNTPL;
|
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 */
|
/* 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
|
static void
|
||||||
brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||||
struct brcms_bss_cfg *cfg,
|
struct brcms_bss_cfg *cfg,
|
||||||
|
struct sk_buff *probe_resp,
|
||||||
bool suspend)
|
bool suspend)
|
||||||
{
|
{
|
||||||
u16 *prb_resp;
|
int len;
|
||||||
int len = BCN_TMPL_LEN;
|
|
||||||
|
|
||||||
prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
|
len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN);
|
||||||
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);
|
|
||||||
|
|
||||||
if (suspend)
|
if (suspend)
|
||||||
brcms_c_suspend_mac_and_wait(wlc);
|
brcms_c_suspend_mac_and_wait(wlc);
|
||||||
|
|
||||||
/* write the probe response into the template region */
|
/* write the probe response into the template region */
|
||||||
brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
|
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) */
|
/* write the length of the probe response frame (+PLCP/-FCS) */
|
||||||
brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
|
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()
|
* PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
|
||||||
* by subtracting the PLCP len and adding the FCS.
|
* by subtracting the PLCP len and adding the FCS.
|
||||||
*/
|
*/
|
||||||
len += (-D11_PHY_HDR_LEN + FCS_LEN);
|
brcms_c_mod_prb_rsp_rate_table(wlc,
|
||||||
brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
|
(u16)len + FCS_LEN - D11_PHY_HDR_LEN);
|
||||||
|
|
||||||
if (suspend)
|
if (suspend)
|
||||||
brcms_c_enable_mac(wlc);
|
brcms_c_enable_mac(wlc);
|
||||||
|
|
||||||
kfree(prb_resp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
|
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;
|
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||||
|
|
||||||
/* update AP or IBSS probe responses */
|
/* update AP or IBSS probe responses */
|
||||||
if (bsscfg->up && !bsscfg->BSS)
|
if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
|
||||||
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
|
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,
|
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)
|
void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
|
||||||
{
|
{
|
||||||
wlc->pub->associated = 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);
|
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)
|
int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
|
||||||
{
|
{
|
||||||
uint qdbm;
|
uint qdbm;
|
||||||
|
@ -7737,6 +7904,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
|
||||||
brcms_rfkill_set_hw_state(wlc->wl);
|
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 */
|
/* it isn't done and needs to be resched if macintstatus is non-zero */
|
||||||
return wlc->macintstatus != 0;
|
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);
|
brcms_c_set_bssid(wlc->bsscfg);
|
||||||
|
|
||||||
/* Update tsf_cfprep if associated and up */
|
/* Update tsf_cfprep if associated and up */
|
||||||
if (wlc->pub->associated && wlc->bsscfg->up) {
|
if (wlc->pub->associated && wlc->pub->up) {
|
||||||
u32 bi;
|
u32 bi;
|
||||||
|
|
||||||
/* get beacon period and convert to uS */
|
/* 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->unit = unit;
|
||||||
pub->_piomode = piomode;
|
pub->_piomode = piomode;
|
||||||
wlc->bandinit_pending = false;
|
wlc->bandinit_pending = false;
|
||||||
|
wlc->beacon_template_virgin = true;
|
||||||
|
|
||||||
/* populate struct brcms_c_info with default values */
|
/* populate struct brcms_c_info with default values */
|
||||||
brcms_c_info_init(wlc, unit);
|
brcms_c_info_init(wlc, unit);
|
||||||
|
|
|
@ -492,6 +492,8 @@ struct brcms_c_info {
|
||||||
bool radio_monitor;
|
bool radio_monitor;
|
||||||
bool going_down;
|
bool going_down;
|
||||||
|
|
||||||
|
bool beacon_template_virgin;
|
||||||
|
|
||||||
struct brcms_timer *wdtimer;
|
struct brcms_timer *wdtimer;
|
||||||
struct brcms_timer *radio_timer;
|
struct brcms_timer *radio_timer;
|
||||||
|
|
||||||
|
@ -561,6 +563,11 @@ struct brcms_c_info {
|
||||||
|
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct scb pri_scb;
|
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 */
|
/* antsel module specific state */
|
||||||
|
@ -576,14 +583,17 @@ struct antsel_info {
|
||||||
struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
|
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
|
* BSS configuration state
|
||||||
*
|
*
|
||||||
* wlc: wlc to which this bsscfg belongs to.
|
* wlc: wlc to which this bsscfg belongs to.
|
||||||
* up: is this configuration up operational
|
* type: interface type
|
||||||
* enable: is this configuration enabled
|
|
||||||
* associated: is BSS in ASSOCIATED state
|
|
||||||
* BSS: infraustructure or adhoc
|
|
||||||
* SSID_len: the length of SSID
|
* SSID_len: the length of SSID
|
||||||
* SSID: SSID string
|
* SSID: SSID string
|
||||||
*
|
*
|
||||||
|
@ -599,14 +609,10 @@ struct antsel_info {
|
||||||
*/
|
*/
|
||||||
struct brcms_bss_cfg {
|
struct brcms_bss_cfg {
|
||||||
struct brcms_c_info *wlc;
|
struct brcms_c_info *wlc;
|
||||||
bool up;
|
enum brcms_bss_type type;
|
||||||
bool enable;
|
|
||||||
bool associated;
|
|
||||||
bool BSS;
|
|
||||||
u8 SSID_len;
|
u8 SSID_len;
|
||||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||||
u8 BSSID[ETH_ALEN];
|
u8 BSSID[ETH_ALEN];
|
||||||
u8 cur_etheraddr[ETH_ALEN];
|
|
||||||
struct brcms_bss_info *current_bss;
|
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,
|
extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
void (*dma_callback_fn));
|
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 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 int brcms_c_set_nmode(struct brcms_c_info *wlc);
|
||||||
extern void brcms_c_beacon_phytxctl_txant_upd(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)
|
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)) ||
|
if ((D11REV_GE(pi->sh->corerev, 24)) ||
|
||||||
(D11REV_IS(pi->sh->corerev, 22)
|
(D11REV_IS(pi->sh->corerev, 22)
|
||||||
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
|
&& (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);
|
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)) {
|
(++pi->phy_wreg >= pi->phy_wreg_limit)) {
|
||||||
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
|
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
|
||||||
pi->phy_wreg = 0;
|
pi->phy_wreg = 0;
|
||||||
|
@ -297,10 +295,8 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
|
||||||
if (addr == 0x72)
|
if (addr == 0x72)
|
||||||
(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
|
(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
|
||||||
#else
|
#else
|
||||||
struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
|
|
||||||
|
|
||||||
bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
|
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 >= pi->phy_wreg_limit)) {
|
||||||
pi->phy_wreg = 0;
|
pi->phy_wreg = 0;
|
||||||
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
|
(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)
|
if (sh == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sh->sih = shp->sih;
|
|
||||||
sh->physhim = shp->physhim;
|
sh->physhim = shp->physhim;
|
||||||
sh->unit = shp->unit;
|
sh->unit = shp->unit;
|
||||||
sh->corerev = shp->corerev;
|
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);
|
mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
|
||||||
|
|
||||||
}
|
}
|
||||||
ai_cc_reg(pi->sh->sih,
|
|
||||||
offsetof(struct chipcregs, gpiocontrol),
|
bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
|
||||||
~0x0, 0x0);
|
0x0, 0x0);
|
||||||
ai_cc_reg(pi->sh->sih,
|
bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
|
||||||
offsetof(struct chipcregs, gpioout),
|
~0x40, 0x40);
|
||||||
0x40, 0x40);
|
bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
|
||||||
ai_cc_reg(pi->sh->sih,
|
~0x40, 0x40);
|
||||||
offsetof(struct chipcregs, gpioouten),
|
|
||||||
0x40, 0x40);
|
|
||||||
} else {
|
} else {
|
||||||
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
|
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
|
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
|
||||||
|
|
||||||
ai_cc_reg(pi->sh->sih,
|
bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
|
||||||
offsetof(struct chipcregs, gpioout),
|
~0x40, 0x00);
|
||||||
0x40, 0x00);
|
bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
|
||||||
ai_cc_reg(pi->sh->sih,
|
~0x40, 0x00);
|
||||||
offsetof(struct chipcregs, gpioouten),
|
bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
|
||||||
0x40, 0x0);
|
0x0, 0x40);
|
||||||
ai_cc_reg(pi->sh->sih,
|
|
||||||
offsetof(struct chipcregs, gpiocontrol),
|
|
||||||
~0x0, 0x40);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,7 +488,6 @@ struct lcnphy_cal_results {
|
||||||
struct shared_phy {
|
struct shared_phy {
|
||||||
struct brcms_phy *phy_head;
|
struct brcms_phy *phy_head;
|
||||||
uint unit;
|
uint unit;
|
||||||
struct si_pub *sih;
|
|
||||||
struct phy_shim_info *physhim;
|
struct phy_shim_info *physhim;
|
||||||
uint corerev;
|
uint corerev;
|
||||||
u32 machwcap;
|
u32 machwcap;
|
||||||
|
|
|
@ -1595,11 +1595,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
|
||||||
if (channel == 1 || channel == 2 || channel == 3 ||
|
if (channel == 1 || channel == 2 || channel == 3 ||
|
||||||
channel == 4 || channel == 9 ||
|
channel == 4 || channel == 9 ||
|
||||||
channel == 10 || channel == 11 || channel == 12) {
|
channel == 10 || channel == 11 || channel == 12) {
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
|
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
|
0x03000c04);
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
|
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);
|
write_phy_reg(pi, 0x942, 0);
|
||||||
wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
|
wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
|
||||||
pi_lcn->lcnphy_spurmod = 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);
|
write_phy_reg(pi, 0x425, 0x5907);
|
||||||
} else {
|
} else {
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
|
bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
|
0x03140c04);
|
||||||
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
|
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);
|
write_phy_reg(pi, 0x942, 0);
|
||||||
wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
|
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);
|
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)
|
if ((pi->sh->boardflags & BFL_FEM)
|
||||||
&& wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
|
&& 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->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_lcn->lcnphy_papd_rxGnCtrl_init = 0;
|
||||||
|
|
||||||
pi->pi_fptr.init = wlc_phy_init_lcnphy;
|
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))) {
|
(pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
|
||||||
if ((pi->sh->boardflags & BFL_EXTLNA) &&
|
if ((pi->sh->boardflags & BFL_EXTLNA) &&
|
||||||
(CHSPEC_IS2G(pi->radio_chanspec)))
|
(CHSPEC_IS2G(pi->radio_chanspec)))
|
||||||
ai_cc_reg(pi->sh->sih,
|
bcma_cc_set32(&pi->d11core->bus->drv_cc,
|
||||||
offsetof(struct chipcregs, chipcontrol),
|
BCMA_CC_CHIPCTL, 0x40);
|
||||||
0x40, 0x40);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
|
if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
|
||||||
si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
|
bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1,
|
||||||
CCTRL5357_EXTPA);
|
~CCTRL5357_EXTPA, CCTRL5357_EXTPA);
|
||||||
|
|
||||||
if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
|
if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
|
||||||
CHSPEC_IS40(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)
|
const struct nphy_sfo_cfg *ci)
|
||||||
{
|
{
|
||||||
u16 val;
|
u16 val;
|
||||||
struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
|
|
||||||
|
|
||||||
val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
|
val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
|
||||||
if (CHSPEC_IS5G(chanspec) && !val) {
|
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) ||
|
if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
|
||||||
(pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
|
(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);
|
spuravoid);
|
||||||
} else {
|
} else {
|
||||||
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
|
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);
|
spuravoid);
|
||||||
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
|
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;
|
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)
|
u32 si_pmu_measure_alpclk(struct si_pub *sih)
|
||||||
{
|
{
|
||||||
struct si_info *sii = container_of(sih, struct si_info, pub);
|
struct si_info *sii = container_of(sih, struct si_info, pub);
|
||||||
|
|
|
@ -21,12 +21,6 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
|
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);
|
extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
|
||||||
|
|
||||||
#endif /* _BRCM_PMU_H_ */
|
#endif /* _BRCM_PMU_H_ */
|
||||||
|
|
|
@ -164,8 +164,6 @@ struct brcms_pub {
|
||||||
|
|
||||||
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
|
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
|
||||||
|
|
||||||
int bcmerror; /* last bcm error */
|
|
||||||
|
|
||||||
u32 radio_disabled; /* bit vector for radio disabled reasons */
|
u32 radio_disabled; /* bit vector for radio disabled reasons */
|
||||||
|
|
||||||
u16 boardrev; /* version # of particular board */
|
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);
|
s8 sslot_override);
|
||||||
extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
|
extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
|
||||||
u8 interval);
|
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_set_tx_power(struct brcms_c_info *wlc, int txpwr);
|
||||||
extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
|
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 bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
|
||||||
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
|
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 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_ */
|
#endif /* _BRCM_PUB_H_ */
|
||||||
|
|
|
@ -32,8 +32,9 @@
|
||||||
#define CH_20MHZ_APART 4
|
#define CH_20MHZ_APART 4
|
||||||
#define CH_10MHZ_APART 2
|
#define CH_10MHZ_APART 2
|
||||||
#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
|
#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 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 */
|
/* bandstate array indices */
|
||||||
#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
|
#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
|
||||||
|
@ -60,6 +61,7 @@
|
||||||
#define WL_CHANSPEC_BW_10 0x0400
|
#define WL_CHANSPEC_BW_10 0x0400
|
||||||
#define WL_CHANSPEC_BW_20 0x0800
|
#define WL_CHANSPEC_BW_20 0x0800
|
||||||
#define WL_CHANSPEC_BW_40 0x0C00
|
#define WL_CHANSPEC_BW_40 0x0C00
|
||||||
|
#define WL_CHANSPEC_BW_80 0x2000
|
||||||
|
|
||||||
#define WL_CHANSPEC_BAND_MASK 0xf000
|
#define WL_CHANSPEC_BAND_MASK 0xf000
|
||||||
#define WL_CHANSPEC_BAND_SHIFT 12
|
#define WL_CHANSPEC_BAND_SHIFT 12
|
||||||
|
@ -67,6 +69,25 @@
|
||||||
#define WL_CHANSPEC_BAND_2G 0x2000
|
#define WL_CHANSPEC_BAND_2G 0x2000
|
||||||
#define INVCHANSPEC 255
|
#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_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
|
||||||
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
|
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
|
||||||
|
|
||||||
|
@ -79,10 +100,11 @@
|
||||||
#define CHSPEC_IS20(chspec) \
|
#define CHSPEC_IS20(chspec) \
|
||||||
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
|
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
|
||||||
|
|
||||||
#ifndef CHSPEC_IS40
|
|
||||||
#define CHSPEC_IS40(chspec) \
|
#define CHSPEC_IS40(chspec) \
|
||||||
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
|
(((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) \
|
#define CHSPEC_IS5G(chspec) \
|
||||||
(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
|
(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
|
||||||
|
|
|
@ -4701,8 +4701,7 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(il_mac_change_interface);
|
EXPORT_SYMBOL(il_mac_change_interface);
|
||||||
|
|
||||||
void
|
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||||
il_mac_flush(struct ieee80211_hw *hw, bool drop)
|
|
||||||
{
|
{
|
||||||
struct il_priv *il = hw->priv;
|
struct il_priv *il = hw->priv;
|
||||||
unsigned long timeout = jiffies + msecs_to_jiffies(500);
|
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);
|
struct ieee80211_vif *vif);
|
||||||
int il_mac_change_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);
|
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);
|
int il_alloc_txq_mem(struct il_priv *il);
|
||||||
void il_free_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;
|
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);
|
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);
|
bool, S_IRUGO);
|
||||||
MODULE_PARM_DESC(auto_agg,
|
MODULE_PARM_DESC(auto_agg,
|
||||||
"enable agg w/o check traffic load (default: enable)");
|
"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;
|
__le32 event_trigger;
|
||||||
} __packed;
|
} __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
|
* struct iwl_fw - variables associated with the firmware
|
||||||
*
|
*
|
||||||
|
@ -190,4 +203,16 @@ struct iwl_fw {
|
||||||
bool mvm_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__ */
|
#endif /* __iwl_fw_h__ */
|
||||||
|
|
|
@ -103,7 +103,6 @@ enum iwl_power_level {
|
||||||
* @ant_coupling: antenna coupling in dB, default = 0
|
* @ant_coupling: antenna coupling in dB, default = 0
|
||||||
* @bt_ch_announce: BT channel inhibition, default = enable
|
* @bt_ch_announce: BT channel inhibition, default = enable
|
||||||
* @auto_agg: enable agg. without check, default = true
|
* @auto_agg: enable agg. without check, default = true
|
||||||
* @disable_5ghz: disable 5GHz capability, default = false
|
|
||||||
*/
|
*/
|
||||||
struct iwl_mod_params {
|
struct iwl_mod_params {
|
||||||
int sw_crypto;
|
int sw_crypto;
|
||||||
|
@ -120,7 +119,6 @@ struct iwl_mod_params {
|
||||||
int ant_coupling;
|
int ant_coupling;
|
||||||
bool bt_ch_announce;
|
bool bt_ch_announce;
|
||||||
bool auto_agg;
|
bool auto_agg;
|
||||||
bool disable_5ghz;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* #__iwl_modparams_h__ */
|
#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;
|
reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||||
skb = iwl_test_alloc_reply(tst, reply_len + 20);
|
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) {
|
if (!skb || !reply_buf) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
kfree(reply_buf);
|
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. */
|
/* The reply is in a page, that we cannot send to user space. */
|
||||||
memcpy(reply_buf, &(pkt->hdr), reply_len);
|
|
||||||
iwl_free_resp(&cmd);
|
iwl_free_resp(&cmd);
|
||||||
|
|
||||||
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
|
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] = {
|
static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
|
||||||
0xffffffff,
|
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
|
||||||
0xfffffc00,
|
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
|
||||||
0,
|
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
|
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
|
||||||
0xffffffff,
|
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
|
||||||
0xfffffc00,
|
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
|
||||||
0,
|
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
|
#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) */
|
/* BT Antenna Coupling Threshold (dB) */
|
||||||
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
|
#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)
|
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 ?
|
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
|
||||||
BT_COEX_NW : BT_COEX_DISABLE;
|
BT_COEX_NW : BT_COEX_DISABLE;
|
||||||
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ?
|
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
|
||||||
BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0;
|
|
||||||
cmd.flags |= BT_SYNC_2_BT_DISABLE;
|
cmd.flags |= BT_SYNC_2_BT_DISABLE;
|
||||||
|
|
||||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
|
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)
|
if (data->notif->bt_status)
|
||||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
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;
|
smps_mode = IEEE80211_SMPS_STATIC;
|
||||||
|
|
||||||
IWL_DEBUG_COEX(data->mvm,
|
IWL_DEBUG_COEX(data->mvm,
|
||||||
|
@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
IWL_DEBUG_COEX(mvm,
|
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_kill_msk,
|
||||||
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
|
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
|
||||||
BT_MBOX_MSG(notif, 3, A2DP_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);
|
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
|
||||||
|
|
||||||
if (wowlan->rfkill_release)
|
if (wowlan->rfkill_release)
|
||||||
d3_cfg_cmd.wakeup_flags |=
|
wowlan_config_cmd.wakeup_filter |=
|
||||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
|
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
|
||||||
|
|
||||||
if (wowlan->tcp) {
|
if (wowlan->tcp) {
|
||||||
/*
|
/*
|
||||||
* The firmware currently doesn't really look at these, only
|
* Set the "link change" (really "link lost") flag as well
|
||||||
* the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that
|
* since that implies losing the TCP connection.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
wowlan_config_cmd.wakeup_filter |=
|
wowlan_config_cmd.wakeup_filter |=
|
||||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
|
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
|
||||||
|
|
|
@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd {
|
||||||
struct ieee80211_hdr frame[0];
|
struct ieee80211_hdr frame[0];
|
||||||
} __packed;
|
} __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
|
* enum iwl_dump_control - dump (flush) control flags
|
||||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
||||||
|
|
|
@ -151,6 +151,7 @@ enum {
|
||||||
|
|
||||||
SET_CALIB_DEFAULT_CMD = 0x8e,
|
SET_CALIB_DEFAULT_CMD = 0x8e,
|
||||||
|
|
||||||
|
BEACON_NOTIFICATION = 0x90,
|
||||||
BEACON_TEMPLATE_CMD = 0x91,
|
BEACON_TEMPLATE_CMD = 0x91,
|
||||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||||
BT_CONFIG = 0x9b,
|
BT_CONFIG = 0x9b,
|
||||||
|
@ -278,38 +279,7 @@ enum {
|
||||||
NVM_ACCESS_TARGET_EEPROM = 2,
|
NVM_ACCESS_TARGET_EEPROM = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/* Section types for NVM_ACCESS_CMD */
|
||||||
* 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 */
|
|
||||||
enum {
|
enum {
|
||||||
NVM_SECTION_TYPE_HW = 0,
|
NVM_SECTION_TYPE_HW = 0,
|
||||||
NVM_SECTION_TYPE_SW,
|
NVM_SECTION_TYPE_SW,
|
||||||
|
@ -330,7 +300,7 @@ enum {
|
||||||
* @length: in bytes, to read/write
|
* @length: in bytes, to read/write
|
||||||
* @data: if write operation, the data to write. On read its empty
|
* @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 op_code;
|
||||||
u8 target;
|
u8 target;
|
||||||
__le16 type;
|
__le16 type;
|
||||||
|
@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 {
|
||||||
* @status: 0 for success, fail otherwise
|
* @status: 0 for success, fail otherwise
|
||||||
* @data: if read operation, the data returned. Empty on write.
|
* @data: if read operation, the data returned. Empty on write.
|
||||||
*/
|
*/
|
||||||
struct iwl_nvm_access_resp_ver2 {
|
struct iwl_nvm_access_resp {
|
||||||
__le16 offset;
|
__le16 offset;
|
||||||
__le16 length;
|
__le16 length;
|
||||||
__le16 type;
|
__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),
|
.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,
|
return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
|
||||||
sizeof(tx_ant_cmd), &tx_ant_cmd);
|
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->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
|
||||||
|
|
||||||
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
|
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,
|
le16_to_cpu(palive->status), palive->ver_type,
|
||||||
palive->ver_subtype);
|
palive->ver_subtype, palive->flags);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||||
WARN_ON(ret);
|
WARN_ON(ret);
|
||||||
|
|
||||||
/* Send TX valid antennas before triggering calibrations */
|
/* 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)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* WkP doesn't have all calibrations, need to set default values */
|
/* need to set default values */
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
ret = iwl_set_default_calibrations(mvm);
|
||||||
ret = iwl_set_default_calibrations(mvm);
|
if (ret)
|
||||||
if (ret)
|
goto error;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send phy configurations command to init uCode
|
* Send phy configurations command to init uCode
|
||||||
|
@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||||
goto error;
|
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)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
|
||||||
goto error;
|
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)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
|
||||||
u32 qmask, ac;
|
u32 qmask, ac;
|
||||||
|
|
||||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
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) ?
|
qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
|
||||||
BIT(vif->cab_queue) : 0;
|
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);
|
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
|
||||||
|
|
||||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
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);
|
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);
|
TX_CMD_FLG_TSF);
|
||||||
|
|
||||||
mvm->mgmt_last_antenna_idx =
|
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);
|
mvm->mgmt_last_antenna_idx);
|
||||||
|
|
||||||
beacon_cmd.tx.rate_n_flags =
|
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;
|
mvmvif->uploaded = false;
|
||||||
return 0;
|
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_AMPDU_AGGREGATION |
|
||||||
IEEE80211_HW_TIMING_BEACON_ONLY;
|
IEEE80211_HW_TIMING_BEACON_ONLY;
|
||||||
|
|
||||||
hw->queues = IWL_FIRST_AMPDU_QUEUE;
|
hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
|
||||||
hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE;
|
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
|
||||||
hw->rate_control_algorithm = "iwl-mvm-rs";
|
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 =
|
hw->wiphy->n_iface_combinations =
|
||||||
ARRAY_SIZE(iwl_mvm_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;
|
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
|
||||||
|
|
||||||
/* Extract MAC address */
|
/* Extract MAC address */
|
||||||
|
@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
|
||||||
goto drop;
|
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))
|
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
|
@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SET_KEY:
|
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");
|
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
|
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
|
||||||
if (ret) {
|
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
|
* can't add key for RX, but we don't need it
|
||||||
* in the device for TX so still return 0
|
* in the device for TX so still return 0
|
||||||
*/
|
*/
|
||||||
|
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DISABLE_KEY:
|
case DISABLE_KEY:
|
||||||
|
if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
|
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
|
||||||
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
|
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
|
||||||
break;
|
break;
|
||||||
|
@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
||||||
&chandef, 1, 1);
|
&chandef, 1, 1);
|
||||||
|
|
||||||
/* Schedule the time events */
|
/* 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);
|
mutex_unlock(&mvm->mutex);
|
||||||
IWL_DEBUG_MAC80211(mvm, "leave\n");
|
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.
|
* will handle quota settings.
|
||||||
*/
|
*/
|
||||||
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
||||||
|
mvmvif->monitor_active = true;
|
||||||
ret = iwl_mvm_update_quotas(mvm, vif);
|
ret = iwl_mvm_update_quotas(mvm, vif);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_remove_binding;
|
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)
|
if (vif->type == NL80211_IFTYPE_AP)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
|
||||||
switch (vif->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
iwl_mvm_update_quotas(mvm, vif);
|
mvmvif->monitor_active = false;
|
||||||
|
iwl_mvm_update_quotas(mvm, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mvmvif->phy_ctxt = NULL;
|
mvmvif->phy_ctxt = NULL;
|
||||||
mutex_unlock(&mvm->mutex);
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
|
@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo {
|
||||||
IWL_MVM_TX_FIFO_VO,
|
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;
|
extern struct ieee80211_ops iwl_mvm_hw_ops;
|
||||||
/**
|
/**
|
||||||
* struct iwl_mvm_mod_params - module parameters for iwlmvm
|
* 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
|
* @uploaded: indicates the MAC context has been added to the device
|
||||||
* @ap_active: indicates that ap context is configured, and that the interface
|
* @ap_active: indicates that ap context is configured, and that the interface
|
||||||
* should get quota etc.
|
* 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
|
* @queue_params: QoS params for this MAC
|
||||||
* @bcast_sta: station used for broadcast packets. Used by the following
|
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||||
* vifs: P2P_DEVICE, GO and AP.
|
* vifs: P2P_DEVICE, GO and AP.
|
||||||
|
@ -173,6 +171,7 @@ struct iwl_mvm_vif {
|
||||||
|
|
||||||
bool uploaded;
|
bool uploaded;
|
||||||
bool ap_active;
|
bool ap_active;
|
||||||
|
bool monitor_active;
|
||||||
|
|
||||||
u32 ap_beacon_time;
|
u32 ap_beacon_time;
|
||||||
|
|
||||||
|
@ -281,10 +280,7 @@ struct iwl_mvm {
|
||||||
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
|
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
|
||||||
|
|
||||||
struct iwl_nvm_data *nvm_data;
|
struct iwl_nvm_data *nvm_data;
|
||||||
/* eeprom blob for debugfs/testmode */
|
/* NVM sections */
|
||||||
u8 *eeprom_blob;
|
|
||||||
size_t eeprom_blob_size;
|
|
||||||
/* NVM sections for 7000 family */
|
|
||||||
struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
|
struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
|
||||||
|
|
||||||
/* EEPROM MAC addresses */
|
/* EEPROM MAC addresses */
|
||||||
|
@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif);
|
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 */
|
/* Bindings */
|
||||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
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 */
|
/* Default NVM size to read */
|
||||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
|
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
|
||||||
|
|
||||||
/* used to simplify the shared operations on NCM_ACCESS_CMD versions */
|
static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
|
||||||
union iwl_nvm_access_cmd {
|
u16 offset, u16 length, u16 section)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
cmd->offset = cpu_to_le16(offset);
|
cmd->offset = cpu_to_le16(offset);
|
||||||
cmd->length = cpu_to_le16(length);
|
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,
|
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
||||||
u16 offset, u16 length, u8 *data)
|
u16 offset, u16 length, u8 *data)
|
||||||
{
|
{
|
||||||
union iwl_nvm_access_cmd nvm_access_cmd;
|
struct iwl_nvm_access_cmd nvm_access_cmd = {};
|
||||||
union iwl_nvm_access_resp *nvm_resp;
|
struct iwl_nvm_access_resp *nvm_resp;
|
||||||
struct iwl_rx_packet *pkt;
|
struct iwl_rx_packet *pkt;
|
||||||
struct iwl_host_cmd cmd = {
|
struct iwl_host_cmd cmd = {
|
||||||
.id = NVM_ACCESS_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;
|
int ret, bytes_read, offset_read;
|
||||||
u8 *resp_data;
|
u8 *resp_data;
|
||||||
|
|
||||||
memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd));
|
iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
|
||||||
|
cmd.len[0] = sizeof(struct iwl_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
||||||
|
|
||||||
/* Extract NVM response */
|
/* Extract NVM response */
|
||||||
nvm_resp = (void *)pkt->data;
|
nvm_resp = (void *)pkt->data;
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
ret = le16_to_cpu(nvm_resp->status);
|
||||||
ret = le16_to_cpu(nvm_resp->ver2.status);
|
bytes_read = le16_to_cpu(nvm_resp->length);
|
||||||
bytes_read = le16_to_cpu(nvm_resp->ver2.length);
|
offset_read = le16_to_cpu(nvm_resp->offset);
|
||||||
offset_read = le16_to_cpu(nvm_resp->ver2.offset);
|
resp_data = nvm_resp->data;
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_ERR(mvm,
|
IWL_ERR(mvm,
|
||||||
"NVM access command failed with status %d (device: %s)\n",
|
"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;
|
u16 length, offset = 0;
|
||||||
int ret;
|
int ret;
|
||||||
bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
|
|
||||||
|
|
||||||
/* Set nvm section read length */
|
/* Set nvm section read length */
|
||||||
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
|
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;
|
ret = length;
|
||||||
|
|
||||||
/* Read the NVM until exhausted (reading less than requested) */
|
/* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
offset += ret;
|
offset += ret;
|
||||||
if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_INFO(mvm, "NVM section %d read completed\n", section);
|
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;
|
int ret, i, section;
|
||||||
u8 *nvm_buffer, *temp;
|
u8 *nvm_buffer, *temp;
|
||||||
|
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
/* TODO: find correct NVM max size for a section */
|
||||||
/* TODO: find correct NVM max size for a section */
|
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
|
||||||
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
|
GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
if (!nvm_buffer)
|
||||||
if (!nvm_buffer)
|
return -ENOMEM;
|
||||||
return -ENOMEM;
|
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
|
||||||
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
|
section = nvm_to_read[i];
|
||||||
section = nvm_to_read[i];
|
/* we override the constness for initial read */
|
||||||
/* we override the constness for initial read */
|
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
|
||||||
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);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
break;
|
||||||
} else {
|
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
|
||||||
/* allocate eeprom */
|
if (!temp) {
|
||||||
mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size;
|
ret = -ENOMEM;
|
||||||
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n",
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
mvm->nvm_sections[section].data = temp;
|
||||||
|
mvm->nvm_sections[section].length = ret;
|
||||||
}
|
}
|
||||||
|
kfree(nvm_buffer);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
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;
|
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
|
||||||
u32 reg_val = 0;
|
u32 reg_val = 0;
|
||||||
|
|
||||||
/*
|
radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
|
||||||
* We can't upload the correct value to the INIT image
|
FW_PHY_CFG_RADIO_TYPE_POS;
|
||||||
* as we don't have nvm_data by that time.
|
radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
|
||||||
*
|
FW_PHY_CFG_RADIO_STEP_POS;
|
||||||
* TODO: Figure out what we should do here
|
radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
|
||||||
*/
|
FW_PHY_CFG_RADIO_DASH_POS;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SKU control */
|
/* SKU control */
|
||||||
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
|
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 */
|
/* silicon bits */
|
||||||
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
|
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,
|
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
|
||||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
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(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
|
||||||
|
|
||||||
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
|
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(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
|
||||||
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, 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(WEP_KEY),
|
||||||
CMD(REPLY_RX_PHY_CMD),
|
CMD(REPLY_RX_PHY_CMD),
|
||||||
CMD(REPLY_RX_MPDU_CMD),
|
CMD(REPLY_RX_MPDU_CMD),
|
||||||
|
CMD(BEACON_NOTIFICATION),
|
||||||
CMD(BEACON_TEMPLATE_CMD),
|
CMD(BEACON_TEMPLATE_CMD),
|
||||||
CMD(STATISTICS_NOTIFICATION),
|
CMD(STATISTICS_NOTIFICATION),
|
||||||
CMD(TX_ANT_CONFIGURATION_CMD),
|
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;
|
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
|
* 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:
|
out_free:
|
||||||
iwl_phy_db_free(mvm->phy_db);
|
iwl_phy_db_free(mvm->phy_db);
|
||||||
kfree(mvm->scan_cmd);
|
kfree(mvm->scan_cmd);
|
||||||
kfree(mvm->eeprom_blob);
|
|
||||||
iwl_trans_stop_hw(trans, true);
|
iwl_trans_stop_hw(trans, true);
|
||||||
ieee80211_free_hw(mvm->hw);
|
ieee80211_free_hw(mvm->hw);
|
||||||
return NULL;
|
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);
|
iwl_phy_db_free(mvm->phy_db);
|
||||||
mvm->phy_db = NULL;
|
mvm->phy_db = NULL;
|
||||||
|
|
||||||
kfree(mvm->eeprom_blob);
|
|
||||||
iwl_free_nvm_data(mvm->nvm_data);
|
iwl_free_nvm_data(mvm->nvm_data);
|
||||||
for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
|
for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
|
||||||
kfree(mvm->nvm_sections[i].data);
|
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,
|
struct cfg80211_chan_def *chandef,
|
||||||
u8 chains_static, u8 chains_dynamic)
|
u8 chains_static, u8 chains_dynamic)
|
||||||
{
|
{
|
||||||
u8 valid_rx_chains, active_cnt, idle_cnt;
|
u8 active_cnt, idle_cnt;
|
||||||
|
|
||||||
/* Set the channel info data */
|
/* Set the channel info data */
|
||||||
cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
|
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
|
* Need to add on chain noise calibration limitations, and
|
||||||
* BT coex considerations.
|
* BT coex considerations.
|
||||||
*/
|
*/
|
||||||
valid_rx_chains = mvm->nvm_data->valid_rx_ant;
|
|
||||||
idle_cnt = chains_static;
|
idle_cnt = chains_static;
|
||||||
active_cnt = chains_dynamic;
|
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);
|
PHY_RX_CHAIN_VALID_POS);
|
||||||
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
|
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
|
||||||
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
|
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
|
||||||
PHY_RX_CHAIN_MIMO_CNT_POS);
|
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]++;
|
data->n_interfaces[id]++;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
data->n_interfaces[id]++;
|
if (mvmvif->monitor_active)
|
||||||
|
data->n_interfaces[id]++;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
|
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
u16 rx_chain;
|
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_VALID_POS;
|
||||||
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_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;
|
u32 tx_ant;
|
||||||
|
|
||||||
mvm->scan_last_antenna_idx =
|
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);
|
mvm->scan_last_antenna_idx);
|
||||||
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
|
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 TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
|
||||||
#define MSEC_TO_TU(_msec) (_msec*1000/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
|
* For the high priority TE use a time event type that has similar priority to
|
||||||
* priority similar to the TE priority used for action scans by the FW.
|
* the FW's action scan priority.
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
#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,
|
void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_time_event_data *te_data)
|
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
|
* issue as it will have to complete before the next command is
|
||||||
* executed, and a new time event means a new command.
|
* 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)
|
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 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_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
|
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.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||||
time_cmd.id_and_color =
|
time_cmd.id_and_color =
|
||||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->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.apply_time = cpu_to_le32(0);
|
||||||
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
|
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
|
||||||
time_cmd.is_present = cpu_to_le32(1);
|
time_cmd.is_present = cpu_to_le32(1);
|
||||||
|
|
||||||
time_cmd.interval = 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
|
* 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
|
* scheduled. To improve the chances of it being scheduled, allow them
|
||||||
* be fragmented.
|
* to be fragmented, and in addition allow them to be delayed.
|
||||||
* In addition, for the same reasons, allow to delay the scheduling of
|
|
||||||
* the time event.
|
|
||||||
*/
|
*/
|
||||||
time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
|
time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
|
||||||
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
|
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
|
* that the vif type is NL80211_IFTYPE_P2P_DEVICE
|
||||||
* @duration: the requested duration in millisecond for the fw to be on the
|
* @duration: the requested duration in millisecond for the fw to be on the
|
||||||
* channel that is bound to the vif.
|
* 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,
|
* 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
|
* 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.
|
* another notification to the driver.
|
||||||
*/
|
*/
|
||||||
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
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
|
* 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);
|
spin_unlock(&mvmsta->lock);
|
||||||
|
|
||||||
if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
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);
|
atomic_inc(&mvmsta->pending_frames);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||||
info);
|
info);
|
||||||
|
|
||||||
/* Single frame failure in an AMPDU queue => send BAR */
|
/* 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_ACK))
|
||||||
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
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);
|
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:
|
/* If this is an aggregation queue, we use the ssn since:
|
||||||
* ssn = wifi seq_num % 256.
|
* ssn = wifi seq_num % 256.
|
||||||
* The seq_ctl is the sequence control of the packet to which
|
* 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
|
* If there are no pending frames for this STA, notify mac80211 that
|
||||||
* this station can go to sleep in its STA table.
|
* 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) &&
|
!WARN_ON(skb_freed > 1) &&
|
||||||
mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
||||||
atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
|
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);
|
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||||
struct ieee80211_sta *sta;
|
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;
|
return;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS))
|
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))
|
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
|
||||||
return -EIO;
|
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;
|
return -ERFKILL;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->flags & CMD_ASYNC)
|
if (cmd->flags & CMD_ASYNC)
|
||||||
return iwl_pcie_send_hcmd_async(trans, cmd);
|
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);
|
newtype, vif->addr);
|
||||||
hwsim_check_magic(vif);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,7 +1395,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
||||||
return 0;
|
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 */
|
/* Not implemented, queues only on kernel side */
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,3 +259,44 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
|
||||||
|
|
||||||
return ret_len;
|
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_
|
#ifndef _MWIFIEX_11AC_H_
|
||||||
#define _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,
|
int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
|
||||||
struct mwifiex_bssdescriptor *bss_desc,
|
struct mwifiex_bssdescriptor *bss_desc,
|
||||||
u8 **buffer);
|
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_ */
|
#endif /* _MWIFIEX_11AC_H_ */
|
||||||
|
|
|
@ -679,3 +679,25 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
|
||||||
|
|
||||||
return;
|
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);
|
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);
|
mwifiex_set_wmm_params(priv, bss_cfg, params);
|
||||||
|
|
||||||
if (params->inactivity_timeout > 0) {
|
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");
|
" or cmd size is 0, not sending\n");
|
||||||
if (cmd_node->wait_q_enabled)
|
if (cmd_node->wait_q_enabled)
|
||||||
adapter->cmd_wait_q.status = -1;
|
adapter->cmd_wait_q.status = -1;
|
||||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||||
return -1;
|
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",
|
"DNLD_CMD: FW in reset state, ignore cmd %#x\n",
|
||||||
cmd_code);
|
cmd_code);
|
||||||
mwifiex_complete_cmd(adapter, cmd_node);
|
mwifiex_complete_cmd(adapter, cmd_node);
|
||||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
||||||
adapter->cmd_sent = false;
|
adapter->cmd_sent = false;
|
||||||
if (cmd_node->wait_q_enabled)
|
if (cmd_node->wait_q_enabled)
|
||||||
adapter->cmd_wait_q.status = -1;
|
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);
|
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||||
adapter->curr_cmd = NULL;
|
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);
|
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.
|
* 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);
|
list_add(&cmd_node->list, &adapter->cmd_pending_q);
|
||||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
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) {
|
if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
|
||||||
dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n",
|
dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n",
|
||||||
le16_to_cpu(resp->command));
|
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);
|
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||||
adapter->curr_cmd = NULL;
|
adapter->curr_cmd = NULL;
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
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)
|
if (adapter->curr_cmd->wait_q_enabled)
|
||||||
adapter->cmd_wait_q.status = -1;
|
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);
|
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||||
adapter->curr_cmd = NULL;
|
adapter->curr_cmd = NULL;
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
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)
|
if (adapter->curr_cmd->wait_q_enabled)
|
||||||
adapter->cmd_wait_q.status = ret;
|
adapter->cmd_wait_q.status = ret;
|
||||||
|
|
||||||
/* Clean up and put current command back to cmd_free_q */
|
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
|
||||||
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||||
adapter->curr_cmd = NULL;
|
adapter->curr_cmd = NULL;
|
||||||
|
@ -993,7 +1008,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
||||||
mwifiex_complete_cmd(adapter, cmd_node);
|
mwifiex_complete_cmd(adapter, cmd_node);
|
||||||
cmd_node->wait_q_enabled = false;
|
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_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&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 = adapter->curr_cmd;
|
||||||
cmd_node->wait_q_enabled = false;
|
cmd_node->wait_q_enabled = false;
|
||||||
cmd_node->cmd_flag |= CMD_F_CANCELED;
|
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);
|
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
|
||||||
adapter->curr_cmd = NULL;
|
adapter->curr_cmd = NULL;
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||||
|
|
|
@ -41,8 +41,15 @@
|
||||||
#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2
|
#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2
|
||||||
#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16
|
#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16
|
||||||
|
|
||||||
#define MWIFIEX_AMPDU_DEF_TXWINSIZE 32
|
#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 16
|
||||||
#define MWIFIEX_AMPDU_DEF_RXWINSIZE 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_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
|
||||||
|
|
||||||
#define MWIFIEX_RATE_BITMAP_MCS0 32
|
#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_PCIE_DESC_DETAILS 0x00fa
|
||||||
#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
|
#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
|
||||||
#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
|
#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
|
||||||
|
#define HostCmd_CMD_11AC_CFG 0x0112
|
||||||
|
|
||||||
#define PROTOCOL_NO_SECURITY 0x01
|
#define PROTOCOL_NO_SECURITY 0x01
|
||||||
#define PROTOCOL_STATIC_WEP 0x02
|
#define PROTOCOL_STATIC_WEP 0x02
|
||||||
|
@ -1363,6 +1364,15 @@ struct host_cmd_ds_sys_config {
|
||||||
u8 tlv[0];
|
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_akmp {
|
||||||
struct host_cmd_tlv tlv;
|
struct host_cmd_tlv tlv;
|
||||||
__le16 key_mgmt;
|
__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_eeprom_access eeprom;
|
||||||
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
|
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
|
||||||
struct host_cmd_ds_sys_config uap_sys_config;
|
struct host_cmd_ds_sys_config uap_sys_config;
|
||||||
|
struct host_cmd_11ac_vht_cfg vht_cfg;
|
||||||
} params;
|
} params;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
|
|
@ -533,10 +533,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
|
||||||
if (!adapter->priv[i])
|
if (!adapter->priv[i])
|
||||||
continue;
|
continue;
|
||||||
priv = adapter->priv[i];
|
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);
|
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->tx_ba_stream_tbl_ptr);
|
||||||
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
|
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
|
||||||
INIT_LIST_HEAD(&priv->sta_list);
|
INIT_LIST_HEAD(&priv->sta_list);
|
||||||
|
@ -713,7 +711,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
|
||||||
if (adapter->curr_cmd) {
|
if (adapter->curr_cmd) {
|
||||||
dev_warn(adapter->dev, "curr_cmd is still in processing\n");
|
dev_warn(adapter->dev, "curr_cmd is still in processing\n");
|
||||||
del_timer(&adapter->cmd_timer);
|
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;
|
adapter->curr_cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg {
|
||||||
} param;
|
} 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 {
|
struct mwifiex_ds_11n_tx_cfg {
|
||||||
u16 tx_htcap;
|
u16 tx_htcap;
|
||||||
u16 tx_htinfo;
|
u16 tx_htinfo;
|
||||||
|
|
|
@ -1295,6 +1295,14 @@ int mwifiex_associate(struct mwifiex_private *priv,
|
||||||
(bss_desc->bss_mode != NL80211_IFTYPE_STATION))
|
(bss_desc->bss_mode != NL80211_IFTYPE_STATION))
|
||||||
return -1;
|
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,
|
memcpy(¤t_bssid,
|
||||||
&priv->curr_bss_params.bss_descriptor.mac_address,
|
&priv->curr_bss_params.bss_descriptor.mac_address,
|
||||||
sizeof(current_bssid));
|
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",
|
dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
|
||||||
priv->curr_bss_params.band);
|
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,
|
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START,
|
||||||
HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
|
HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
|
||||||
}
|
}
|
||||||
|
@ -1356,6 +1371,14 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
|
||||||
return -1;
|
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",
|
dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
|
||||||
priv->curr_bss_params.bss_descriptor.channel);
|
priv->curr_bss_params.bss_descriptor.channel);
|
||||||
dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",
|
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 mwifiex_tid_tbl {
|
||||||
struct list_head ra_list;
|
struct list_head ra_list;
|
||||||
/* spin lock for tid table */
|
|
||||||
spinlock_t tid_tbl_lock;
|
|
||||||
struct mwifiex_ra_list_tbl *ra_list_curr;
|
struct mwifiex_ra_list_tbl *ra_list_curr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WMM_HIGHEST_PRIORITY 7
|
#define WMM_HIGHEST_PRIORITY 7
|
||||||
#define HIGH_PRIO_TID 7
|
#define HIGH_PRIO_TID 7
|
||||||
#define LOW_PRIO_TID 0
|
#define LOW_PRIO_TID 0
|
||||||
#define NO_PKT_PRIO_TID (-1)
|
|
||||||
|
|
||||||
struct mwifiex_wmm_desc {
|
struct mwifiex_wmm_desc {
|
||||||
struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
|
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,
|
void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
||||||
struct cmd_ctrl_node *cmd_node);
|
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,
|
void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
|
||||||
struct cmd_ctrl_node *cmd_node,
|
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,
|
void mwifiex_set_ht_params(struct mwifiex_private *priv,
|
||||||
struct mwifiex_uap_bss_param *bss_cfg,
|
struct mwifiex_uap_bss_param *bss_cfg,
|
||||||
struct cfg80211_ap_settings *params);
|
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,
|
void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
|
||||||
struct cfg80211_ap_settings *params);
|
struct cfg80211_ap_settings *params);
|
||||||
|
void mwifiex_set_vht_width(struct mwifiex_private *priv,
|
||||||
|
enum nl80211_chan_width width,
|
||||||
|
bool ap_11ac_disable);
|
||||||
void
|
void
|
||||||
mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
||||||
struct mwifiex_uap_bss_param *bss_cfg,
|
struct mwifiex_uap_bss_param *bss_cfg,
|
||||||
struct cfg80211_ap_settings *params);
|
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.
|
* 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.
|
* This function adds delay loop to ensure FW is awake before proceeding.
|
||||||
*
|
|
||||||
* A host power up command is written to the card configuration
|
|
||||||
* register to wake up the card.
|
|
||||||
*/
|
*/
|
||||||
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
|
static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
|
||||||
{
|
{
|
||||||
int i = 0;
|
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++;
|
i++;
|
||||||
usleep_range(10, 20);
|
usleep_range(10, 20);
|
||||||
/* 50ms max wait */
|
/* 50ms max wait */
|
||||||
|
@ -306,16 +301,32 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
|
||||||
break;
|
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");
|
dev_dbg(adapter->dev, "event: Wakeup device...\n");
|
||||||
|
|
||||||
/* Enable interrupts or any chip access will wakeup device */
|
if (reg->sleep_cookie)
|
||||||
if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) {
|
mwifiex_pcie_dev_wakeup_delay(adapter);
|
||||||
dev_warn(adapter->dev, "Enable host interrupt failed\n");
|
|
||||||
|
/* 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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
|
if (reg->sleep_cookie) {
|
||||||
adapter->ps_state = PS_STATE_AWAKE;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1984,12 +1995,13 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!adapter->pps_uapsd_mode &&
|
} 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
|
/* Potentially for PCIe we could get other
|
||||||
* interrupts like shared. Don't change power
|
* interrupts like shared. Don't change power
|
||||||
* state until cookie is set */
|
* 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",
|
dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
|
||||||
adapter->cmd_sent, adapter->data_sent);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1393,8 +1393,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
||||||
queue_work(adapter->workqueue, &adapter->main_work);
|
queue_work(adapter->workqueue, &adapter->main_work);
|
||||||
|
|
||||||
/* Perform internal scan synchronously */
|
/* 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);
|
mwifiex_wait_queue_complete(adapter, cmd_node);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||||
flags);
|
flags);
|
||||||
|
@ -1793,7 +1795,12 @@ check_next_scan:
|
||||||
/* Need to indicate IOCTL complete */
|
/* Need to indicate IOCTL complete */
|
||||||
if (adapter->curr_cmd->wait_q_enabled) {
|
if (adapter->curr_cmd->wait_q_enabled) {
|
||||||
adapter->cmd_wait_q.status = 0;
|
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)
|
if (priv->report_scan_result)
|
||||||
priv->report_scan_result = false;
|
priv->report_scan_result = false;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "wmm.h"
|
#include "wmm.h"
|
||||||
#include "11n.h"
|
#include "11n.h"
|
||||||
|
#include "11ac.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function prepares command to set/get RSSI information.
|
* 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) +
|
cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
|
||||||
S_DS_GEN);
|
S_DS_GEN);
|
||||||
break;
|
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:
|
case HostCmd_CMD_P2P_MODE_CFG:
|
||||||
cmd_ptr->command = cpu_to_le16(cmd_no);
|
cmd_ptr->command = cpu_to_le16(cmd_no);
|
||||||
cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
|
cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
|
||||||
|
|
|
@ -95,7 +95,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Handling errors here */
|
/* 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);
|
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||||
adapter->curr_cmd = NULL;
|
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:
|
case HostCmd_CMD_REMAIN_ON_CHAN:
|
||||||
ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
|
ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
|
||||||
break;
|
break;
|
||||||
|
case HostCmd_CMD_11AC_CFG:
|
||||||
|
break;
|
||||||
case HostCmd_CMD_P2P_MODE_CFG:
|
case HostCmd_CMD_P2P_MODE_CFG:
|
||||||
ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
|
ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
|
||||||
break;
|
break;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue