mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
Merge branch 'wireless'
John W. Linville says: ==================== Please accept this pull request for the 3.10 stream... Regarding the mac80211 bits, Johannes says: "Here I have a bunch of minstrel fixes from Felix, per-interface multicast filtering from Alex, set_tim debouncing from Ilan, per-interface debugfs cleanups from Stanislaw, an error return fix from Wei and a number of small improvements and fixes that I made myself." And for the iwlwifi bits, Johannes says: "Andrei changed an instance of kmalloc+memdup to kmemdup, Stanislaw removed the now unused 5ghz_disable module parameter. I also have a number of fixes from Ilan, Emmanuel and myself, Emmanuel also continued working on Bluetooth coexistence." For the sizeable batch of Bluetooth bits, Gustavo says: "This is our first batch of patches for 3.10. The biggest changes of this pull request are from Johan Hedberg, he implemented a HCI request framework to make life easier when we have to send many HCI commands and a block and wait for all of the to finish, we were able to fix a few issues in stack with the introduction of this framework. Other than that Dean Jenkins did a good work cleaning the RFCOMM code, the refcnt infrastructure was removed and now we use NULL pointer checks to know when a object was freed or not. That code was buggy and now it looks a way better. The rest of changes are clean ups, fixes and small improvements all over the Bluetooth subsystem." Regarding the wl12xx bits, Luca says: "Some patches intended for 3.10. Mostly bug fixes and other small improvements." On top of that, there are updates to brcmfmac, brcmsmac, b43, ssb and bcma, as well as mwifiex, rt2x00, and ath9k and a few others. The most notable bit is the addition of a new driver in the rtlwifi family. Please let me know if there are problems! ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e355fbbcae
258 changed files with 23464 additions and 3976 deletions
|
@ -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 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||||
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 @@ static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||||
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 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||||
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 @@ int brcmf_bus_start(struct device *dev)
|
||||||
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 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
|
||||||
* 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 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
|
||||||
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 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
|
||||||
|
|
||||||
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 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
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 @@ brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
|
||||||
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 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
}
|
}
|
||||||
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 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||||
/* 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