Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
This commit is contained in:
commit
c597f6653d
|
@ -1122,12 +1122,12 @@ exit:
|
|||
static void at76_dump_mib_local(struct at76_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
|
||||
struct mib_local *m = kmalloc(sizeof(*m), GFP_KERNEL);
|
||||
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
|
||||
ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(*m));
|
||||
if (ret < 0) {
|
||||
wiphy_err(priv->hw->wiphy,
|
||||
"at76_get_mib (LOCAL) failed: %d\n", ret);
|
||||
|
|
|
@ -36,6 +36,15 @@ config BRCMFMAC_SDIO
|
|||
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
|
||||
use the driver for a SDIO wireless card.
|
||||
|
||||
config BRCMFMAC_SDIO_OOB
|
||||
bool "Out of band interrupt support for SDIO interface chipset"
|
||||
depends on BRCMFMAC_SDIO
|
||||
---help---
|
||||
This option enables out-of-band interrupt support for Broadcom
|
||||
SDIO Wifi chipset using fullmac in order to gain better
|
||||
performance and deep sleep wake up capability on certain
|
||||
platforms. Say N if you are unsure.
|
||||
|
||||
config BRCMFMAC_USB
|
||||
bool "USB bus interface support for FullMAC driver"
|
||||
depends on USB
|
||||
|
|
|
@ -39,37 +39,113 @@
|
|||
|
||||
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
|
||||
|
||||
static void brcmf_sdioh_irqhandler(struct sdio_func *func)
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
|
||||
{
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
|
||||
|
||||
brcmf_dbg(TRACE, "***IRQHandler\n");
|
||||
brcmf_dbg(INTR, "oob intr triggered\n");
|
||||
|
||||
sdio_release_host(func);
|
||||
/*
|
||||
* out-of-band interrupt is level-triggered which won't
|
||||
* be cleared until dpc
|
||||
*/
|
||||
if (sdiodev->irq_en) {
|
||||
disable_irq_nosync(irq);
|
||||
sdiodev->irq_en = false;
|
||||
}
|
||||
|
||||
brcmf_sdbrcm_isr(sdiodev->bus);
|
||||
|
||||
sdio_claim_host(func);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 data;
|
||||
unsigned long flags;
|
||||
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
|
||||
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
|
||||
sdiodev->irq_flags, "brcmf_oob_intr",
|
||||
&sdiodev->func[1]->card->dev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
spin_lock_init(&sdiodev->irq_en_lock);
|
||||
spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
|
||||
sdiodev->irq_en = true;
|
||||
spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
|
||||
|
||||
ret = enable_irq_wake(sdiodev->irq);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
sdiodev->irq_wake = true;
|
||||
|
||||
/* must configure SDIO_CCCR_IENx to enable irq */
|
||||
data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0,
|
||||
SDIO_CCCR_IENx, &ret);
|
||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx,
|
||||
data, &ret);
|
||||
|
||||
/* redirect, configure ane enable io for interrupt signal */
|
||||
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
||||
if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH)
|
||||
data |= SDIO_SEPINT_ACT_HI;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
|
||||
data, &ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
|
||||
0, NULL);
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL);
|
||||
|
||||
if (sdiodev->irq_wake) {
|
||||
disable_irq_wake(sdiodev->irq);
|
||||
sdiodev->irq_wake = false;
|
||||
}
|
||||
free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
|
||||
sdiodev->irq_en = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
static void brcmf_sdio_irqhandler(struct sdio_func *func)
|
||||
{
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
|
||||
brcmf_dbg(INTR, "ib intr triggered\n");
|
||||
|
||||
brcmf_sdbrcm_isr(sdiodev->bus);
|
||||
}
|
||||
|
||||
/* dummy handler for SDIO function 2 interrupt */
|
||||
static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func)
|
||||
static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
|
||||
{
|
||||
}
|
||||
|
||||
int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
|
||||
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
|
||||
sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler);
|
||||
sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
|
||||
sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
|
||||
int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
|
@ -80,6 +156,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
|
||||
int *err)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/sched.h> /* request_irq() */
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <defs.h>
|
||||
|
@ -55,6 +56,15 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static struct list_head oobirq_lh;
|
||||
struct brcmf_sdio_oobirq {
|
||||
unsigned int irq;
|
||||
unsigned long flags;
|
||||
struct list_head list;
|
||||
};
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static bool
|
||||
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
|
@ -107,7 +117,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
|
|||
}
|
||||
sdio_release_host(sdfunc);
|
||||
}
|
||||
} else if (regaddr == SDIO_CCCR_ABORT) {
|
||||
} else if ((regaddr == SDIO_CCCR_ABORT) ||
|
||||
(regaddr == SDIO_CCCR_IENx)) {
|
||||
sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
|
||||
GFP_KERNEL);
|
||||
if (!sdfunc)
|
||||
|
@ -467,12 +478,40 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
struct brcmf_sdio_oobirq *oobirq_entry;
|
||||
|
||||
if (list_empty(&oobirq_lh)) {
|
||||
brcmf_dbg(ERROR, "no valid oob irq resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
|
||||
list);
|
||||
|
||||
sdiodev->irq = oobirq_entry->irq;
|
||||
sdiodev->irq_flags = oobirq_entry->flags;
|
||||
list_del(&oobirq_entry->list);
|
||||
kfree(oobirq_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
struct brcmf_bus *bus_if;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "func->class=%x\n", func->class);
|
||||
brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
|
||||
|
@ -511,6 +550,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||
sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
|
||||
return -ENODEV;
|
||||
|
||||
ret = brcmf_sdio_getintrcfg(sdiodev);
|
||||
if (ret)
|
||||
return ret;
|
||||
sdiodev->func[2] = func;
|
||||
|
||||
bus_if = sdiodev->bus_if;
|
||||
|
@ -603,6 +646,65 @@ static struct sdio_driver brcmf_sdmmc_driver = {
|
|||
#endif /* CONFIG_PM_SLEEP */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct brcmf_sdio_oobirq *oobirq_entry;
|
||||
int i, ret;
|
||||
|
||||
INIT_LIST_HEAD(&oobirq_lh);
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
|
||||
GFP_KERNEL);
|
||||
oobirq_entry->irq = res->start;
|
||||
oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
|
||||
list_add_tail(&oobirq_entry->list, &oobirq_lh);
|
||||
}
|
||||
if (i == 0)
|
||||
return -ENXIO;
|
||||
|
||||
ret = sdio_register_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
if (ret)
|
||||
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver brcmf_sdio_pd = {
|
||||
.probe = brcmf_sdio_pd_probe,
|
||||
.driver = {
|
||||
.name = "brcmf_sdio_pd"
|
||||
}
|
||||
};
|
||||
|
||||
void brcmf_sdio_exit(void)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
|
||||
platform_driver_unregister(&brcmf_sdio_pd);
|
||||
}
|
||||
|
||||
void brcmf_sdio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
ret = platform_driver_register(&brcmf_sdio_pd);
|
||||
|
||||
if (ret)
|
||||
brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret);
|
||||
}
|
||||
#else
|
||||
void brcmf_sdio_exit(void)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
@ -621,3 +723,4 @@ void brcmf_sdio_init(void)
|
|||
if (ret)
|
||||
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
|
|
@ -2352,6 +2352,24 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
up(&bus->sdsem);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
|
||||
if (!bus->sdiodev->irq_en && !bus->ipend) {
|
||||
enable_irq(bus->sdiodev->irq);
|
||||
bus->sdiodev->irq_en = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
|
||||
}
|
||||
#else
|
||||
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||
{
|
||||
u32 intstatus, newstatus = 0;
|
||||
|
@ -2509,6 +2527,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
bus->intstatus = intstatus;
|
||||
|
||||
clkwait:
|
||||
brcmf_sdbrcm_clrintr(bus);
|
||||
|
||||
if (data_ok(bus) && bus->ctrl_frame_stat &&
|
||||
(bus->clkstate == CLK_AVAIL)) {
|
||||
int ret, i;
|
||||
|
@ -3508,8 +3528,14 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = brcmf_sdio_intr_register(bus->sdiodev);
|
||||
if (ret != 0)
|
||||
brcmf_dbg(ERROR, "intr register failed:%d\n", ret);
|
||||
}
|
||||
|
||||
/* If we didn't come up, turn off backplane clock */
|
||||
if (!ret)
|
||||
if (bus_if->state != BRCMF_BUS_DATA)
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
|
||||
exit:
|
||||
|
@ -3867,7 +3893,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
|
|||
|
||||
if (bus) {
|
||||
/* De-register interrupt handler */
|
||||
brcmf_sdcard_intr_dereg(bus->sdiodev);
|
||||
brcmf_sdio_intr_unregister(bus->sdiodev);
|
||||
|
||||
if (bus->sdiodev->bus_if->drvr) {
|
||||
brcmf_detach(bus->sdiodev->dev);
|
||||
|
@ -3968,15 +3994,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* Register interrupt callback, but mask it (not operational yet). */
|
||||
brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n");
|
||||
ret = brcmf_sdcard_intr_reg(bus->sdiodev);
|
||||
if (ret != 0) {
|
||||
brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
brcmf_dbg(INTR, "registered SDIO interrupt function ok\n");
|
||||
|
||||
brcmf_dbg(INFO, "completed!!\n");
|
||||
|
||||
/* if firmware path present try to download and bring up bus */
|
||||
|
|
|
@ -43,6 +43,13 @@
|
|||
/* as of sdiod rev 0, supports 3 functions */
|
||||
#define SBSDIO_NUM_FUNCTION 3
|
||||
|
||||
/* function 0 vendor specific CCCR registers */
|
||||
#define SDIO_CCCR_BRCM_SEPINT 0xf2
|
||||
|
||||
#define SDIO_SEPINT_MASK 0x01
|
||||
#define SDIO_SEPINT_OE 0x02
|
||||
#define SDIO_SEPINT_ACT_HI 0x04
|
||||
|
||||
/* function 1 miscellaneous registers */
|
||||
|
||||
/* sprom command and status */
|
||||
|
@ -144,13 +151,18 @@ struct brcmf_sdio_dev {
|
|||
wait_queue_head_t request_buffer_wait;
|
||||
struct device *dev;
|
||||
struct brcmf_bus *bus_if;
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
unsigned int irq; /* oob interrupt number */
|
||||
unsigned long irq_flags; /* board specific oob flags */
|
||||
bool irq_en; /* irq enable flags */
|
||||
spinlock_t irq_en_lock;
|
||||
bool irq_wake; /* irq wake enable flags */
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
};
|
||||
|
||||
/* Register/deregister device interrupt handler. */
|
||||
extern int
|
||||
brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev);
|
||||
|
||||
extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev);
|
||||
/* Register/deregister interrupt handler. */
|
||||
extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
|
||||
extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
|
||||
|
||||
/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
|
||||
* fn: function number
|
||||
|
|
|
@ -1963,10 +1963,8 @@ static int ipw2100_wdev_init(struct net_device *dev)
|
|||
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
|
||||
|
||||
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
|
||||
if (wiphy_register(wdev->wiphy)) {
|
||||
ipw2100_down(priv);
|
||||
if (wiphy_register(wdev->wiphy))
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6331,6 +6329,11 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
printk(KERN_INFO DRV_NAME
|
||||
": Detected Intel PRO/Wireless 2100 Network Connection\n");
|
||||
|
||||
err = ipw2100_wdev_init(dev);
|
||||
if (err)
|
||||
goto fail;
|
||||
registered = 1;
|
||||
|
||||
/* Bring up the interface. Pre 0.46, after we registered the
|
||||
* network device we would call ipw2100_up. This introduced a race
|
||||
* condition with newer hotplug configurations (network was coming
|
||||
|
@ -6347,11 +6350,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
"Error calling register_netdev.\n");
|
||||
goto fail;
|
||||
}
|
||||
registered = 1;
|
||||
|
||||
err = ipw2100_wdev_init(dev);
|
||||
if (err)
|
||||
goto fail;
|
||||
registered = 2;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
||||
|
@ -6390,13 +6389,16 @@ out:
|
|||
|
||||
fail_unlock:
|
||||
mutex_unlock(&priv->action_mutex);
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
fail:
|
||||
if (dev) {
|
||||
if (registered)
|
||||
if (registered >= 2)
|
||||
unregister_netdev(dev);
|
||||
|
||||
if (registered) {
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
}
|
||||
|
||||
ipw2100_hw_stop_adapter(priv);
|
||||
|
||||
ipw2100_disable_interrupts(priv);
|
||||
|
|
|
@ -11443,20 +11443,6 @@ static void ipw_bg_down(struct work_struct *work)
|
|||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/* Called by register_netdev() */
|
||||
static int ipw_net_init(struct net_device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct ipw_priv *priv = libipw_priv(dev);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (ipw_up(priv))
|
||||
rc = -EIO;
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ipw_wdev_init(struct net_device *dev)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
@ -11725,7 +11711,6 @@ static void ipw_prom_free(struct ipw_priv *priv)
|
|||
#endif
|
||||
|
||||
static const struct net_device_ops ipw_netdev_ops = {
|
||||
.ndo_init = ipw_net_init,
|
||||
.ndo_open = ipw_net_open,
|
||||
.ndo_stop = ipw_net_stop,
|
||||
.ndo_set_rx_mode = ipw_net_set_multicast_list,
|
||||
|
@ -11848,17 +11833,24 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
goto out_release_irq;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
err = register_netdev(net_dev);
|
||||
if (err) {
|
||||
IPW_ERROR("failed to register network device\n");
|
||||
if (ipw_up(priv)) {
|
||||
mutex_unlock(&priv->mutex);
|
||||
err = -EIO;
|
||||
goto out_remove_sysfs;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
err = ipw_wdev_init(net_dev);
|
||||
if (err) {
|
||||
IPW_ERROR("failed to register wireless device\n");
|
||||
goto out_unregister_netdev;
|
||||
goto out_remove_sysfs;
|
||||
}
|
||||
|
||||
err = register_netdev(net_dev);
|
||||
if (err) {
|
||||
IPW_ERROR("failed to register network device\n");
|
||||
goto out_unregister_wiphy;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPW2200_PROMISCUOUS
|
||||
|
@ -11867,10 +11859,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
if (err) {
|
||||
IPW_ERROR("Failed to register promiscuous network "
|
||||
"device (error %d).\n", err);
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->a_band.channels);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
goto out_unregister_netdev;
|
||||
unregister_netdev(priv->net_dev);
|
||||
goto out_unregister_wiphy;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -11882,8 +11872,10 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
return 0;
|
||||
|
||||
out_unregister_netdev:
|
||||
unregister_netdev(priv->net_dev);
|
||||
out_unregister_wiphy:
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->a_band.channels);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
out_remove_sysfs:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
|
||||
out_release_irq:
|
||||
|
|
|
@ -186,76 +186,8 @@ done:
|
|||
/*
|
||||
* BT coex
|
||||
*/
|
||||
/*
|
||||
* Macros to access the lookup table.
|
||||
*
|
||||
* The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
|
||||
* wifi_prio, wifi_txrx and wifi_sh_ant_req.
|
||||
*
|
||||
* It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
|
||||
*
|
||||
* The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
|
||||
* one after another in 32-bit registers, and "registers" 0 through 7 contain
|
||||
* the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
|
||||
*
|
||||
* These macros encode that format.
|
||||
*/
|
||||
#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
|
||||
wifi_txrx, wifi_sh_ant_req) \
|
||||
(bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
|
||||
(wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
|
||||
|
||||
#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
|
||||
lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
|
||||
#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
(!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \
|
||||
bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
|
||||
wifi_sh_ant_req))))
|
||||
#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
|
||||
bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
|
||||
wifi_sh_ant_req))
|
||||
#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, \
|
||||
wifi_sh_ant_req) \
|
||||
LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
|
||||
bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
|
||||
wifi_sh_ant_req))
|
||||
|
||||
#define LUT_WLAN_KILL_OP(lut, op, val) \
|
||||
lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
|
||||
#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
(!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
|
||||
#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
|
||||
#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
|
||||
|
||||
#define LUT_ANT_SWITCH_OP(lut, op, val) \
|
||||
lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
|
||||
#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
(!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, \
|
||||
wifi_sh_ant_req))))
|
||||
#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
|
||||
#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
|
||||
wifi_prio, wifi_txrx, wifi_sh_ant_req) \
|
||||
LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
|
||||
wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
|
||||
|
||||
static const __le32 iwlagn_def_3w_lookup[12] = {
|
||||
/* Notmal TDM */
|
||||
static const __le32 iwlagn_def_3w_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaeaaaaaa),
|
||||
|
@ -270,7 +202,25 @@ static const __le32 iwlagn_def_3w_lookup[12] = {
|
|||
cpu_to_le32(0xf0005000),
|
||||
};
|
||||
|
||||
static const __le32 iwlagn_concurrent_lookup[12] = {
|
||||
|
||||
/* Loose Coex */
|
||||
static const __le32 iwlagn_loose_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaeaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xcc00ff28),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0xcc00aaaa),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
};
|
||||
|
||||
/* Full concurrency */
|
||||
static const __le32 iwlagn_concurrent_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
|
@ -325,6 +275,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||
|
||||
basic.kill_ack_mask = priv->kill_ack_mask;
|
||||
basic.kill_cts_mask = priv->kill_cts_mask;
|
||||
basic.reduce_txpower = priv->reduced_txpower;
|
||||
basic.valid = priv->bt_valid;
|
||||
|
||||
/*
|
||||
|
@ -610,29 +561,62 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
|
|||
BT_UART_MSG_FRAME7CONNECTABLE_POS);
|
||||
}
|
||||
|
||||
static void iwlagn_set_kill_msk(struct iwl_priv *priv,
|
||||
static bool iwlagn_set_kill_msk(struct iwl_priv *priv,
|
||||
struct iwl_bt_uart_msg *uart_msg)
|
||||
{
|
||||
u8 kill_msk;
|
||||
static const __le32 bt_kill_ack_msg[2] = {
|
||||
bool need_update = false;
|
||||
u8 kill_msk = IWL_BT_KILL_REDUCE;
|
||||
static const __le32 bt_kill_ack_msg[3] = {
|
||||
IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
|
||||
static const __le32 bt_kill_cts_msg[2] = {
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
|
||||
static const __le32 bt_kill_cts_msg[3] = {
|
||||
IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
|
||||
IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
|
||||
|
||||
kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
|
||||
? 1 : 0;
|
||||
if (!priv->reduced_txpower)
|
||||
kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
|
||||
? IWL_BT_KILL_OVERRIDE : IWL_BT_KILL_DEFAULT;
|
||||
if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
|
||||
priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
|
||||
priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
|
||||
priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
|
||||
priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
|
||||
priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
|
||||
|
||||
/* schedule to send runtime bt_config */
|
||||
queue_work(priv->workqueue, &priv->bt_runtime_config);
|
||||
need_update = true;
|
||||
}
|
||||
return need_update;
|
||||
}
|
||||
|
||||
static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
|
||||
struct iwl_bt_uart_msg *uart_msg)
|
||||
{
|
||||
bool need_update = false;
|
||||
|
||||
if (!priv->reduced_txpower &&
|
||||
!iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
|
||||
(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
|
||||
BT_UART_MSG_FRAME3OBEX_MSK)) &&
|
||||
!(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
|
||||
BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK))) {
|
||||
/* enabling reduced tx power */
|
||||
priv->reduced_txpower = true;
|
||||
priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
|
||||
need_update = true;
|
||||
} else if (priv->reduced_txpower &&
|
||||
(iwl_is_associated(priv, IWL_RXON_CTX_PAN) ||
|
||||
(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
|
||||
BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) ||
|
||||
!(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
|
||||
BT_UART_MSG_FRAME3OBEX_MSK)))) {
|
||||
/* disable reduced tx power */
|
||||
priv->reduced_txpower = false;
|
||||
priv->bt_valid &= ~IWLAGN_BT_VALID_REDUCED_TX_PWR;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
return need_update;
|
||||
}
|
||||
|
||||
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
|
@ -680,7 +664,12 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
|||
}
|
||||
}
|
||||
|
||||
iwlagn_set_kill_msk(priv, uart_msg);
|
||||
/* schedule to send runtime bt_config */
|
||||
/* check reduce power before change ack/cts kill mask */
|
||||
if (iwlagn_fill_txpower_mode(priv, uart_msg) ||
|
||||
iwlagn_set_kill_msk(priv, uart_msg))
|
||||
queue_work(priv->workqueue, &priv->bt_runtime_config);
|
||||
|
||||
|
||||
/* FIXME: based on notification, adjust the prio_boost */
|
||||
|
||||
|
|
|
@ -764,7 +764,8 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
fraglen = len - hdrlen;
|
||||
|
||||
if (fraglen) {
|
||||
int offset = (void *)hdr - rxb_addr(rxb) + rxb_offset(rxb);
|
||||
int offset = (void *)hdr + hdrlen -
|
||||
rxb_addr(rxb) + rxb_offset(rxb);
|
||||
|
||||
skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
|
||||
fraglen, rxb->truesize);
|
||||
|
|
|
@ -1307,6 +1307,9 @@ static int iwl_init_geos(struct iwl_priv *priv)
|
|||
priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
||||
}
|
||||
|
||||
if (iwlwifi_mod_params.disable_5ghz)
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0;
|
||||
|
||||
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
||||
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
|
||||
|
@ -1417,38 +1420,37 @@ void iwl_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
|
||||
|
||||
void iwl_debug_config(struct iwl_priv *priv)
|
||||
/* show what optional capabilities we have */
|
||||
void iwl_option_config(struct iwl_priv *priv)
|
||||
{
|
||||
dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEBUG "
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
"enabled\n");
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
|
||||
#else
|
||||
"disabled\n");
|
||||
#endif
|
||||
dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEBUGFS "
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
"enabled\n");
|
||||
#else
|
||||
"disabled\n");
|
||||
#endif
|
||||
dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEVICE_TRACING "
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
|
||||
"enabled\n");
|
||||
#else
|
||||
"disabled\n");
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG disabled\n");
|
||||
#endif
|
||||
|
||||
dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
"enabled\n");
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS enabled\n");
|
||||
#else
|
||||
"disabled\n");
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS disabled\n");
|
||||
#endif
|
||||
dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_P2P "
|
||||
#ifdef CONFIG_IWLWIFI_P2P
|
||||
"enabled\n");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING enabled\n");
|
||||
#else
|
||||
"disabled\n");
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE enabled\n");
|
||||
#else
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE disabled\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_P2P
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
|
||||
#else
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1567,8 +1569,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
|
||||
SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
|
||||
|
||||
/* show what debugging capabilities we have */
|
||||
iwl_debug_config(priv);
|
||||
iwl_option_config(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
|
||||
|
||||
|
@ -1586,7 +1587,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
/* these spin locks will be used in apm_ops.init and EEPROM access
|
||||
* we should init now
|
||||
*/
|
||||
spin_lock_init(&priv->trans->reg_lock);
|
||||
spin_lock_init(&priv->statistics.lock);
|
||||
|
||||
/***********************
|
||||
|
|
|
@ -523,7 +523,7 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
|
|||
void iwl_setup_deferred_work(struct iwl_priv *priv);
|
||||
int iwl_send_wimax_coex(struct iwl_priv *priv);
|
||||
int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
|
||||
void iwl_debug_config(struct iwl_priv *priv);
|
||||
void iwl_option_config(struct iwl_priv *priv);
|
||||
void iwl_set_hw_params(struct iwl_priv *priv);
|
||||
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
|
||||
int iwl_init_drv(struct iwl_priv *priv);
|
||||
|
|
|
@ -1877,9 +1877,16 @@ struct iwl_bt_cmd {
|
|||
|
||||
#define IWLAGN_BT3_T7_DEFAULT 1
|
||||
|
||||
enum iwl_bt_kill_idx {
|
||||
IWL_BT_KILL_DEFAULT = 0,
|
||||
IWL_BT_KILL_OVERRIDE = 1,
|
||||
IWL_BT_KILL_REDUCE = 2,
|
||||
};
|
||||
|
||||
#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffff0000)
|
||||
#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffff0000)
|
||||
#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO cpu_to_le32(0xffffffff)
|
||||
#define IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE cpu_to_le32(0)
|
||||
|
||||
#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2
|
||||
|
||||
|
@ -1891,7 +1898,7 @@ struct iwl_bt_cmd {
|
|||
#define IWLAGN_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3))
|
||||
#define IWLAGN_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4))
|
||||
#define IWLAGN_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5))
|
||||
#define IWLAGN_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6))
|
||||
#define IWLAGN_BT_VALID_REDUCED_TX_PWR cpu_to_le16(BIT(6))
|
||||
#define IWLAGN_BT_VALID_3W_LUT cpu_to_le16(BIT(7))
|
||||
|
||||
#define IWLAGN_BT_ALL_VALID_MSK (IWLAGN_BT_VALID_ENABLE_FLAGS | \
|
||||
|
@ -1900,9 +1907,11 @@ struct iwl_bt_cmd {
|
|||
IWLAGN_BT_VALID_3W_TIMERS | \
|
||||
IWLAGN_BT_VALID_KILL_ACK_MASK | \
|
||||
IWLAGN_BT_VALID_KILL_CTS_MASK | \
|
||||
IWLAGN_BT_VALID_BT4_TIMES | \
|
||||
IWLAGN_BT_VALID_REDUCED_TX_PWR | \
|
||||
IWLAGN_BT_VALID_3W_LUT)
|
||||
|
||||
#define IWLAGN_BT_DECISION_LUT_SIZE 12
|
||||
|
||||
struct iwl_basic_bt_cmd {
|
||||
u8 flags;
|
||||
u8 ledtime; /* unused */
|
||||
|
@ -1913,8 +1922,9 @@ struct iwl_basic_bt_cmd {
|
|||
u8 bt3_prio_sample_time;
|
||||
u8 bt3_timer_t2_value;
|
||||
__le16 bt4_reaction_time; /* unused */
|
||||
__le32 bt3_lookup_table[12];
|
||||
__le16 bt4_decision_time; /* unused */
|
||||
__le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE];
|
||||
u8 reduce_txpower;
|
||||
u8 reserved;
|
||||
__le16 valid;
|
||||
};
|
||||
|
||||
|
@ -3634,6 +3644,9 @@ enum iwl_bt_coex_profile_traffic_load {
|
|||
(0x3<<BT_UART_MSG_2_FRAME7RESERVED_POS)
|
||||
|
||||
|
||||
#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
|
||||
#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
|
||||
|
||||
struct iwl_bt_uart_msg {
|
||||
u8 header;
|
||||
u8 frame1;
|
||||
|
|
|
@ -921,6 +921,7 @@ struct iwl_priv {
|
|||
__le32 kill_ack_mask;
|
||||
__le32 kill_cts_mask;
|
||||
__le16 bt_valid;
|
||||
bool reduced_txpower;
|
||||
u16 bt_on_thresh;
|
||||
u16 bt_duration;
|
||||
u16 dynamic_frag_thresh;
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include <linux/module.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
|
@ -892,10 +893,9 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
|||
int ret;
|
||||
|
||||
drv = kzalloc(sizeof(*drv), GFP_KERNEL);
|
||||
if (!drv) {
|
||||
dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
|
||||
if (!drv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drv->trans = trans;
|
||||
drv->dev = trans->dev;
|
||||
drv->cfg = cfg;
|
||||
|
@ -905,7 +905,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
|||
ret = iwl_request_firmware(drv, true);
|
||||
|
||||
if (ret) {
|
||||
dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
|
||||
IWL_ERR(trans, "Couldn't request the fw\n");
|
||||
kfree(drv);
|
||||
drv = NULL;
|
||||
}
|
||||
|
@ -1012,3 +1012,7 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
|
|||
bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(auto_agg,
|
||||
"enable agg w/o check traffic load (default: enable)");
|
||||
|
||||
module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz,
|
||||
bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])");
|
||||
|
|
|
@ -60,8 +60,8 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __iwl_shared_h__
|
||||
#define __iwl_shared_h__
|
||||
#ifndef __iwl_modparams_h__
|
||||
#define __iwl_modparams_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -103,6 +103,7 @@ enum iwl_power_level {
|
|||
* @ant_coupling: antenna coupling in dB, default = 0
|
||||
* @bt_ch_announce: BT channel inhibition, default = enable
|
||||
* @auto_agg: enable agg. without check, default = true
|
||||
* @disable_5ghz: disable 5GHz capability, default = false
|
||||
*/
|
||||
struct iwl_mod_params {
|
||||
int sw_crypto;
|
||||
|
@ -119,6 +120,7 @@ struct iwl_mod_params {
|
|||
int ant_coupling;
|
||||
bool bt_ch_announce;
|
||||
bool auto_agg;
|
||||
bool disable_5ghz;
|
||||
};
|
||||
|
||||
#endif /* #__iwl_shared_h__ */
|
||||
#endif /* #__iwl_modparams_h__ */
|
||||
|
|
|
@ -2175,6 +2175,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
|
||||
/* Initialize the wait queue for commands */
|
||||
init_waitqueue_head(&trans->wait_command_queue);
|
||||
spin_lock_init(&trans->reg_lock);
|
||||
|
||||
return trans;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Firmware loading and handling functions.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -10,12 +10,12 @@ config MWIFIEX
|
|||
mwifiex.
|
||||
|
||||
config MWIFIEX_SDIO
|
||||
tristate "Marvell WiFi-Ex Driver for SD8787/SD8797"
|
||||
tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797"
|
||||
depends on MWIFIEX && MMC
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This adds support for wireless adapters based on Marvell
|
||||
8787/8797 chipsets with SDIO interface.
|
||||
8786/8787/8797 chipsets with SDIO interface.
|
||||
|
||||
If you choose to build it as a module, it will be called
|
||||
mwifiex_sdio.
|
||||
|
|
|
@ -993,8 +993,7 @@ struct mwifiex_ie_types_wmm_queue_status {
|
|||
struct ieee_types_vendor_header {
|
||||
u8 element_id;
|
||||
u8 len;
|
||||
u8 oui[3];
|
||||
u8 oui_type;
|
||||
u8 oui[4]; /* 0~2: oui, 3: oui_type */
|
||||
u8 oui_subtype;
|
||||
u8 version;
|
||||
} __packed;
|
||||
|
|
|
@ -253,6 +253,8 @@ static int mwifiex_sdio_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Device ID for SD8786 */
|
||||
#define SDIO_DEVICE_ID_MARVELL_8786 (0x9116)
|
||||
/* Device ID for SD8787 */
|
||||
#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119)
|
||||
/* Device ID for SD8797 */
|
||||
|
@ -260,6 +262,7 @@ static int mwifiex_sdio_resume(struct device *dev)
|
|||
|
||||
/* WLAN IDs */
|
||||
static const struct sdio_device_id mwifiex_ids[] = {
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786)},
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)},
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)},
|
||||
{},
|
||||
|
@ -1599,6 +1602,9 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
|
|||
adapter->dev = &func->dev;
|
||||
|
||||
switch (func->device) {
|
||||
case SDIO_DEVICE_ID_MARVELL_8786:
|
||||
strcpy(adapter->fw_name, SD8786_DEFAULT_FW_NAME);
|
||||
break;
|
||||
case SDIO_DEVICE_ID_MARVELL_8797:
|
||||
strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME);
|
||||
break;
|
||||
|
@ -1807,5 +1813,6 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
|||
MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
|
||||
MODULE_VERSION(SDIO_VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
|
||||
MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
|
||||
MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin"
|
||||
#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
|
||||
#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@
|
|||
#define BBP_SIZE 0x00ff
|
||||
#define RF_BASE 0x0004
|
||||
#define RF_SIZE 0x0010
|
||||
#define RFCSR_BASE 0x0000
|
||||
#define RFCSR_SIZE 0x0040
|
||||
|
||||
/*
|
||||
* Number of TX queues.
|
||||
|
|
|
@ -836,6 +836,13 @@ const struct rt2x00debug rt2800_rt2x00debug = {
|
|||
.word_size = sizeof(u32),
|
||||
.word_count = RF_SIZE / sizeof(u32),
|
||||
},
|
||||
.rfcsr = {
|
||||
.read = rt2800_rfcsr_read,
|
||||
.write = rt2800_rfcsr_write,
|
||||
.word_base = RFCSR_BASE,
|
||||
.word_size = sizeof(u8),
|
||||
.word_count = RFCSR_SIZE / sizeof(u8),
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);
|
||||
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
|
||||
|
|
|
@ -70,6 +70,7 @@ struct rt2x00debug_intf {
|
|||
* - eeprom offset/value files
|
||||
* - bbp offset/value files
|
||||
* - rf offset/value files
|
||||
* - rfcsr offset/value files
|
||||
* - queue folder
|
||||
* - frame dump file
|
||||
* - queue stats file
|
||||
|
@ -89,6 +90,8 @@ struct rt2x00debug_intf {
|
|||
struct dentry *bbp_val_entry;
|
||||
struct dentry *rf_off_entry;
|
||||
struct dentry *rf_val_entry;
|
||||
struct dentry *rfcsr_off_entry;
|
||||
struct dentry *rfcsr_val_entry;
|
||||
struct dentry *queue_folder;
|
||||
struct dentry *queue_frame_dump_entry;
|
||||
struct dentry *queue_stats_entry;
|
||||
|
@ -131,6 +134,7 @@ struct rt2x00debug_intf {
|
|||
unsigned int offset_eeprom;
|
||||
unsigned int offset_bbp;
|
||||
unsigned int offset_rf;
|
||||
unsigned int offset_rfcsr;
|
||||
};
|
||||
|
||||
void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -525,6 +529,7 @@ RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
|
|||
RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
|
||||
RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
|
||||
RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
|
||||
RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
|
||||
|
||||
static ssize_t rt2x00debug_read_dev_flags(struct file *file,
|
||||
char __user *buf,
|
||||
|
@ -614,7 +619,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
|||
const struct rt2x00debug *debug = intf->debug;
|
||||
char *data;
|
||||
|
||||
data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL);
|
||||
data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
|
@ -624,22 +629,22 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
|||
data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
|
||||
data += sprintf(data, "\n");
|
||||
data += sprintf(data, "register\tbase\twords\twordsize\n");
|
||||
data += sprintf(data, "csr\t%d\t%d\t%d\n",
|
||||
debug->csr.word_base,
|
||||
debug->csr.word_count,
|
||||
debug->csr.word_size);
|
||||
data += sprintf(data, "eeprom\t%d\t%d\t%d\n",
|
||||
debug->eeprom.word_base,
|
||||
debug->eeprom.word_count,
|
||||
debug->eeprom.word_size);
|
||||
data += sprintf(data, "bbp\t%d\t%d\t%d\n",
|
||||
debug->bbp.word_base,
|
||||
debug->bbp.word_count,
|
||||
debug->bbp.word_size);
|
||||
data += sprintf(data, "rf\t%d\t%d\t%d\n",
|
||||
debug->rf.word_base,
|
||||
debug->rf.word_count,
|
||||
debug->rf.word_size);
|
||||
#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name) \
|
||||
{ \
|
||||
if(debug->__name.read) \
|
||||
data += sprintf(data, __stringify(__name) \
|
||||
"\t%d\t%d\t%d\n", \
|
||||
debug->__name.word_base, \
|
||||
debug->__name.word_count, \
|
||||
debug->__name.word_size); \
|
||||
}
|
||||
RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
|
||||
RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
|
||||
RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
|
||||
RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
|
||||
RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
|
||||
#undef RT2X00DEBUGFS_SPRINTF_REGISTER
|
||||
|
||||
blob->size = strlen(blob->data);
|
||||
|
||||
return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
|
||||
|
@ -694,31 +699,34 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
if (IS_ERR(intf->register_folder) || !intf->register_folder)
|
||||
goto exit;
|
||||
|
||||
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
|
||||
({ \
|
||||
(__intf)->__name##_off_entry = \
|
||||
debugfs_create_u32(__stringify(__name) "_offset", \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
&(__intf)->offset_##__name); \
|
||||
if (IS_ERR((__intf)->__name##_off_entry) \
|
||||
|| !(__intf)->__name##_off_entry) \
|
||||
goto exit; \
|
||||
\
|
||||
(__intf)->__name##_val_entry = \
|
||||
debugfs_create_file(__stringify(__name) "_value", \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
(__intf), &rt2x00debug_fop_##__name);\
|
||||
if (IS_ERR((__intf)->__name##_val_entry) \
|
||||
|| !(__intf)->__name##_val_entry) \
|
||||
goto exit; \
|
||||
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
|
||||
({ \
|
||||
if(debug->__name.read) { \
|
||||
(__intf)->__name##_off_entry = \
|
||||
debugfs_create_u32(__stringify(__name) "_offset", \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
&(__intf)->offset_##__name); \
|
||||
if (IS_ERR((__intf)->__name##_off_entry) \
|
||||
|| !(__intf)->__name##_off_entry) \
|
||||
goto exit; \
|
||||
\
|
||||
(__intf)->__name##_val_entry = \
|
||||
debugfs_create_file(__stringify(__name) "_value", \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
(__intf), &rt2x00debug_fop_##__name); \
|
||||
if (IS_ERR((__intf)->__name##_val_entry) \
|
||||
|| !(__intf)->__name##_val_entry) \
|
||||
goto exit; \
|
||||
} \
|
||||
})
|
||||
|
||||
RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
|
||||
RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
|
||||
RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
|
||||
RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
|
||||
RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
|
||||
|
||||
#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
|
||||
|
||||
|
@ -770,6 +778,8 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
|
|||
debugfs_remove(intf->queue_stats_entry);
|
||||
debugfs_remove(intf->queue_frame_dump_entry);
|
||||
debugfs_remove(intf->queue_folder);
|
||||
debugfs_remove(intf->rfcsr_val_entry);
|
||||
debugfs_remove(intf->rfcsr_off_entry);
|
||||
debugfs_remove(intf->rf_val_entry);
|
||||
debugfs_remove(intf->rf_off_entry);
|
||||
debugfs_remove(intf->bbp_val_entry);
|
||||
|
|
|
@ -65,6 +65,7 @@ struct rt2x00debug {
|
|||
RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
|
||||
RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
|
||||
RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
|
||||
RT2X00DEBUGFS_REGISTER_ENTRY(rfcsr, u8);
|
||||
};
|
||||
|
||||
#endif /* RT2X00DEBUG_H */
|
||||
|
|
|
@ -2154,6 +2154,8 @@ enum nl80211_mntr_flags {
|
|||
* @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors
|
||||
* to synchronize to for 11s default synchronization method (see 11C.12.2.2)
|
||||
*
|
||||
* @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode.
|
||||
*
|
||||
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
enum nl80211_meshconf_params {
|
||||
|
@ -2179,6 +2181,7 @@ enum nl80211_meshconf_params {
|
|||
NL80211_MESHCONF_FORWARDING,
|
||||
NL80211_MESHCONF_RSSI_THRESHOLD,
|
||||
NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
|
||||
NL80211_MESHCONF_HT_OPMODE,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_MESHCONF_ATTR_AFTER_LAST,
|
||||
|
|
|
@ -821,6 +821,7 @@ struct mesh_config {
|
|||
bool dot11MeshGateAnnouncementProtocol;
|
||||
bool dot11MeshForwarding;
|
||||
s32 rssi_threshold;
|
||||
u16 ht_opmode;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1514,6 +1515,16 @@ struct cfg80211_gtk_rekey_data {
|
|||
* later passes to cfg80211_probe_status().
|
||||
*
|
||||
* @set_noack_map: Set the NoAck Map for the TIDs.
|
||||
*
|
||||
* @get_et_sset_count: Ethtool API to get string-set count.
|
||||
* See @ethtool_ops.get_sset_count
|
||||
*
|
||||
* @get_et_stats: Ethtool API to get a set of u64 stats.
|
||||
* See @ethtool_ops.get_ethtool_stats
|
||||
*
|
||||
* @get_et_strings: Ethtool API to get a set of strings to describe stats
|
||||
* and perhaps other supported types of ethtool data-sets.
|
||||
* See @ethtool_ops.get_strings
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
|
@ -1712,6 +1723,13 @@ struct cfg80211_ops {
|
|||
|
||||
struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy,
|
||||
enum nl80211_channel_type *type);
|
||||
|
||||
int (*get_et_sset_count)(struct wiphy *wiphy,
|
||||
struct net_device *dev, int sset);
|
||||
void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data);
|
||||
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u32 sset, u8 *data);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -2223,6 +2223,14 @@ enum ieee80211_rate_control_changed {
|
|||
* The @tids parameter is a bitmap and tells the driver which TIDs the
|
||||
* frames will be on; it will at most have two bits set.
|
||||
* This callback must be atomic.
|
||||
*
|
||||
* @get_et_sset_count: Ethtool API to get string-set count.
|
||||
*
|
||||
* @get_et_stats: Ethtool API to get a set of u64 stats.
|
||||
*
|
||||
* @get_et_strings: Ethtool API to get a set of strings to describe stats
|
||||
* and perhaps other supported types of ethtool data-sets.
|
||||
*
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
|
@ -2353,6 +2361,15 @@ struct ieee80211_ops {
|
|||
u16 tids, int num_frames,
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool more_data);
|
||||
|
||||
int (*get_et_sset_count)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int sset);
|
||||
void (*get_et_stats)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ethtool_stats *stats, u64 *data);
|
||||
void (*get_et_strings)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 sset, u8 *data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -450,6 +450,180 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
}
|
||||
|
||||
static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
|
||||
"rx_packets", "rx_bytes", "wep_weak_iv_count",
|
||||
"rx_duplicates", "rx_fragments", "rx_dropped",
|
||||
"tx_packets", "tx_bytes", "tx_fragments",
|
||||
"tx_filtered", "tx_retry_failed", "tx_retries",
|
||||
"beacon_loss", "sta_state", "txrate", "rxrate", "signal",
|
||||
"channel", "noise", "ch_time", "ch_time_busy",
|
||||
"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
|
||||
};
|
||||
#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
|
||||
|
||||
static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
int sset)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
int rv = 0;
|
||||
|
||||
if (sset == ETH_SS_STATS)
|
||||
rv += STA_STATS_LEN;
|
||||
|
||||
rv += drv_get_et_sset_count(sdata, sset);
|
||||
|
||||
if (rv == 0)
|
||||
return -EOPNOTSUPP;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void ieee80211_get_et_stats(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct ethtool_stats *stats,
|
||||
u64 *data)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct station_info sinfo;
|
||||
struct survey_info survey;
|
||||
int i, q;
|
||||
#define STA_STATS_SURVEY_LEN 7
|
||||
|
||||
memset(data, 0, sizeof(u64) * STA_STATS_LEN);
|
||||
|
||||
#define ADD_STA_STATS(sta) \
|
||||
do { \
|
||||
data[i++] += sta->rx_packets; \
|
||||
data[i++] += sta->rx_bytes; \
|
||||
data[i++] += sta->wep_weak_iv_count; \
|
||||
data[i++] += sta->num_duplicates; \
|
||||
data[i++] += sta->rx_fragments; \
|
||||
data[i++] += sta->rx_dropped; \
|
||||
\
|
||||
data[i++] += sta->tx_packets; \
|
||||
data[i++] += sta->tx_bytes; \
|
||||
data[i++] += sta->tx_fragments; \
|
||||
data[i++] += sta->tx_filtered_count; \
|
||||
data[i++] += sta->tx_retry_failed; \
|
||||
data[i++] += sta->tx_retry_count; \
|
||||
data[i++] += sta->beacon_loss_count; \
|
||||
} while (0)
|
||||
|
||||
/* For Managed stations, find the single station based on BSSID
|
||||
* and use that. For interface types, iterate through all available
|
||||
* stations and add stats for any station that is assigned to this
|
||||
* network device.
|
||||
*/
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
|
||||
|
||||
if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
|
||||
goto do_survey;
|
||||
|
||||
i = 0;
|
||||
ADD_STA_STATS(sta);
|
||||
|
||||
data[i++] = sta->sta_state;
|
||||
|
||||
sinfo.filled = 0;
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
|
||||
if (sinfo.filled | STATION_INFO_TX_BITRATE)
|
||||
data[i] = 100000 *
|
||||
cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||
i++;
|
||||
if (sinfo.filled | STATION_INFO_RX_BITRATE)
|
||||
data[i] = 100000 *
|
||||
cfg80211_calculate_bitrate(&sinfo.rxrate);
|
||||
i++;
|
||||
|
||||
if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
|
||||
data[i] = (u8)sinfo.signal_avg;
|
||||
i++;
|
||||
} else {
|
||||
list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
||||
/* Make sure this station belongs to the proper dev */
|
||||
if (sta->sdata->dev != dev)
|
||||
continue;
|
||||
|
||||
i = 0;
|
||||
ADD_STA_STATS(sta);
|
||||
}
|
||||
}
|
||||
|
||||
do_survey:
|
||||
i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
|
||||
/* Get survey stats for current channel */
|
||||
q = 0;
|
||||
while (true) {
|
||||
survey.filled = 0;
|
||||
if (drv_get_survey(local, q, &survey) != 0) {
|
||||
survey.filled = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (survey.channel &&
|
||||
(local->oper_channel->center_freq ==
|
||||
survey.channel->center_freq))
|
||||
break;
|
||||
q++;
|
||||
}
|
||||
|
||||
if (survey.filled)
|
||||
data[i++] = survey.channel->center_freq;
|
||||
else
|
||||
data[i++] = 0;
|
||||
if (survey.filled & SURVEY_INFO_NOISE_DBM)
|
||||
data[i++] = (u8)survey.noise;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
|
||||
data[i++] = survey.channel_time;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
|
||||
data[i++] = survey.channel_time_busy;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
|
||||
data[i++] = survey.channel_time_ext_busy;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
|
||||
data[i++] = survey.channel_time_rx;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
|
||||
data[i++] = survey.channel_time_tx;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (WARN_ON(i != STA_STATS_LEN))
|
||||
return;
|
||||
|
||||
drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
|
||||
}
|
||||
|
||||
static void ieee80211_get_et_strings(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u32 sset, u8 *data)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
int sz_sta_stats = 0;
|
||||
|
||||
if (sset == ETH_SS_STATS) {
|
||||
sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
|
||||
memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
|
||||
}
|
||||
drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
|
||||
}
|
||||
|
||||
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
|
@ -1364,6 +1538,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
|
|||
return -ENOTSUPP;
|
||||
conf->rssi_threshold = nconf->rssi_threshold;
|
||||
}
|
||||
if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) {
|
||||
conf->ht_opmode = nconf->ht_opmode;
|
||||
sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2794,4 +2973,7 @@ struct cfg80211_ops mac80211_config_ops = {
|
|||
#ifdef CONFIG_PM
|
||||
.set_wakeup = ieee80211_set_wakeup,
|
||||
#endif
|
||||
.get_et_sset_count = ieee80211_get_et_sset_count,
|
||||
.get_et_stats = ieee80211_get_et_stats,
|
||||
.get_et_strings = ieee80211_get_et_strings,
|
||||
};
|
||||
|
|
|
@ -35,6 +35,43 @@ static inline void drv_tx_frags(struct ieee80211_local *local,
|
|||
local->ops->tx_frags(&local->hw, vif, sta, skbs);
|
||||
}
|
||||
|
||||
static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
|
||||
u32 sset, u8 *data)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
if (local->ops->get_et_strings) {
|
||||
trace_drv_get_et_strings(local, sset);
|
||||
local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
|
||||
struct ethtool_stats *stats,
|
||||
u64 *data)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
if (local->ops->get_et_stats) {
|
||||
trace_drv_get_et_stats(local);
|
||||
local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
|
||||
int sset)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int rv = 0;
|
||||
if (local->ops->get_et_sset_count) {
|
||||
trace_drv_get_et_sset_count(local, sset);
|
||||
rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
|
||||
sset);
|
||||
trace_drv_return_int(local, rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline int drv_start(struct ieee80211_local *local)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -161,6 +161,21 @@ DEFINE_EVENT(local_only_evt, drv_start,
|
|||
TP_ARGS(local)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_u32_evt, drv_get_et_strings,
|
||||
TP_PROTO(struct ieee80211_local *local, u32 sset),
|
||||
TP_ARGS(local, sset)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_u32_evt, drv_get_et_sset_count,
|
||||
TP_PROTO(struct ieee80211_local *local, u32 sset),
|
||||
TP_ARGS(local, sset)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_only_evt, drv_get_et_stats,
|
||||
TP_PROTO(struct ieee80211_local *local),
|
||||
TP_ARGS(local)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_only_evt, drv_suspend,
|
||||
TP_PROTO(struct ieee80211_local *local),
|
||||
TP_ARGS(local)
|
||||
|
|
|
@ -164,7 +164,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
|
||||
sband->ht_cap.cap);
|
||||
pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
|
||||
chan, channel_type);
|
||||
chan, channel_type, 0);
|
||||
}
|
||||
|
||||
if (local->hw.queues >= IEEE80211_NUM_ACS) {
|
||||
|
|
|
@ -1497,7 +1497,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
|||
u16 cap);
|
||||
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_channel_type channel_type);
|
||||
enum nl80211_channel_type channel_type,
|
||||
u16 prot_mode);
|
||||
|
||||
/* internal work items */
|
||||
void ieee80211_work_init(struct ieee80211_local *local);
|
||||
|
|
|
@ -76,6 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
u32 basic_rates = 0;
|
||||
enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT;
|
||||
|
||||
/*
|
||||
* As support for each feature is added, check for matching
|
||||
|
@ -102,10 +103,15 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
|
|||
if (sdata->vif.bss_conf.basic_rates != basic_rates)
|
||||
goto mismatch;
|
||||
|
||||
/* disallow peering with mismatched channel types for now */
|
||||
if (ie->ht_operation)
|
||||
sta_channel_type =
|
||||
ieee80211_ht_oper_to_channel_type(ie->ht_operation);
|
||||
|
||||
/* Disallow HT40+/- mismatch */
|
||||
if (ie->ht_operation &&
|
||||
(local->_oper_channel_type !=
|
||||
ieee80211_ht_oper_to_channel_type(ie->ht_operation)))
|
||||
local->_oper_channel_type > NL80211_CHAN_HT20 &&
|
||||
sta_channel_type > NL80211_CHAN_HT20 &&
|
||||
local->_oper_channel_type != sta_channel_type)
|
||||
goto mismatch;
|
||||
|
||||
return true;
|
||||
|
@ -396,7 +402,8 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
|
|||
return -ENOMEM;
|
||||
|
||||
pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
|
||||
ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type);
|
||||
ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type,
|
||||
sdata->vif.bss_conf.ht_operation_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -588,12 +595,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
|
||||
ieee80211_mesh_root_setup(ifmsh);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
sdata->vif.bss_conf.ht_operation_mode =
|
||||
ifmsh->mshcfg.ht_opmode;
|
||||
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
|
||||
sdata->vif.bss_conf.basic_rates =
|
||||
ieee80211_mandatory_rates(sdata->local,
|
||||
sdata->local->hw.conf.channel->band);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_HT |
|
||||
BSS_CHANGED_BASIC_RATES |
|
||||
BSS_CHANGED_BEACON_INT);
|
||||
}
|
||||
|
|
|
@ -102,12 +102,70 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
set_sta_flag(sta, WLAN_STA_WME);
|
||||
|
||||
if (sta_info_insert(sta))
|
||||
return NULL;
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
||||
/** mesh_set_ht_prot_mode - set correct HT protection mode
|
||||
*
|
||||
* Section 9.23.3.5 of IEEE 80211s standard describes the protection rules for
|
||||
* HT mesh STA in a MBSS. Three HT protection modes are supported for now,
|
||||
* non-HT mixed mode, 20MHz-protection and no-protection mode. non-HT mixed
|
||||
* mode is selected if any non-HT peers are present in our MBSS.
|
||||
* 20MHz-protection mode is selected if all peers in our 20/40MHz MBSS support
|
||||
* HT and atleast one HT20 peer is present. Otherwise no-protection mode is
|
||||
* selected.
|
||||
*/
|
||||
static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
u32 changed = 0;
|
||||
u16 ht_opmode;
|
||||
bool non_ht_sta = false, ht20_sta = false;
|
||||
|
||||
if (local->_oper_channel_type == NL80211_CHAN_NO_HT)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
||||
if (sdata == sta->sdata &&
|
||||
sta->plink_state == NL80211_PLINK_ESTAB) {
|
||||
switch (sta->ch_type) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
|
||||
sdata->vif.addr, sta->sta.addr);
|
||||
non_ht_sta = true;
|
||||
goto out;
|
||||
case NL80211_CHAN_HT20:
|
||||
mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
|
||||
sdata->vif.addr, sta->sta.addr);
|
||||
ht20_sta = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (non_ht_sta)
|
||||
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
|
||||
else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20)
|
||||
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
|
||||
else
|
||||
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
|
||||
|
||||
if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
|
||||
sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
|
||||
sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
|
||||
changed = BSS_CHANGED_HT;
|
||||
mpl_dbg("mesh_plink %pM: protection mode changed to %d",
|
||||
sdata->vif.addr, ht_opmode);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* __mesh_plink_deactivate - deactivate mesh peer link
|
||||
*
|
||||
|
@ -281,6 +339,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_supported_band *sband;
|
||||
u32 rates, basic_rates = 0;
|
||||
struct sta_info *sta;
|
||||
bool insert = false;
|
||||
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
|
||||
|
@ -290,6 +349,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
|
|||
sta = mesh_plink_alloc(sdata, addr);
|
||||
if (!sta)
|
||||
return NULL;
|
||||
insert = true;
|
||||
}
|
||||
|
||||
spin_lock_bh(&sta->lock);
|
||||
|
@ -303,9 +363,21 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
|
|||
else
|
||||
memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
|
||||
|
||||
if (elems->ht_operation) {
|
||||
if (!(elems->ht_operation->ht_param &
|
||||
IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
|
||||
sta->sta.ht_cap.cap &=
|
||||
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
sta->ch_type =
|
||||
ieee80211_ht_oper_to_channel_type(elems->ht_operation);
|
||||
}
|
||||
|
||||
rate_control_rate_init(sta);
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
if (insert && sta_info_insert(sta))
|
||||
return NULL;
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
||||
|
@ -487,9 +559,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
|||
enum plink_event event;
|
||||
enum ieee80211_self_protected_actioncode ftype;
|
||||
size_t baselen;
|
||||
bool deactivated, matches_local = true;
|
||||
bool matches_local = true;
|
||||
u8 ie_len;
|
||||
u8 *baseaddr;
|
||||
u32 changed = 0;
|
||||
__le16 plid, llid, reason;
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
|
||||
static const char *mplstates[] = {
|
||||
|
@ -775,7 +848,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
|||
sta->plink_state = NL80211_PLINK_ESTAB;
|
||||
spin_unlock_bh(&sta->lock);
|
||||
mesh_plink_inc_estab_count(sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
|
||||
sta->sta.addr);
|
||||
break;
|
||||
|
@ -810,7 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
|||
sta->plink_state = NL80211_PLINK_ESTAB;
|
||||
spin_unlock_bh(&sta->lock);
|
||||
mesh_plink_inc_estab_count(sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
|
||||
sta->sta.addr);
|
||||
mesh_plink_frame_tx(sdata,
|
||||
|
@ -828,13 +903,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
|||
case CLS_ACPT:
|
||||
reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
|
||||
sta->reason = reason;
|
||||
deactivated = __mesh_plink_deactivate(sta);
|
||||
__mesh_plink_deactivate(sta);
|
||||
sta->plink_state = NL80211_PLINK_HOLDING;
|
||||
llid = sta->llid;
|
||||
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
|
||||
spin_unlock_bh(&sta->lock);
|
||||
if (deactivated)
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
|
||||
sta->sta.addr, llid, plid, reason);
|
||||
break;
|
||||
|
@ -881,4 +956,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
|||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (changed)
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
|
|||
disable_40 = true;
|
||||
|
||||
if (sta && (!reconfig ||
|
||||
(disable_40 != !!(sta->sta.ht_cap.cap &
|
||||
(disable_40 != !(sta->sta.ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) {
|
||||
|
||||
if (disable_40)
|
||||
|
|
|
@ -362,6 +362,7 @@ struct sta_info {
|
|||
struct timer_list plink_timer;
|
||||
s64 t_offset;
|
||||
s64 t_offset_setpoint;
|
||||
enum nl80211_channel_type ch_type;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
|
|
|
@ -1663,7 +1663,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
|||
|
||||
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_channel_type channel_type)
|
||||
enum nl80211_channel_type channel_type,
|
||||
u16 prot_mode)
|
||||
{
|
||||
struct ieee80211_ht_operation *ht_oper;
|
||||
/* Build HT Information */
|
||||
|
@ -1689,11 +1690,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
|||
channel_type != NL80211_CHAN_HT20)
|
||||
ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
|
||||
|
||||
/*
|
||||
* Note: According to 802.11n-2009 9.13.3.1, HT Protection field and
|
||||
* RIFS Mode are reserved in IBSS mode, therefore keep them at 0
|
||||
*/
|
||||
ht_oper->operation_mode = 0x0000;
|
||||
ht_oper->operation_mode = cpu_to_le16(prot_mode);
|
||||
ht_oper->stbc_param = 0x0000;
|
||||
|
||||
/* It seems that Basic MCS set and Supported MCS set
|
||||
|
|
|
@ -68,6 +68,32 @@ static int cfg80211_set_ringparam(struct net_device *dev,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int cfg80211_get_sset_count(struct net_device *dev, int sset)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
if (rdev->ops->get_et_sset_count)
|
||||
return rdev->ops->get_et_sset_count(wdev->wiphy, dev, sset);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void cfg80211_get_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
if (rdev->ops->get_et_stats)
|
||||
rdev->ops->get_et_stats(wdev->wiphy, dev, stats, data);
|
||||
}
|
||||
|
||||
static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
if (rdev->ops->get_et_strings)
|
||||
rdev->ops->get_et_strings(wdev->wiphy, dev, sset, data);
|
||||
}
|
||||
|
||||
const struct ethtool_ops cfg80211_ethtool_ops = {
|
||||
.get_drvinfo = cfg80211_get_drvinfo,
|
||||
.get_regs_len = cfg80211_get_regs_len,
|
||||
|
@ -75,4 +101,7 @@ const struct ethtool_ops cfg80211_ethtool_ops = {
|
|||
.get_link = ethtool_op_get_link,
|
||||
.get_ringparam = cfg80211_get_ringparam,
|
||||
.set_ringparam = cfg80211_set_ringparam,
|
||||
.get_strings = cfg80211_get_strings,
|
||||
.get_ethtool_stats = cfg80211_get_stats,
|
||||
.get_sset_count = cfg80211_get_sset_count,
|
||||
};
|
||||
|
|
|
@ -61,6 +61,7 @@ const struct mesh_config default_mesh_config = {
|
|||
.dot11MeshGateAnnouncementProtocol = false,
|
||||
.dot11MeshForwarding = true,
|
||||
.rssi_threshold = MESH_RSSI_THRESHOLD,
|
||||
.ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
|
||||
};
|
||||
|
||||
const struct mesh_setup default_mesh_setup = {
|
||||
|
|
|
@ -3390,7 +3390,9 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
|
|||
nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
|
||||
cur_params.dot11MeshForwarding) ||
|
||||
nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
|
||||
cur_params.rssi_threshold))
|
||||
cur_params.rssi_threshold) ||
|
||||
nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
|
||||
cur_params.ht_opmode))
|
||||
goto nla_put_failure;
|
||||
nla_nest_end(msg, pinfoattr);
|
||||
genlmsg_end(msg, hdr);
|
||||
|
@ -3426,6 +3428,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
|
|||
[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
|
||||
[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
|
||||
[NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
|
||||
[NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16},
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
|
@ -3523,6 +3526,8 @@ do {\
|
|||
mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
|
||||
mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode,
|
||||
mask, NL80211_MESHCONF_HT_OPMODE, nla_get_u16);
|
||||
if (mask_out)
|
||||
*mask_out = mask;
|
||||
|
||||
|
|
|
@ -378,7 +378,11 @@ static int cmp_bss_core(struct cfg80211_bss *a,
|
|||
b->len_information_elements);
|
||||
}
|
||||
|
||||
return compare_ether_addr(a->bssid, b->bssid);
|
||||
/*
|
||||
* we can't use compare_ether_addr here since we need a < > operator.
|
||||
* The binary return value of compare_ether_addr isn't enough
|
||||
*/
|
||||
return memcmp(a->bssid, b->bssid, sizeof(a->bssid));
|
||||
}
|
||||
|
||||
static int cmp_bss(struct cfg80211_bss *a,
|
||||
|
|
Loading…
Reference in New Issue