forked from Minki/linux
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
This commit is contained in:
commit
00b14825ee
@ -48,12 +48,6 @@ min_adv_mss - INTEGER
|
||||
The advertised MSS depends on the first hop route MTU, but will
|
||||
never be lower than this setting.
|
||||
|
||||
rt_cache_rebuild_count - INTEGER
|
||||
The per net-namespace route cache emergency rebuild threshold.
|
||||
Any net-namespace having its route cache rebuilt due to
|
||||
a hash bucket chain being too long more than this many times
|
||||
will have its route caching disabled
|
||||
|
||||
IP Fragmentation:
|
||||
|
||||
ipfrag_high_thresh - INTEGER
|
||||
|
@ -48,12 +48,12 @@ config BCMA_DRIVER_MIPS
|
||||
|
||||
config BCMA_SFLASH
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS && BROKEN
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
default y
|
||||
|
||||
config BCMA_NFLASH
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS && BROKEN
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
default y
|
||||
|
||||
config BCMA_DRIVER_GMAC_CMN
|
||||
|
@ -54,6 +54,7 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
/* driver_chipcommon_sflash.c */
|
||||
int bcma_sflash_init(struct bcma_drv_cc *cc);
|
||||
extern struct platform_device bcma_sflash_dev;
|
||||
#else
|
||||
static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
@ -65,6 +66,7 @@ static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||
#ifdef CONFIG_BCMA_NFLASH
|
||||
/* driver_chipcommon_nflash.c */
|
||||
int bcma_nflash_init(struct bcma_drv_cc *cc);
|
||||
extern struct platform_device bcma_nflash_dev;
|
||||
#else
|
||||
static inline int bcma_nflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
|
@ -5,15 +5,37 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/bcma/bcma_driver_chipcommon.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
struct platform_device bcma_nflash_dev = {
|
||||
.name = "bcma_nflash",
|
||||
.num_resources = 0,
|
||||
};
|
||||
|
||||
/* Initialize NAND flash access */
|
||||
int bcma_nflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
bcma_err(cc->core->bus, "NAND flash support is broken\n");
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
|
||||
cc->core->id.rev != 0x38) {
|
||||
bcma_err(bus, "NAND flash on unsupported board!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) {
|
||||
bcma_err(bus, "NAND flash not present according to ChipCommon\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cc->nflash.present = true;
|
||||
|
||||
/* Prepare platform device, but don't register it yet. It's too early,
|
||||
* malloc (required by device_private_init) is not available yet. */
|
||||
bcma_nflash_dev.dev.platform_data = &cc->nflash;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
|
||||
}
|
||||
|
||||
void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
@ -257,7 +257,7 @@ static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
||||
}
|
||||
|
||||
/* query bus clock frequency for PMU-enabled chipcommon */
|
||||
u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
||||
static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
|
@ -5,15 +5,132 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/bcma/bcma_driver_chipcommon.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SFLASH,
|
||||
.end = 0,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_READONLY,
|
||||
};
|
||||
|
||||
struct platform_device bcma_sflash_dev = {
|
||||
.name = "bcma_sflash",
|
||||
.resource = &bcma_sflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
struct bcma_sflash_tbl_e {
|
||||
char *name;
|
||||
u32 id;
|
||||
u32 blocksize;
|
||||
u16 numblocks;
|
||||
};
|
||||
|
||||
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
|
||||
{ "", 0x14, 0x10000, 32, },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
|
||||
{
|
||||
int i;
|
||||
bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
|
||||
BCMA_CC_FLASHCTL_START | opcode);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) &
|
||||
BCMA_CC_FLASHCTL_BUSY))
|
||||
return;
|
||||
cpu_relax();
|
||||
}
|
||||
bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n");
|
||||
}
|
||||
|
||||
/* Initialize serial flash access */
|
||||
int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
bcma_err(cc->core->bus, "Serial flash support is broken\n");
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
struct bcma_sflash *sflash = &cc->sflash;
|
||||
struct bcma_sflash_tbl_e *e;
|
||||
u32 id, id2;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
|
||||
|
||||
bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
|
||||
bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
|
||||
id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
|
||||
|
||||
bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
|
||||
bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
|
||||
id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
|
||||
|
||||
switch (id) {
|
||||
case 0xbf:
|
||||
for (e = bcma_sflash_sst_tbl; e->name; e++) {
|
||||
if (e->id == id2)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (e = bcma_sflash_st_tbl; e->name; e++) {
|
||||
if (e->id == id)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!e->name) {
|
||||
bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
break;
|
||||
case BCMA_CC_FLASHT_ATSER:
|
||||
bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
|
||||
id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
|
||||
|
||||
for (e = bcma_sflash_at_tbl; e->name; e++) {
|
||||
if (e->id == id)
|
||||
break;
|
||||
}
|
||||
if (!e->name) {
|
||||
bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Unsupported flash type\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
sflash->window = BCMA_SFLASH;
|
||||
sflash->blocksize = e->blocksize;
|
||||
sflash->numblocks = e->numblocks;
|
||||
sflash->size = sflash->blocksize * sflash->numblocks;
|
||||
sflash->present = true;
|
||||
|
||||
bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
|
||||
e->name, sflash->size / 1024, sflash->blocksize,
|
||||
sflash->numblocks);
|
||||
|
||||
/* Prepare platform device, but don't register it yet. It's too early,
|
||||
* malloc (required by device_private_init) is not available yet. */
|
||||
bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start +
|
||||
sflash->size;
|
||||
bcma_sflash_dev.dev.platform_data = sflash;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_BLOCKIO
|
||||
void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
void __iomem *addr = core->bus->mmio + offset;
|
||||
if (core->bus->mapped_core != core)
|
||||
@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
static void bcma_host_pci_block_write(struct bcma_device *core,
|
||||
const void *buffer, size_t count,
|
||||
u16 offset, u8 reg_width)
|
||||
{
|
||||
void __iomem *addr = core->bus->mmio + offset;
|
||||
if (core->bus->mapped_core != core)
|
||||
@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
|
||||
iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
|
||||
}
|
||||
|
||||
const struct bcma_host_ops bcma_host_pci_ops = {
|
||||
static const struct bcma_host_ops bcma_host_pci_ops = {
|
||||
.read8 = bcma_host_pci_read8,
|
||||
.read16 = bcma_host_pci_read16,
|
||||
.read32 = bcma_host_pci_read32,
|
||||
|
@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
|
||||
writel(value, core->io_wrap + offset);
|
||||
}
|
||||
|
||||
const struct bcma_host_ops bcma_host_soc_ops = {
|
||||
static const struct bcma_host_ops bcma_host_soc_ops = {
|
||||
.read8 = bcma_host_soc_read8,
|
||||
.read16 = bcma_host_soc_read16,
|
||||
.read32 = bcma_host_soc_read32,
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@ -136,6 +137,22 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
||||
dev_id++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
if (bus->drv_cc.sflash.present) {
|
||||
err = platform_device_register(&bcma_sflash_dev);
|
||||
if (err)
|
||||
bcma_err(bus, "Error registering serial flash\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCMA_NFLASH
|
||||
if (bus->drv_cc.nflash.present) {
|
||||
err = platform_device_register(&bcma_nflash_dev);
|
||||
if (err)
|
||||
bcma_err(bus, "Error registering NAND flash\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
BT_ERR("Can't allocate memory for data structure");
|
||||
return -ENOMEM;
|
||||
@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
data->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!data->urb) {
|
||||
BT_ERR("Can't allocate URB");
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
||||
BT_ERR("Mini driver request failed");
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
BT_ERR("Can't allocate memory for mini driver");
|
||||
release_firmware(firmware);
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
BT_ERR("Firmware request failed");
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
release_firmware(firmware);
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->fw_data);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bcm203x_driver = {
|
||||
|
@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
}
|
||||
|
||||
/* Initialize control structure and load firmware */
|
||||
data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
BT_ERR("Can't allocate memory for control structure");
|
||||
goto done;
|
||||
@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
|
||||
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
|
||||
BT_ERR("Firmware request failed");
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
|
||||
@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
BT_ERR("Can't allocate HCI device");
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
data->hdev = hdev;
|
||||
@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
if (hci_register_dev(hdev) < 0) {
|
||||
BT_ERR("Can't register HCI device");
|
||||
hci_free_dev(hdev);
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, data);
|
||||
@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
release:
|
||||
release_firmware(firmware);
|
||||
|
||||
error:
|
||||
kfree(data);
|
||||
|
||||
done:
|
||||
return -EIO;
|
||||
}
|
||||
@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bfusb_driver = {
|
||||
|
@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||
bluecard_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||
|
||||
static void bluecard_detach(struct pcmcia_device *link)
|
||||
{
|
||||
bluecard_info_t *info = link->priv;
|
||||
|
||||
bluecard_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
init_usb_anchor(&data->rx_anchor);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_USB;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
|
||||
hci_free_dev(data->hdev);
|
||||
kfree_skb(data->rx_skb[0]);
|
||||
kfree_skb(data->rx_skb[1]);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bpa10x_driver = {
|
||||
|
@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||
bt3c_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||
|
||||
static void bt3c_detach(struct pcmcia_device *link)
|
||||
{
|
||||
bt3c_info_t *info = link->priv;
|
||||
|
||||
bt3c_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
|
||||
id->vendor, id->device, id->class, func->num);
|
||||
|
||||
card = kzalloc(sizeof(*card), GFP_KERNEL);
|
||||
if (!card) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
card->func = func;
|
||||
|
||||
@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
|
||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||
BT_ERR("Failed to register BT device!");
|
||||
ret = -ENODEV;
|
||||
goto free_card;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Disable the interrupts on the card */
|
||||
@ -1023,9 +1020,6 @@ disable_host_int:
|
||||
btmrvl_sdio_disable_host_int(card);
|
||||
unreg_dev:
|
||||
btmrvl_sdio_unregister_dev(card);
|
||||
free_card:
|
||||
kfree(card);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
|
||||
BT_DBG("unregester dev");
|
||||
btmrvl_sdio_unregister_dev(card);
|
||||
btmrvl_remove_card(card->priv);
|
||||
kfree(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
tuple = tuple->next;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
skb_queue_head_init(&data->txq);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_SDIO;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func)
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct sdio_driver btsdio_driver = {
|
||||
|
@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||
btuart_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||
|
||||
static void btuart_detach(struct pcmcia_device *link)
|
||||
{
|
||||
btuart_info_t *info = link->priv;
|
||||
|
||||
btuart_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
|
||||
kfree(data);
|
||||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cmdreq_type = USB_TYPE_CLASS;
|
||||
|
||||
@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
init_usb_anchor(&data->deferred);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_USB;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
data->isoc, data);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
|
||||
hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL);
|
||||
if (!hst)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Expose "hciX" device to user space */
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(hst);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
BT_DBG("hdev %p", hdev);
|
||||
|
||||
@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't register HCI device error %d", err);
|
||||
kfree(hst);
|
||||
hci_free_dev(hdev);
|
||||
return err;
|
||||
}
|
||||
@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev)
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(hst);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
return 0;
|
||||
|
@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link)
|
||||
dtl1_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link)
|
||||
|
||||
dtl1_close(info);
|
||||
pcmcia_disable_device(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -449,7 +449,8 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
struct hdlc_hw *hdlc;
|
||||
int count, fs, cnt = 0, idx, fillempty = 0;
|
||||
int count, fs, cnt = 0, idx;
|
||||
bool fillempty = false;
|
||||
u8 *p;
|
||||
u32 *ptr, val, addr;
|
||||
|
||||
@ -462,7 +463,7 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
return;
|
||||
count = fs;
|
||||
p = bch->fill;
|
||||
fillempty = 1;
|
||||
fillempty = true;
|
||||
} else {
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if (count <= 0)
|
||||
@ -477,7 +478,7 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
|
||||
}
|
||||
ptr = (u32 *)p;
|
||||
if (fillempty) {
|
||||
if (!fillempty) {
|
||||
pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count,
|
||||
bch->tx_idx, bch->tx_skb->len);
|
||||
bch->tx_idx += count;
|
||||
|
@ -9360,8 +9360,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
|
||||
struct bnx2x_prev_path_list *tmp_list;
|
||||
int rc;
|
||||
|
||||
tmp_list = (struct bnx2x_prev_path_list *)
|
||||
kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
|
||||
tmp_list = kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
|
||||
if (!tmp_list) {
|
||||
BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n");
|
||||
return -ENOMEM;
|
||||
|
@ -92,7 +92,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define TG3_MAJ_NUM 3
|
||||
#define TG3_MIN_NUM 123
|
||||
#define TG3_MIN_NUM 124
|
||||
#define DRV_MODULE_VERSION \
|
||||
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
|
||||
#define DRV_MODULE_RELDATE "March 21, 2012"
|
||||
@ -672,6 +672,12 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
|
||||
else
|
||||
bit = 1 << tp->pci_fn;
|
||||
break;
|
||||
case TG3_APE_LOCK_PHY0:
|
||||
case TG3_APE_LOCK_PHY1:
|
||||
case TG3_APE_LOCK_PHY2:
|
||||
case TG3_APE_LOCK_PHY3:
|
||||
bit = APE_LOCK_REQ_DRIVER;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -723,6 +729,12 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
|
||||
else
|
||||
bit = 1 << tp->pci_fn;
|
||||
break;
|
||||
case TG3_APE_LOCK_PHY0:
|
||||
case TG3_APE_LOCK_PHY1:
|
||||
case TG3_APE_LOCK_PHY2:
|
||||
case TG3_APE_LOCK_PHY3:
|
||||
bit = APE_LOCK_GRANT_DRIVER;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -1052,6 +1064,8 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
|
||||
udelay(80);
|
||||
}
|
||||
|
||||
tg3_ape_lock(tp, tp->phy_ape_lock);
|
||||
|
||||
*val = 0x0;
|
||||
|
||||
frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
|
||||
@ -1086,6 +1100,8 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
|
||||
udelay(80);
|
||||
}
|
||||
|
||||
tg3_ape_unlock(tp, tp->phy_ape_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1105,6 +1121,8 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
|
||||
udelay(80);
|
||||
}
|
||||
|
||||
tg3_ape_lock(tp, tp->phy_ape_lock);
|
||||
|
||||
frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
|
||||
MI_COM_PHY_ADDR_MASK);
|
||||
frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
|
||||
@ -1135,6 +1153,8 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
|
||||
udelay(80);
|
||||
}
|
||||
|
||||
tg3_ape_unlock(tp, tp->phy_ape_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9066,8 +9086,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
|
||||
tg3_flag(tp, 57765_PLUS)) {
|
||||
val = tr32(TG3_RDMA_RSRVCTRL_REG);
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
|
||||
if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) {
|
||||
val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
|
||||
TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
|
||||
TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
|
||||
@ -9257,6 +9276,19 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||
tw32_f(RDMAC_MODE, rdmac_mode);
|
||||
udelay(40);
|
||||
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
|
||||
for (i = 0; i < TG3_NUM_RDMA_CHANNELS; i++) {
|
||||
if (tr32(TG3_RDMA_LENGTH + (i << 2)) > TG3_MAX_MTU(tp))
|
||||
break;
|
||||
}
|
||||
if (i < TG3_NUM_RDMA_CHANNELS) {
|
||||
val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
|
||||
val |= TG3_LSO_RD_DMA_TX_LENGTH_WA;
|
||||
tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
|
||||
tg3_flag_set(tp, 5719_RDMA_BUG);
|
||||
}
|
||||
}
|
||||
|
||||
tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
|
||||
if (!tg3_flag(tp, 5705_PLUS))
|
||||
tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
|
||||
@ -9616,6 +9648,16 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
|
||||
TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST);
|
||||
TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST);
|
||||
TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST);
|
||||
if (unlikely(tg3_flag(tp, 5719_RDMA_BUG) &&
|
||||
(sp->tx_ucast_packets.low + sp->tx_mcast_packets.low +
|
||||
sp->tx_bcast_packets.low) > TG3_NUM_RDMA_CHANNELS)) {
|
||||
u32 val;
|
||||
|
||||
val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
|
||||
val &= ~TG3_LSO_RD_DMA_TX_LENGTH_WA;
|
||||
tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
|
||||
tg3_flag_clear(tp, 5719_RDMA_BUG);
|
||||
}
|
||||
|
||||
TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS);
|
||||
TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS);
|
||||
@ -12482,10 +12524,12 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
|
||||
{
|
||||
struct tg3 *tp = netdev_priv(dev);
|
||||
|
||||
if (!tp->hw_stats)
|
||||
return &tp->net_stats_prev;
|
||||
|
||||
spin_lock_bh(&tp->lock);
|
||||
if (!tp->hw_stats) {
|
||||
spin_unlock_bh(&tp->lock);
|
||||
return &tp->net_stats_prev;
|
||||
}
|
||||
|
||||
tg3_get_nstats(tp, stats);
|
||||
spin_unlock_bh(&tp->lock);
|
||||
|
||||
@ -13648,6 +13692,23 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
|
||||
tg3_flag_set(tp, PAUSE_AUTONEG);
|
||||
tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
|
||||
|
||||
if (tg3_flag(tp, ENABLE_APE)) {
|
||||
switch (tp->pci_fn) {
|
||||
case 0:
|
||||
tp->phy_ape_lock = TG3_APE_LOCK_PHY0;
|
||||
break;
|
||||
case 1:
|
||||
tp->phy_ape_lock = TG3_APE_LOCK_PHY1;
|
||||
break;
|
||||
case 2:
|
||||
tp->phy_ape_lock = TG3_APE_LOCK_PHY2;
|
||||
break;
|
||||
case 3:
|
||||
tp->phy_ape_lock = TG3_APE_LOCK_PHY3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tg3_flag(tp, USE_PHYLIB))
|
||||
return tg3_phy_init(tp);
|
||||
|
||||
|
@ -1376,7 +1376,11 @@
|
||||
#define TG3_LSO_RD_DMA_CRPTEN_CTRL 0x00004910
|
||||
#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
|
||||
#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K 0x000c0000
|
||||
/* 0x4914 --> 0x4c00 unused */
|
||||
#define TG3_LSO_RD_DMA_TX_LENGTH_WA 0x02000000
|
||||
/* 0x4914 --> 0x4be0 unused */
|
||||
|
||||
#define TG3_NUM_RDMA_CHANNELS 4
|
||||
#define TG3_RDMA_LENGTH 0x00004be0
|
||||
|
||||
/* Write DMA control registers */
|
||||
#define WDMAC_MODE 0x00004c00
|
||||
@ -2959,6 +2963,7 @@ enum TG3_FLAGS {
|
||||
TG3_FLAG_L1PLLPD_EN,
|
||||
TG3_FLAG_APE_HAS_NCSI,
|
||||
TG3_FLAG_4K_FIFO_LIMIT,
|
||||
TG3_FLAG_5719_RDMA_BUG,
|
||||
TG3_FLAG_RESET_TASK_PENDING,
|
||||
TG3_FLAG_5705_PLUS,
|
||||
TG3_FLAG_IS_5788,
|
||||
@ -3107,6 +3112,7 @@ struct tg3 {
|
||||
int old_link;
|
||||
|
||||
u8 phy_addr;
|
||||
u8 phy_ape_lock;
|
||||
|
||||
/* PHY info */
|
||||
u32 phy_id;
|
||||
|
@ -4682,6 +4682,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
|
||||
NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM;
|
||||
ndev->features = ndev->hw_features |
|
||||
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
|
||||
ndev->vlan_features = ndev->hw_features;
|
||||
|
||||
if (test_bit(QL_DMA64, &qdev->flags))
|
||||
ndev->features |= NETIF_F_HIGHDMA;
|
||||
|
@ -736,9 +736,7 @@ MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
|
||||
int __init init_module(void)
|
||||
{
|
||||
dev_seeq = seeq8005_probe(-1);
|
||||
if (IS_ERR(dev_seeq))
|
||||
return PTR_ERR(dev_seeq);
|
||||
return 0;
|
||||
return PTR_RET(dev_seeq);
|
||||
}
|
||||
|
||||
void __exit cleanup_module(void)
|
||||
|
@ -1379,10 +1379,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
|
||||
int vnet_hdr_sz;
|
||||
int ret;
|
||||
|
||||
if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
|
||||
if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
|
||||
if (copy_from_user(&ifr, argp, ifreq_len))
|
||||
return -EFAULT;
|
||||
|
||||
} else {
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
}
|
||||
if (cmd == TUNGETFEATURES) {
|
||||
/* Currently this just means: "what IFF flags are valid?".
|
||||
* This is needed because we never checked for invalid flags on
|
||||
|
@ -1314,7 +1314,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev,
|
||||
int retv;
|
||||
int length = 0; /* shut up GCC */
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_NOIO);
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1331,7 +1331,6 @@ struct ath5k_hw {
|
||||
unsigned int nexttbtt; /* next beacon time in TU */
|
||||
struct ath5k_txq *cabq; /* content after beacon */
|
||||
|
||||
int power_level; /* Requested tx power in dBm */
|
||||
bool assoc; /* associate state */
|
||||
bool enable_beacon; /* true if beacons are on */
|
||||
|
||||
@ -1425,6 +1424,7 @@ struct ath5k_hw {
|
||||
/* Value in dB units */
|
||||
s16 txp_cck_ofdm_pwr_delta;
|
||||
bool txp_setup;
|
||||
int txp_requested; /* Requested tx power in dBm */
|
||||
} ah_txpower;
|
||||
|
||||
struct ath5k_nfcal_hist ah_nfcal_hist;
|
||||
|
@ -723,7 +723,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
get_hw_packet_type(skb),
|
||||
(ah->power_level * 2),
|
||||
(ah->ah_txpower.txp_requested * 2),
|
||||
hw_rate,
|
||||
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
|
||||
cts_rate, duration);
|
||||
@ -1778,7 +1778,8 @@ ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
|
||||
ds->ds_data = bf->skbaddr;
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
AR5K_PKT_TYPE_BEACON, (ah->power_level * 2),
|
||||
AR5K_PKT_TYPE_BEACON,
|
||||
(ah->ah_txpower.txp_requested * 2),
|
||||
ieee80211_get_tx_rate(ah->hw, info)->hw_value,
|
||||
1, AR5K_TXKEYIX_INVALID,
|
||||
antenna, flags, 0, 0);
|
||||
|
@ -208,8 +208,8 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
|
||||
(ah->power_level != conf->power_level)) {
|
||||
ah->power_level = conf->power_level;
|
||||
(ah->ah_txpower.txp_requested != conf->power_level)) {
|
||||
ah->ah_txpower.txp_requested = conf->power_level;
|
||||
|
||||
/* Half dB steps */
|
||||
ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
|
||||
|
@ -3516,6 +3516,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
|
||||
{
|
||||
unsigned int i;
|
||||
u16 *rates;
|
||||
s16 rate_idx_scaled = 0;
|
||||
|
||||
/* max_pwr is power level we got from driver/user in 0.5dB
|
||||
* units, switch to 0.25dB units so we can compare */
|
||||
@ -3562,20 +3563,32 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
|
||||
for (i = 8; i <= 15; i++)
|
||||
rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
|
||||
|
||||
/* Save min/max and current tx power for this channel
|
||||
* in 0.25dB units.
|
||||
*
|
||||
* Note: We use rates[0] for current tx power because
|
||||
* it covers most of the rates, in most cases. It's our
|
||||
* tx power limit and what the user expects to see. */
|
||||
ah->ah_txpower.txp_min_pwr = 2 * rates[7];
|
||||
ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
|
||||
|
||||
/* Set max txpower for correct OFDM operation on all rates
|
||||
* -that is the txpower for 54Mbit-, it's used for the PAPD
|
||||
* gain probe and it's in 0.5dB units */
|
||||
ah->ah_txpower.txp_ofdm = rates[7];
|
||||
|
||||
/* Now that we have all rates setup use table offset to
|
||||
* match the power range set by user with the power indices
|
||||
* on PCDAC/PDADC table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
rates[i] += ah->ah_txpower.txp_offset;
|
||||
rate_idx_scaled = rates[i] + ah->ah_txpower.txp_offset;
|
||||
/* Don't get out of bounds */
|
||||
if (rates[i] > 63)
|
||||
rates[i] = 63;
|
||||
if (rate_idx_scaled > 63)
|
||||
rate_idx_scaled = 63;
|
||||
if (rate_idx_scaled < 0)
|
||||
rate_idx_scaled = 0;
|
||||
rates[i] = rate_idx_scaled;
|
||||
}
|
||||
|
||||
/* Min/max in 0.25dB units */
|
||||
ah->ah_txpower.txp_min_pwr = 2 * rates[7];
|
||||
ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
|
||||
ah->ah_txpower.txp_ofdm = rates[7];
|
||||
}
|
||||
|
||||
|
||||
@ -3639,10 +3652,17 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
if (!ah->ah_txpower.txp_setup ||
|
||||
(channel->hw_value != curr_channel->hw_value) ||
|
||||
(channel->center_freq != curr_channel->center_freq)) {
|
||||
/* Reset TX power values */
|
||||
/* Reset TX power values but preserve requested
|
||||
* tx power from above */
|
||||
int requested_txpower = ah->ah_txpower.txp_requested;
|
||||
|
||||
memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
|
||||
|
||||
/* Restore TPC setting and requested tx power */
|
||||
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
||||
|
||||
ah->ah_txpower.txp_requested = requested_txpower;
|
||||
|
||||
/* Calculate the powertable */
|
||||
ret = ath5k_setup_channel_powertable(ah, channel,
|
||||
ee_mode, type);
|
||||
@ -3789,8 +3809,9 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
* RF buffer settings on 5211/5212+ so that we
|
||||
* properly set curve indices.
|
||||
*/
|
||||
ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ?
|
||||
ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER);
|
||||
ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_requested ?
|
||||
ah->ah_txpower.txp_requested * 2 :
|
||||
AR5K_TUNE_MAX_TXPOWER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -4901,90 +4901,79 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
|
||||
i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
|
||||
chan->channel);
|
||||
|
||||
/*
|
||||
* compare test group from regulatory
|
||||
* channel list with test mode from pCtlMode
|
||||
* list
|
||||
*/
|
||||
if ((((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
ctlIndex[i]) ||
|
||||
(((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
((ctlIndex[i] & CTL_MODE_M) |
|
||||
SD_NO_CTL))) {
|
||||
twiceMinEdgePower =
|
||||
ar9003_hw_get_max_edge_power(pEepData,
|
||||
freq, i,
|
||||
is2ghz);
|
||||
/*
|
||||
* compare test group from regulatory
|
||||
* channel list with test mode from pCtlMode
|
||||
* list
|
||||
*/
|
||||
if ((((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
ctlIndex[i]) ||
|
||||
(((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
((ctlIndex[i] & CTL_MODE_M) |
|
||||
SD_NO_CTL))) {
|
||||
twiceMinEdgePower =
|
||||
ar9003_hw_get_max_edge_power(pEepData,
|
||||
freq, i,
|
||||
is2ghz);
|
||||
|
||||
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
|
||||
/*
|
||||
* Find the minimum of all CTL
|
||||
* edge powers that apply to
|
||||
* this channel
|
||||
*/
|
||||
twiceMaxEdgePower =
|
||||
min(twiceMaxEdgePower,
|
||||
twiceMinEdgePower);
|
||||
else {
|
||||
/* specific */
|
||||
twiceMaxEdgePower =
|
||||
twiceMinEdgePower;
|
||||
break;
|
||||
}
|
||||
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
|
||||
/*
|
||||
* Find the minimum of all CTL
|
||||
* edge powers that apply to
|
||||
* this channel
|
||||
*/
|
||||
twiceMaxEdgePower =
|
||||
min(twiceMaxEdgePower,
|
||||
twiceMinEdgePower);
|
||||
else {
|
||||
/* specific */
|
||||
twiceMaxEdgePower = twiceMinEdgePower;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
|
||||
minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
|
||||
|
||||
ath_dbg(common, REGULATORY,
|
||||
"SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
|
||||
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
|
||||
scaledPower, minCtlPower);
|
||||
ath_dbg(common, REGULATORY,
|
||||
"SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
|
||||
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
|
||||
scaledPower, minCtlPower);
|
||||
|
||||
/* Apply ctl mode to correct target power set */
|
||||
switch (pCtlMode[ctlMode]) {
|
||||
case CTL_11B:
|
||||
for (i = ALL_TARGET_LEGACY_1L_5L;
|
||||
i <= ALL_TARGET_LEGACY_11S; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_11A:
|
||||
case CTL_11G:
|
||||
for (i = ALL_TARGET_LEGACY_6_24;
|
||||
i <= ALL_TARGET_LEGACY_54; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT20:
|
||||
case CTL_2GHT20:
|
||||
for (i = ALL_TARGET_HT20_0_8_16;
|
||||
i <= ALL_TARGET_HT20_21; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
pPwrArray[ALL_TARGET_HT20_22] =
|
||||
(u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
|
||||
minCtlPower);
|
||||
pPwrArray[ALL_TARGET_HT20_23] =
|
||||
(u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT40:
|
||||
case CTL_2GHT40:
|
||||
for (i = ALL_TARGET_HT40_0_8_16;
|
||||
i <= ALL_TARGET_HT40_23; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Apply ctl mode to correct target power set */
|
||||
switch (pCtlMode[ctlMode]) {
|
||||
case CTL_11B:
|
||||
for (i = ALL_TARGET_LEGACY_1L_5L;
|
||||
i <= ALL_TARGET_LEGACY_11S; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_11A:
|
||||
case CTL_11G:
|
||||
for (i = ALL_TARGET_LEGACY_6_24;
|
||||
i <= ALL_TARGET_LEGACY_54; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT20:
|
||||
case CTL_2GHT20:
|
||||
for (i = ALL_TARGET_HT20_0_8_16;
|
||||
i <= ALL_TARGET_HT20_23; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT40:
|
||||
case CTL_2GHT40:
|
||||
for (i = ALL_TARGET_HT40_0_8_16;
|
||||
i <= ALL_TARGET_HT40_23; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} /* end ctl mode checking */
|
||||
}
|
||||
|
||||
|
@ -1333,6 +1333,34 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_rate trate;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
||||
memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
|
||||
ath9k_htc_setup_rate(priv, sta, &trate);
|
||||
if (!ath9k_htc_send_rate_cmd(priv, &trate))
|
||||
ath_dbg(common, CONFIG,
|
||||
"Supported rates for sta: %pM updated, rate caps: 0x%X\n",
|
||||
sta->addr, be32_to_cpu(trate.capflags));
|
||||
else
|
||||
ath_dbg(common, CONFIG,
|
||||
"Unable to update supported rates for sta: %pM\n",
|
||||
sta->addr);
|
||||
}
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
@ -1760,6 +1788,7 @@ struct ieee80211_ops ath9k_htc_ops = {
|
||||
.sta_add = ath9k_htc_sta_add,
|
||||
.sta_remove = ath9k_htc_sta_remove,
|
||||
.conf_tx = ath9k_htc_conf_tx,
|
||||
.sta_rc_update = ath9k_htc_sta_rc_update,
|
||||
.bss_info_changed = ath9k_htc_bss_info_changed,
|
||||
.set_key = ath9k_htc_set_key,
|
||||
.get_tsf = ath9k_htc_get_tsf,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -160,10 +160,6 @@ struct ath_rate_table {
|
||||
u32 user_ratekbps;
|
||||
u8 ratecode;
|
||||
u8 dot11rate;
|
||||
u8 ctrl_rate;
|
||||
u8 cw40index;
|
||||
u8 sgi_index;
|
||||
u8 ht_index;
|
||||
} info[RATE_TABLE_SIZE];
|
||||
u32 probe_interval;
|
||||
u8 initial_ratemax;
|
||||
|
@ -425,6 +425,7 @@ struct ar9170 {
|
||||
bool rx_has_plcp;
|
||||
struct sk_buff *rx_failover;
|
||||
int rx_failover_missing;
|
||||
u32 ampdu_ref;
|
||||
|
||||
/* FIFO for collecting outstanding BlockAckRequest */
|
||||
struct list_head bar_list[__AR9170_NUM_TXQ];
|
||||
|
@ -341,6 +341,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
||||
if (SUPP(CARL9170FW_WLANTX_CAB)) {
|
||||
if_comb_types |=
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
}
|
||||
}
|
||||
|
@ -318,10 +318,10 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
||||
bssid = common->curbssid;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cam_mode |= AR9170_MAC_CAM_IBSS;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
cam_mode |= AR9170_MAC_CAM_AP;
|
||||
|
||||
|
@ -616,10 +616,12 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
goto unlock;
|
||||
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
if ((vif->type == NL80211_IFTYPE_STATION) ||
|
||||
(vif->type == NL80211_IFTYPE_WDS) ||
|
||||
(vif->type == NL80211_IFTYPE_AP))
|
||||
(vif->type == NL80211_IFTYPE_AP) ||
|
||||
(vif->type == NL80211_IFTYPE_MESH_POINT))
|
||||
break;
|
||||
|
||||
err = -EBUSY;
|
||||
|
@ -206,6 +206,7 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
carl9170_update_beacon(ar, true);
|
||||
break;
|
||||
|
||||
@ -623,7 +624,8 @@ static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
|
||||
#undef TID_CHECK
|
||||
}
|
||||
|
||||
static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
|
||||
static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
__le16 fc;
|
||||
|
||||
@ -636,6 +638,9 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
|
||||
return true;
|
||||
}
|
||||
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
|
||||
rx_status->ampdu_reference = ar->ampdu_ref;
|
||||
|
||||
/*
|
||||
* "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
|
||||
* certain frame types can be part of an aMPDU.
|
||||
@ -684,12 +689,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
||||
if (unlikely(len < sizeof(*mac)))
|
||||
goto drop;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
|
||||
mpdu_len = len - sizeof(*mac);
|
||||
|
||||
mac = (void *)(buf + mpdu_len);
|
||||
mac_status = mac->status;
|
||||
switch (mac_status & AR9170_RX_STATUS_MPDU) {
|
||||
case AR9170_RX_STATUS_MPDU_FIRST:
|
||||
ar->ampdu_ref++;
|
||||
/* Aggregated MPDUs start with an PLCP header */
|
||||
if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
|
||||
head = (void *) buf;
|
||||
@ -720,12 +728,13 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
||||
break;
|
||||
|
||||
case AR9170_RX_STATUS_MPDU_LAST:
|
||||
status.flag |= RX_FLAG_AMPDU_IS_LAST;
|
||||
|
||||
/*
|
||||
* The last frame of an A-MPDU has an extra tail
|
||||
* which does contain the phy status of the whole
|
||||
* aggregate.
|
||||
*/
|
||||
|
||||
if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
|
||||
mpdu_len -= sizeof(struct ar9170_rx_phystatus);
|
||||
phy = (void *)(buf + mpdu_len);
|
||||
@ -773,11 +782,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
||||
if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
|
||||
goto drop;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
|
||||
goto drop;
|
||||
|
||||
if (!carl9170_ampdu_check(ar, buf, mac_status))
|
||||
if (!carl9170_ampdu_check(ar, buf, mac_status, &status))
|
||||
goto drop;
|
||||
|
||||
if (phy)
|
||||
|
@ -4,6 +4,7 @@ b43-y += tables.o
|
||||
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2056.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2057.o
|
||||
b43-y += phy_common.o
|
||||
b43-y += phy_g.o
|
||||
b43-y += phy_a.o
|
||||
|
@ -241,16 +241,18 @@ enum {
|
||||
#define B43_SHM_SH_PHYVER 0x0050 /* PHY version */
|
||||
#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
|
||||
#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
|
||||
#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
|
||||
#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
|
||||
#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
|
||||
#define B43_SHM_SH_HOSTF1 0x005E /* Hostflags 1 for ucode options */
|
||||
#define B43_SHM_SH_HOSTF2 0x0060 /* Hostflags 2 for ucode options */
|
||||
#define B43_SHM_SH_HOSTF3 0x0062 /* Hostflags 3 for ucode options */
|
||||
#define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
|
||||
#define B43_SHM_SH_RADAR 0x0066 /* Radar register */
|
||||
#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
|
||||
#define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */
|
||||
#define B43_SHM_SH_HOSTF4 0x0078 /* Hostflags 4 for ucode options */
|
||||
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
|
||||
#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5 Ghz channel */
|
||||
#define B43_SHM_SH_CHAN_40MHZ 0x0200 /* Bit set, if 40 Mhz channel width */
|
||||
#define B43_SHM_SH_HOSTF5 0x00D4 /* Hostflags 5 for ucode options */
|
||||
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
|
||||
/* TSSI information */
|
||||
#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
|
||||
@ -415,6 +417,8 @@ enum {
|
||||
#define B43_PHYTYPE_HT 0x07
|
||||
#define B43_PHYTYPE_LCN 0x08
|
||||
#define B43_PHYTYPE_LCNXN 0x09
|
||||
#define B43_PHYTYPE_LCN40 0x0a
|
||||
#define B43_PHYTYPE_AC 0x0b
|
||||
|
||||
/* PHYRegisters */
|
||||
#define B43_PHY_ILT_A_CTRL 0x0072
|
||||
|
@ -533,11 +533,11 @@ u64 b43_hf_read(struct b43_wldev *dev)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
|
||||
ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3);
|
||||
ret <<= 16;
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2);
|
||||
ret <<= 16;
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -550,9 +550,9 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
|
||||
lo = (value & 0x00000000FFFFULL);
|
||||
mi = (value & 0x0000FFFF0000ULL) >> 16;
|
||||
hi = (value & 0xFFFF00000000ULL) >> 32;
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1, lo);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2, mi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3, hi);
|
||||
}
|
||||
|
||||
/* Read the firmware capabilities bitmask (Opensource firmware only) */
|
||||
@ -4278,6 +4278,35 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
|
||||
{
|
||||
switch (phy_type) {
|
||||
case B43_PHYTYPE_A:
|
||||
return "A";
|
||||
case B43_PHYTYPE_B:
|
||||
return "B";
|
||||
case B43_PHYTYPE_G:
|
||||
return "G";
|
||||
case B43_PHYTYPE_N:
|
||||
return "N";
|
||||
case B43_PHYTYPE_LP:
|
||||
return "LP";
|
||||
case B43_PHYTYPE_SSLPN:
|
||||
return "SSLPN";
|
||||
case B43_PHYTYPE_HT:
|
||||
return "HT";
|
||||
case B43_PHYTYPE_LCN:
|
||||
return "LCN";
|
||||
case B43_PHYTYPE_LCNXN:
|
||||
return "LCNXN";
|
||||
case B43_PHYTYPE_LCN40:
|
||||
return "LCN40";
|
||||
case B43_PHYTYPE_AC:
|
||||
return "AC";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
/* Get PHY and RADIO versioning numbers */
|
||||
static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
{
|
||||
@ -4338,13 +4367,13 @@ static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
unsupported = 1;
|
||||
}
|
||||
if (unsupported) {
|
||||
b43err(dev->wl, "FOUND UNSUPPORTED PHY "
|
||||
"(Analog %u, Type %u, Revision %u)\n",
|
||||
analog_type, phy_type, phy_rev);
|
||||
b43err(dev->wl, "FOUND UNSUPPORTED PHY (Analog %u, Type %d (%s), Revision %u)\n",
|
||||
analog_type, phy_type, b43_phy_name(dev, phy_type),
|
||||
phy_rev);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n",
|
||||
analog_type, phy_type, phy_rev);
|
||||
b43info(dev->wl, "Found PHY: Analog %u, Type %d (%s), Revision %u\n",
|
||||
analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
|
||||
|
||||
/* Get RADIO versioning */
|
||||
if (dev->dev->core_rev >= 24) {
|
||||
|
@ -240,6 +240,21 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
|
||||
(b43_radio_read16(dev, offset) & mask) | set);
|
||||
}
|
||||
|
||||
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
|
||||
u16 value, int delay, int timeout)
|
||||
{
|
||||
u16 val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < timeout; i += delay) {
|
||||
val = b43_radio_read(dev, offset);
|
||||
if ((val & mask) == value)
|
||||
return true;
|
||||
udelay(delay);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
assert_mac_suspended(dev);
|
||||
@ -428,7 +443,7 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
|
||||
average = (a + b + c + d + 2) / 4;
|
||||
if (is_ofdm) {
|
||||
/* Adjust for CCK-boost */
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1)
|
||||
& B43_HF_CCKBOOST)
|
||||
average = (average >= 13) ? (average - 13) : 0;
|
||||
}
|
||||
|
@ -364,6 +364,12 @@ void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
*/
|
||||
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
/**
|
||||
* b43_radio_wait_value - Waits for a given value in masked register read
|
||||
*/
|
||||
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
|
||||
u16 value, int delay, int timeout);
|
||||
|
||||
/**
|
||||
* b43_radio_lock - Lock firmware radio register access
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "tables_nphy.h"
|
||||
#include "radio_2055.h"
|
||||
#include "radio_2056.h"
|
||||
#include "radio_2057.h"
|
||||
#include "main.h"
|
||||
|
||||
struct nphy_txgains {
|
||||
@ -126,6 +127,46 @@ ok:
|
||||
b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
|
||||
static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
|
||||
u16 value, u8 core, bool off,
|
||||
u8 override)
|
||||
{
|
||||
const struct nphy_rf_control_override_rev7 *e;
|
||||
u16 en_addrs[3][2] = {
|
||||
{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
|
||||
};
|
||||
u16 en_addr;
|
||||
u16 en_mask = field;
|
||||
u16 val_addr;
|
||||
u8 i;
|
||||
|
||||
/* Remember: we can get NULL! */
|
||||
e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (override >= ARRAY_SIZE(en_addrs)) {
|
||||
b43err(dev->wl, "Invalid override value %d\n", override);
|
||||
return;
|
||||
}
|
||||
en_addr = en_addrs[override][i];
|
||||
|
||||
val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
|
||||
|
||||
if (off) {
|
||||
b43_phy_mask(dev, en_addr, ~en_mask);
|
||||
if (e) /* Do it safer, better than wl */
|
||||
b43_phy_mask(dev, val_addr, ~e->val_mask);
|
||||
} else {
|
||||
if (!core || (core & (1 << i))) {
|
||||
b43_phy_set(dev, en_addr, en_mask);
|
||||
if (e)
|
||||
b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
|
||||
static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
|
||||
u16 value, u8 core, bool off)
|
||||
@ -458,6 +499,137 @@ static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
|
||||
b43_nphy_stay_in_carrier_search(dev, false);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Radio 0x2057
|
||||
**************************************************/
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
|
||||
static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 tmp;
|
||||
|
||||
if (phy->radio_rev == 5) {
|
||||
b43_phy_mask(dev, 0x342, ~0x2);
|
||||
udelay(10);
|
||||
b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
|
||||
b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
|
||||
}
|
||||
|
||||
b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
|
||||
udelay(10);
|
||||
b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
|
||||
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
|
||||
return 0;
|
||||
}
|
||||
b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
|
||||
tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
|
||||
b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
|
||||
|
||||
if (phy->radio_rev == 5) {
|
||||
b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
|
||||
b43_radio_mask(dev, 0x1ca, ~0x2);
|
||||
}
|
||||
if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
|
||||
b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
|
||||
b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
|
||||
tmp << 2);
|
||||
}
|
||||
|
||||
return tmp & 0x3e;
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */
|
||||
static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
|
||||
phy->radio_rev == 6);
|
||||
u16 tmp;
|
||||
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x61);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000))
|
||||
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x69);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000))
|
||||
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x73);
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000)) {
|
||||
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
|
||||
return 0;
|
||||
}
|
||||
tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void b43_radio_2057_init_pre(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
|
||||
b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
|
||||
b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
}
|
||||
|
||||
static void b43_radio_2057_init_post(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
|
||||
|
||||
b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
|
||||
b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
|
||||
mdelay(2);
|
||||
b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
|
||||
b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
|
||||
|
||||
if (dev->phy.n->init_por) {
|
||||
b43_radio_2057_rcal(dev);
|
||||
b43_radio_2057_rccal(dev);
|
||||
}
|
||||
b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
|
||||
|
||||
dev->phy.n->init_por = false;
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
|
||||
static void b43_radio_2057_init(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_2057_init_pre(dev);
|
||||
r2057_upload_inittabs(dev);
|
||||
b43_radio_2057_init_post(dev);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Radio 0x2056
|
||||
**************************************************/
|
||||
@ -545,7 +717,9 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
enum ieee80211_band band = b43_current_band(dev->wl);
|
||||
u16 offset;
|
||||
u8 i;
|
||||
u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
|
||||
u16 bias, cbias;
|
||||
u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
|
||||
u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
|
||||
|
||||
B43_WARN_ON(dev->phy.rev < 3);
|
||||
|
||||
@ -630,7 +804,56 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
|
||||
}
|
||||
} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
|
||||
/* TODO */
|
||||
u16 freq = dev->phy.channel_freq;
|
||||
if (freq < 5100) {
|
||||
paa_boost = 0xA;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xF;
|
||||
mixa_boost = 0xF;
|
||||
} else if (freq < 5340) {
|
||||
paa_boost = 0x8;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xFB;
|
||||
mixa_boost = 0xF;
|
||||
} else if (freq < 5650) {
|
||||
paa_boost = 0x0;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xB;
|
||||
mixa_boost = 0xF;
|
||||
} else {
|
||||
paa_boost = 0x0;
|
||||
pada_boost = 0x77;
|
||||
if (freq != 5825)
|
||||
pgaa_boost = -(freq - 18) / 36 + 168;
|
||||
else
|
||||
pgaa_boost = 6;
|
||||
mixa_boost = 0xF;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
offset = i ? B2056_TX1 : B2056_TX0;
|
||||
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_TXSPARE1, 0x30);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PA_SPARE2, 0xee);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PADA_CASCBIAS, 0x03);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_IAUX_STAT, 0x50);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_IMAIN_STAT, 0x50);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_CASCBIAS, 0x30);
|
||||
}
|
||||
}
|
||||
|
||||
udelay(50);
|
||||
@ -643,6 +866,37 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
udelay(300);
|
||||
}
|
||||
|
||||
static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 mast2, tmp;
|
||||
|
||||
if (phy->rev != 3)
|
||||
return 0;
|
||||
|
||||
mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
|
||||
b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
|
||||
|
||||
udelay(10);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
|
||||
udelay(10);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);
|
||||
|
||||
if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
|
||||
1000000)) {
|
||||
b43err(dev->wl, "Radio recalibration timeout\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
|
||||
tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);
|
||||
|
||||
b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);
|
||||
|
||||
return tmp & 0x1f;
|
||||
}
|
||||
|
||||
static void b43_radio_init2056_pre(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
@ -665,10 +919,8 @@ static void b43_radio_init2056_post(struct b43_wldev *dev)
|
||||
b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
|
||||
b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
|
||||
b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
|
||||
/*
|
||||
if (nphy->init_por)
|
||||
Call Radio 2056 Recalibrate
|
||||
*/
|
||||
if (dev->phy.n->init_por)
|
||||
b43_radio_2056_rcal(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -680,6 +932,8 @@ static void b43_radio_init2056(struct b43_wldev *dev)
|
||||
b43_radio_init2056_pre(dev);
|
||||
b2056_upload_inittabs(dev, 0, 0);
|
||||
b43_radio_init2056_post(dev);
|
||||
|
||||
dev->phy.n->init_por = false;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
@ -753,8 +1007,6 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
int i;
|
||||
u16 val;
|
||||
bool workaround = false;
|
||||
|
||||
if (sprom->revision < 4)
|
||||
@ -777,15 +1029,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x1);
|
||||
msleep(1);
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x40);
|
||||
for (i = 0; i < 200; i++) {
|
||||
val = b43_radio_read(dev, B2055_CAL_COUT2);
|
||||
if (val & 0x80) {
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
udelay(10);
|
||||
}
|
||||
if (i)
|
||||
if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
|
||||
b43err(dev->wl, "radio post init timeout\n");
|
||||
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
@ -1860,12 +2104,334 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
|
||||
static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
|
||||
{
|
||||
if (dev->phy.rev >= 3)
|
||||
if (dev->phy.rev >= 7)
|
||||
; /* TODO */
|
||||
else if (dev->phy.rev >= 3)
|
||||
b43_nphy_gain_ctl_workarounds_rev3plus(dev);
|
||||
else
|
||||
b43_nphy_gain_ctl_workarounds_rev1_2(dev);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
|
||||
static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
|
||||
{
|
||||
if (!offset)
|
||||
offset = (dev->phy.is_40mhz) ? 0x159 : 0x154;
|
||||
return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
|
||||
{
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
|
||||
0x1F };
|
||||
u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
|
||||
|
||||
u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
|
||||
u8 ntab7_138_146[] = { 0x11, 0x11 };
|
||||
u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
|
||||
|
||||
u16 lpf_20, lpf_40, lpf_11b;
|
||||
u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
|
||||
u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
|
||||
bool rccal_ovrd = false;
|
||||
|
||||
u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
|
||||
u16 bias, conv, filt;
|
||||
|
||||
u32 tmp32;
|
||||
u8 core;
|
||||
|
||||
if (phy->rev == 7) {
|
||||
b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
|
||||
}
|
||||
if (phy->rev <= 8) {
|
||||
b43_phy_write(dev, 0x23F, 0x1B0);
|
||||
b43_phy_write(dev, 0x240, 0x1B0);
|
||||
}
|
||||
if (phy->rev >= 8)
|
||||
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
|
||||
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
|
||||
tmp32 &= 0xffffff;
|
||||
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
|
||||
|
||||
if (b43_nphy_ipa(dev))
|
||||
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
|
||||
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
|
||||
|
||||
b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000);
|
||||
b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000);
|
||||
|
||||
lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
|
||||
lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
|
||||
lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
|
||||
if (b43_nphy_ipa(dev)) {
|
||||
if ((phy->radio_rev == 5 && phy->is_40mhz) ||
|
||||
phy->radio_rev == 7 || phy->radio_rev == 8) {
|
||||
bcap_val = b43_radio_read(dev, 0x16b);
|
||||
scap_val = b43_radio_read(dev, 0x16a);
|
||||
scap_val_11b = scap_val;
|
||||
bcap_val_11b = bcap_val;
|
||||
if (phy->radio_rev == 5 && phy->is_40mhz) {
|
||||
scap_val_11n_20 = scap_val;
|
||||
bcap_val_11n_20 = bcap_val;
|
||||
scap_val_11n_40 = bcap_val_11n_40 = 0xc;
|
||||
rccal_ovrd = true;
|
||||
} else { /* Rev 7/8 */
|
||||
lpf_20 = 4;
|
||||
lpf_11b = 1;
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
scap_val_11n_20 = 0xc;
|
||||
bcap_val_11n_20 = 0xc;
|
||||
scap_val_11n_40 = 0xa;
|
||||
bcap_val_11n_40 = 0xa;
|
||||
} else {
|
||||
scap_val_11n_20 = 0x14;
|
||||
bcap_val_11n_20 = 0x14;
|
||||
scap_val_11n_40 = 0xf;
|
||||
bcap_val_11n_40 = 0xf;
|
||||
}
|
||||
rccal_ovrd = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (phy->radio_rev == 5) {
|
||||
lpf_20 = 1;
|
||||
lpf_40 = 3;
|
||||
bcap_val = b43_radio_read(dev, 0x16b);
|
||||
scap_val = b43_radio_read(dev, 0x16a);
|
||||
scap_val_11b = scap_val;
|
||||
bcap_val_11b = bcap_val;
|
||||
scap_val_11n_20 = 0x11;
|
||||
scap_val_11n_40 = 0x11;
|
||||
bcap_val_11n_20 = 0x13;
|
||||
bcap_val_11n_40 = 0x13;
|
||||
rccal_ovrd = true;
|
||||
}
|
||||
}
|
||||
if (rccal_ovrd) {
|
||||
rx2tx_lut_20_11b = (bcap_val_11b << 8) |
|
||||
(scap_val_11b << 3) |
|
||||
lpf_11b;
|
||||
rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
|
||||
(scap_val_11n_20 << 3) |
|
||||
lpf_20;
|
||||
rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
|
||||
(scap_val_11n_40 << 3) |
|
||||
lpf_40;
|
||||
for (core = 0; core < 2; core++) {
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
|
||||
rx2tx_lut_20_11b);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
|
||||
rx2tx_lut_20_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
|
||||
rx2tx_lut_20_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
}
|
||||
b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2);
|
||||
}
|
||||
b43_phy_write(dev, 0x32F, 0x3);
|
||||
if (phy->radio_rev == 4 || phy->radio_rev == 6)
|
||||
b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0);
|
||||
|
||||
if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
|
||||
if (sprom->revision &&
|
||||
sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {
|
||||
b43_radio_write(dev, 0x5, 0x05);
|
||||
b43_radio_write(dev, 0x6, 0x30);
|
||||
b43_radio_write(dev, 0x7, 0x00);
|
||||
b43_radio_set(dev, 0x4f, 0x1);
|
||||
b43_radio_set(dev, 0xd4, 0x1);
|
||||
bias = 0x1f;
|
||||
conv = 0x6f;
|
||||
filt = 0xaa;
|
||||
} else {
|
||||
bias = 0x2b;
|
||||
conv = 0x7f;
|
||||
filt = 0xee;
|
||||
}
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x5F, bias);
|
||||
b43_radio_write(dev, 0x64, conv);
|
||||
b43_radio_write(dev, 0x66, filt);
|
||||
} else {
|
||||
b43_radio_write(dev, 0xE8, bias);
|
||||
b43_radio_write(dev, 0xE9, conv);
|
||||
b43_radio_write(dev, 0xEB, filt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b43_nphy_ipa(dev)) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
|
||||
phy->radio_rev == 6) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0)
|
||||
b43_radio_write(dev, 0x51,
|
||||
0x7f);
|
||||
else
|
||||
b43_radio_write(dev, 0xd6,
|
||||
0x7f);
|
||||
}
|
||||
}
|
||||
if (phy->radio_rev == 3) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x64,
|
||||
0x13);
|
||||
b43_radio_write(dev, 0x5F,
|
||||
0x1F);
|
||||
b43_radio_write(dev, 0x66,
|
||||
0xEE);
|
||||
b43_radio_write(dev, 0x59,
|
||||
0x8A);
|
||||
b43_radio_write(dev, 0x80,
|
||||
0x3E);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x69,
|
||||
0x13);
|
||||
b43_radio_write(dev, 0xE8,
|
||||
0x1F);
|
||||
b43_radio_write(dev, 0xEB,
|
||||
0xEE);
|
||||
b43_radio_write(dev, 0xDE,
|
||||
0x8A);
|
||||
b43_radio_write(dev, 0x105,
|
||||
0x3E);
|
||||
}
|
||||
}
|
||||
} else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
|
||||
if (!phy->is_40mhz) {
|
||||
b43_radio_write(dev, 0x5F, 0x14);
|
||||
b43_radio_write(dev, 0xE8, 0x12);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x5F, 0x16);
|
||||
b43_radio_write(dev, 0xE8, 0x16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
u16 freq = phy->channel_freq;
|
||||
if ((freq >= 5180 && freq <= 5230) ||
|
||||
(freq >= 5745 && freq <= 5805)) {
|
||||
b43_radio_write(dev, 0x7D, 0xFF);
|
||||
b43_radio_write(dev, 0xFE, 0xFF);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (phy->radio_rev != 5) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x5c, 0x61);
|
||||
b43_radio_write(dev, 0x51, 0x70);
|
||||
} else {
|
||||
b43_radio_write(dev, 0xe1, 0x61);
|
||||
b43_radio_write(dev, 0xd6, 0x70);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (phy->radio_rev == 4) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x1a1, 0x00);
|
||||
b43_radio_write(dev, 0x1a2, 0x3f);
|
||||
b43_radio_write(dev, 0x1a6, 0x3f);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1a7, 0x00);
|
||||
b43_radio_write(dev, 0x1ab, 0x3f);
|
||||
b43_radio_write(dev, 0x1ac, 0x3f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
|
||||
}
|
||||
|
||||
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
|
||||
|
||||
if (!phy->is_40mhz) {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
|
||||
} else {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
|
||||
}
|
||||
|
||||
b43_nphy_gain_ctl_workarounds(dev);
|
||||
|
||||
/* TODO
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
|
||||
aux_adc_vmid_rev7_core0);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
|
||||
aux_adc_vmid_rev7_core1);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
|
||||
aux_adc_gain_rev7);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
|
||||
aux_adc_gain_rev7);
|
||||
*/
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
@ -1916,7 +2482,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
rx2tx_delays[6] = 1;
|
||||
rx2tx_events[7] = 0x1F;
|
||||
}
|
||||
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
|
||||
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
|
||||
ARRAY_SIZE(rx2tx_events));
|
||||
}
|
||||
|
||||
@ -1926,8 +2492,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
|
||||
b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
|
||||
if (!dev->phy.is_40mhz) {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
|
||||
} else {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
|
||||
}
|
||||
|
||||
b43_nphy_gain_ctl_workarounds(dev);
|
||||
|
||||
@ -1963,13 +2534,14 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
|
||||
|
||||
if (dev->phy.rev == 4 &&
|
||||
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
|
||||
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
|
||||
b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
|
||||
0x70);
|
||||
b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
|
||||
0x70);
|
||||
}
|
||||
|
||||
/* Dropped probably-always-true condition */
|
||||
b43_phy_write(dev, 0x224, 0x03eb);
|
||||
b43_phy_write(dev, 0x225, 0x03eb);
|
||||
b43_phy_write(dev, 0x226, 0x0341);
|
||||
@ -1982,6 +2554,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, 0x22d, 0x042b);
|
||||
b43_phy_write(dev, 0x22e, 0x0381);
|
||||
b43_phy_write(dev, 0x22f, 0x0381);
|
||||
|
||||
if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
|
||||
; /* TODO: 0x0080000000000000 HF */
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
@ -1996,6 +2571,12 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
|
||||
u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
|
||||
|
||||
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
|
||||
dev->dev->board_type == 0x8B) {
|
||||
delays1[0] = 0x1;
|
||||
delays1[5] = 0x14;
|
||||
}
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
|
||||
nphy->band5g_pwrgain) {
|
||||
b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
|
||||
@ -2007,8 +2588,10 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
|
||||
if (dev->phy.rev < 3) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
|
||||
}
|
||||
|
||||
if (dev->phy.rev < 2) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
|
||||
@ -2024,11 +2607,6 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
|
||||
|
||||
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
|
||||
dev->dev->board_type == 0x8B) {
|
||||
delays1[0] = 0x1;
|
||||
delays1[5] = 0x14;
|
||||
}
|
||||
b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
|
||||
b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
|
||||
|
||||
@ -2055,11 +2633,13 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
|
||||
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
|
||||
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
|
||||
if (dev->phy.rev < 3) {
|
||||
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
|
||||
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
|
||||
}
|
||||
|
||||
if (dev->phy.rev == 2)
|
||||
b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
|
||||
@ -2083,7 +2663,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
|
||||
b43_phy_set(dev, B43_NPHY_IQFLIP,
|
||||
B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
|
||||
|
||||
if (dev->phy.rev >= 3)
|
||||
if (dev->phy.rev >= 7)
|
||||
b43_nphy_workarounds_rev7plus(dev);
|
||||
else if (dev->phy.rev >= 3)
|
||||
b43_nphy_workarounds_rev3plus(dev);
|
||||
else
|
||||
b43_nphy_workarounds_rev1_2(dev);
|
||||
@ -2542,7 +3124,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
b43_nphy_ipa_internal_tssi_setup(dev);
|
||||
|
||||
if (phy->rev >= 7)
|
||||
; /* TODO: Override Rev7 with 0x2000, 0, 3, 0, 0 as arguments */
|
||||
b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0);
|
||||
else if (phy->rev >= 3)
|
||||
b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
|
||||
|
||||
@ -2554,7 +3136,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
b43_nphy_rssi_select(dev, 0, 0);
|
||||
|
||||
if (phy->rev >= 7)
|
||||
; /* TODO: Override Rev7 with 0x2000, 0, 3, 1, 0 as arguments */
|
||||
b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0);
|
||||
else if (phy->rev >= 3)
|
||||
b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
|
||||
|
||||
@ -4761,6 +5343,7 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
|
||||
nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
|
||||
nphy->spur_avoid = (phy->rev >= 3) ?
|
||||
B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
|
||||
nphy->init_por = true;
|
||||
nphy->gain_boost = true; /* this way we follow wl, assume it is true */
|
||||
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
|
||||
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
|
||||
@ -4801,6 +5384,8 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
|
||||
nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
|
||||
nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
|
||||
}
|
||||
|
||||
nphy->init_por = true;
|
||||
}
|
||||
|
||||
static void b43_nphy_op_free(struct b43_wldev *dev)
|
||||
@ -4887,7 +5472,9 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
if (blocked) {
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
~B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (dev->phy.rev >= 7) {
|
||||
/* TODO */
|
||||
} else if (dev->phy.rev >= 3) {
|
||||
b43_radio_mask(dev, 0x09, ~0x2);
|
||||
|
||||
b43_radio_write(dev, 0x204D, 0);
|
||||
@ -4905,7 +5492,10 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
b43_radio_write(dev, 0x3064, 0);
|
||||
}
|
||||
} else {
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (dev->phy.rev >= 7) {
|
||||
b43_radio_2057_init(dev);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
} else if (dev->phy.rev >= 3) {
|
||||
b43_radio_init2056(dev);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
} else {
|
||||
|
@ -785,6 +785,7 @@ struct b43_phy_n {
|
||||
u16 papd_epsilon_offset[2];
|
||||
s32 preamble_override;
|
||||
u32 bb_mult_save;
|
||||
bool init_por;
|
||||
|
||||
bool gain_boost;
|
||||
bool elna_gain_config;
|
||||
|
141
drivers/net/wireless/b43/radio_2057.c
Normal file
141
drivers/net/wireless/b43/radio_2057.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
IEEE 802.11n 2057 radio device data tables
|
||||
|
||||
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "b43.h"
|
||||
#include "radio_2057.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
static u16 r2057_rev4_init[42][2] = {
|
||||
{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
|
||||
{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
|
||||
{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
|
||||
{ 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c },
|
||||
{ 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 },
|
||||
{ 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c },
|
||||
{ 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
|
||||
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
|
||||
{ 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
|
||||
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
|
||||
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev5_init[44][2] = {
|
||||
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
|
||||
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
|
||||
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
|
||||
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
|
||||
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
|
||||
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
|
||||
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
|
||||
{ 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 },
|
||||
{ 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 },
|
||||
{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev5a_init[45][2] = {
|
||||
{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
|
||||
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
|
||||
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
|
||||
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
|
||||
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
|
||||
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 },
|
||||
{ 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 },
|
||||
{ 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
|
||||
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
|
||||
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 },
|
||||
{ 0x1C2, 0x80 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev7_init[54][2] = {
|
||||
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
|
||||
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
|
||||
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
|
||||
{ 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 },
|
||||
{ 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f },
|
||||
{ 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
|
||||
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee },
|
||||
{ 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 },
|
||||
{ 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 },
|
||||
{ 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
|
||||
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
|
||||
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
|
||||
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev8_init[54][2] = {
|
||||
{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
|
||||
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
|
||||
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
|
||||
{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
|
||||
{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
|
||||
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
|
||||
{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
|
||||
{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
|
||||
{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
|
||||
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
|
||||
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
|
||||
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
|
||||
};
|
||||
|
||||
void r2057_upload_inittabs(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 *table = NULL;
|
||||
u16 size, i;
|
||||
|
||||
if (phy->rev == 7) {
|
||||
table = r2057_rev4_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev4_init);
|
||||
} else if (phy->rev == 8 || phy->rev == 9) {
|
||||
if (phy->radio_rev == 5) {
|
||||
if (phy->radio_rev == 8) {
|
||||
table = r2057_rev5_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev5_init);
|
||||
} else {
|
||||
table = r2057_rev5a_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev5a_init);
|
||||
}
|
||||
} else if (phy->radio_rev == 7) {
|
||||
table = r2057_rev7_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev7_init);
|
||||
} else if (phy->radio_rev == 9) {
|
||||
table = r2057_rev8_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev8_init);
|
||||
}
|
||||
}
|
||||
|
||||
if (table) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
pr_info("radio_write 0x%X ", *table);
|
||||
table++;
|
||||
pr_info("0x%X\n", *table);
|
||||
table++;
|
||||
}
|
||||
}
|
||||
}
|
430
drivers/net/wireless/b43/radio_2057.h
Normal file
430
drivers/net/wireless/b43/radio_2057.h
Normal file
@ -0,0 +1,430 @@
|
||||
#ifndef B43_RADIO_2057_H_
|
||||
#define B43_RADIO_2057_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "tables_nphy.h"
|
||||
|
||||
#define R2057_DACBUF_VINCM_CORE0 0x000
|
||||
#define R2057_IDCODE 0x001
|
||||
#define R2057_RCCAL_MASTER 0x002
|
||||
#define R2057_RCCAL_CAP_SIZE 0x003
|
||||
#define R2057_RCAL_CONFIG 0x004
|
||||
#define R2057_GPAIO_CONFIG 0x005
|
||||
#define R2057_GPAIO_SEL1 0x006
|
||||
#define R2057_GPAIO_SEL0 0x007
|
||||
#define R2057_CLPO_CONFIG 0x008
|
||||
#define R2057_BANDGAP_CONFIG 0x009
|
||||
#define R2057_BANDGAP_RCAL_TRIM 0x00a
|
||||
#define R2057_AFEREG_CONFIG 0x00b
|
||||
#define R2057_TEMPSENSE_CONFIG 0x00c
|
||||
#define R2057_XTAL_CONFIG1 0x00d
|
||||
#define R2057_XTAL_ICORE_SIZE 0x00e
|
||||
#define R2057_XTAL_BUF_SIZE 0x00f
|
||||
#define R2057_XTAL_PULLCAP_SIZE 0x010
|
||||
#define R2057_RFPLL_MASTER 0x011
|
||||
#define R2057_VCOMONITOR_VTH_L 0x012
|
||||
#define R2057_VCOMONITOR_VTH_H 0x013
|
||||
#define R2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x014
|
||||
#define R2057_VCO_VARCSIZE_IDAC 0x015
|
||||
#define R2057_VCOCAL_COUNTVAL0 0x016
|
||||
#define R2057_VCOCAL_COUNTVAL1 0x017
|
||||
#define R2057_VCOCAL_INTCLK_COUNT 0x018
|
||||
#define R2057_VCOCAL_MASTER 0x019
|
||||
#define R2057_VCOCAL_NUMCAPCHANGE 0x01a
|
||||
#define R2057_VCOCAL_WINSIZE 0x01b
|
||||
#define R2057_VCOCAL_DELAY_AFTER_REFRESH 0x01c
|
||||
#define R2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x01d
|
||||
#define R2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x01e
|
||||
#define R2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x01f
|
||||
#define R2057_VCO_FORCECAPEN_FORCECAP1 0x020
|
||||
#define R2057_VCO_FORCECAP0 0x021
|
||||
#define R2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x022
|
||||
#define R2057_RFPLL_PFD_RESET_PW 0x023
|
||||
#define R2057_RFPLL_LOOPFILTER_R2 0x024
|
||||
#define R2057_RFPLL_LOOPFILTER_R1 0x025
|
||||
#define R2057_RFPLL_LOOPFILTER_C3 0x026
|
||||
#define R2057_RFPLL_LOOPFILTER_C2 0x027
|
||||
#define R2057_RFPLL_LOOPFILTER_C1 0x028
|
||||
#define R2057_CP_KPD_IDAC 0x029
|
||||
#define R2057_RFPLL_IDACS 0x02a
|
||||
#define R2057_RFPLL_MISC_EN 0x02b
|
||||
#define R2057_RFPLL_MMD0 0x02c
|
||||
#define R2057_RFPLL_MMD1 0x02d
|
||||
#define R2057_RFPLL_MISC_CAL_RESETN 0x02e
|
||||
#define R2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x02f
|
||||
#define R2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x030
|
||||
#define R2057_VCOCAL_READCAP0 0x031
|
||||
#define R2057_VCOCAL_READCAP1 0x032
|
||||
#define R2057_VCOCAL_STATUS 0x033
|
||||
#define R2057_LOGEN_PUS 0x034
|
||||
#define R2057_LOGEN_PTAT_RESETS 0x035
|
||||
#define R2057_VCOBUF_IDACS 0x036
|
||||
#define R2057_VCOBUF_TUNE 0x037
|
||||
#define R2057_CMOSBUF_TX2GQ_IDACS 0x038
|
||||
#define R2057_CMOSBUF_TX2GI_IDACS 0x039
|
||||
#define R2057_CMOSBUF_TX5GQ_IDACS 0x03a
|
||||
#define R2057_CMOSBUF_TX5GI_IDACS 0x03b
|
||||
#define R2057_CMOSBUF_RX2GQ_IDACS 0x03c
|
||||
#define R2057_CMOSBUF_RX2GI_IDACS 0x03d
|
||||
#define R2057_CMOSBUF_RX5GQ_IDACS 0x03e
|
||||
#define R2057_CMOSBUF_RX5GI_IDACS 0x03f
|
||||
#define R2057_LOGEN_MX2G_IDACS 0x040
|
||||
#define R2057_LOGEN_MX2G_TUNE 0x041
|
||||
#define R2057_LOGEN_MX5G_IDACS 0x042
|
||||
#define R2057_LOGEN_MX5G_TUNE 0x043
|
||||
#define R2057_LOGEN_MX5G_RCCR 0x044
|
||||
#define R2057_LOGEN_INDBUF2G_IDAC 0x045
|
||||
#define R2057_LOGEN_INDBUF2G_IBOOST 0x046
|
||||
#define R2057_LOGEN_INDBUF2G_TUNE 0x047
|
||||
#define R2057_LOGEN_INDBUF5G_IDAC 0x048
|
||||
#define R2057_LOGEN_INDBUF5G_IBOOST 0x049
|
||||
#define R2057_LOGEN_INDBUF5G_TUNE 0x04a
|
||||
#define R2057_CMOSBUF_TX_RCCR 0x04b
|
||||
#define R2057_CMOSBUF_RX_RCCR 0x04c
|
||||
#define R2057_LOGEN_SEL_PKDET 0x04d
|
||||
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
|
||||
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
|
||||
#define R2057_TXGM_TXRF_PUS_CORE0 0x050
|
||||
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
|
||||
#define R2057_TXGM_GAIN_CORE0 0x056
|
||||
#define R2057_TXGM2G_PKDET_PUS_CORE0 0x057
|
||||
#define R2057_PAD2G_PTATS_CORE0 0x058
|
||||
#define R2057_PAD2G_IDACS_CORE0 0x059
|
||||
#define R2057_PAD2G_BOOST_PU_CORE0 0x05a
|
||||
#define R2057_PAD2G_CASCV_GAIN_CORE0 0x05b
|
||||
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x05c
|
||||
#define R2057_TXMIX2G_LODC_CORE0 0x05d
|
||||
#define R2057_PAD2G_TUNE_PUS_CORE0 0x05e
|
||||
#define R2057_IPA2G_GAIN_CORE0 0x05f
|
||||
#define R2057_TSSI2G_SPARE1_CORE0 0x060
|
||||
#define R2057_TSSI2G_SPARE2_CORE0 0x061
|
||||
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x062
|
||||
#define R2057_IPA2G_IMAIN_CORE0 0x063
|
||||
#define R2057_IPA2G_CASCONV_CORE0 0x064
|
||||
#define R2057_IPA2G_CASCOFFV_CORE0 0x065
|
||||
#define R2057_IPA2G_BIAS_FILTER_CORE0 0x066
|
||||
#define R2057_TX5G_PKDET_CORE0 0x069
|
||||
#define R2057_PGA_PTAT_TXGM5G_PU_CORE0 0x06a
|
||||
#define R2057_PAD5G_PTATS1_CORE0 0x06b
|
||||
#define R2057_PAD5G_CLASS_PTATS2_CORE0 0x06c
|
||||
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x06d
|
||||
#define R2057_PAD5G_CASCV_IMAIN_CORE0 0x06e
|
||||
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x06f
|
||||
#define R2057_PGA_BOOST_TUNE_CORE0 0x070
|
||||
#define R2057_PGA_GAIN_CORE0 0x071
|
||||
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x072
|
||||
#define R2057_TXMIX5G_BOOST_TUNE_CORE0 0x073
|
||||
#define R2057_PAD5G_TUNE_MISC_PUS_CORE0 0x074
|
||||
#define R2057_IPA5G_IAUX_CORE0 0x075
|
||||
#define R2057_IPA5G_GAIN_CORE0 0x076
|
||||
#define R2057_TSSI5G_SPARE1_CORE0 0x077
|
||||
#define R2057_TSSI5G_SPARE2_CORE0 0x078
|
||||
#define R2057_IPA5G_CASCOFFV_PU_CORE0 0x079
|
||||
#define R2057_IPA5G_PTAT_CORE0 0x07a
|
||||
#define R2057_IPA5G_IMAIN_CORE0 0x07b
|
||||
#define R2057_IPA5G_CASCONV_CORE0 0x07c
|
||||
#define R2057_IPA5G_BIAS_FILTER_CORE0 0x07d
|
||||
#define R2057_PAD_BIAS_FILTER_BWS_CORE0 0x080
|
||||
#define R2057_TR2G_CONFIG1_CORE0_NU 0x081
|
||||
#define R2057_TR2G_CONFIG2_CORE0_NU 0x082
|
||||
#define R2057_LNA5G_RFEN_CORE0 0x083
|
||||
#define R2057_TR5G_CONFIG2_CORE0_NU 0x084
|
||||
#define R2057_RXRFBIAS_IBOOST_PU_CORE0 0x085
|
||||
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x086
|
||||
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x087
|
||||
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x088
|
||||
#define R2057_RXMIX_CMFBITAIL_PU_CORE0 0x089
|
||||
#define R2057_LNA2_IMAIN_PTAT_PU_CORE0 0x08a
|
||||
#define R2057_LNA2_IAUX_PTAT_CORE0 0x08b
|
||||
#define R2057_LNA1_IMAIN_PTAT_PU_CORE0 0x08c
|
||||
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x08d
|
||||
#define R2057_RXRFBIAS_BANDSEL_CORE0 0x08e
|
||||
#define R2057_TIA_CONFIG_CORE0 0x08f
|
||||
#define R2057_TIA_IQGAIN_CORE0 0x090
|
||||
#define R2057_TIA_IBIAS2_CORE0 0x091
|
||||
#define R2057_TIA_IBIAS1_CORE0 0x092
|
||||
#define R2057_TIA_SPARE_Q_CORE0 0x093
|
||||
#define R2057_TIA_SPARE_I_CORE0 0x094
|
||||
#define R2057_RXMIX2G_PUS_CORE0 0x095
|
||||
#define R2057_RXMIX2G_VCMREFS_CORE0 0x096
|
||||
#define R2057_RXMIX2G_LODC_QI_CORE0 0x097
|
||||
#define R2057_W12G_BW_LNA2G_PUS_CORE0 0x098
|
||||
#define R2057_LNA2G_GAIN_CORE0 0x099
|
||||
#define R2057_LNA2G_TUNE_CORE0 0x09a
|
||||
#define R2057_RXMIX5G_PUS_CORE0 0x09b
|
||||
#define R2057_RXMIX5G_VCMREFS_CORE0 0x09c
|
||||
#define R2057_RXMIX5G_LODC_QI_CORE0 0x09d
|
||||
#define R2057_W15G_BW_LNA5G_PUS_CORE0 0x09e
|
||||
#define R2057_LNA5G_GAIN_CORE0 0x09f
|
||||
#define R2057_LNA5G_TUNE_CORE0 0x0a0
|
||||
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0x0a1
|
||||
#define R2057_RXBB_BIAS_MASTER_CORE0 0x0a2
|
||||
#define R2057_RXBB_VGABUF_IDACS_CORE0 0x0a3
|
||||
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0x0a4
|
||||
#define R2057_TXBUF_VINCM_CORE0 0x0a5
|
||||
#define R2057_TXBUF_IDACS_CORE0 0x0a6
|
||||
#define R2057_LPF_RESP_RXBUF_BW_CORE0 0x0a7
|
||||
#define R2057_RXBB_CC_CORE0 0x0a8
|
||||
#define R2057_RXBB_SPARE3_CORE0 0x0a9
|
||||
#define R2057_RXBB_RCCAL_HPC_CORE0 0x0aa
|
||||
#define R2057_LPF_IDACS_CORE0 0x0ab
|
||||
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0x0ac
|
||||
#define R2057_TXBUF_GAIN_CORE0 0x0ad
|
||||
#define R2057_AFELOOPBACK_AACI_RESP_CORE0 0x0ae
|
||||
#define R2057_RXBUF_DEGEN_CORE0 0x0af
|
||||
#define R2057_RXBB_SPARE2_CORE0 0x0b0
|
||||
#define R2057_RXBB_SPARE1_CORE0 0x0b1
|
||||
#define R2057_RSSI_MASTER_CORE0 0x0b2
|
||||
#define R2057_W2_MASTER_CORE0 0x0b3
|
||||
#define R2057_NB_MASTER_CORE0 0x0b4
|
||||
#define R2057_W2_IDACS0_Q_CORE0 0x0b5
|
||||
#define R2057_W2_IDACS1_Q_CORE0 0x0b6
|
||||
#define R2057_W2_IDACS0_I_CORE0 0x0b7
|
||||
#define R2057_W2_IDACS1_I_CORE0 0x0b8
|
||||
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0x0b9
|
||||
#define R2057_NB_IDACS_Q_CORE0 0x0ba
|
||||
#define R2057_NB_IDACS_I_CORE0 0x0bb
|
||||
#define R2057_BACKUP4_CORE0 0x0c1
|
||||
#define R2057_BACKUP3_CORE0 0x0c2
|
||||
#define R2057_BACKUP2_CORE0 0x0c3
|
||||
#define R2057_BACKUP1_CORE0 0x0c4
|
||||
#define R2057_SPARE16_CORE0 0x0c5
|
||||
#define R2057_SPARE15_CORE0 0x0c6
|
||||
#define R2057_SPARE14_CORE0 0x0c7
|
||||
#define R2057_SPARE13_CORE0 0x0c8
|
||||
#define R2057_SPARE12_CORE0 0x0c9
|
||||
#define R2057_SPARE11_CORE0 0x0ca
|
||||
#define R2057_TX2G_BIAS_RESETS_CORE0 0x0cb
|
||||
#define R2057_TX5G_BIAS_RESETS_CORE0 0x0cc
|
||||
#define R2057_IQTEST_SEL_PU 0x0cd
|
||||
#define R2057_XTAL_CONFIG2 0x0ce
|
||||
#define R2057_BUFS_MISC_LPFBW_CORE0 0x0cf
|
||||
#define R2057_TXLPF_RCCAL_CORE0 0x0d0
|
||||
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
|
||||
#define R2057_LPF_GAIN_CORE0 0x0d2
|
||||
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
|
||||
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
|
||||
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
|
||||
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
|
||||
#define R2057_TXGM_GAIN_CORE1 0x0db
|
||||
#define R2057_TXGM2G_PKDET_PUS_CORE1 0x0dc
|
||||
#define R2057_PAD2G_PTATS_CORE1 0x0dd
|
||||
#define R2057_PAD2G_IDACS_CORE1 0x0de
|
||||
#define R2057_PAD2G_BOOST_PU_CORE1 0x0df
|
||||
#define R2057_PAD2G_CASCV_GAIN_CORE1 0x0e0
|
||||
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0x0e1
|
||||
#define R2057_TXMIX2G_LODC_CORE1 0x0e2
|
||||
#define R2057_PAD2G_TUNE_PUS_CORE1 0x0e3
|
||||
#define R2057_IPA2G_GAIN_CORE1 0x0e4
|
||||
#define R2057_TSSI2G_SPARE1_CORE1 0x0e5
|
||||
#define R2057_TSSI2G_SPARE2_CORE1 0x0e6
|
||||
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0x0e7
|
||||
#define R2057_IPA2G_IMAIN_CORE1 0x0e8
|
||||
#define R2057_IPA2G_CASCONV_CORE1 0x0e9
|
||||
#define R2057_IPA2G_CASCOFFV_CORE1 0x0ea
|
||||
#define R2057_IPA2G_BIAS_FILTER_CORE1 0x0eb
|
||||
#define R2057_TX5G_PKDET_CORE1 0x0ee
|
||||
#define R2057_PGA_PTAT_TXGM5G_PU_CORE1 0x0ef
|
||||
#define R2057_PAD5G_PTATS1_CORE1 0x0f0
|
||||
#define R2057_PAD5G_CLASS_PTATS2_CORE1 0x0f1
|
||||
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE1 0x0f2
|
||||
#define R2057_PAD5G_CASCV_IMAIN_CORE1 0x0f3
|
||||
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0x0f4
|
||||
#define R2057_PGA_BOOST_TUNE_CORE1 0x0f5
|
||||
#define R2057_PGA_GAIN_CORE1 0x0f6
|
||||
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0x0f7
|
||||
#define R2057_TXMIX5G_BOOST_TUNE_CORE1 0x0f8
|
||||
#define R2057_PAD5G_TUNE_MISC_PUS_CORE1 0x0f9
|
||||
#define R2057_IPA5G_IAUX_CORE1 0x0fa
|
||||
#define R2057_IPA5G_GAIN_CORE1 0x0fb
|
||||
#define R2057_TSSI5G_SPARE1_CORE1 0x0fc
|
||||
#define R2057_TSSI5G_SPARE2_CORE1 0x0fd
|
||||
#define R2057_IPA5G_CASCOFFV_PU_CORE1 0x0fe
|
||||
#define R2057_IPA5G_PTAT_CORE1 0x0ff
|
||||
#define R2057_IPA5G_IMAIN_CORE1 0x100
|
||||
#define R2057_IPA5G_CASCONV_CORE1 0x101
|
||||
#define R2057_IPA5G_BIAS_FILTER_CORE1 0x102
|
||||
#define R2057_PAD_BIAS_FILTER_BWS_CORE1 0x105
|
||||
#define R2057_TR2G_CONFIG1_CORE1_NU 0x106
|
||||
#define R2057_TR2G_CONFIG2_CORE1_NU 0x107
|
||||
#define R2057_LNA5G_RFEN_CORE1 0x108
|
||||
#define R2057_TR5G_CONFIG2_CORE1_NU 0x109
|
||||
#define R2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a
|
||||
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
|
||||
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c
|
||||
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d
|
||||
#define R2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e
|
||||
#define R2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f
|
||||
#define R2057_LNA2_IAUX_PTAT_CORE1 0x110
|
||||
#define R2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111
|
||||
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
|
||||
#define R2057_RXRFBIAS_BANDSEL_CORE1 0x113
|
||||
#define R2057_TIA_CONFIG_CORE1 0x114
|
||||
#define R2057_TIA_IQGAIN_CORE1 0x115
|
||||
#define R2057_TIA_IBIAS2_CORE1 0x116
|
||||
#define R2057_TIA_IBIAS1_CORE1 0x117
|
||||
#define R2057_TIA_SPARE_Q_CORE1 0x118
|
||||
#define R2057_TIA_SPARE_I_CORE1 0x119
|
||||
#define R2057_RXMIX2G_PUS_CORE1 0x11a
|
||||
#define R2057_RXMIX2G_VCMREFS_CORE1 0x11b
|
||||
#define R2057_RXMIX2G_LODC_QI_CORE1 0x11c
|
||||
#define R2057_W12G_BW_LNA2G_PUS_CORE1 0x11d
|
||||
#define R2057_LNA2G_GAIN_CORE1 0x11e
|
||||
#define R2057_LNA2G_TUNE_CORE1 0x11f
|
||||
#define R2057_RXMIX5G_PUS_CORE1 0x120
|
||||
#define R2057_RXMIX5G_VCMREFS_CORE1 0x121
|
||||
#define R2057_RXMIX5G_LODC_QI_CORE1 0x122
|
||||
#define R2057_W15G_BW_LNA5G_PUS_CORE1 0x123
|
||||
#define R2057_LNA5G_GAIN_CORE1 0x124
|
||||
#define R2057_LNA5G_TUNE_CORE1 0x125
|
||||
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126
|
||||
#define R2057_RXBB_BIAS_MASTER_CORE1 0x127
|
||||
#define R2057_RXBB_VGABUF_IDACS_CORE1 0x128
|
||||
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
|
||||
#define R2057_TXBUF_VINCM_CORE1 0x12a
|
||||
#define R2057_TXBUF_IDACS_CORE1 0x12b
|
||||
#define R2057_LPF_RESP_RXBUF_BW_CORE1 0x12c
|
||||
#define R2057_RXBB_CC_CORE1 0x12d
|
||||
#define R2057_RXBB_SPARE3_CORE1 0x12e
|
||||
#define R2057_RXBB_RCCAL_HPC_CORE1 0x12f
|
||||
#define R2057_LPF_IDACS_CORE1 0x130
|
||||
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131
|
||||
#define R2057_TXBUF_GAIN_CORE1 0x132
|
||||
#define R2057_AFELOOPBACK_AACI_RESP_CORE1 0x133
|
||||
#define R2057_RXBUF_DEGEN_CORE1 0x134
|
||||
#define R2057_RXBB_SPARE2_CORE1 0x135
|
||||
#define R2057_RXBB_SPARE1_CORE1 0x136
|
||||
#define R2057_RSSI_MASTER_CORE1 0x137
|
||||
#define R2057_W2_MASTER_CORE1 0x138
|
||||
#define R2057_NB_MASTER_CORE1 0x139
|
||||
#define R2057_W2_IDACS0_Q_CORE1 0x13a
|
||||
#define R2057_W2_IDACS1_Q_CORE1 0x13b
|
||||
#define R2057_W2_IDACS0_I_CORE1 0x13c
|
||||
#define R2057_W2_IDACS1_I_CORE1 0x13d
|
||||
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e
|
||||
#define R2057_NB_IDACS_Q_CORE1 0x13f
|
||||
#define R2057_NB_IDACS_I_CORE1 0x140
|
||||
#define R2057_BACKUP4_CORE1 0x146
|
||||
#define R2057_BACKUP3_CORE1 0x147
|
||||
#define R2057_BACKUP2_CORE1 0x148
|
||||
#define R2057_BACKUP1_CORE1 0x149
|
||||
#define R2057_SPARE16_CORE1 0x14a
|
||||
#define R2057_SPARE15_CORE1 0x14b
|
||||
#define R2057_SPARE14_CORE1 0x14c
|
||||
#define R2057_SPARE13_CORE1 0x14d
|
||||
#define R2057_SPARE12_CORE1 0x14e
|
||||
#define R2057_SPARE11_CORE1 0x14f
|
||||
#define R2057_TX2G_BIAS_RESETS_CORE1 0x150
|
||||
#define R2057_TX5G_BIAS_RESETS_CORE1 0x151
|
||||
#define R2057_SPARE8_CORE1 0x152
|
||||
#define R2057_SPARE7_CORE1 0x153
|
||||
#define R2057_BUFS_MISC_LPFBW_CORE1 0x154
|
||||
#define R2057_TXLPF_RCCAL_CORE1 0x155
|
||||
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
|
||||
#define R2057_LPF_GAIN_CORE1 0x157
|
||||
#define R2057_DACBUF_IDACS_BW_CORE1 0x158
|
||||
#define R2057_DACBUF_VINCM_CORE1 0x159
|
||||
#define R2057_RCCAL_START_R1_Q1_P1 0x15a
|
||||
#define R2057_RCCAL_X1 0x15b
|
||||
#define R2057_RCCAL_TRC0 0x15c
|
||||
#define R2057_RCCAL_TRC1 0x15d
|
||||
#define R2057_RCCAL_DONE_OSCCAP 0x15e
|
||||
#define R2057_RCCAL_N0_0 0x15f
|
||||
#define R2057_RCCAL_N0_1 0x160
|
||||
#define R2057_RCCAL_N1_0 0x161
|
||||
#define R2057_RCCAL_N1_1 0x162
|
||||
#define R2057_RCAL_STATUS 0x163
|
||||
#define R2057_XTALPUOVR_PINCTRL 0x164
|
||||
#define R2057_OVR_REG0 0x165
|
||||
#define R2057_OVR_REG1 0x166
|
||||
#define R2057_OVR_REG2 0x167
|
||||
#define R2057_OVR_REG3 0x168
|
||||
#define R2057_OVR_REG4 0x169
|
||||
#define R2057_RCCAL_SCAP_VAL 0x16a
|
||||
#define R2057_RCCAL_BCAP_VAL 0x16b
|
||||
#define R2057_RCCAL_HPC_VAL 0x16c
|
||||
#define R2057_RCCAL_OVERRIDES 0x16d
|
||||
#define R2057_TX0_IQCAL_GAIN_BW 0x170
|
||||
#define R2057_TX0_LOFT_FINE_I 0x171
|
||||
#define R2057_TX0_LOFT_FINE_Q 0x172
|
||||
#define R2057_TX0_LOFT_COARSE_I 0x173
|
||||
#define R2057_TX0_LOFT_COARSE_Q 0x174
|
||||
#define R2057_TX0_TX_SSI_MASTER 0x175
|
||||
#define R2057_TX0_IQCAL_VCM_HG 0x176
|
||||
#define R2057_TX0_IQCAL_IDAC 0x177
|
||||
#define R2057_TX0_TSSI_VCM 0x178
|
||||
#define R2057_TX0_TX_SSI_MUX 0x179
|
||||
#define R2057_TX0_TSSIA 0x17a
|
||||
#define R2057_TX0_TSSIG 0x17b
|
||||
#define R2057_TX0_TSSI_MISC1 0x17c
|
||||
#define R2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d
|
||||
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
|
||||
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
|
||||
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
|
||||
#define R2057_TX1_IQCAL_GAIN_BW 0x190
|
||||
#define R2057_TX1_LOFT_FINE_I 0x191
|
||||
#define R2057_TX1_LOFT_FINE_Q 0x192
|
||||
#define R2057_TX1_LOFT_COARSE_I 0x193
|
||||
#define R2057_TX1_LOFT_COARSE_Q 0x194
|
||||
#define R2057_TX1_TX_SSI_MASTER 0x195
|
||||
#define R2057_TX1_IQCAL_VCM_HG 0x196
|
||||
#define R2057_TX1_IQCAL_IDAC 0x197
|
||||
#define R2057_TX1_TSSI_VCM 0x198
|
||||
#define R2057_TX1_TX_SSI_MUX 0x199
|
||||
#define R2057_TX1_TSSIA 0x19a
|
||||
#define R2057_TX1_TSSIG 0x19b
|
||||
#define R2057_TX1_TSSI_MISC1 0x19c
|
||||
#define R2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d
|
||||
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
|
||||
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
|
||||
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
|
||||
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
|
||||
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
|
||||
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
|
||||
#define R2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4
|
||||
#define R2057_AFE_STATUS_VCM_I_CORE0 0x1a5
|
||||
#define R2057_AFE_STATUS_VCM_Q_CORE0 0x1a6
|
||||
#define R2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7
|
||||
#define R2057_AFE_SET_VCM_I_CORE1 0x1a8
|
||||
#define R2057_AFE_SET_VCM_Q_CORE1 0x1a9
|
||||
#define R2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa
|
||||
#define R2057_AFE_STATUS_VCM_I_CORE1 0x1ab
|
||||
#define R2057_AFE_STATUS_VCM_Q_CORE1 0x1ac
|
||||
|
||||
#define R2057v7_DACBUF_VINCM_CORE0 0x1ad
|
||||
#define R2057v7_RCCAL_MASTER 0x1ae
|
||||
#define R2057v7_TR2G_CONFIG3_CORE0_NU 0x1af
|
||||
#define R2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0
|
||||
#define R2057v7_LOGEN_PUS1 0x1b1
|
||||
#define R2057v7_OVR_REG5 0x1b2
|
||||
#define R2057v7_OVR_REG6 0x1b3
|
||||
#define R2057v7_OVR_REG7 0x1b4
|
||||
#define R2057v7_OVR_REG8 0x1b5
|
||||
#define R2057v7_OVR_REG9 0x1b6
|
||||
#define R2057v7_OVR_REG10 0x1b7
|
||||
#define R2057v7_OVR_REG11 0x1b8
|
||||
#define R2057v7_OVR_REG12 0x1b9
|
||||
#define R2057v7_OVR_REG13 0x1ba
|
||||
#define R2057v7_OVR_REG14 0x1bb
|
||||
#define R2057v7_OVR_REG15 0x1bc
|
||||
#define R2057v7_OVR_REG16 0x1bd
|
||||
#define R2057v7_OVR_REG1 0x1be
|
||||
#define R2057v7_OVR_REG18 0x1bf
|
||||
#define R2057v7_OVR_REG19 0x1c0
|
||||
#define R2057v7_OVR_REG20 0x1c1
|
||||
#define R2057v7_OVR_REG21 0x1c2
|
||||
#define R2057v7_OVR_REG2 0x1c3
|
||||
#define R2057v7_OVR_REG23 0x1c4
|
||||
#define R2057v7_OVR_REG24 0x1c5
|
||||
#define R2057v7_OVR_REG25 0x1c6
|
||||
#define R2057v7_OVR_REG26 0x1c7
|
||||
#define R2057v7_OVR_REG27 0x1c8
|
||||
#define R2057v7_OVR_REG28 0x1c9
|
||||
#define R2057v7_IQTEST_SEL_PU2 0x1ca
|
||||
|
||||
#define R2057_VCM_MASK 0x7
|
||||
|
||||
void r2057_upload_inittabs(struct b43_wldev *dev);
|
||||
|
||||
#endif /* B43_RADIO_2057_H_ */
|
@ -2757,6 +2757,49 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
|
||||
{ 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over0[] = {
|
||||
{ 0x0004, 0x07A, 0x07D, 0x0002, 1 },
|
||||
{ 0x0008, 0x07A, 0x07D, 0x0004, 2 },
|
||||
{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
|
||||
{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
|
||||
{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
|
||||
{ 0x0080, 0x0F8, 0x0FA, 0x0080, 7 },
|
||||
{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
|
||||
{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
|
||||
{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
|
||||
{ 0x6000, 0x348, 0x349, 0xFFFF, 0 },
|
||||
{ 0x2000, 0x348, 0x349, 0x000F, 0 },
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over1[] = {
|
||||
{ 0x0002, 0x340, 0x341, 0x0002, 1 },
|
||||
{ 0x0008, 0x340, 0x341, 0x0008, 3 },
|
||||
{ 0x0020, 0x340, 0x341, 0x0020, 5 },
|
||||
{ 0x0010, 0x340, 0x341, 0x0010, 4 },
|
||||
{ 0x0004, 0x340, 0x341, 0x0004, 2 },
|
||||
{ 0x0080, 0x340, 0x341, 0x0700, 8 },
|
||||
{ 0x0800, 0x340, 0x341, 0x4000, 14 },
|
||||
{ 0x0400, 0x340, 0x341, 0x2000, 13 },
|
||||
{ 0x0200, 0x340, 0x341, 0x0800, 12 },
|
||||
{ 0x0100, 0x340, 0x341, 0x0100, 11 },
|
||||
{ 0x0040, 0x340, 0x341, 0x0040, 6 },
|
||||
{ 0x0001, 0x340, 0x341, 0x0001, 0 },
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over2[] = {
|
||||
{ 0x0008, 0x344, 0x345, 0x0008, 3 },
|
||||
{ 0x0002, 0x344, 0x345, 0x0002, 1 },
|
||||
{ 0x0001, 0x344, 0x345, 0x0001, 0 },
|
||||
{ 0x0004, 0x344, 0x345, 0x0004, 2 },
|
||||
{ 0x0010, 0x344, 0x345, 0x0010, 4 },
|
||||
};
|
||||
|
||||
struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
|
||||
{ 10, 14, 19, 27 },
|
||||
{ -5, 6, 10, 15 },
|
||||
@ -3248,3 +3291,35 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
|
||||
struct b43_wldev *dev, u16 field, u8 override)
|
||||
{
|
||||
const struct nphy_rf_control_override_rev7 *e;
|
||||
u8 size, i;
|
||||
|
||||
switch (override) {
|
||||
case 0:
|
||||
e = tbl_rf_control_override_rev7_over0;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over0);
|
||||
break;
|
||||
case 1:
|
||||
e = tbl_rf_control_override_rev7_over1;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over1);
|
||||
break;
|
||||
case 2:
|
||||
e = tbl_rf_control_override_rev7_over2;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over2);
|
||||
break;
|
||||
default:
|
||||
b43err(dev->wl, "Invalid override value %d\n", override);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (e[i].field == field)
|
||||
return &e[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -35,6 +35,14 @@ struct nphy_rf_control_override_rev3 {
|
||||
u8 val_addr1;
|
||||
};
|
||||
|
||||
struct nphy_rf_control_override_rev7 {
|
||||
u16 field;
|
||||
u16 val_addr_core0;
|
||||
u16 val_addr_core1;
|
||||
u16 val_mask;
|
||||
u8 val_shift;
|
||||
};
|
||||
|
||||
struct nphy_gain_ctl_workaround_entry {
|
||||
s8 lna1_gain[4];
|
||||
s8 lna2_gain[4];
|
||||
@ -202,5 +210,7 @@ extern const struct nphy_rf_control_override_rev2
|
||||
tbl_rf_control_override_rev2[];
|
||||
extern const struct nphy_rf_control_override_rev3
|
||||
tbl_rf_control_override_rev3[];
|
||||
const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
|
||||
struct b43_wldev *dev, u16 field, u8 override);
|
||||
|
||||
#endif /* B43_TABLES_NPHY_H_ */
|
||||
|
@ -1920,7 +1920,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
|
||||
return 0;
|
||||
ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,
|
||||
(ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)
|
||||
& mask) | set);
|
||||
& ~mask) | set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,7 +86,9 @@ MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
|
||||
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* This needs to be adjusted when brcms_firmwares changes */
|
||||
MODULE_FIRMWARE("brcm/bcm43xx-0.fw");
|
||||
MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw");
|
||||
|
||||
/* recognized BCMA Core IDs */
|
||||
static struct bcma_device_id brcms_coreid_table[] = {
|
||||
|
@ -7512,15 +7512,10 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
|
||||
|
||||
channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
|
||||
|
||||
if (channel > 14) {
|
||||
rx_status->band = IEEE80211_BAND_5GHZ;
|
||||
rx_status->freq = ieee80211_ofdm_chan_to_freq(
|
||||
WF_CHAN_FACTOR_5_G/2, channel);
|
||||
|
||||
} else {
|
||||
rx_status->band = IEEE80211_BAND_2GHZ;
|
||||
rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
|
||||
}
|
||||
rx_status->band =
|
||||
channel > 14 ? IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
|
||||
rx_status->freq =
|
||||
ieee80211_channel_to_frequency(channel, rx_status->band);
|
||||
|
||||
rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh);
|
||||
|
||||
|
@ -67,11 +67,6 @@
|
||||
#define WL_CHANSPEC_BAND_2G 0x2000
|
||||
#define INVCHANSPEC 255
|
||||
|
||||
/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */
|
||||
#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */
|
||||
#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
|
||||
#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
|
||||
|
||||
#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
|
||||
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
|
||||
|
||||
|
@ -4860,7 +4860,7 @@ EXPORT_SYMBOL(il_add_beacon_time);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int
|
||||
static int
|
||||
il_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
@ -4877,9 +4877,8 @@ il_pci_suspend(struct device *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(il_pci_suspend);
|
||||
|
||||
int
|
||||
static int
|
||||
il_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
@ -4906,16 +4905,8 @@ il_pci_resume(struct device *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(il_pci_resume);
|
||||
|
||||
const struct dev_pm_ops il_pm_ops = {
|
||||
.suspend = il_pci_suspend,
|
||||
.resume = il_pci_resume,
|
||||
.freeze = il_pci_suspend,
|
||||
.thaw = il_pci_resume,
|
||||
.poweroff = il_pci_suspend,
|
||||
.restore = il_pci_resume,
|
||||
};
|
||||
SIMPLE_DEV_PM_OPS(il_pm_ops, il_pci_suspend, il_pci_resume);
|
||||
EXPORT_SYMBOL(il_pm_ops);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
@ -1845,8 +1845,6 @@ __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
|
||||
u32 beacon_interval);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int il_pci_suspend(struct device *device);
|
||||
int il_pci_resume(struct device *device);
|
||||
extern const struct dev_pm_ops il_pm_ops;
|
||||
|
||||
#define IL_LEGACY_PM_OPS (&il_pm_ops)
|
||||
|
@ -487,16 +487,13 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
|
||||
void iwl_dbgfs_unregister(struct iwl_priv *priv);
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir);
|
||||
#else
|
||||
static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
static inline int iwl_dbgfs_register(struct iwl_priv *priv,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
@ -2349,24 +2349,19 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
|
||||
* Create the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
|
||||
{
|
||||
struct dentry *phyd = priv->hw->wiphy->debugfsdir;
|
||||
struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
|
||||
struct dentry *dir_data, *dir_rf, *dir_debug;
|
||||
|
||||
dir_drv = debugfs_create_dir(name, phyd);
|
||||
if (!dir_drv)
|
||||
return -ENOMEM;
|
||||
priv->debugfs_dir = dbgfs_dir;
|
||||
|
||||
priv->debugfs_dir = dir_drv;
|
||||
|
||||
dir_data = debugfs_create_dir("data", dir_drv);
|
||||
dir_data = debugfs_create_dir("data", dbgfs_dir);
|
||||
if (!dir_data)
|
||||
goto err;
|
||||
dir_rf = debugfs_create_dir("rf", dir_drv);
|
||||
dir_rf = debugfs_create_dir("rf", dbgfs_dir);
|
||||
if (!dir_rf)
|
||||
goto err;
|
||||
dir_debug = debugfs_create_dir("debug", dir_drv);
|
||||
dir_debug = debugfs_create_dir("debug", dbgfs_dir);
|
||||
if (!dir_debug)
|
||||
goto err;
|
||||
|
||||
@ -2412,25 +2407,30 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
/* Calibrations disabled/enabled status*/
|
||||
DEBUGFS_ADD_FILE(calib_disabled, dir_rf, S_IWUSR | S_IRUSR);
|
||||
|
||||
if (iwl_trans_dbgfs_register(priv->trans, dir_debug))
|
||||
goto err;
|
||||
/*
|
||||
* Create a symlink with mac80211. This is not very robust, as it does
|
||||
* not remove the symlink created. The implicit assumption is that
|
||||
* when the opmode exits, mac80211 will also exit, and will remove
|
||||
* this symlink as part of its cleanup.
|
||||
*/
|
||||
if (priv->mac80211_registered) {
|
||||
char buf[100];
|
||||
struct dentry *mac80211_dir, *dev_dir, *root_dir;
|
||||
|
||||
dev_dir = dbgfs_dir->d_parent;
|
||||
root_dir = dev_dir->d_parent;
|
||||
mac80211_dir = priv->hw->wiphy->debugfsdir;
|
||||
|
||||
snprintf(buf, 100, "../../%s/%s", root_dir->d_name.name,
|
||||
dev_dir->d_name.name);
|
||||
|
||||
if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
IWL_ERR(priv, "Can't create the debugfs directory\n");
|
||||
iwl_dbgfs_unregister(priv);
|
||||
IWL_ERR(priv, "failed to create the dvm debugfs entries\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
if (!priv->debugfs_dir)
|
||||
return;
|
||||
|
||||
debugfs_remove_recursive(priv->debugfs_dir);
|
||||
priv->debugfs_dir = NULL;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
|
||||
}
|
||||
|
||||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||
hw->wiphy->max_remain_on_channel_duration = 500;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
|
@ -862,7 +862,8 @@ void iwl_down(struct iwl_priv *priv)
|
||||
* No race since we hold the mutex here and a new one
|
||||
* can't come in at this time.
|
||||
*/
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
|
||||
exit_pending =
|
||||
test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
@ -994,7 +995,11 @@ static void iwl_bg_restart(struct work_struct *data)
|
||||
iwlagn_prepare_restart(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
else
|
||||
IWL_ERR(priv,
|
||||
"Cannot request restart before registrating with mac80211");
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
@ -1222,7 +1227,8 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||
|
||||
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw)
|
||||
const struct iwl_fw *fw,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
struct iwl_priv *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
@ -1466,13 +1472,17 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
if (iwl_dbgfs_register(priv, DRV_NAME))
|
||||
IWL_ERR(priv,
|
||||
"failed to create debugfs files. Ignoring error\n");
|
||||
if (iwl_dbgfs_register(priv, dbgfs_dir))
|
||||
goto out_mac80211_unregister;
|
||||
|
||||
return op_mode;
|
||||
|
||||
out_mac80211_unregister:
|
||||
iwlagn_mac_unregister(priv);
|
||||
out_destroy_workqueue:
|
||||
iwl_tt_exit(priv);
|
||||
iwl_testmode_free(priv);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
iwl_uninit_drv(priv);
|
||||
@ -1493,8 +1503,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
|
||||
iwl_testmode_free(priv);
|
||||
iwlagn_mac_unregister(priv);
|
||||
|
||||
|
@ -150,7 +150,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
|
||||
|
||||
if (!(flags & CMD_ASYNC)) {
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
|
||||
might_sleep();
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
|
||||
* only. Check this here.
|
||||
*/
|
||||
if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
|
||||
tid_data->agg.state != IWL_AGG_OFF,
|
||||
tid_data->agg.state != IWL_AGG_OFF,
|
||||
"Tx while agg.state = %d", tid_data->agg.state))
|
||||
goto drop_unlock_sta;
|
||||
|
||||
|
@ -101,6 +101,10 @@ MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static struct dentry *iwl_dbgfs_root;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct iwl_drv - drv common data
|
||||
* @list: list of drv structures using this opmode
|
||||
@ -126,6 +130,12 @@ struct iwl_drv {
|
||||
char firmware_name[25]; /* name of firmware file to load */
|
||||
|
||||
struct completion request_firmware_complete;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct dentry *dbgfs_drv;
|
||||
struct dentry *dbgfs_trans;
|
||||
struct dentry *dbgfs_op_mode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DVM_OP_MODE 0
|
||||
@ -194,7 +204,8 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
|
||||
void *context);
|
||||
|
||||
#define UCODE_EXPERIMENTAL_INDEX 100
|
||||
#define UCODE_EXPERIMENTAL_TAG "exp"
|
||||
@ -231,7 +242,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
|
||||
return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
|
||||
drv->trans->dev,
|
||||
GFP_KERNEL, drv, iwl_ucode_callback);
|
||||
GFP_KERNEL, drv, iwl_req_fw_callback);
|
||||
}
|
||||
|
||||
struct fw_img_parsing {
|
||||
@ -759,13 +770,57 @@ static int validate_sec_sizes(struct iwl_drv *drv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *
|
||||
_iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
||||
{
|
||||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
struct dentry *dbgfs_dir = NULL;
|
||||
struct iwl_op_mode *op_mode = NULL;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
if (!drv->dbgfs_op_mode) {
|
||||
IWL_ERR(drv,
|
||||
"failed to create opmode debugfs directory\n");
|
||||
return op_mode;
|
||||
}
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->cfg, &drv->fw, dbgfs_dir);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (!op_mode) {
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return op_mode;
|
||||
}
|
||||
|
||||
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||
{
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
drv->op_mode = NULL;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_ucode_callback - callback when firmware was loaded
|
||||
* iwl_req_fw_callback - callback when firmware was loaded
|
||||
*
|
||||
* If loaded successfully, copies the firmware into buffers
|
||||
* for the card to fetch (via DMA).
|
||||
*/
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
{
|
||||
struct iwl_drv *drv = context;
|
||||
struct iwl_fw *fw = &drv->fw;
|
||||
@ -908,8 +963,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
||||
if (op->ops) {
|
||||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw);
|
||||
drv->op_mode = _iwl_op_mode_start(drv, op);
|
||||
|
||||
if (!drv->op_mode) {
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
@ -969,14 +1023,43 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
init_completion(&drv->request_firmware_complete);
|
||||
INIT_LIST_HEAD(&drv->list);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the device debugfs entries. */
|
||||
drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
|
||||
iwl_dbgfs_root);
|
||||
|
||||
if (!drv->dbgfs_drv) {
|
||||
IWL_ERR(drv, "failed to create debugfs directory\n");
|
||||
goto err_free_drv;
|
||||
}
|
||||
|
||||
/* Create transport layer debugfs dir */
|
||||
drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv);
|
||||
|
||||
if (!drv->trans->dbgfs_dir) {
|
||||
IWL_ERR(drv, "failed to create transport debugfs directory\n");
|
||||
goto err_free_dbgfs;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = iwl_request_firmware(drv, true);
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Couldn't request the fw\n");
|
||||
kfree(drv);
|
||||
drv = NULL;
|
||||
goto err_fw;
|
||||
}
|
||||
|
||||
return drv;
|
||||
|
||||
err_fw:
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
err_free_dbgfs:
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
err_free_drv:
|
||||
#endif
|
||||
kfree(drv);
|
||||
drv = NULL;
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
@ -984,9 +1067,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
||||
{
|
||||
wait_for_completion(&drv->request_firmware_complete);
|
||||
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode)
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
iwl_dealloc_ucode(drv);
|
||||
|
||||
@ -1000,6 +1081,10 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
||||
list_del(&drv->list);
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
#endif
|
||||
|
||||
kfree(drv);
|
||||
}
|
||||
|
||||
@ -1022,15 +1107,18 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
|
||||
{
|
||||
int i;
|
||||
struct iwl_drv *drv;
|
||||
struct iwlwifi_opmode_table *op;
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
|
||||
if (strcmp(iwlwifi_opmode_table[i].name, name))
|
||||
op = &iwlwifi_opmode_table[i];
|
||||
if (strcmp(op->name, name))
|
||||
continue;
|
||||
iwlwifi_opmode_table[i].ops = ops;
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
|
||||
drv->op_mode = ops->start(drv->trans, drv->cfg,
|
||||
&drv->fw);
|
||||
op->ops = ops;
|
||||
/* TODO: need to handle exceptional case */
|
||||
list_for_each_entry(drv, &op->drv, list)
|
||||
drv->op_mode = _iwl_op_mode_start(drv, op);
|
||||
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
return 0;
|
||||
}
|
||||
@ -1051,12 +1139,9 @@ void iwl_opmode_deregister(const char *name)
|
||||
iwlwifi_opmode_table[i].ops = NULL;
|
||||
|
||||
/* call the stop routine for all devices */
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) {
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
drv->op_mode = NULL;
|
||||
}
|
||||
}
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
return;
|
||||
}
|
||||
@ -1076,6 +1161,14 @@ static int __init iwl_drv_init(void)
|
||||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
pr_info(DRV_COPYRIGHT "\n");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the root of iwlwifi debugfs subsystem. */
|
||||
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
|
||||
|
||||
if (!iwl_dbgfs_root)
|
||||
return -EFAULT;
|
||||
#endif
|
||||
|
||||
return iwl_pci_register_driver();
|
||||
}
|
||||
module_init(iwl_drv_init);
|
||||
@ -1083,6 +1176,10 @@ module_init(iwl_drv_init);
|
||||
static void __exit iwl_drv_exit(void)
|
||||
{
|
||||
iwl_pci_unregister_driver();
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(iwl_dbgfs_root);
|
||||
#endif
|
||||
}
|
||||
module_exit(iwl_drv_exit);
|
||||
|
||||
|
@ -90,9 +90,9 @@
|
||||
* 4) The bus specific component configures the bus
|
||||
* 5) The bus specific component calls to the drv bus agnostic part
|
||||
* (iwl_drv_start)
|
||||
* 6) iwl_drv_start fetches the fw ASYNC, iwl_ucode_callback
|
||||
* 7) iwl_ucode_callback parses the fw file
|
||||
* 8) iwl_ucode_callback starts the wifi implementation to matches the fw
|
||||
* 6) iwl_drv_start fetches the fw ASYNC, iwl_req_fw_callback
|
||||
* 7) iwl_req_fw_callback parses the fw file
|
||||
* 8) iwl_req_fw_callback starts the wifi implementation to matches the fw
|
||||
*/
|
||||
|
||||
struct iwl_drv;
|
||||
|
@ -134,7 +134,8 @@ struct iwl_cfg;
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw);
|
||||
const struct iwl_fw *fw,
|
||||
struct dentry *dbgfs_dir);
|
||||
void (*stop)(struct iwl_op_mode *op_mode);
|
||||
int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
@ -184,14 +184,20 @@ struct iwl_rx_packet {
|
||||
* @CMD_SYNC: The caller will be stalled until the fw responds to the command
|
||||
* @CMD_ASYNC: Return right away and don't want for the response
|
||||
* @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
|
||||
* response.
|
||||
* response. The caller needs to call iwl_free_resp when done.
|
||||
* @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
|
||||
* response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
|
||||
* copied. The pointer passed to the response handler is in the transport
|
||||
* ownership and don't need to be freed by the op_mode. This also means
|
||||
* that the pointer is invalidated after the op_mode's handler returns.
|
||||
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_ON_DEMAND = BIT(2),
|
||||
CMD_WANT_HCMD = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
};
|
||||
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
@ -460,6 +466,8 @@ struct iwl_trans {
|
||||
size_t dev_cmd_headroom;
|
||||
char dev_cmd_pool_name[50];
|
||||
|
||||
struct dentry *dbgfs_dir;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
char trans_specific[0] __aligned(sizeof(void *));
|
||||
|
@ -282,8 +282,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!trans_pcie->drv)
|
||||
goto out_free_trans;
|
||||
|
||||
/* register transport layer debugfs here */
|
||||
if (iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir))
|
||||
goto out_free_drv;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_drv:
|
||||
iwl_drv_stop(trans_pcie->drv);
|
||||
out_free_trans:
|
||||
iwl_trans_pcie_free(iwl_trans);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
@ -184,6 +184,7 @@ struct iwl_queue {
|
||||
|
||||
struct iwl_pcie_tx_queue_entry {
|
||||
struct iwl_device_cmd *cmd;
|
||||
struct iwl_device_cmd *copy_cmd;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_cmd_meta meta;
|
||||
};
|
||||
|
@ -421,13 +421,23 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim)
|
||||
cmd = txq->entries[cmd_index].cmd;
|
||||
else
|
||||
if (reclaim) {
|
||||
struct iwl_pcie_tx_queue_entry *ent;
|
||||
ent = &txq->entries[cmd_index];
|
||||
cmd = ent->copy_cmd;
|
||||
WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
|
||||
} else {
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
|
||||
|
||||
if (reclaim) {
|
||||
/* The original command isn't needed any more */
|
||||
kfree(txq->entries[cmd_index].copy_cmd);
|
||||
txq->entries[cmd_index].copy_cmd = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* After here, we should always check rxcb._page_stolen,
|
||||
* if it is true then one of the handlers took the page.
|
||||
|
@ -492,10 +492,11 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
|
||||
iwl_tx_queue_unmap(trans, txq_id);
|
||||
|
||||
/* De-alloc array of command/tx buffers */
|
||||
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < txq->q.n_window; i++)
|
||||
for (i = 0; i < txq->q.n_window; i++) {
|
||||
kfree(txq->entries[i].cmd);
|
||||
kfree(txq->entries[i].copy_cmd);
|
||||
}
|
||||
|
||||
/* De-alloc circular buffer of TFDs */
|
||||
if (txq->q.n_bd) {
|
||||
@ -896,6 +897,7 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
|
||||
static int iwl_prepare_card_hw(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
int t = 0;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
|
||||
|
||||
@ -908,17 +910,15 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PREPARE);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
|
||||
do {
|
||||
ret = iwl_set_hw_ready(trans);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
usleep_range(200, 1000);
|
||||
t += 200;
|
||||
} while (t < 150000);
|
||||
|
||||
/* HW should be ready by now, check again. */
|
||||
ret = iwl_set_hw_ready(trans);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1769,7 +1769,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
if (!debugfs_create_file(#name, mode, parent, trans, \
|
||||
&iwl_dbgfs_##name##_ops)) \
|
||||
return -ENOMEM; \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
/* file operation */
|
||||
@ -2033,6 +2033,10 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||
DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#else
|
||||
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||
|
@ -521,7 +521,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
u16 copy_size, cmd_size;
|
||||
bool had_nocopy = false;
|
||||
int i;
|
||||
u8 *cmd_dest;
|
||||
u32 cmd_pos;
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
|
||||
const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
|
||||
int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
|
||||
@ -584,15 +584,31 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
INDEX_TO_SEQ(q->write_ptr));
|
||||
|
||||
/* and copy the data that needs to be copied */
|
||||
|
||||
cmd_dest = out_cmd->payload;
|
||||
cmd_pos = offsetof(struct iwl_device_cmd, payload);
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
if (!cmd->len[i])
|
||||
continue;
|
||||
if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
|
||||
break;
|
||||
memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
|
||||
cmd_dest += cmd->len[i];
|
||||
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
|
||||
cmd_pos += cmd->len[i];
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(txq->entries[idx].copy_cmd);
|
||||
|
||||
/*
|
||||
* since out_cmd will be the source address of the FH, it will write
|
||||
* the retry count there. So when the user needs to receivce the HCMD
|
||||
* that corresponds to the response in the response handler, it needs
|
||||
* to set CMD_WANT_HCMD.
|
||||
*/
|
||||
if (cmd->flags & CMD_WANT_HCMD) {
|
||||
txq->entries[idx].copy_cmd =
|
||||
kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
|
||||
if (unlikely(!txq->entries[idx].copy_cmd)) {
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_HC(trans,
|
||||
|
@ -726,3 +726,29 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function retrieves the entry for specific tx BA stream table by RA and
|
||||
* deletes it.
|
||||
*/
|
||||
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
|
||||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ra)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
|
||||
flags);
|
||||
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
|
||||
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
|
||||
int cmd_action,
|
||||
struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
|
||||
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
|
||||
|
||||
/*
|
||||
* This function checks whether AMPDU is allowed or not for a particular TID.
|
||||
@ -157,4 +158,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks whether associated station is 11n enabled
|
||||
*/
|
||||
static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
|
||||
struct mwifiex_sta_node *node)
|
||||
{
|
||||
|
||||
if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
|
||||
!priv->ap_11n_enabled)
|
||||
return 0;
|
||||
|
||||
return node->is_11n_enabled;
|
||||
}
|
||||
#endif /* !_MWIFIEX_11N_H_ */
|
||||
|
@ -62,9 +62,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
|
||||
};
|
||||
struct tx_packet_hdr *tx_header;
|
||||
|
||||
skb_put(skb_aggr, sizeof(*tx_header));
|
||||
|
||||
tx_header = (struct tx_packet_hdr *) skb_aggr->data;
|
||||
tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
|
||||
|
||||
/* Copy DA and SA */
|
||||
dt_offset = 2 * ETH_ALEN;
|
||||
@ -82,12 +80,10 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
|
||||
tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
|
||||
|
||||
/* Add payload */
|
||||
skb_put(skb_aggr, skb_src->len);
|
||||
memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data,
|
||||
skb_src->len);
|
||||
*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
|
||||
LLC_SNAP_LEN)) & 3)) : 0;
|
||||
skb_put(skb_aggr, *pad);
|
||||
memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
|
||||
|
||||
/* Add padding for new MSDU to start from 4 byte boundary */
|
||||
*pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
|
||||
|
||||
return skb_aggr->len + *pad;
|
||||
}
|
||||
|
@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
|
||||
if (rx_tmp_ptr)
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
if (rx_tmp_ptr) {
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
rx_tmp_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
||||
@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
||||
rx_tmp_ptr = tbl->rx_reorder_ptr[i];
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
||||
@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
|
||||
* This function returns the pointer to an entry in Rx reordering
|
||||
* table which matches the given TA/TID pair.
|
||||
*/
|
||||
static struct mwifiex_rx_reorder_tbl *
|
||||
struct mwifiex_rx_reorder_tbl *
|
||||
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl;
|
||||
@ -167,6 +176,31 @@ mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function retrieves the pointer to an entry in Rx reordering
|
||||
* table which matches the given TA and deletes it.
|
||||
*/
|
||||
void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ta)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
mwifiex_del_rx_reorder_entry(priv, tbl);
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds the last sequence number used in the packets
|
||||
* buffered in Rx reordering table.
|
||||
@ -226,6 +260,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *new_node;
|
||||
u16 last_seq = 0;
|
||||
unsigned long flags;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
/*
|
||||
* If we get a TID, ta pair which is already present dispatch all the
|
||||
@ -248,13 +283,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
||||
new_node->tid = tid;
|
||||
memcpy(new_node->ta, ta, ETH_ALEN);
|
||||
new_node->start_win = seq_num;
|
||||
if (mwifiex_queuing_ra_based(priv))
|
||||
/* TODO for adhoc */
|
||||
|
||||
if (mwifiex_queuing_ra_based(priv)) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: ADHOC:last_seq=%d start_win=%d\n",
|
||||
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
|
||||
last_seq, new_node->start_win);
|
||||
else
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
last_seq = node->rx_seq[tid];
|
||||
}
|
||||
} else {
|
||||
last_seq = priv->rx_seq[tid];
|
||||
}
|
||||
|
||||
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
|
||||
last_seq >= new_node->start_win)
|
||||
@ -396,8 +437,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
|
||||
|
||||
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
|
||||
if (!tbl) {
|
||||
if (pkt_type != PKT_TYPE_BAR)
|
||||
mwifiex_process_rx_packet(priv->adapter, payload);
|
||||
if (pkt_type != PKT_TYPE_BAR) {
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, payload);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
payload);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
start_win = tbl->start_win;
|
||||
|
@ -38,6 +38,8 @@
|
||||
#define ADDBA_RSP_STATUS_ACCEPT 0
|
||||
|
||||
#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
|
||||
#define BA_SETUP_MAX_PACKET_THRESHOLD 16
|
||||
#define BA_SETUP_PACKET_OFFSET 16
|
||||
|
||||
static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
|
||||
{
|
||||
@ -68,5 +70,8 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
|
||||
mwifiex_private
|
||||
*priv, int tid,
|
||||
u8 *ta);
|
||||
struct mwifiex_rx_reorder_tbl *
|
||||
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
|
||||
void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
|
||||
|
||||
#endif /* _MWIFIEX_11N_RXREORDER_H_ */
|
||||
|
@ -33,8 +33,10 @@ mwifiex-y += uap_cmd.o
|
||||
mwifiex-y += ie.o
|
||||
mwifiex-y += sta_cmdresp.o
|
||||
mwifiex-y += sta_event.o
|
||||
mwifiex-y += uap_event.o
|
||||
mwifiex-y += sta_tx.o
|
||||
mwifiex-y += sta_rx.o
|
||||
mwifiex-y += uap_txrx.o
|
||||
mwifiex-y += cfg80211.o
|
||||
mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
obj-$(CONFIG_MWIFIEX) += mwifiex.o
|
||||
|
@ -99,7 +99,7 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
|
||||
|
||||
if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) {
|
||||
if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
|
||||
wiphy_err(wiphy, "deleting the crypto keys\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -171,7 +171,8 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
|
||||
priv->wep_key_curr_index = key_index;
|
||||
} else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
|
||||
} else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
|
||||
NULL, 0)) {
|
||||
wiphy_err(wiphy, "set default Tx key index\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -207,7 +208,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mwifiex_set_encode(priv, params->key, params->key_len,
|
||||
if (mwifiex_set_encode(priv, params, params->key, params->key_len,
|
||||
key_index, peer_mac, 0)) {
|
||||
wiphy_err(wiphy, "crypto keys added\n");
|
||||
return -EFAULT;
|
||||
@ -748,6 +749,7 @@ static const u32 mwifiex_cipher_suites[] = {
|
||||
WLAN_CIPHER_SUITE_WEP104,
|
||||
WLAN_CIPHER_SUITE_TKIP,
|
||||
WLAN_CIPHER_SUITE_CCMP,
|
||||
WLAN_CIPHER_SUITE_AES_CMAC,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -906,6 +908,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
if (mwifiex_del_mgmt_ies(priv))
|
||||
wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
|
||||
|
||||
priv->ap_11n_enabled = 0;
|
||||
|
||||
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL)) {
|
||||
wiphy_err(wiphy, "Failed to stop the BSS\n");
|
||||
@ -1159,7 +1163,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
priv->wep_key_curr_index = 0;
|
||||
priv->sec_info.encryption_mode = 0;
|
||||
priv->sec_info.is_authtype_auto = 0;
|
||||
ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1);
|
||||
ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
|
||||
|
||||
if (mode == NL80211_IFTYPE_ADHOC) {
|
||||
/* "privacy" is set only for ad-hoc mode */
|
||||
@ -1206,8 +1210,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
"info: setting wep encryption"
|
||||
" with key len %d\n", sme->key_len);
|
||||
priv->wep_key_curr_index = sme->key_idx;
|
||||
ret = mwifiex_set_encode(priv, sme->key, sme->key_len,
|
||||
sme->key_idx, NULL, 0);
|
||||
ret = mwifiex_set_encode(priv, NULL, sme->key,
|
||||
sme->key_len, sme->key_idx,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
@ -447,7 +447,10 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
}
|
||||
|
||||
ret = mwifiex_process_sta_event(priv);
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
ret = mwifiex_process_uap_event(priv);
|
||||
else
|
||||
ret = mwifiex_process_sta_event(priv);
|
||||
|
||||
adapter->event_cause = 0;
|
||||
adapter->event_skb = NULL;
|
||||
|
@ -60,6 +60,9 @@
|
||||
#define MWIFIEX_SDIO_BLOCK_SIZE 256
|
||||
|
||||
#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0)
|
||||
#define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1)
|
||||
|
||||
#define MWIFIEX_BRIDGED_PKTS_THRESHOLD 1024
|
||||
|
||||
enum mwifiex_bss_type {
|
||||
MWIFIEX_BSS_TYPE_STA = 0,
|
||||
|
@ -65,10 +65,12 @@ enum KEY_TYPE_ID {
|
||||
KEY_TYPE_ID_TKIP,
|
||||
KEY_TYPE_ID_AES,
|
||||
KEY_TYPE_ID_WAPI,
|
||||
KEY_TYPE_ID_AES_CMAC,
|
||||
};
|
||||
#define KEY_MCAST BIT(0)
|
||||
#define KEY_UNICAST BIT(1)
|
||||
#define KEY_ENABLED BIT(2)
|
||||
#define KEY_IGTK BIT(10)
|
||||
|
||||
#define WAPI_KEY_LEN 50
|
||||
|
||||
@ -424,10 +426,10 @@ struct txpd {
|
||||
struct rxpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
u16 rx_pkt_length;
|
||||
u16 rx_pkt_offset;
|
||||
u16 rx_pkt_type;
|
||||
u16 seq_num;
|
||||
__le16 rx_pkt_length;
|
||||
__le16 rx_pkt_offset;
|
||||
__le16 rx_pkt_type;
|
||||
__le16 seq_num;
|
||||
u8 priority;
|
||||
u8 rx_rate;
|
||||
s8 snr;
|
||||
@ -439,6 +441,31 @@ struct rxpd {
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct uap_txpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
__le16 tx_pkt_length;
|
||||
__le16 tx_pkt_offset;
|
||||
__le16 tx_pkt_type;
|
||||
__le32 tx_control;
|
||||
u8 priority;
|
||||
u8 flags;
|
||||
u8 pkt_delay_2ms;
|
||||
u8 reserved1;
|
||||
__le32 reserved2;
|
||||
};
|
||||
|
||||
struct uap_rxpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
__le16 rx_pkt_length;
|
||||
__le16 rx_pkt_offset;
|
||||
__le16 rx_pkt_type;
|
||||
__le16 seq_num;
|
||||
u8 priority;
|
||||
u8 reserved1;
|
||||
};
|
||||
|
||||
enum mwifiex_chan_scan_mode_bitmasks {
|
||||
MWIFIEX_PASSIVE_SCAN = BIT(0),
|
||||
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
|
||||
@ -558,6 +585,13 @@ struct mwifiex_ie_type_key_param_set {
|
||||
u8 key[50];
|
||||
} __packed;
|
||||
|
||||
#define IGTK_PN_LEN 8
|
||||
|
||||
struct mwifiex_cmac_param {
|
||||
u8 ipn[IGTK_PN_LEN];
|
||||
u8 key[WLAN_KEY_LEN_AES_CMAC];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_802_11_key_material {
|
||||
__le16 action;
|
||||
struct mwifiex_ie_type_key_param_set key_param_set;
|
||||
|
@ -64,60 +64,72 @@ static void scan_delay_timer_fn(unsigned long data)
|
||||
struct cmd_ctrl_node *cmd_node, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
if (!mwifiex_wmm_lists_empty(adapter)) {
|
||||
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
|
||||
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
|
||||
/*
|
||||
* Abort scan operation by cancelling all pending scan
|
||||
* commands
|
||||
*/
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
adapter->scan_delay_cnt = 0;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: scan aborted\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!atomic_read(&priv->adapter->is_tx_received)) {
|
||||
adapter->empty_tx_q_cnt++;
|
||||
if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
|
||||
/*
|
||||
* Abort scan operation by cancelling all pending scan
|
||||
* command
|
||||
* No Tx traffic for 200msec. Get scan command from
|
||||
* scan pending queue and put to cmd pending queue to
|
||||
* resume scan operation
|
||||
*/
|
||||
adapter->scan_delay_cnt = 0;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q,
|
||||
list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock,
|
||||
flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: scan aborted\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Tx data queue is still not empty, delay scan
|
||||
* operation further by 20msec.
|
||||
*/
|
||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||
adapter->scan_delay_cnt++;
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
|
||||
true);
|
||||
goto done;
|
||||
}
|
||||
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
|
||||
} else {
|
||||
/*
|
||||
* Tx data queue is empty. Get scan command from scan_pending_q
|
||||
* and put to cmd_pending_q to resume scan operation
|
||||
*/
|
||||
adapter->scan_delay_cnt = 0;
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
}
|
||||
|
||||
/* Delay scan operation further by 20msec */
|
||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||
adapter->scan_delay_cnt++;
|
||||
|
||||
done:
|
||||
if (atomic_read(&priv->adapter->is_tx_received))
|
||||
atomic_set(&priv->adapter->is_tx_received, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -196,6 +208,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
|
||||
priv->curr_bcn_size = 0;
|
||||
priv->wps_ie = NULL;
|
||||
priv->wps_ie_len = 0;
|
||||
priv->ap_11n_enabled = 0;
|
||||
|
||||
priv->scan_block = false;
|
||||
|
||||
@ -345,6 +358,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
|
||||
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
|
||||
adapter->arp_filter_size = 0;
|
||||
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -410,6 +424,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
|
||||
list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
|
||||
list_del(&priv->tx_ba_stream_tbl_ptr);
|
||||
list_del(&priv->rx_reorder_tbl_ptr);
|
||||
list_del(&priv->sta_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -472,6 +487,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
|
||||
spin_lock_init(&priv->rx_pkt_lock);
|
||||
spin_lock_init(&priv->wmm.ra_list_spinlock);
|
||||
spin_lock_init(&priv->curr_bcn_buf_lock);
|
||||
spin_lock_init(&priv->sta_list_spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,6 +520,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
|
||||
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
|
||||
INIT_LIST_HEAD(&priv->sta_list);
|
||||
|
||||
spin_lock_init(&priv->tx_ba_stream_tbl_lock);
|
||||
spin_lock_init(&priv->rx_reorder_tbl_lock);
|
||||
|
@ -213,7 +213,7 @@ struct mwifiex_debug_info {
|
||||
};
|
||||
|
||||
#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000
|
||||
#define WAPI_RXPN_LEN 16
|
||||
#define PN_LEN 16
|
||||
|
||||
struct mwifiex_ds_encrypt_key {
|
||||
u32 key_disable;
|
||||
@ -222,7 +222,8 @@ struct mwifiex_ds_encrypt_key {
|
||||
u8 key_material[WLAN_MAX_KEY_LEN];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u32 is_wapi_key;
|
||||
u8 wapi_rxpn[WAPI_RXPN_LEN];
|
||||
u8 pn[PN_LEN]; /* packet number */
|
||||
u8 is_igtk_key;
|
||||
};
|
||||
|
||||
struct mwifiex_power_cfg {
|
||||
|
@ -520,6 +520,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
mwifiex_wmm_add_buf_txqueue(priv, skb);
|
||||
atomic_inc(&priv->adapter->tx_pending);
|
||||
|
||||
if (priv->adapter->scan_delay_cnt)
|
||||
atomic_set(&priv->adapter->is_tx_received, true);
|
||||
|
||||
if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
|
||||
mwifiex_set_trans_start(dev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
|
||||
|
@ -88,6 +88,7 @@ enum {
|
||||
#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
|
||||
|
||||
#define MWIFIEX_MAX_SCAN_DELAY_CNT 50
|
||||
#define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10
|
||||
#define MWIFIEX_SCAN_DELAY_MSEC 20
|
||||
|
||||
#define RSN_GTK_OUI_OFFSET 2
|
||||
@ -199,6 +200,9 @@ struct mwifiex_ra_list_tbl {
|
||||
u8 ra[ETH_ALEN];
|
||||
u32 total_pkts_size;
|
||||
u32 is_11n_enabled;
|
||||
u16 max_amsdu;
|
||||
u16 pkt_count;
|
||||
u8 ba_packet_thr;
|
||||
};
|
||||
|
||||
struct mwifiex_tid_tbl {
|
||||
@ -431,6 +435,9 @@ struct mwifiex_private {
|
||||
u8 wmm_enabled;
|
||||
u8 wmm_qosinfo;
|
||||
struct mwifiex_wmm_desc wmm;
|
||||
struct list_head sta_list;
|
||||
/* spin lock for associated station list */
|
||||
spinlock_t sta_list_spinlock;
|
||||
struct list_head tx_ba_stream_tbl_ptr;
|
||||
/* spin lock for tx_ba_stream_tbl_ptr queue */
|
||||
spinlock_t tx_ba_stream_tbl_lock;
|
||||
@ -486,6 +493,7 @@ struct mwifiex_private {
|
||||
u16 assocresp_idx;
|
||||
u16 rsn_idx;
|
||||
struct timer_list scan_delay_timer;
|
||||
u8 ap_11n_enabled;
|
||||
};
|
||||
|
||||
enum mwifiex_ba_status {
|
||||
@ -550,6 +558,19 @@ struct mwifiex_bss_priv {
|
||||
u64 fw_tsf;
|
||||
};
|
||||
|
||||
/* This is AP specific structure which stores information
|
||||
* about associated STA
|
||||
*/
|
||||
struct mwifiex_sta_node {
|
||||
struct list_head list;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 is_wmm_enabled;
|
||||
u8 is_11n_enabled;
|
||||
u8 ampdu_sta[MAX_NUM_TID];
|
||||
u16 rx_seq[MAX_NUM_TID];
|
||||
u16 max_amsdu;
|
||||
};
|
||||
|
||||
struct mwifiex_if_ops {
|
||||
int (*init_if) (struct mwifiex_adapter *);
|
||||
void (*cleanup_if) (struct mwifiex_adapter *);
|
||||
@ -690,6 +711,9 @@ struct mwifiex_adapter {
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
u16 max_mgmt_ie_index;
|
||||
u8 scan_delay_cnt;
|
||||
u8 empty_tx_q_cnt;
|
||||
atomic_t is_tx_received;
|
||||
atomic_t pending_bridged_pkts;
|
||||
};
|
||||
|
||||
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
|
||||
@ -780,7 +804,15 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
|
||||
struct host_cmd_ds_command *resp);
|
||||
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_process_sta_event(struct mwifiex_private *);
|
||||
int mwifiex_process_uap_event(struct mwifiex_private *);
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
|
||||
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
|
||||
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
|
||||
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
|
||||
@ -949,9 +981,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
||||
const struct mwifiex_user_scan_cfg *user_scan_in);
|
||||
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
|
||||
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index, const u8 *mac_addr,
|
||||
int disable);
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
||||
const u8 *key, int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable);
|
||||
|
||||
int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
|
||||
|
||||
|
@ -989,6 +989,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
||||
*max_chan_per_scan = 2;
|
||||
else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD)
|
||||
*max_chan_per_scan = 3;
|
||||
else
|
||||
*max_chan_per_scan = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1433,9 +1435,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
|
||||
if (ret)
|
||||
dev_err(priv->adapter->dev, "cannot find ssid "
|
||||
"%s\n", bss_desc->ssid.ssid);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +610,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
memcpy(&key_material->key_param_set.key[2],
|
||||
enc_key->key_material, enc_key->key_len);
|
||||
memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
|
||||
enc_key->wapi_rxpn, WAPI_RXPN_LEN);
|
||||
enc_key->pn, PN_LEN);
|
||||
key_material->key_param_set.length =
|
||||
cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN);
|
||||
|
||||
@ -621,23 +621,38 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
return ret;
|
||||
}
|
||||
if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
if (enc_key->is_igtk_key) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: CMAC_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(KEY_ENABLED);
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(!KEY_ENABLED);
|
||||
|
||||
if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_IGTK);
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(KEY_ENABLED);
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(!KEY_ENABLED);
|
||||
|
||||
if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
|
||||
/* AES pairwise key: unicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_UNICAST);
|
||||
else /* AES group key: multicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
else /* AES group key: multicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_MCAST);
|
||||
}
|
||||
} else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
@ -668,6 +683,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
|
||||
+ sizeof(struct mwifiex_ie_types_header);
|
||||
|
||||
if (le16_to_cpu(key_material->key_param_set.key_type_id) ==
|
||||
KEY_TYPE_ID_AES_CMAC) {
|
||||
struct mwifiex_cmac_param *param =
|
||||
(void *)key_material->key_param_set.key;
|
||||
|
||||
memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN);
|
||||
memcpy(param->key, enc_key->key_material,
|
||||
WLAN_KEY_LEN_AES_CMAC);
|
||||
|
||||
key_param_len = sizeof(struct mwifiex_cmac_param);
|
||||
key_material->key_param_set.key_len =
|
||||
cpu_to_le16(key_param_len);
|
||||
key_param_len += KEYPARAMSET_FIXED_LEN;
|
||||
key_material->key_param_set.length =
|
||||
cpu_to_le16(key_param_len);
|
||||
key_param_len += sizeof(struct mwifiex_ie_types_header);
|
||||
}
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
|
||||
+ key_param_len);
|
||||
|
||||
|
@ -184,10 +184,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
|
||||
int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int len, ret = 0;
|
||||
int ret = 0;
|
||||
u32 eventcause = adapter->event_cause;
|
||||
struct station_info sinfo;
|
||||
struct mwifiex_assoc_event *event;
|
||||
u16 ctrl;
|
||||
|
||||
switch (eventcause) {
|
||||
case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
|
||||
@ -279,10 +278,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
|
||||
case EVENT_MIC_ERR_UNICAST:
|
||||
dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n");
|
||||
cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
|
||||
NL80211_KEYTYPE_PAIRWISE,
|
||||
-1, NULL, GFP_KERNEL);
|
||||
break;
|
||||
|
||||
case EVENT_MIC_ERR_MULTICAST:
|
||||
dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n");
|
||||
cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
|
||||
NL80211_KEYTYPE_GROUP,
|
||||
-1, NULL, GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_MIB_CHANGED:
|
||||
case EVENT_INIT_DONE:
|
||||
@ -384,11 +389,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
adapter->event_body);
|
||||
break;
|
||||
case EVENT_AMSDU_AGGR_CTRL:
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n",
|
||||
*(u16 *) adapter->event_body);
|
||||
ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
|
||||
|
||||
adapter->tx_buf_size =
|
||||
min(adapter->curr_tx_buf_size,
|
||||
le16_to_cpu(*(__le16 *) adapter->event_body));
|
||||
min_t(u16, adapter->curr_tx_buf_size, ctrl);
|
||||
dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
|
||||
adapter->tx_buf_size);
|
||||
break;
|
||||
@ -405,51 +410,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
|
||||
break;
|
||||
|
||||
case EVENT_UAP_STA_ASSOC:
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
event = (struct mwifiex_assoc_event *)
|
||||
(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
|
||||
len = -1;
|
||||
|
||||
if (ieee80211_is_assoc_req(event->frame_control))
|
||||
len = 0;
|
||||
else if (ieee80211_is_reassoc_req(event->frame_control))
|
||||
/* There will be ETH_ALEN bytes of
|
||||
* current_ap_addr before the re-assoc ies.
|
||||
*/
|
||||
len = ETH_ALEN;
|
||||
|
||||
if (len != -1) {
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.assoc_req_ies = &event->data[len];
|
||||
len = (u8 *)sinfo.assoc_req_ies -
|
||||
(u8 *)&event->frame_control;
|
||||
sinfo.assoc_req_ies_len =
|
||||
le16_to_cpu(event->len) - (u16)len;
|
||||
}
|
||||
}
|
||||
cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_UAP_STA_DEAUTH:
|
||||
cfg80211_del_sta(priv->netdev, adapter->event_body +
|
||||
MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_UAP_BSS_IDLE:
|
||||
priv->media_connected = false;
|
||||
break;
|
||||
case EVENT_UAP_BSS_ACTIVE:
|
||||
priv->media_connected = true;
|
||||
break;
|
||||
case EVENT_UAP_BSS_START:
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN);
|
||||
break;
|
||||
case EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
/* For future development */
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
|
||||
eventcause);
|
||||
|
@ -942,20 +942,26 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
|
||||
* This function allocates the IOCTL request buffer, fills it
|
||||
* with requisite parameters and calls the IOCTL handler.
|
||||
*/
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable)
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
||||
const u8 *key, int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable)
|
||||
{
|
||||
struct mwifiex_ds_encrypt_key encrypt_key;
|
||||
|
||||
memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
|
||||
encrypt_key.key_len = key_len;
|
||||
|
||||
if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
||||
encrypt_key.is_igtk_key = true;
|
||||
|
||||
if (!disable) {
|
||||
encrypt_key.key_index = key_index;
|
||||
if (key_len)
|
||||
memcpy(encrypt_key.key_material, key, key_len);
|
||||
if (mac_addr)
|
||||
memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
|
||||
if (kp && kp->seq && kp->seq_len)
|
||||
memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
|
||||
} else {
|
||||
encrypt_key.key_disable = true;
|
||||
if (mac_addr)
|
||||
|
@ -54,8 +54,8 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
||||
|
||||
local_rx_pd = (struct rxpd *) (skb->data);
|
||||
|
||||
rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
|
||||
local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_hdr = (void *)local_rx_pd +
|
||||
le16_to_cpu(local_rx_pd->rx_pkt_offset);
|
||||
|
||||
if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
|
||||
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
|
||||
@ -125,7 +125,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u8 ta[ETH_ALEN];
|
||||
u16 rx_pkt_type;
|
||||
u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
|
||||
struct mwifiex_private *priv =
|
||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
||||
rx_info->bss_type);
|
||||
@ -134,16 +134,17 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
return -1;
|
||||
|
||||
local_rx_pd = (struct rxpd *) (skb->data);
|
||||
rx_pkt_type = local_rx_pd->rx_pkt_type;
|
||||
rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
|
||||
rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
|
||||
seq_num = le16_to_cpu(local_rx_pd->seq_num);
|
||||
|
||||
rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
|
||||
local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
|
||||
|
||||
if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) >
|
||||
(u16) skb->len) {
|
||||
dev_err(adapter->dev, "wrong rx packet: len=%d,"
|
||||
" rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len,
|
||||
local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length);
|
||||
if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
|
||||
dev_err(adapter->dev,
|
||||
"wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
|
||||
skb->len, rx_pkt_offset, rx_pkt_length);
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
if (adapter->if_ops.data_complete)
|
||||
@ -154,14 +155,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
|
||||
if (rx_pkt_type == PKT_TYPE_AMSDU) {
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
|
||||
skb_pull(skb, local_rx_pd->rx_pkt_offset);
|
||||
skb_trim(skb, local_rx_pd->rx_pkt_length);
|
||||
skb_pull(skb, rx_pkt_offset);
|
||||
skb_trim(skb, rx_pkt_length);
|
||||
|
||||
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
||||
priv->wdev->iftype, 0, false);
|
||||
@ -189,17 +190,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||
} else {
|
||||
if (rx_pkt_type != PKT_TYPE_BAR)
|
||||
priv->rx_seq[local_rx_pd->priority] =
|
||||
local_rx_pd->seq_num;
|
||||
priv->rx_seq[local_rx_pd->priority] = seq_num;
|
||||
memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
/* Reorder and send to OS */
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
|
||||
local_rx_pd->priority, ta,
|
||||
(u8) local_rx_pd->rx_pkt_type,
|
||||
skb);
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
|
||||
ta, (u8) rx_pkt_type, skb);
|
||||
|
||||
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
|
||||
if (adapter->if_ops.data_complete)
|
||||
|
@ -51,6 +51,9 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
|
||||
rx_info->bss_num = priv->bss_num;
|
||||
rx_info->bss_type = priv->bss_type;
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
return mwifiex_process_uap_rx_packet(adapter, skb);
|
||||
|
||||
return mwifiex_process_sta_rx_packet(adapter, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
|
||||
@ -157,6 +160,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
|
||||
priv->stats.tx_errors++;
|
||||
}
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
|
||||
atomic_dec_return(&adapter->pending_bridged_pkts);
|
||||
if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
|
||||
goto done;
|
||||
|
||||
|
@ -167,6 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
|
||||
if (ht_ie) {
|
||||
memcpy(&bss_cfg->ht_cap, ht_ie + 2,
|
||||
sizeof(struct ieee80211_ht_cap));
|
||||
priv->ap_11n_enabled = 1;
|
||||
} else {
|
||||
memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
|
||||
bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
|
||||
|
290
drivers/net/wireless/mwifiex/uap_event.c
Normal file
290
drivers/net/wireless/mwifiex/uap_event.c
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Marvell Wireless LAN device driver: AP event handling
|
||||
*
|
||||
* Copyright (C) 2012, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*/
|
||||
|
||||
#include "decl.h"
|
||||
#include "main.h"
|
||||
#include "11n.h"
|
||||
|
||||
/*
|
||||
* This function will return the pointer to station entry in station list
|
||||
* table which matches specified mac address.
|
||||
* This function should be called after acquiring RA list spinlock.
|
||||
* NULL is returned if station entry is not found in associated STA list.
|
||||
*/
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(node, &priv->sta_list, list) {
|
||||
if (!memcmp(node->mac_addr, mac, ETH_ALEN))
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will add a sta_node entry to associated station list
|
||||
* table with the given mac address.
|
||||
* If entry exist already, existing entry is returned.
|
||||
* If received mac address is NULL, NULL is returned.
|
||||
*/
|
||||
static struct mwifiex_sta_node *
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node)
|
||||
goto done;
|
||||
|
||||
node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_ATOMIC);
|
||||
if (!node)
|
||||
goto done;
|
||||
|
||||
memcpy(node->mac_addr, mac, ETH_ALEN);
|
||||
list_add_tail(&node->list, &priv->sta_list);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will search for HT IE in association request IEs
|
||||
* and set station HT parameters accordingly.
|
||||
*/
|
||||
static void
|
||||
mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
|
||||
int ies_len, struct mwifiex_sta_node *node)
|
||||
{
|
||||
const struct ieee80211_ht_cap *ht_cap;
|
||||
|
||||
if (!ies)
|
||||
return;
|
||||
|
||||
ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
|
||||
if (ht_cap) {
|
||||
node->is_11n_enabled = 1;
|
||||
node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
|
||||
IEEE80211_HT_CAP_MAX_AMSDU ?
|
||||
MWIFIEX_TX_DATA_BUF_SIZE_8K :
|
||||
MWIFIEX_TX_DATA_BUF_SIZE_4K;
|
||||
} else {
|
||||
node->is_11n_enabled = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will delete a station entry from station list
|
||||
*/
|
||||
static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node) {
|
||||
list_for_each_entry_safe(node, tmp, &priv->sta_list,
|
||||
list) {
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will delete all stations from associated station list.
|
||||
*/
|
||||
static void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_sta_node *node, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->sta_list);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles AP interface specific events generated by firmware.
|
||||
*
|
||||
* Event specific routines are called by this function based
|
||||
* upon the generated event cause.
|
||||
*
|
||||
*
|
||||
* Events supported for AP -
|
||||
* - EVENT_UAP_STA_ASSOC
|
||||
* - EVENT_UAP_STA_DEAUTH
|
||||
* - EVENT_UAP_BSS_ACTIVE
|
||||
* - EVENT_UAP_BSS_START
|
||||
* - EVENT_UAP_BSS_IDLE
|
||||
* - EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
*/
|
||||
int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int len, i;
|
||||
u32 eventcause = adapter->event_cause;
|
||||
struct station_info sinfo;
|
||||
struct mwifiex_assoc_event *event;
|
||||
struct mwifiex_sta_node *node;
|
||||
u8 *deauth_mac;
|
||||
struct host_cmd_ds_11n_batimeout *ba_timeout;
|
||||
u16 ctrl;
|
||||
|
||||
switch (eventcause) {
|
||||
case EVENT_UAP_STA_ASSOC:
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
event = (struct mwifiex_assoc_event *)
|
||||
(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
|
||||
len = -1;
|
||||
|
||||
if (ieee80211_is_assoc_req(event->frame_control))
|
||||
len = 0;
|
||||
else if (ieee80211_is_reassoc_req(event->frame_control))
|
||||
/* There will be ETH_ALEN bytes of
|
||||
* current_ap_addr before the re-assoc ies.
|
||||
*/
|
||||
len = ETH_ALEN;
|
||||
|
||||
if (len != -1) {
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.assoc_req_ies = &event->data[len];
|
||||
len = (u8 *)sinfo.assoc_req_ies -
|
||||
(u8 *)&event->frame_control;
|
||||
sinfo.assoc_req_ies_len =
|
||||
le16_to_cpu(event->len) - (u16)len;
|
||||
}
|
||||
}
|
||||
cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
|
||||
GFP_KERNEL);
|
||||
|
||||
node = mwifiex_add_sta_entry(priv, event->sta_addr);
|
||||
if (!node) {
|
||||
dev_warn(adapter->dev,
|
||||
"could not create station entry!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!priv->ap_11n_enabled)
|
||||
break;
|
||||
|
||||
mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
|
||||
sinfo.assoc_req_ies_len, node);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; i++) {
|
||||
if (node->is_11n_enabled)
|
||||
node->ampdu_sta[i] =
|
||||
priv->aggr_prio_tbl[i].ampdu_user;
|
||||
else
|
||||
node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
|
||||
}
|
||||
memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
|
||||
break;
|
||||
case EVENT_UAP_STA_DEAUTH:
|
||||
deauth_mac = adapter->event_body +
|
||||
MWIFIEX_UAP_EVENT_EXTRA_HEADER;
|
||||
cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
|
||||
|
||||
if (priv->ap_11n_enabled) {
|
||||
mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
|
||||
mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
|
||||
}
|
||||
mwifiex_del_sta_entry(priv, deauth_mac);
|
||||
break;
|
||||
case EVENT_UAP_BSS_IDLE:
|
||||
priv->media_connected = false;
|
||||
mwifiex_clean_txrx(priv);
|
||||
mwifiex_del_all_sta_list(priv);
|
||||
break;
|
||||
case EVENT_UAP_BSS_ACTIVE:
|
||||
priv->media_connected = true;
|
||||
break;
|
||||
case EVENT_UAP_BSS_START:
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
|
||||
ETH_ALEN);
|
||||
break;
|
||||
case EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
/* For future development */
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
break;
|
||||
case EVENT_AMSDU_AGGR_CTRL:
|
||||
ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
|
||||
|
||||
if (priv->media_connected) {
|
||||
adapter->tx_buf_size =
|
||||
min_t(u16, adapter->curr_tx_buf_size, ctrl);
|
||||
dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
|
||||
adapter->tx_buf_size);
|
||||
}
|
||||
break;
|
||||
case EVENT_ADDBA:
|
||||
dev_dbg(adapter->dev, "event: ADDBA Request\n");
|
||||
if (priv->media_connected)
|
||||
mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
adapter->event_body);
|
||||
break;
|
||||
case EVENT_DELBA:
|
||||
dev_dbg(adapter->dev, "event: DELBA Request\n");
|
||||
if (priv->media_connected)
|
||||
mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
|
||||
break;
|
||||
case EVENT_BA_STREAM_TIEMOUT:
|
||||
dev_dbg(adapter->dev, "event: BA Stream timeout\n");
|
||||
if (priv->media_connected) {
|
||||
ba_timeout = (void *)adapter->event_body;
|
||||
mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
|
||||
eventcause);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
255
drivers/net/wireless/mwifiex/uap_txrx.c
Normal file
255
drivers/net/wireless/mwifiex/uap_txrx.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Marvell Wireless LAN device driver: AP TX and RX data handling
|
||||
*
|
||||
* Copyright (C) 2012, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*/
|
||||
|
||||
#include "decl.h"
|
||||
#include "ioctl.h"
|
||||
#include "main.h"
|
||||
#include "wmm.h"
|
||||
#include "11n_aggr.h"
|
||||
#include "11n_rxreorder.h"
|
||||
|
||||
static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
struct sk_buff *new_skb;
|
||||
struct mwifiex_txinfo *tx_info;
|
||||
int hdr_chop;
|
||||
struct timeval tv;
|
||||
u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
if ((atomic_read(&adapter->pending_bridged_pkts) >=
|
||||
MWIFIEX_BRIDGED_PKTS_THRESHOLD)) {
|
||||
dev_err(priv->adapter->dev,
|
||||
"Tx: Bridge packet limit reached. Drop packet!\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
|
||||
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)))
|
||||
/* Chop off the rxpd + the excess memory from
|
||||
* 802.2/llc/snap header that was removed.
|
||||
*/
|
||||
hdr_chop = (u8 *)eth_hdr - (u8 *)uap_rx_pd;
|
||||
else
|
||||
/* Chop off the rxpd */
|
||||
hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
|
||||
|
||||
/* Chop off the leading header bytes so the it points
|
||||
* to the start of either the reconstructed EthII frame
|
||||
* or the 802.2/llc/snap frame.
|
||||
*/
|
||||
skb_pull(skb, hdr_chop);
|
||||
|
||||
if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"data: Tx: insufficient skb headroom %d\n",
|
||||
skb_headroom(skb));
|
||||
/* Insufficient skb headroom - allocate a new skb */
|
||||
new_skb =
|
||||
skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
|
||||
if (unlikely(!new_skb)) {
|
||||
dev_err(priv->adapter->dev,
|
||||
"Tx: cannot allocate new_skb\n");
|
||||
kfree_skb(skb);
|
||||
priv->stats.tx_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
skb = new_skb;
|
||||
dev_dbg(priv->adapter->dev, "info: new skb headroom %d\n",
|
||||
skb_headroom(skb));
|
||||
}
|
||||
|
||||
tx_info = MWIFIEX_SKB_TXCB(skb);
|
||||
tx_info->bss_num = priv->bss_num;
|
||||
tx_info->bss_type = priv->bss_type;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
skb->tstamp = timeval_to_ktime(tv);
|
||||
mwifiex_wmm_add_buf_txqueue(priv, skb);
|
||||
atomic_inc(&adapter->tx_pending);
|
||||
atomic_inc(&adapter->pending_bridged_pkts);
|
||||
|
||||
if ((atomic_read(&adapter->tx_pending) >= MAX_TX_PENDING)) {
|
||||
mwifiex_set_trans_start(priv->netdev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function contains logic for AP packet forwarding.
|
||||
*
|
||||
* If a packet is multicast/broadcast, it is sent to kernel/upper layer
|
||||
* as well as queued back to AP TX queue so that it can be sent to other
|
||||
* associated stations.
|
||||
* If a packet is unicast and RA is present in associated station list,
|
||||
* it is again requeued into AP TX queue.
|
||||
* If a packet is unicast and RA is not in associated station list,
|
||||
* packet is forwarded to kernel to handle routing logic.
|
||||
*/
|
||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u8 ra[ETH_ALEN];
|
||||
struct sk_buff *skb_uap;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
/* don't do packet forwarding in disconnected state */
|
||||
if (!priv->media_connected) {
|
||||
dev_err(adapter->dev, "drop packet in disconnected state.\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
|
||||
|
||||
if (is_multicast_ether_addr(ra)) {
|
||||
skb_uap = skb_copy(skb, GFP_ATOMIC);
|
||||
mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
|
||||
} else {
|
||||
if (mwifiex_get_sta_entry(priv, ra)) {
|
||||
/* Requeue Intra-BSS packet */
|
||||
mwifiex_uap_queue_bridged_pkt(priv, skb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward unicat/Inter-BSS packets to kernel. */
|
||||
return mwifiex_process_rx_packet(adapter, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function processes the packet received on AP interface.
|
||||
*
|
||||
* The function looks into the RxPD and performs sanity tests on the
|
||||
* received buffer to ensure its a valid packet before processing it
|
||||
* further. If the packet is determined to be aggregated, it is
|
||||
* de-aggregated accordingly. Then skb is passed to AP packet forwarding logic.
|
||||
*
|
||||
* The completion callback is called after processing is complete.
|
||||
*/
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int ret;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u16 rx_pkt_type;
|
||||
u8 ta[ETH_ALEN], pkt_type;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
struct mwifiex_private *priv =
|
||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
||||
rx_info->bss_type);
|
||||
|
||||
if (!priv)
|
||||
return -1;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
|
||||
dev_err(adapter->dev,
|
||||
"wrong rx packet: len=%d, offset=%d, length=%d\n",
|
||||
skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length));
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
if (adapter->if_ops.data_complete)
|
||||
adapter->if_ops.data_complete(adapter, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
|
||||
skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length));
|
||||
|
||||
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
||||
priv->wdev->iftype, 0, false);
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
rx_skb = __skb_dequeue(&list);
|
||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
||||
if (ret)
|
||||
dev_err(adapter->dev,
|
||||
"AP:Rx A-MSDU failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||
|
||||
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
node->rx_seq[uap_rx_pd->priority] =
|
||||
le16_to_cpu(uap_rx_pd->seq_num);
|
||||
}
|
||||
|
||||
if (!priv->ap_11n_enabled ||
|
||||
(!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
|
||||
(le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
|
||||
ret = mwifiex_handle_uap_rx_forward(priv, skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reorder and send to kernel */
|
||||
pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
|
||||
uap_rx_pd->priority, ta, pkt_type,
|
||||
skb);
|
||||
|
||||
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
|
||||
if (adapter->if_ops.data_complete)
|
||||
adapter->if_ops.data_complete(adapter, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
return ret;
|
||||
}
|
@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
|
||||
return ra_list;
|
||||
}
|
||||
|
||||
/* This function returns random no between 16 and 32 to be used as threshold
|
||||
* for no of packets after which BA setup is initiated.
|
||||
*/
|
||||
static u8 mwifiex_get_random_ba_threshold(void)
|
||||
{
|
||||
u32 sec, usec;
|
||||
struct timeval ba_tstamp;
|
||||
u8 ba_threshold;
|
||||
|
||||
/* setup ba_packet_threshold here random number between
|
||||
* [BA_SETUP_PACKET_OFFSET,
|
||||
* BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
|
||||
*/
|
||||
|
||||
do_gettimeofday(&ba_tstamp);
|
||||
sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
|
||||
usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
|
||||
ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
|
||||
+ BA_SETUP_PACKET_OFFSET;
|
||||
|
||||
return ba_threshold;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function allocates and adds a RA list for all TIDs
|
||||
* with the given RA.
|
||||
@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
|
||||
int i;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
node = mwifiex_get_sta_entry(priv, ra);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
|
||||
@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
|
||||
if (!ra_list)
|
||||
break;
|
||||
|
||||
if (!mwifiex_queuing_ra_based(priv))
|
||||
ra_list->is_11n_enabled = 0;
|
||||
if (!mwifiex_queuing_ra_based(priv)) {
|
||||
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
|
||||
else
|
||||
ra_list->is_11n_enabled = false;
|
||||
} else {
|
||||
ra_list->is_11n_enabled =
|
||||
mwifiex_is_sta_11n_enabled(priv, node);
|
||||
if (ra_list->is_11n_enabled)
|
||||
ra_list->max_amsdu = node->max_amsdu;
|
||||
}
|
||||
|
||||
dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
|
||||
ra_list, ra_list->is_11n_enabled);
|
||||
|
||||
if (ra_list->is_11n_enabled) {
|
||||
ra_list->pkt_count = 0;
|
||||
ra_list->ba_packet_thr =
|
||||
mwifiex_get_random_ba_threshold();
|
||||
}
|
||||
list_add_tail(&ra_list->list,
|
||||
&priv->wmm.tid_tbl_ptr[i].ra_list);
|
||||
|
||||
@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
||||
skb_queue_tail(&ra_list->skb_head, skb);
|
||||
|
||||
ra_list->total_pkts_size += skb->len;
|
||||
ra_list->pkt_count++;
|
||||
|
||||
atomic_inc(&priv->wmm.tx_pkts_queued);
|
||||
|
||||
@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
|
||||
{
|
||||
int count = 0, total_size = 0;
|
||||
struct sk_buff *skb, *tmp;
|
||||
int max_amsdu_size;
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
|
||||
ptr->is_11n_enabled)
|
||||
max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
|
||||
else
|
||||
max_amsdu_size = max_buf_size;
|
||||
|
||||
skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
|
||||
total_size += skb->len;
|
||||
if (total_size >= max_buf_size)
|
||||
if (total_size >= max_amsdu_size)
|
||||
break;
|
||||
if (++count >= MIN_NUM_AMSDU)
|
||||
return true;
|
||||
@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
|
||||
skb_queue_tail(&ptr->skb_head, skb);
|
||||
|
||||
ptr->total_pkts_size += skb->len;
|
||||
ptr->pkt_count++;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
||||
/* ra_list_spinlock has been freed in
|
||||
mwifiex_send_single_packet() */
|
||||
} else {
|
||||
if (mwifiex_is_ampdu_allowed(priv, tid)) {
|
||||
if (mwifiex_is_ampdu_allowed(priv, tid) &&
|
||||
ptr->pkt_count > ptr->ba_packet_thr) {
|
||||
if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
|
||||
mwifiex_create_ba_tbl(priv, ptr->ra, tid,
|
||||
BA_SETUP_INPROGRESS);
|
||||
|
@ -76,6 +76,7 @@ struct p54_channel_entry {
|
||||
u16 freq;
|
||||
u16 data;
|
||||
int index;
|
||||
int max_power;
|
||||
enum ieee80211_band band;
|
||||
};
|
||||
|
||||
@ -173,6 +174,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
|
||||
for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
|
||||
(i < list->entries); i++) {
|
||||
struct p54_channel_entry *chan = &list->channels[i];
|
||||
struct ieee80211_channel *dest = &tmp->channels[j];
|
||||
|
||||
if (chan->band != band)
|
||||
continue;
|
||||
@ -190,14 +192,15 @@ static int p54_generate_band(struct ieee80211_hw *dev,
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp->channels[j].band = chan->band;
|
||||
tmp->channels[j].center_freq = chan->freq;
|
||||
dest->band = chan->band;
|
||||
dest->center_freq = chan->freq;
|
||||
dest->max_power = chan->max_power;
|
||||
priv->survey[*chan_num].channel = &tmp->channels[j];
|
||||
priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
tmp->channels[j].hw_value = (*chan_num);
|
||||
dest->hw_value = (*chan_num);
|
||||
j++;
|
||||
(*chan_num)++;
|
||||
}
|
||||
@ -229,10 +232,11 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void p54_update_channel_param(struct p54_channel_list *list,
|
||||
u16 freq, u16 data)
|
||||
static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list,
|
||||
u16 freq, u16 data)
|
||||
{
|
||||
int band, i;
|
||||
int i;
|
||||
struct p54_channel_entry *entry = NULL;
|
||||
|
||||
/*
|
||||
* usually all lists in the eeprom are mostly sorted.
|
||||
@ -241,30 +245,78 @@ static void p54_update_channel_param(struct p54_channel_list *list,
|
||||
*/
|
||||
for (i = list->entries; i >= 0; i--) {
|
||||
if (freq == list->channels[i].freq) {
|
||||
list->channels[i].data |= data;
|
||||
entry = &list->channels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i < 0) && (list->entries < list->max_entries)) {
|
||||
/* entry does not exist yet. Initialize a new one. */
|
||||
band = p54_get_band_from_freq(freq);
|
||||
int band = p54_get_band_from_freq(freq);
|
||||
|
||||
/*
|
||||
* filter out frequencies which don't belong into
|
||||
* any supported band.
|
||||
*/
|
||||
if (band < 0)
|
||||
return ;
|
||||
if (band >= 0) {
|
||||
i = list->entries++;
|
||||
list->band_channel_num[band]++;
|
||||
|
||||
i = list->entries++;
|
||||
list->band_channel_num[band]++;
|
||||
entry = &list->channels[i];
|
||||
entry->freq = freq;
|
||||
entry->band = band;
|
||||
entry->index = ieee80211_frequency_to_channel(freq);
|
||||
entry->max_power = 0;
|
||||
entry->data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
list->channels[i].freq = freq;
|
||||
list->channels[i].data = data;
|
||||
list->channels[i].band = band;
|
||||
list->channels[i].index = ieee80211_frequency_to_channel(freq);
|
||||
/* TODO: parse output_limit and fill max_power */
|
||||
if (entry)
|
||||
entry->data |= data;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int p54_get_maxpower(struct p54_common *priv, void *data)
|
||||
{
|
||||
switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) {
|
||||
case PDR_SYNTH_FRONTEND_LONGBOW: {
|
||||
struct pda_channel_output_limit_longbow *pda = data;
|
||||
int j;
|
||||
u16 rawpower = 0;
|
||||
pda = data;
|
||||
for (j = 0; j < ARRAY_SIZE(pda->point); j++) {
|
||||
struct pda_channel_output_limit_point_longbow *point =
|
||||
&pda->point[j];
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_qpsk));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_bpsk));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_16qam));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_64qam));
|
||||
}
|
||||
/* longbow seems to use 1/16 dBm units */
|
||||
return rawpower / 16;
|
||||
}
|
||||
|
||||
case PDR_SYNTH_FRONTEND_DUETTE3:
|
||||
case PDR_SYNTH_FRONTEND_DUETTE2:
|
||||
case PDR_SYNTH_FRONTEND_FRISBEE:
|
||||
case PDR_SYNTH_FRONTEND_XBOW: {
|
||||
struct pda_channel_output_limit *pda = data;
|
||||
u8 rawpower = 0;
|
||||
rawpower = max(rawpower, pda->val_qpsk);
|
||||
rawpower = max(rawpower, pda->val_bpsk);
|
||||
rawpower = max(rawpower, pda->val_16qam);
|
||||
rawpower = max(rawpower, pda->val_64qam);
|
||||
/* raw values are in 1/4 dBm units */
|
||||
return rawpower / 4;
|
||||
}
|
||||
|
||||
default:
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,12 +367,19 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
if (i < priv->output_limit->entries) {
|
||||
freq = le16_to_cpup((__le16 *) (i *
|
||||
priv->output_limit->entry_size +
|
||||
priv->output_limit->offset +
|
||||
priv->output_limit->data));
|
||||
struct p54_channel_entry *tmp;
|
||||
|
||||
p54_update_channel_param(list, freq, CHAN_HAS_LIMIT);
|
||||
void *data = (void *) ((unsigned long) i *
|
||||
priv->output_limit->entry_size +
|
||||
priv->output_limit->offset +
|
||||
priv->output_limit->data);
|
||||
|
||||
freq = le16_to_cpup((__le16 *) data);
|
||||
tmp = p54_update_channel_param(list, freq,
|
||||
CHAN_HAS_LIMIT);
|
||||
if (tmp) {
|
||||
tmp->max_power = p54_get_maxpower(priv, data);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < priv->curve_data->entries) {
|
||||
@ -834,11 +893,12 @@ good_eeprom:
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
|
||||
|
||||
err = p54_generate_channel_lists(dev);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
|
||||
if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
|
||||
p54_init_xbow_synth(priv);
|
||||
if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
|
||||
|
@ -57,6 +57,18 @@ struct pda_channel_output_limit {
|
||||
u8 rate_set_size;
|
||||
} __packed;
|
||||
|
||||
struct pda_channel_output_limit_point_longbow {
|
||||
__le16 val_bpsk;
|
||||
__le16 val_qpsk;
|
||||
__le16 val_16qam;
|
||||
__le16 val_64qam;
|
||||
} __packed;
|
||||
|
||||
struct pda_channel_output_limit_longbow {
|
||||
__le16 freq;
|
||||
struct pda_channel_output_limit_point_longbow point[3];
|
||||
} __packed;
|
||||
|
||||
struct pda_pa_curve_data_sample_rev0 {
|
||||
u8 rf_power;
|
||||
u8 pa_detector;
|
||||
|
@ -488,6 +488,58 @@ static int p54p_open(struct ieee80211_hw *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p54p_firmware_step2(const struct firmware *fw,
|
||||
void *context)
|
||||
{
|
||||
struct p54p_priv *priv = context;
|
||||
struct ieee80211_hw *dev = priv->common.hw;
|
||||
struct pci_dev *pdev = priv->pdev;
|
||||
int err;
|
||||
|
||||
if (!fw) {
|
||||
dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->firmware = fw;
|
||||
|
||||
err = p54p_open(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = p54_read_eeprom(dev);
|
||||
p54p_stop(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = p54_register_common(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
|
||||
complete(&priv->fw_loaded);
|
||||
|
||||
if (err) {
|
||||
struct device *parent = pdev->dev.parent;
|
||||
|
||||
if (parent)
|
||||
device_lock(parent);
|
||||
|
||||
/*
|
||||
* This will indirectly result in a call to p54p_remove.
|
||||
* Hence, we don't need to bother with freeing any
|
||||
* allocated ressources at all.
|
||||
*/
|
||||
device_release_driver(&pdev->dev);
|
||||
|
||||
if (parent)
|
||||
device_unlock(parent);
|
||||
}
|
||||
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
@ -496,6 +548,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
unsigned long mem_addr, mem_len;
|
||||
int err;
|
||||
|
||||
pci_dev_get(pdev);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot enable new PCI device\n");
|
||||
@ -537,6 +590,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
priv = dev->priv;
|
||||
priv->pdev = pdev;
|
||||
|
||||
init_completion(&priv->fw_loaded);
|
||||
SET_IEEE80211_DEV(dev, &pdev->dev);
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
@ -561,32 +615,12 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
spin_lock_init(&priv->lock);
|
||||
tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
|
||||
|
||||
err = request_firmware(&priv->firmware, "isl3886pci",
|
||||
&priv->pdev->dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
|
||||
err = request_firmware(&priv->firmware, "isl3886",
|
||||
&priv->pdev->dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
}
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, "isl3886pci",
|
||||
&priv->pdev->dev, GFP_KERNEL,
|
||||
priv, p54p_firmware_step2);
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
err = p54p_open(dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
err = p54_read_eeprom(dev);
|
||||
p54p_stop(dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
|
||||
err = p54_register_common(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_common:
|
||||
release_firmware(priv->firmware);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
|
||||
@ -601,6 +635,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
pci_release_regions(pdev);
|
||||
err_disable_dev:
|
||||
pci_disable_device(pdev);
|
||||
pci_dev_put(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -612,8 +647,9 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
p54_unregister_common(dev);
|
||||
priv = dev->priv;
|
||||
wait_for_completion(&priv->fw_loaded);
|
||||
p54_unregister_common(dev);
|
||||
release_firmware(priv->firmware);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user