Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John says: -------------------- I apologize for not having sent this sooner. FWIW, I was in a car somewhere between Illinois and North Carolina for most of the day Sunday and Monday... :-) This is (obviously) the last non-fix pull request for wireless bits intended for 3.5. It includes AP support for mwifiex, a variety of HCI and other updates for NFC, some brcmfmac and brcmsmac refactoring, a large batch of ssb and bcma updates, a batch of ath6kl updates, some cfg80211 and mac80211 updates/refactoring from Johannes Berg, a rather large collection of Bluetooth updates by way of Gustavo, and a variety of other bits here and there. -------------------- Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c3719a1ef5
|
@ -534,6 +534,18 @@ Who: Kees Cook <keescook@chromium.org>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: Removing the pn544 raw driver.
|
||||
When: 3.6
|
||||
Why: With the introduction of the NFC HCI and SHDL kernel layers, pn544.c
|
||||
is being replaced by pn544_hci.c which is accessible through the netlink
|
||||
and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to
|
||||
work properly with the latest Android stacks.
|
||||
Having 2 drivers for the same hardware is confusing and as such we
|
||||
should only keep the one following the kernel NFC APIs.
|
||||
Who: Samuel Ortiz <sameo@linux.intel.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: setitimer accepts user NULL pointer (value)
|
||||
When: 3.6
|
||||
Why: setitimer is not returning -EFAULT if user pointer is NULL. This
|
||||
|
|
|
@ -22,9 +22,9 @@ response to arrive.
|
|||
HCI events can also be received from the host controller. They will be handled
|
||||
and a translation will be forwarded to NFC Core as needed.
|
||||
HCI uses 2 execution contexts:
|
||||
- one if for executing commands : nfc_hci_msg_tx_work(). Only one command
|
||||
- one for executing commands : nfc_hci_msg_tx_work(). Only one command
|
||||
can be executing at any given moment.
|
||||
- one if for dispatching received events and responses : nfc_hci_msg_rx_work()
|
||||
- one for dispatching received events and commands : nfc_hci_msg_rx_work().
|
||||
|
||||
HCI Session initialization:
|
||||
---------------------------
|
||||
|
@ -52,18 +52,42 @@ entry points:
|
|||
struct nfc_hci_ops {
|
||||
int (*open)(struct nfc_hci_dev *hdev);
|
||||
void (*close)(struct nfc_hci_dev *hdev);
|
||||
int (*hci_ready) (struct nfc_hci_dev *hdev);
|
||||
int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
|
||||
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*data_exchange) (struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target,
|
||||
struct sk_buff *skb, struct sk_buff **res_skb);
|
||||
int (*check_presence)(struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target);
|
||||
};
|
||||
|
||||
open() and close() shall turn the hardware on and off. xmit() shall simply
|
||||
write a frame to the chip. start_poll() is an optional entrypoint that shall
|
||||
set the hardware in polling mode. This must be implemented only if the hardware
|
||||
uses proprietary gates or a mechanism slightly different from the HCI standard.
|
||||
target_from_gate() is another optional entrypoint to return the protocols
|
||||
- open() and close() shall turn the hardware on and off.
|
||||
- hci_ready() is an optional entry point that is called right after the hci
|
||||
session has been set up. The driver can use it to do additional initialization
|
||||
that must be performed using HCI commands.
|
||||
- xmit() shall simply write a frame to the chip.
|
||||
- start_poll() is an optional entrypoint that shall set the hardware in polling
|
||||
mode. This must be implemented only if the hardware uses proprietary gates or a
|
||||
mechanism slightly different from the HCI standard.
|
||||
- target_from_gate() is an optional entrypoint to return the nfc protocols
|
||||
corresponding to a proprietary gate.
|
||||
- complete_target_discovered() is an optional entry point to let the driver
|
||||
perform additional proprietary processing necessary to auto activate the
|
||||
discovered target.
|
||||
- data_exchange() must be implemented by the driver if proprietary HCI commands
|
||||
are required to send data to the tag. Some tag types will require custom
|
||||
commands, others can be written to using the standard HCI commands. The driver
|
||||
can check the tag type and either do proprietary processing, or return 1 to ask
|
||||
for standard processing.
|
||||
- check_presence() is an optional entry point that will be called regularly
|
||||
by the core to check that an activated tag is still in the field. If this is
|
||||
not implemented, the core will not be able to push tag_lost events to the user
|
||||
space
|
||||
|
||||
On the rx path, the driver is responsible to push incoming HCP frames to HCI
|
||||
using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling
|
||||
|
@ -99,7 +123,8 @@ fast, cannot sleep. stores incoming frames into an shdlc rx queue
|
|||
handles shdlc rx & tx queues. Dispatches HCI cmd responses.
|
||||
|
||||
- HCI Tx Cmd worker (MSGTXWQ)
|
||||
Serialize execution of HCI commands. Complete execution in case of resp timeout.
|
||||
Serializes execution of HCI commands. Completes execution in case of response
|
||||
timeout.
|
||||
|
||||
- HCI Rx worker (MSGRXWQ)
|
||||
Dispatches incoming HCI commands or events.
|
||||
|
@ -133,11 +158,11 @@ able to complete the command with a timeout error if no response arrive.
|
|||
SMW context gets scheduled and invokes nfc_shdlc_sm_work(). This function
|
||||
handles shdlc framing in and out. It uses the driver xmit to send frames and
|
||||
receives incoming frames in an skb queue filled from the driver IRQ handler.
|
||||
SHDLC I(nformation) frames payload are HCP fragments. They are agregated to
|
||||
SHDLC I(nformation) frames payload are HCP fragments. They are aggregated to
|
||||
form complete HCI frames, which can be a response, command, or event.
|
||||
|
||||
HCI Responses are dispatched immediately from this context to unblock
|
||||
waiting command execution. Reponse processing involves invoking the completion
|
||||
waiting command execution. Response processing involves invoking the completion
|
||||
callback that was provided by nfc_hci_msg_tx_work() when it sent the command.
|
||||
The completion callback will then wake the syscall context.
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
|
|||
char prefix[10];
|
||||
|
||||
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
memset(out, 0, sizeof(struct ssb_sprom));
|
||||
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
||||
bus->host_pci->bus->number + 1,
|
||||
PCI_SLOT(bus->host_pci->devfn));
|
||||
|
@ -109,15 +110,9 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
|
|||
/* Fill boardinfo structure */
|
||||
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
|
||||
|
||||
if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
|
||||
iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
|
||||
else
|
||||
iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
|
||||
if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
|
||||
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
|
||||
if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
|
||||
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
|
||||
bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
|
||||
|
||||
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
|
||||
bcm47xx_fill_sprom(&iv->sprom, NULL);
|
||||
|
||||
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
||||
|
@ -166,12 +161,14 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
|
|||
|
||||
switch (bus->hosttype) {
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
memset(out, 0, sizeof(struct ssb_sprom));
|
||||
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
||||
bus->host_pci->bus->number + 1,
|
||||
PCI_SLOT(bus->host_pci->devfn));
|
||||
bcm47xx_fill_sprom(out, prefix);
|
||||
return 0;
|
||||
case BCMA_HOSTTYPE_SOC:
|
||||
memset(out, 0, sizeof(struct ssb_sprom));
|
||||
bcm47xx_fill_sprom_ethernet(out, NULL);
|
||||
core = bcma_find_core(bus, BCMA_CORE_80211);
|
||||
if (core) {
|
||||
|
@ -197,6 +194,8 @@ static void __init bcm47xx_register_bcma(void)
|
|||
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
|
||||
if (err)
|
||||
panic("Failed to initialize BCMA bus (err %d)", err);
|
||||
|
||||
bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
|
|||
const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
|
||||
if (!sprom->board_rev)
|
||||
nvram_read_u16(NULL, NULL, "boardrev", &sprom->board_rev, 0);
|
||||
nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
|
||||
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
|
||||
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
|
||||
|
@ -555,8 +557,6 @@ void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
|
|||
|
||||
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
memset(sprom, 0, sizeof(struct ssb_sprom));
|
||||
|
||||
bcm47xx_fill_sprom_ethernet(sprom, prefix);
|
||||
|
||||
nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
|
||||
|
@ -618,3 +618,27 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
|
|||
bcm47xx_fill_sprom_r1(sprom, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCM47XX_SSB
|
||||
void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
|
||||
if (!boardinfo->vendor)
|
||||
boardinfo->vendor = SSB_BOARDVENDOR_BCM;
|
||||
|
||||
nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCM47XX_BCMA
|
||||
void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
|
||||
if (!boardinfo->vendor)
|
||||
boardinfo->vendor = SSB_BOARDVENDOR_BCM;
|
||||
|
||||
nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -47,4 +47,13 @@ extern enum bcm47xx_bus_type bcm47xx_bus_type;
|
|||
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
|
||||
void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
|
||||
|
||||
#ifdef CONFIG_BCM47XX_SSB
|
||||
void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
|
||||
const char *prefix);
|
||||
#endif
|
||||
#ifdef CONFIG_BCM47XX_BCMA
|
||||
void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
|
||||
const char *prefix);
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_BCM47XX_H */
|
||||
|
|
|
@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_device *core, u32 flags)
|
|||
udelay(10);
|
||||
|
||||
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
||||
bcma_aread32(core, BCMA_RESET_CTL);
|
||||
udelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_disable);
|
||||
|
@ -77,7 +78,7 @@ void bcma_core_set_clockmode(struct bcma_device *core,
|
|||
pr_err("HT force timeout\n");
|
||||
break;
|
||||
case BCMA_CLKMODE_DYNAMIC:
|
||||
pr_warn("Dynamic clockmode not supported yet!\n");
|
||||
bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,12 @@ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
|
|||
return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
|
||||
{
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
||||
pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
|
||||
{
|
||||
|
@ -170,13 +168,50 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
|
|||
tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
|
||||
}
|
||||
|
||||
static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
|
||||
{
|
||||
struct bcma_device *core = pc->core;
|
||||
u16 val16, core_index;
|
||||
uint regoff;
|
||||
|
||||
regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
|
||||
core_index = (u16)core->core_index;
|
||||
|
||||
val16 = pcicore_read16(pc, regoff);
|
||||
if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
|
||||
!= core_index) {
|
||||
val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
|
||||
(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
|
||||
pcicore_write16(pc, regoff, val16);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
|
||||
{
|
||||
u16 val16;
|
||||
uint regoff;
|
||||
|
||||
regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
|
||||
|
||||
val16 = pcicore_read16(pc, regoff);
|
||||
|
||||
if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
|
||||
val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
|
||||
pcicore_write16(pc, regoff, val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Init.
|
||||
**************************************************/
|
||||
|
||||
static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
bcma_core_pci_fixcfg(pc);
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
bcma_core_pci_config_fixup(pc);
|
||||
}
|
||||
|
||||
void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
|
@ -224,3 +259,17 @@ out:
|
|||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
|
||||
|
||||
void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
|
||||
{
|
||||
u32 w;
|
||||
|
||||
w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
|
||||
if (extend)
|
||||
w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
|
||||
else
|
||||
w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
|
||||
bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
|
||||
bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
|
||||
|
|
|
@ -119,7 +119,7 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
if (unlikely(!addr))
|
||||
goto out;
|
||||
err = -ENOMEM;
|
||||
mmio = ioremap_nocache(addr, len);
|
||||
mmio = ioremap_nocache(addr, sizeof(val));
|
||||
if (!mmio)
|
||||
goto out;
|
||||
|
||||
|
@ -171,7 +171,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
||||
addr |= (func << 8);
|
||||
addr |= (off & 0xfc);
|
||||
mmio = ioremap_nocache(addr, len);
|
||||
mmio = ioremap_nocache(addr, sizeof(val));
|
||||
if (!mmio)
|
||||
goto out;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
if (unlikely(!addr))
|
||||
goto out;
|
||||
err = -ENOMEM;
|
||||
mmio = ioremap_nocache(addr, len);
|
||||
mmio = ioremap_nocache(addr, sizeof(val));
|
||||
if (!mmio)
|
||||
goto out;
|
||||
|
||||
|
@ -491,8 +491,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
|||
/* Ok, ready to run, register it to the system.
|
||||
* The following needs change, if we want to port hostmode
|
||||
* to non-MIPS platform. */
|
||||
io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
|
||||
0x04000000);
|
||||
io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
|
||||
resource_size(&pc_host->mem_resource));
|
||||
pc_host->pci_controller.io_map_base = io_map_base;
|
||||
set_io_port_base(pc_host->pci_controller.io_map_base);
|
||||
/* Give some time to the PCI controller to configure itself with the new
|
||||
|
|
|
@ -201,6 +201,9 @@ static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
|
|||
bus->hosttype = BCMA_HOSTTYPE_PCI;
|
||||
bus->ops = &bcma_host_pci_ops;
|
||||
|
||||
bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
|
||||
bus->boardinfo.type = bus->host_pci->subsystem_device;
|
||||
|
||||
/* Register */
|
||||
err = bcma_bus_register(bus);
|
||||
if (err)
|
||||
|
@ -222,7 +225,7 @@ err_kfree_bus:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void bcma_host_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct bcma_bus *bus = pci_get_drvdata(dev);
|
||||
|
||||
|
@ -277,7 +280,7 @@ static struct pci_driver bcma_pci_bridge_driver = {
|
|||
.name = "bcma-pci-bridge",
|
||||
.id_table = bcma_pci_bridge_tbl,
|
||||
.probe = bcma_host_pci_probe,
|
||||
.remove = bcma_host_pci_remove,
|
||||
.remove = __devexit_p(bcma_host_pci_remove),
|
||||
.driver.pm = BCMA_PM_OPS,
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,14 @@ struct bcma_device_id_name {
|
|||
u16 id;
|
||||
const char *name;
|
||||
};
|
||||
struct bcma_device_id_name bcma_device_names[] = {
|
||||
|
||||
static const struct bcma_device_id_name bcma_arm_device_names[] = {
|
||||
{ BCMA_CORE_ARM_1176, "ARM 1176" },
|
||||
{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
|
||||
{ BCMA_CORE_ARM_CM3, "ARM CM3" },
|
||||
};
|
||||
|
||||
static const struct bcma_device_id_name bcma_bcm_device_names[] = {
|
||||
{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
|
||||
{ BCMA_CORE_INVALID, "Invalid" },
|
||||
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
|
||||
|
@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_names[] = {
|
|||
{ BCMA_CORE_SRAM, "SRAM" },
|
||||
{ BCMA_CORE_SDRAM, "SDRAM" },
|
||||
{ BCMA_CORE_PCI, "PCI" },
|
||||
{ BCMA_CORE_MIPS, "MIPS" },
|
||||
{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
|
||||
{ BCMA_CORE_V90, "V90" },
|
||||
{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
|
||||
|
@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_names[] = {
|
|||
{ BCMA_CORE_PHY_A, "PHY A" },
|
||||
{ BCMA_CORE_PHY_B, "PHY B" },
|
||||
{ BCMA_CORE_PHY_G, "PHY G" },
|
||||
{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
|
||||
{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
|
||||
{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
|
||||
{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
|
||||
|
@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_names[] = {
|
|||
{ BCMA_CORE_PHY_N, "PHY N" },
|
||||
{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
|
||||
{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
|
||||
{ BCMA_CORE_ARM_1176, "ARM 1176" },
|
||||
{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
|
||||
{ BCMA_CORE_PHY_LP, "PHY LP" },
|
||||
{ BCMA_CORE_PMU, "PMU" },
|
||||
{ BCMA_CORE_PHY_SSN, "PHY SSN" },
|
||||
{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
|
||||
{ BCMA_CORE_ARM_CM3, "ARM CM3" },
|
||||
{ BCMA_CORE_PHY_HT, "PHY HT" },
|
||||
{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
|
||||
{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
|
||||
{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
|
||||
{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
|
||||
|
@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_names[] = {
|
|||
{ BCMA_CORE_SHIM, "SHIM" },
|
||||
{ BCMA_CORE_DEFAULT, "Default" },
|
||||
};
|
||||
const char *bcma_device_name(struct bcma_device_id *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (id->manuf == BCMA_MANUF_BCM) {
|
||||
for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
|
||||
if (bcma_device_names[i].id == id->id)
|
||||
return bcma_device_names[i].name;
|
||||
}
|
||||
static const struct bcma_device_id_name bcma_mips_device_names[] = {
|
||||
{ BCMA_CORE_MIPS, "MIPS" },
|
||||
{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
|
||||
{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
|
||||
};
|
||||
|
||||
static const char *bcma_device_name(const struct bcma_device_id *id)
|
||||
{
|
||||
const struct bcma_device_id_name *names;
|
||||
int size, i;
|
||||
|
||||
/* search manufacturer specific names */
|
||||
switch (id->manuf) {
|
||||
case BCMA_MANUF_ARM:
|
||||
names = bcma_arm_device_names;
|
||||
size = ARRAY_SIZE(bcma_arm_device_names);
|
||||
break;
|
||||
case BCMA_MANUF_BCM:
|
||||
names = bcma_bcm_device_names;
|
||||
size = ARRAY_SIZE(bcma_bcm_device_names);
|
||||
break;
|
||||
case BCMA_MANUF_MIPS:
|
||||
names = bcma_mips_device_names;
|
||||
size = ARRAY_SIZE(bcma_mips_device_names);
|
||||
break;
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (names[i].id == id->id)
|
||||
return names[i].name;
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,22 @@ static int bcma_sprom_valid(const u16 *sprom)
|
|||
#define SPEX(_field, _offset, _mask, _shift) \
|
||||
bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
|
||||
|
||||
#define SPEX32(_field, _offset, _mask, _shift) \
|
||||
bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
|
||||
sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
|
||||
|
||||
#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
|
||||
do { \
|
||||
SPEX(_field[0], _offset + 0, _mask, _shift); \
|
||||
SPEX(_field[1], _offset + 2, _mask, _shift); \
|
||||
SPEX(_field[2], _offset + 4, _mask, _shift); \
|
||||
SPEX(_field[3], _offset + 6, _mask, _shift); \
|
||||
SPEX(_field[4], _offset + 8, _mask, _shift); \
|
||||
SPEX(_field[5], _offset + 10, _mask, _shift); \
|
||||
SPEX(_field[6], _offset + 12, _mask, _shift); \
|
||||
SPEX(_field[7], _offset + 14, _mask, _shift); \
|
||||
} while (0)
|
||||
|
||||
static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
||||
{
|
||||
u16 v, o;
|
||||
|
@ -243,7 +259,8 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
|||
SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
|
||||
SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
|
||||
|
||||
SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0);
|
||||
SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
|
||||
SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
|
||||
|
||||
/* Extract cores power info info */
|
||||
for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
|
||||
|
@ -298,6 +315,136 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
|||
SSB_SROM8_FEM_TR_ISO_SHIFT);
|
||||
SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
|
||||
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
|
||||
|
||||
SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
|
||||
SSB_SPROM8_ANTAVAIL_A_SHIFT);
|
||||
SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
|
||||
SSB_SPROM8_ANTAVAIL_BG_SHIFT);
|
||||
SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
|
||||
SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
|
||||
SSB_SPROM8_ITSSI_BG_SHIFT);
|
||||
SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
|
||||
SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
|
||||
SSB_SPROM8_ITSSI_A_SHIFT);
|
||||
SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
|
||||
SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
|
||||
SSB_SPROM8_MAXP_AL_SHIFT);
|
||||
SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
|
||||
SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
|
||||
SSB_SPROM8_GPIOA_P1_SHIFT);
|
||||
SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
|
||||
SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
|
||||
SSB_SPROM8_GPIOB_P3_SHIFT);
|
||||
SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
|
||||
SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
|
||||
SSB_SPROM8_TRI5G_SHIFT);
|
||||
SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
|
||||
SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
|
||||
SSB_SPROM8_TRI5GH_SHIFT);
|
||||
SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
|
||||
SSB_SPROM8_RXPO2G_SHIFT);
|
||||
SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
|
||||
SSB_SPROM8_RXPO5G_SHIFT);
|
||||
SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
|
||||
SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
|
||||
SSB_SPROM8_RSSISMC2G_SHIFT);
|
||||
SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
|
||||
SSB_SPROM8_RSSISAV2G_SHIFT);
|
||||
SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
|
||||
SSB_SPROM8_BXA2G_SHIFT);
|
||||
SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
|
||||
SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
|
||||
SSB_SPROM8_RSSISMC5G_SHIFT);
|
||||
SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
|
||||
SSB_SPROM8_RSSISAV5G_SHIFT);
|
||||
SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
|
||||
SSB_SPROM8_BXA5G_SHIFT);
|
||||
|
||||
SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
|
||||
SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
|
||||
SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
|
||||
SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
|
||||
SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
|
||||
SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
|
||||
SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
|
||||
SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
|
||||
SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
|
||||
SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
|
||||
SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
|
||||
SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
|
||||
SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
|
||||
SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
|
||||
SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
|
||||
SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
|
||||
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
|
||||
|
||||
/* Extract the antenna gain values. */
|
||||
SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
|
||||
SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
|
||||
SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
|
||||
SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
|
||||
SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
|
||||
SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
|
||||
SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
|
||||
SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
|
||||
|
||||
SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
|
||||
SSB_SPROM8_LEDDC_ON_SHIFT);
|
||||
SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
|
||||
SSB_SPROM8_LEDDC_OFF_SHIFT);
|
||||
|
||||
SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
|
||||
SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
|
||||
SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
|
||||
SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
|
||||
SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
|
||||
SSB_SPROM8_TXRXC_SWITCH_SHIFT);
|
||||
|
||||
SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
|
||||
|
||||
SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
|
||||
SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
|
||||
SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
|
||||
SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
|
||||
|
||||
SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
|
||||
SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
|
||||
SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
|
||||
SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
|
||||
SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
|
||||
SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
|
||||
SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
|
||||
SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
|
||||
SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
|
||||
SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
|
||||
SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
|
||||
SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
|
||||
SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
|
||||
SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
|
||||
SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
|
||||
SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
|
||||
SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
|
||||
SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
|
||||
SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
|
||||
SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
|
||||
|
||||
SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
|
||||
SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
|
||||
SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
|
||||
SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
|
||||
|
||||
SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
|
||||
SSB_SPROM8_THERMAL_TRESH_SHIFT);
|
||||
SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
|
||||
SSB_SPROM8_THERMAL_OFFSET_SHIFT);
|
||||
SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
|
||||
SSB_SPROM8_TEMPDELTA_PHYCAL,
|
||||
SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
|
||||
SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
|
||||
SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
|
||||
SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
|
||||
SSB_SPROM8_TEMPDELTA_HYSTERESIS,
|
||||
SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -81,6 +81,9 @@ static struct usb_device_id ath3k_table[] = {
|
|||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C) },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ struct btmrvl_adapter {
|
|||
u8 wakeup_tries;
|
||||
wait_queue_head_t cmd_wait_q;
|
||||
u8 cmd_complete;
|
||||
bool is_suspended;
|
||||
};
|
||||
|
||||
struct btmrvl_private {
|
||||
|
@ -139,8 +140,10 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
|
|||
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
|
||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
|
||||
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv);
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||
int btmrvl_enable_hs(struct btmrvl_private *priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void btmrvl_debugfs_init(struct hci_dev *hdev);
|
||||
|
|
|
@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
|
||||
|
||||
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
|
||||
BT_CMD_HOST_SLEEP_CONFIG));
|
||||
cmd->length = 2;
|
||||
cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
|
||||
cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0],
|
||||
cmd->data[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd);
|
||||
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
|
||||
|
||||
static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
|
@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_enable_hs);
|
||||
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct btmrvl_cmd *cmd;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->btmrvl_dev.hscfgcmd) {
|
||||
priv->btmrvl_dev.hscfgcmd = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG));
|
||||
cmd->length = 2;
|
||||
cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
|
||||
cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x",
|
||||
cmd->data[0], cmd->data[1]);
|
||||
btmrvl_send_hscfg_cmd(priv);
|
||||
}
|
||||
|
||||
if (priv->btmrvl_dev.pscmd) {
|
||||
|
|
|
@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
|
|||
|
||||
done:
|
||||
kfree(tmphlprbuf);
|
||||
if (fw_helper)
|
||||
release_firmware(fw_helper);
|
||||
|
||||
release_firmware(fw_helper);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||
|
||||
done:
|
||||
kfree(tmpfwbuf);
|
||||
|
||||
if (fw_firmware)
|
||||
release_firmware(fw_firmware);
|
||||
|
||||
release_firmware(fw_firmware);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
|||
priv->btmrvl_dev.psmode = 1;
|
||||
btmrvl_enable_ps(priv);
|
||||
|
||||
priv->btmrvl_dev.gpio_gap = 0xffff;
|
||||
btmrvl_send_hscfg_cmd(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_host_int:
|
||||
|
@ -1048,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
|
|||
}
|
||||
}
|
||||
|
||||
static int btmrvl_sdio_suspend(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct btmrvl_sdio_card *card;
|
||||
struct btmrvl_private *priv;
|
||||
mmc_pm_flag_t pm_flags;
|
||||
struct hci_dev *hcidev;
|
||||
|
||||
if (func) {
|
||||
pm_flags = sdio_get_host_pm_caps(func);
|
||||
BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func),
|
||||
pm_flags);
|
||||
if (!(pm_flags & MMC_PM_KEEP_POWER)) {
|
||||
BT_ERR("%s: cannot remain alive while suspended",
|
||||
sdio_func_id(func));
|
||||
return -ENOSYS;
|
||||
}
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->priv) {
|
||||
BT_ERR("card or priv structure is not valid");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
BT_ERR("sdio_func is not specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv = card->priv;
|
||||
|
||||
if (priv->adapter->hs_state != HS_ACTIVATED) {
|
||||
if (btmrvl_enable_hs(priv)) {
|
||||
BT_ERR("HS not actived, suspend failed!");
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
hcidev = priv->btmrvl_dev.hcidev;
|
||||
BT_DBG("%s: SDIO suspend", hcidev->name);
|
||||
hci_suspend_dev(hcidev);
|
||||
skb_queue_purge(&priv->adapter->tx_queue);
|
||||
|
||||
priv->adapter->is_suspended = true;
|
||||
|
||||
/* We will keep the power when hs enabled successfully */
|
||||
if (priv->adapter->hs_state == HS_ACTIVATED) {
|
||||
BT_DBG("suspend with MMC_PM_KEEP_POWER");
|
||||
return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
} else {
|
||||
BT_DBG("suspend without MMC_PM_KEEP_POWER");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int btmrvl_sdio_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct btmrvl_sdio_card *card;
|
||||
struct btmrvl_private *priv;
|
||||
mmc_pm_flag_t pm_flags;
|
||||
struct hci_dev *hcidev;
|
||||
|
||||
if (func) {
|
||||
pm_flags = sdio_get_host_pm_caps(func);
|
||||
BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func),
|
||||
pm_flags);
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->priv) {
|
||||
BT_ERR("card or priv structure is not valid");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
BT_ERR("sdio_func is not specified");
|
||||
return 0;
|
||||
}
|
||||
priv = card->priv;
|
||||
|
||||
if (!priv->adapter->is_suspended) {
|
||||
BT_DBG("device already resumed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->adapter->is_suspended = false;
|
||||
hcidev = priv->btmrvl_dev.hcidev;
|
||||
BT_DBG("%s: SDIO resume", hcidev->name);
|
||||
hci_resume_dev(hcidev);
|
||||
priv->hw_wakeup_firmware(priv);
|
||||
priv->adapter->hs_state = HS_DEACTIVATED;
|
||||
BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops btmrvl_sdio_pm_ops = {
|
||||
.suspend = btmrvl_sdio_suspend,
|
||||
.resume = btmrvl_sdio_resume,
|
||||
};
|
||||
|
||||
static struct sdio_driver bt_mrvl_sdio = {
|
||||
.name = "btmrvl_sdio",
|
||||
.id_table = btmrvl_sdio_ids,
|
||||
.probe = btmrvl_sdio_probe,
|
||||
.remove = btmrvl_sdio_remove,
|
||||
.drv = {
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &btmrvl_sdio_pm_ops,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init btmrvl_sdio_init_module(void)
|
||||
|
|
|
@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = {
|
|||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
|
@ -855,6 +858,7 @@ static void btusb_work(struct work_struct *work)
|
|||
{
|
||||
struct btusb_data *data = container_of(work, struct btusb_data, work);
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
int new_alts;
|
||||
int err;
|
||||
|
||||
if (hdev->conn_hash.sco_num > 0) {
|
||||
|
@ -868,11 +872,19 @@ static void btusb_work(struct work_struct *work)
|
|||
|
||||
set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
|
||||
}
|
||||
if (data->isoc_altsetting != 2) {
|
||||
|
||||
if (hdev->voice_setting & 0x0020) {
|
||||
static const int alts[3] = { 2, 4, 5 };
|
||||
new_alts = alts[hdev->conn_hash.sco_num - 1];
|
||||
} else {
|
||||
new_alts = hdev->conn_hash.sco_num;
|
||||
}
|
||||
|
||||
if (data->isoc_altsetting != new_alts) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
if (__set_isoc_interface(hdev, 2) < 0)
|
||||
if (__set_isoc_interface(hdev, new_alts) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -388,7 +388,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
|||
hdev->close = hci_uart_close;
|
||||
hdev->flush = hci_uart_flush;
|
||||
hdev->send = hci_uart_send_frame;
|
||||
hdev->parent = hu->tty->dev;
|
||||
SET_HCIDEV_DEV(hdev, hu->tty->dev);
|
||||
|
||||
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
|
|
@ -252,8 +252,9 @@ static int vhci_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
file->private_data = data;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vhci_release(struct inode *inode, struct file *file)
|
||||
|
|
|
@ -693,8 +693,8 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
|
|||
ie, 2 + vif->ssid_len + beacon_ie_len,
|
||||
0, GFP_KERNEL);
|
||||
if (bss)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
|
||||
"cfg80211\n", bssid);
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"added bss %pM to cfg80211\n", bssid);
|
||||
kfree(ie);
|
||||
} else
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
|
||||
|
@ -882,6 +882,32 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
vif->sme_state = SME_DISCONNECTED;
|
||||
}
|
||||
|
||||
static int ath6kl_set_probed_ssids(struct ath6kl *ar,
|
||||
struct ath6kl_vif *vif,
|
||||
struct cfg80211_ssid *ssids, int n_ssids)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (n_ssids > MAX_PROBED_SSID_INDEX)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < n_ssids; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
|
||||
ssids[i].ssid_len ?
|
||||
SPECIFIC_SSID_FLAG : ANY_SSID_FLAG,
|
||||
ssids[i].ssid_len,
|
||||
ssids[i].ssid);
|
||||
}
|
||||
|
||||
/* Make sure no old entries are left behind */
|
||||
for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
|
||||
DISABLE_SSID_FLAG, 0, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
|
@ -899,36 +925,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
if (!ar->usr_bss_filter) {
|
||||
clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
|
||||
ret = ath6kl_wmi_bssfilter_cmd(
|
||||
ar->wmi, vif->fw_vif_idx,
|
||||
(test_bit(CONNECTED, &vif->flags) ?
|
||||
ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
|
||||
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ALL_BSS_FILTER, 0);
|
||||
if (ret) {
|
||||
ath6kl_err("couldn't set bss filtering\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (request->n_ssids && request->ssids[0].ssid_len) {
|
||||
u8 i;
|
||||
|
||||
if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
|
||||
request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
|
||||
|
||||
for (i = 0; i < request->n_ssids; i++)
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
i + 1, SPECIFIC_SSID_FLAG,
|
||||
request->ssids[i].ssid_len,
|
||||
request->ssids[i].ssid);
|
||||
}
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* this also clears IE in fw if it's not set */
|
||||
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WMI_FRAME_PROBE_REQ,
|
||||
request->ie, request->ie_len);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to set Probe Request appie for "
|
||||
"scan");
|
||||
ath6kl_err("failed to set Probe Request appie for scan");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -945,8 +960,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
|
||||
if (channels == NULL) {
|
||||
ath6kl_warn("failed to set scan channels, "
|
||||
"scan all channels");
|
||||
ath6kl_warn("failed to set scan channels, scan all channels");
|
||||
n_channels = 0;
|
||||
}
|
||||
|
||||
|
@ -1018,6 +1032,20 @@ out:
|
|||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||
enum wmi_phy_mode mode)
|
||||
{
|
||||
enum nl80211_channel_type type;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"channel switch notify nw_type %d freq %d mode %d\n",
|
||||
vif->nw_type, freq, mode);
|
||||
|
||||
type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
|
||||
|
||||
cfg80211_ch_switch_notify(vif->ndev, freq, type);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr,
|
||||
|
@ -1111,9 +1139,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
|||
ar->ap_mode_bkey.key_len = key->key_len;
|
||||
memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
|
||||
if (!test_bit(CONNECTED, &vif->flags)) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
|
||||
"key configuration until AP mode has been "
|
||||
"started\n");
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"Delay initial group key configuration until AP mode has been started\n");
|
||||
/*
|
||||
* The key will be set in ath6kl_connect_ap_mode() once
|
||||
* the connected event is received from the target.
|
||||
|
@ -1129,8 +1156,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
|||
* the AP mode has properly started
|
||||
* (ath6kl_install_statioc_wep_keys).
|
||||
*/
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
|
||||
"until AP mode has been started\n");
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"Delay WEP key configuration until AP mode has been started\n");
|
||||
vif->wep_key_list[key_index].key_len = key->key_len;
|
||||
memcpy(vif->wep_key_list[key_index].key, key->key,
|
||||
key->key_len);
|
||||
|
@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
|
|||
sizeof(discvr_pattern), discvr_offset,
|
||||
discvr_pattern, discvr_mask);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
|
||||
"pattern\n");
|
||||
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
u8 index = 0;
|
||||
__be32 ips[MAX_IP_ADDRS];
|
||||
|
||||
/* The FW currently can't support multi-vif WoW properly. */
|
||||
if (ar->num_vif > 1)
|
||||
return -EIO;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif)
|
||||
return -EIO;
|
||||
|
@ -2044,6 +2074,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clear existing WOW patterns */
|
||||
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
|
||||
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
|
@ -2147,8 +2184,8 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_HOST_MODE_AWAKE);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to configure host sleep mode for "
|
||||
"wow resume: %d\n", ret);
|
||||
ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
|
||||
ret);
|
||||
ar->state = ATH6KL_STATE_WOW;
|
||||
return ret;
|
||||
}
|
||||
|
@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
netif_wake_queue(vif->ndev);
|
||||
|
||||
return 0;
|
||||
|
@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
|
|||
if (!vif)
|
||||
return -EIO;
|
||||
|
||||
if (!ath6kl_cfg80211_ready(vif))
|
||||
if (!test_bit(WMI_READY, &ar->flag)) {
|
||||
ath6kl_err("deepsleep failed as wmi is not ready\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ath6kl_cfg80211_stop_all(ar);
|
||||
|
||||
|
@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
|
|||
band, htcap);
|
||||
}
|
||||
|
||||
static int ath6kl_restore_htcap(struct ath6kl_vif *vif)
|
||||
{
|
||||
struct wiphy *wiphy = vif->ar->wiphy;
|
||||
int band, ret = 0;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
|
||||
ret = ath6kl_set_htcap(vif, band,
|
||||
wiphy->bands[band]->ht_cap.ht_supported);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool ath6kl_is_p2p_ie(const u8 *pos)
|
||||
{
|
||||
return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
|
@ -2568,28 +2632,34 @@ static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
|
|||
/* skip element id and length */
|
||||
rsn_ie += 2;
|
||||
|
||||
/* skip version, group cipher */
|
||||
if (rsn_ie_len < 6)
|
||||
/* skip version */
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
rsn_ie += 6;
|
||||
rsn_ie_len -= 6;
|
||||
rsn_ie += 2;
|
||||
rsn_ie_len -= 2;
|
||||
|
||||
/* skip group cipher suite */
|
||||
if (rsn_ie_len < 4)
|
||||
return 0;
|
||||
rsn_ie += 4;
|
||||
rsn_ie_len -= 4;
|
||||
|
||||
/* skip pairwise cipher suite */
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
cnt = *((u16 *) rsn_ie);
|
||||
return 0;
|
||||
cnt = get_unaligned_le16(rsn_ie);
|
||||
rsn_ie += (2 + cnt * 4);
|
||||
rsn_ie_len -= (2 + cnt * 4);
|
||||
|
||||
/* skip akm suite */
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
cnt = *((u16 *) rsn_ie);
|
||||
return 0;
|
||||
cnt = get_unaligned_le16(rsn_ie);
|
||||
rsn_ie += (2 + cnt * 4);
|
||||
rsn_ie_len -= (2 + cnt * 4);
|
||||
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
memcpy(rsn_capab, rsn_ie, 2);
|
||||
|
||||
|
@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
return res;
|
||||
}
|
||||
|
||||
memcpy(&vif->profile, &p, sizeof(p));
|
||||
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
clear_bit(CONNECTED, &vif->flags);
|
||||
|
||||
/* Restore ht setting in firmware */
|
||||
if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true))
|
||||
return -EIO;
|
||||
|
||||
if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
return ath6kl_restore_htcap(vif);
|
||||
}
|
||||
|
||||
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
@ -3081,7 +3146,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
u16 interval;
|
||||
int ret;
|
||||
u8 i;
|
||||
|
||||
if (ar->state != ATH6KL_STATE_ON)
|
||||
return -EIO;
|
||||
|
@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
if (vif->sme_state != SME_DISCONNECTED)
|
||||
return -EBUSY;
|
||||
|
||||
/* The FW currently can't support multi-vif WoW properly. */
|
||||
if (ar->num_vif > 1)
|
||||
return -EIO;
|
||||
|
||||
ath6kl_cfg80211_scan_complete_event(vif, true);
|
||||
|
||||
for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
i, DISABLE_SSID_FLAG,
|
||||
0, NULL);
|
||||
}
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* fw uses seconds, also make sure that it's >0 */
|
||||
interval = max_t(u16, 1, request->interval / 1000);
|
||||
|
||||
ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
interval, interval,
|
||||
10, 0, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
if (request->n_ssids && request->ssids[0].ssid_len) {
|
||||
for (i = 0; i < request->n_ssids; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
i, SPECIFIC_SSID_FLAG,
|
||||
request->ssids[i].ssid_len,
|
||||
request->ssids[i].ssid);
|
||||
}
|
||||
}
|
||||
vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_WOW_MODE_ENABLE,
|
||||
|
@ -3271,8 +3329,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
|
|||
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
|
||||
|
||||
if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
|
||||
ath6kl_warn("ath6kl_deep_sleep_enable: "
|
||||
"wmi_powermode_cmd failed\n");
|
||||
ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
|||
vif->next_mode = nw_type;
|
||||
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
||||
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
||||
vif->bg_scan_period = 0;
|
||||
vif->htcap.ht_enable = true;
|
||||
|
||||
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
||||
|
@ -3393,6 +3451,7 @@ err:
|
|||
int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||
{
|
||||
struct wiphy *wiphy = ar->wiphy;
|
||||
bool band_2gig = false, band_5gig = false, ht = false;
|
||||
int ret;
|
||||
|
||||
wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
|
||||
|
@ -3413,8 +3472,46 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
/* max num of ssids that can be probed during scanning */
|
||||
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
|
||||
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
|
||||
switch (ar->hw.cap) {
|
||||
case WMI_11AN_CAP:
|
||||
ht = true;
|
||||
case WMI_11A_CAP:
|
||||
band_5gig = true;
|
||||
break;
|
||||
case WMI_11GN_CAP:
|
||||
ht = true;
|
||||
case WMI_11G_CAP:
|
||||
band_2gig = true;
|
||||
break;
|
||||
case WMI_11AGN_CAP:
|
||||
ht = true;
|
||||
case WMI_11AG_CAP:
|
||||
band_2gig = true;
|
||||
band_5gig = true;
|
||||
break;
|
||||
default:
|
||||
ath6kl_err("invalid phy capability!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if the fw has HT support, advertise HT cap only when
|
||||
* the firmware has support to override RSN capability, otherwise
|
||||
* 4-way handshake would fail.
|
||||
*/
|
||||
if (!(ht &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
|
||||
ar->fw_capabilities))) {
|
||||
ath6kl_band_2ghz.ht_cap.cap = 0;
|
||||
ath6kl_band_2ghz.ht_cap.ht_supported = false;
|
||||
ath6kl_band_5ghz.ht_cap.cap = 0;
|
||||
ath6kl_band_5ghz.ht_cap.ht_supported = false;
|
||||
}
|
||||
if (band_2gig)
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
|
||||
if (band_5gig)
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
|
||||
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
|
||||
wiphy->cipher_suites = cipher_suites;
|
||||
|
@ -3430,7 +3527,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
wiphy->wowlan.pattern_min_len = 1;
|
||||
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
|
||||
|
||||
wiphy->max_sched_scan_ssids = 10;
|
||||
wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;
|
||||
|
||||
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
|
||||
WIPHY_FLAG_HAVE_AP_SME |
|
||||
|
@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
ar->wiphy->probe_resp_offload =
|
||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
|
||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
|
||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
|
||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
|
||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
|
||||
|
||||
ret = wiphy_register(wiphy);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode {
|
|||
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
||||
enum nl80211_iftype type,
|
||||
u8 fw_vif_idx, u8 nw_type);
|
||||
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||
enum wmi_phy_mode mode);
|
||||
void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
|
||||
|
||||
void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||
|
|
|
@ -126,9 +126,9 @@ struct ath6kl_fw_ie {
|
|||
#define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77"
|
||||
#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin"
|
||||
#define AR6003_HW_2_0_PATCH_FILE "data.patch.bin"
|
||||
#define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
|
||||
#define AR6003_HW_2_0_BOARD_DATA_FILE AR6003_HW_2_0_FW_DIR "/bdata.bin"
|
||||
#define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \
|
||||
"ath6k/AR6003/hw2.0/bdata.SD31.bin"
|
||||
AR6003_HW_2_0_FW_DIR "/bdata.SD31.bin"
|
||||
|
||||
/* AR6003 3.0 definitions */
|
||||
#define AR6003_HW_2_1_1_VERSION 0x30000582
|
||||
|
@ -139,25 +139,33 @@ struct ath6kl_fw_ie {
|
|||
#define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin"
|
||||
#define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin"
|
||||
#define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin"
|
||||
#define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
|
||||
#define AR6003_HW_2_1_1_BOARD_DATA_FILE AR6003_HW_2_1_1_FW_DIR "/bdata.bin"
|
||||
#define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \
|
||||
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
|
||||
AR6003_HW_2_1_1_FW_DIR "/bdata.SD31.bin"
|
||||
|
||||
/* AR6004 1.0 definitions */
|
||||
#define AR6004_HW_1_0_VERSION 0x30000623
|
||||
#define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0"
|
||||
#define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin"
|
||||
#define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin"
|
||||
#define AR6004_HW_1_0_BOARD_DATA_FILE AR6004_HW_1_0_FW_DIR "/bdata.bin"
|
||||
#define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \
|
||||
"ath6k/AR6004/hw1.0/bdata.DB132.bin"
|
||||
AR6004_HW_1_0_FW_DIR "/bdata.DB132.bin"
|
||||
|
||||
/* AR6004 1.1 definitions */
|
||||
#define AR6004_HW_1_1_VERSION 0x30000001
|
||||
#define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1"
|
||||
#define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin"
|
||||
#define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin"
|
||||
#define AR6004_HW_1_1_BOARD_DATA_FILE AR6004_HW_1_1_FW_DIR "/bdata.bin"
|
||||
#define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \
|
||||
"ath6k/AR6004/hw1.1/bdata.DB132.bin"
|
||||
AR6004_HW_1_1_FW_DIR "/bdata.DB132.bin"
|
||||
|
||||
/* AR6004 1.2 definitions */
|
||||
#define AR6004_HW_1_2_VERSION 0x300007e8
|
||||
#define AR6004_HW_1_2_FW_DIR "ath6k/AR6004/hw1.2"
|
||||
#define AR6004_HW_1_2_FIRMWARE_FILE "fw.ram.bin"
|
||||
#define AR6004_HW_1_2_BOARD_DATA_FILE AR6004_HW_1_2_FW_DIR "/bdata.bin"
|
||||
#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
|
||||
AR6004_HW_1_2_FW_DIR "/bdata.bin"
|
||||
|
||||
/* Per STA data, used in AP mode */
|
||||
#define STA_PS_AWAKE BIT(0)
|
||||
|
@ -502,6 +510,8 @@ enum ath6kl_vif_state {
|
|||
WLAN_ENABLED,
|
||||
STATS_UPDATE_PEND,
|
||||
HOST_SLEEP_MODE_CMD_PROCESSED,
|
||||
NETDEV_MCAST_ALL_ON,
|
||||
NETDEV_MCAST_ALL_OFF,
|
||||
};
|
||||
|
||||
struct ath6kl_vif {
|
||||
|
@ -549,9 +559,11 @@ struct ath6kl_vif {
|
|||
u16 assoc_bss_beacon_int;
|
||||
u16 listen_intvl_t;
|
||||
u16 bmiss_time_t;
|
||||
u16 bg_scan_period;
|
||||
u8 assoc_bss_dtim_period;
|
||||
struct net_device_stats net_stats;
|
||||
struct target_stats target_stats;
|
||||
struct wmi_connect_cmd profile;
|
||||
|
||||
struct list_head mc_filter;
|
||||
};
|
||||
|
@ -640,6 +652,7 @@ struct ath6kl {
|
|||
u8 sta_list_index;
|
||||
struct ath6kl_req_key ap_mode_bkey;
|
||||
struct sk_buff_head mcastpsq;
|
||||
u32 want_ch_switch;
|
||||
|
||||
/*
|
||||
* FIXME: protects access to mcastpsq but is actually useless as
|
||||
|
@ -672,6 +685,7 @@ struct ath6kl {
|
|||
u32 refclk_hz;
|
||||
u32 uarttx_pin;
|
||||
u32 testscript_addr;
|
||||
enum wmi_phy_cap cap;
|
||||
|
||||
struct ath6kl_hw_fw {
|
||||
const char *dir;
|
||||
|
@ -805,7 +819,8 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn);
|
|||
struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr);
|
||||
struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
|
||||
|
||||
void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver);
|
||||
void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
|
||||
enum wmi_phy_cap cap);
|
||||
int ath6kl_control_tx(void *devt, struct sk_buff *skb,
|
||||
enum htc_endpoint_id eid);
|
||||
void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||
|
|
|
@ -401,8 +401,10 @@ static ssize_t ath6kl_fwlog_block_read(struct file *file,
|
|||
|
||||
ret = wait_for_completion_interruptible(
|
||||
&ar->debug.fwlog_completion);
|
||||
if (ret == -ERESTARTSYS)
|
||||
if (ret == -ERESTARTSYS) {
|
||||
vfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock(&ar->debug.fwlog_queue.lock);
|
||||
}
|
||||
|
@ -1570,10 +1572,15 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
struct ath6kl_vif *vif;
|
||||
u16 bgscan_int;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif)
|
||||
return -EIO;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
@ -1585,6 +1592,8 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file,
|
|||
if (bgscan_int == 0)
|
||||
bgscan_int = 0xffff;
|
||||
|
||||
vif->bg_scan_period = bgscan_int;
|
||||
|
||||
ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3,
|
||||
0, 0, 0);
|
||||
|
||||
|
@ -1809,6 +1818,7 @@ int ath6kl_debug_init_fs(struct ath6kl *ar)
|
|||
void ath6kl_debug_cleanup(struct ath6kl *ar)
|
||||
{
|
||||
skb_queue_purge(&ar->debug.fwlog_queue);
|
||||
complete(&ar->debug.fwlog_completion);
|
||||
kfree(ar->debug.roam_tbl);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,10 +83,7 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info,
|
|||
* never goes inactive EVER.
|
||||
*/
|
||||
cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
|
||||
} else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC)
|
||||
/* this is the lowest priority data endpoint */
|
||||
/* FIXME: this looks fishy, check */
|
||||
cred_info->lowestpri_ep_dist = cur_ep_dist->list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Streams have to be created (explicit | implicit) for all
|
||||
|
@ -100,6 +97,13 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info,
|
|||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* For ath6kl_credit_seek function,
|
||||
* it use list_for_each_entry_reverse to walk around the whole ep list.
|
||||
* Therefore assign this lowestpri_ep_dist after walk around the ep_list
|
||||
*/
|
||||
cred_info->lowestpri_ep_dist = cur_ep_dist->list;
|
||||
|
||||
WARN_ON(cred_info->cur_free_credits <= 0);
|
||||
|
||||
list_for_each_entry(cur_ep_dist, ep_list, list) {
|
||||
|
@ -758,7 +762,7 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
|
|||
u32 txb_mask;
|
||||
u8 ac = WMM_NUM_AC;
|
||||
|
||||
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
|
||||
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) &&
|
||||
(WMI_CONTROL_SVC != endpoint->svc_id))
|
||||
ac = target->dev->ar->ep2ac_map[endpoint->eid];
|
||||
|
||||
|
@ -793,16 +797,17 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
|
|||
* itself
|
||||
*/
|
||||
txb_mask = ((1 << ac) - 1);
|
||||
/*
|
||||
* when the scatter request resources drop below a
|
||||
* certain threshold, disable Tx bundling for all
|
||||
* AC's with priority lower than the current requesting
|
||||
* AC. Otherwise re-enable Tx bundling for them
|
||||
*/
|
||||
if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS)
|
||||
target->tx_bndl_mask &= ~txb_mask;
|
||||
else
|
||||
target->tx_bndl_mask |= txb_mask;
|
||||
|
||||
/*
|
||||
* when the scatter request resources drop below a
|
||||
* certain threshold, disable Tx bundling for all
|
||||
* AC's with priority lower than the current requesting
|
||||
* AC. Otherwise re-enable Tx bundling for them
|
||||
*/
|
||||
if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS)
|
||||
target->tx_bndl_mask &= ~txb_mask;
|
||||
else
|
||||
target->tx_bndl_mask |= txb_mask;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n",
|
||||
|
@ -849,6 +854,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
|
|||
int bundle_sent;
|
||||
int n_pkts_bundle;
|
||||
u8 ac = WMM_NUM_AC;
|
||||
int status;
|
||||
|
||||
spin_lock_bh(&target->tx_lock);
|
||||
|
||||
|
@ -866,7 +872,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
|
|||
*/
|
||||
INIT_LIST_HEAD(&txq);
|
||||
|
||||
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
|
||||
if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) &&
|
||||
(WMI_CONTROL_SVC != endpoint->svc_id))
|
||||
ac = target->dev->ar->ep2ac_map[endpoint->eid];
|
||||
|
||||
|
@ -910,7 +916,12 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
|
|||
|
||||
ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags,
|
||||
0, packet->info.tx.seqno);
|
||||
ath6kl_htc_tx_issue(target, packet);
|
||||
status = ath6kl_htc_tx_issue(target, packet);
|
||||
|
||||
if (status) {
|
||||
packet->status = status;
|
||||
packet->completion(packet->context, packet);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_bh(&target->tx_lock);
|
||||
|
|
|
@ -108,8 +108,6 @@ static void get_htc_packet_credit_based(struct htc_target *target,
|
|||
|
||||
/* get packet at head, but don't remove it */
|
||||
packet = list_first_entry(&ep->txq, struct htc_packet, list);
|
||||
if (packet == NULL)
|
||||
break;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC,
|
||||
"%s: got head packet:0x%p , queue depth: %d\n",
|
||||
|
@ -803,8 +801,6 @@ static int htc_send_packets_multiple(struct htc_target *target,
|
|||
|
||||
/* get first packet to find out which ep the packets will go into */
|
||||
packet = list_first_entry(pkt_queue, struct htc_packet, list);
|
||||
if (packet == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (packet->endpoint >= ENDPOINT_MAX) {
|
||||
WARN_ON_ONCE(1);
|
||||
|
@ -1382,6 +1378,9 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target,
|
|||
/* copy all the callbacks */
|
||||
ep->ep_cb = conn_req->ep_cb;
|
||||
|
||||
/* initialize tx_drop_packet_threshold */
|
||||
ep->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM;
|
||||
|
||||
status = ath6kl_hif_pipe_map_service(ar, ep->svc_id,
|
||||
&ep->pipe.pipeid_ul,
|
||||
&ep->pipe.pipeid_dl);
|
||||
|
@ -1636,10 +1635,6 @@ static int ath6kl_htc_pipe_add_rxbuf_multiple(struct htc_target *target,
|
|||
return -EINVAL;
|
||||
|
||||
first = list_first_entry(pkt_queue, struct htc_packet, list);
|
||||
if (first == NULL) {
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (first->endpoint >= ENDPOINT_MAX) {
|
||||
WARN_ON_ONCE(1);
|
||||
|
|
|
@ -119,6 +119,24 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.fw_board = AR6004_HW_1_1_BOARD_DATA_FILE,
|
||||
.fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE,
|
||||
},
|
||||
{
|
||||
.id = AR6004_HW_1_2_VERSION,
|
||||
.name = "ar6004 hw 1.2",
|
||||
.dataset_patch_addr = 0x436ecc,
|
||||
.app_load_addr = 0x1234,
|
||||
.board_ext_data_addr = 0x437000,
|
||||
.reserved_ram_size = 9216,
|
||||
.board_addr = 0x435c00,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_2_FW_DIR,
|
||||
.fw = AR6004_HW_1_2_FIRMWARE_FILE,
|
||||
},
|
||||
.fw_board = AR6004_HW_1_2_BOARD_DATA_FILE,
|
||||
.fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -445,9 +463,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
|
|||
P2P_FLAG_MACADDR_REQ |
|
||||
P2P_FLAG_HMODEL_REQ);
|
||||
if (ret) {
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P "
|
||||
"capabilities (%d) - assuming P2P not "
|
||||
"supported\n", ret);
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC,
|
||||
"failed to request P2P capabilities (%d) - assuming P2P not supported\n",
|
||||
ret);
|
||||
ar->p2p = false;
|
||||
}
|
||||
}
|
||||
|
@ -456,8 +474,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
|
|||
/* Enable Probe Request reporting for P2P */
|
||||
ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
|
||||
if (ret) {
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
|
||||
"Request reporting (%d)\n", ret);
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC,
|
||||
"failed to enable Probe Request reporting (%d)\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -421,8 +421,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
|
|||
if (!ik->valid)
|
||||
break;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
|
||||
"the initial group key for AP mode\n");
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"Delayed addkey for the initial group key for AP mode\n");
|
||||
memset(key_rsc, 0, sizeof(key_rsc));
|
||||
res = ath6kl_wmi_addkey_cmd(
|
||||
ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type,
|
||||
|
@ -430,12 +430,19 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
|
|||
ik->key,
|
||||
KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
|
||||
if (res) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
|
||||
"addkey failed: %d\n", res);
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"Delayed addkey failed: %d\n", res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
|
||||
ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
|
||||
/* we actually don't know the phymode, default to HT20 */
|
||||
ath6kl_cfg80211_ch_switch_notify(vif, channel,
|
||||
WMI_11G_HT20);
|
||||
}
|
||||
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
|
||||
set_bit(CONNECTED, &vif->flags);
|
||||
netif_carrier_on(vif->ndev);
|
||||
|
@ -541,7 +548,8 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
|
|||
|
||||
/* WMI Event handlers */
|
||||
|
||||
void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
|
||||
void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
|
||||
enum wmi_phy_cap cap)
|
||||
{
|
||||
struct ath6kl *ar = devt;
|
||||
|
||||
|
@ -551,6 +559,7 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
|
|||
|
||||
ar->version.wlan_ver = sw_ver;
|
||||
ar->version.abi_ver = abi_ver;
|
||||
ar->hw.cap = cap;
|
||||
|
||||
snprintf(ar->wiphy->fw_version,
|
||||
sizeof(ar->wiphy->fw_version),
|
||||
|
@ -584,6 +593,45 @@ void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
|
|||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status);
|
||||
}
|
||||
|
||||
static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
|
||||
{
|
||||
|
||||
struct ath6kl *ar = vif->ar;
|
||||
|
||||
vif->next_chan = channel;
|
||||
vif->profile.ch = cpu_to_le16(channel);
|
||||
|
||||
switch (vif->nw_type) {
|
||||
case AP_NETWORK:
|
||||
return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
|
||||
&vif->profile);
|
||||
default:
|
||||
ath6kl_err("won't switch channels nw_type=%d\n", vif->nw_type);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
|
||||
{
|
||||
|
||||
struct ath6kl_vif *vif;
|
||||
int res = 0;
|
||||
|
||||
if (!ar->want_ch_switch)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&ar->list_lock);
|
||||
list_for_each_entry(vif, &ar->vif_list, list) {
|
||||
if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
|
||||
res = ath6kl_commit_ch_switch(vif, channel);
|
||||
|
||||
if (res)
|
||||
ath6kl_err("channel switch failed nw_type %d res %d\n",
|
||||
vif->nw_type, res);
|
||||
}
|
||||
spin_unlock_bh(&ar->list_lock);
|
||||
}
|
||||
|
||||
void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
|
||||
u16 listen_int, u16 beacon_int,
|
||||
enum network_type net_type, u8 beacon_ie_len,
|
||||
|
@ -601,9 +649,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
|
|||
memcpy(vif->bssid, bssid, sizeof(vif->bssid));
|
||||
vif->bss_ch = channel;
|
||||
|
||||
if ((vif->nw_type == INFRA_NETWORK))
|
||||
if ((vif->nw_type == INFRA_NETWORK)) {
|
||||
ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
vif->listen_intvl_t, 0);
|
||||
ath6kl_check_ch_switch(ar, channel);
|
||||
}
|
||||
|
||||
netif_wake_queue(vif->ndev);
|
||||
|
||||
|
@ -926,6 +976,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
|
|||
struct ath6kl *ar = vif->ar;
|
||||
|
||||
if (vif->nw_type == AP_NETWORK) {
|
||||
/* disconnect due to other STA vif switching channels */
|
||||
if (reason == BSS_DISCONNECTED &&
|
||||
prot_reason_status == WMI_AP_REASON_STA_ROAM)
|
||||
ar->want_ch_switch |= 1 << vif->fw_vif_idx;
|
||||
|
||||
if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
|
||||
return;
|
||||
|
||||
|
@ -1090,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev,
|
|||
static void ath6kl_set_multicast_list(struct net_device *ndev)
|
||||
{
|
||||
struct ath6kl_vif *vif = netdev_priv(ndev);
|
||||
bool mc_all_on = false, mc_all_off = false;
|
||||
bool mc_all_on = false;
|
||||
int mc_count = netdev_mc_count(ndev);
|
||||
struct netdev_hw_addr *ha;
|
||||
bool found;
|
||||
|
@ -1102,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
|
|||
!test_bit(WLAN_ENABLED, &vif->flags))
|
||||
return;
|
||||
|
||||
/* Enable multicast-all filter. */
|
||||
mc_all_on = !!(ndev->flags & IFF_PROMISC) ||
|
||||
!!(ndev->flags & IFF_ALLMULTI) ||
|
||||
!!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST);
|
||||
|
||||
mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0;
|
||||
if (mc_all_on)
|
||||
set_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
|
||||
else
|
||||
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
|
||||
|
||||
if (mc_all_on || mc_all_off) {
|
||||
/* Enable/disable all multicast */
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n",
|
||||
mc_all_on ? "enabling" : "disabling");
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
|
||||
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
|
||||
|
||||
if (!(ndev->flags & IFF_MULTICAST)) {
|
||||
mc_all_on = false;
|
||||
set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
|
||||
} else {
|
||||
clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
|
||||
}
|
||||
|
||||
/* Enable/disable "multicast-all" filter*/
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n",
|
||||
mc_all_on ? "enabling" : "disabling");
|
||||
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
|
||||
mc_all_on);
|
||||
if (ret)
|
||||
ath6kl_warn("Failed to %s multicast receive\n",
|
||||
mc_all_on ? "enable" : "disable");
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to %s multicast-all receive\n",
|
||||
mc_all_on ? "enable" : "disable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags))
|
||||
return;
|
||||
|
||||
/* Keep the driver and firmware mcast list in sync. */
|
||||
list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
|
||||
found = false;
|
||||
netdev_for_each_mc_addr(ha, ndev) {
|
||||
|
|
|
@ -552,7 +552,7 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
|
|||
|
||||
bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
|
||||
|
||||
if (!bus_req)
|
||||
if (WARN_ON_ONCE(!bus_req))
|
||||
return -ENOMEM;
|
||||
|
||||
bus_req->address = address;
|
||||
|
@ -915,6 +915,9 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
}
|
||||
|
||||
cut_pwr:
|
||||
if (func->card && func->card->host)
|
||||
func->card->host->pm_flags &= ~MMC_PM_KEEP_POWER;
|
||||
|
||||
return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL);
|
||||
}
|
||||
|
||||
|
@ -985,9 +988,8 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
|
|||
}
|
||||
|
||||
if (status) {
|
||||
ath6kl_err("%s: failed to write initial bytes of 0x%x "
|
||||
"to window reg: 0x%X\n", __func__,
|
||||
addr, reg_addr);
|
||||
ath6kl_err("%s: failed to write initial bytes of 0x%x to window reg: 0x%X\n",
|
||||
__func__, addr, reg_addr);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1076,8 +1078,8 @@ static int ath6kl_sdio_bmi_credits(struct ath6kl *ar)
|
|||
(u8 *)&ar->bmi.cmd_credits, 4,
|
||||
HIF_RD_SYNC_BYTE_INC);
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to decrement the command credit "
|
||||
"count register: %d\n", ret);
|
||||
ath6kl_err("Unable to decrement the command credit count register: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1457,3 +1459,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);
|
|||
MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
|
||||
|
|
|
@ -362,15 +362,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
|
|||
skb, skb->data, skb->len);
|
||||
|
||||
/* If target is not associated */
|
||||
if (!test_bit(CONNECTED, &vif->flags)) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (!test_bit(CONNECTED, &vif->flags))
|
||||
goto fail_tx;
|
||||
|
||||
if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON))
|
||||
goto fail_tx;
|
||||
|
||||
if (!test_bit(WMI_READY, &ar->flag))
|
||||
goto fail_tx;
|
||||
|
|
|
@ -1037,6 +1037,14 @@ static void ath6kl_usb_stop(struct ath6kl *ar)
|
|||
hif_stop(ar);
|
||||
}
|
||||
|
||||
static void ath6kl_usb_cleanup_scatter(struct ath6kl *ar)
|
||||
{
|
||||
/*
|
||||
* USB doesn't support it. Just return.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct ath6kl_hif_ops ath6kl_usb_ops = {
|
||||
.diag_read32 = ath6kl_usb_diag_read32,
|
||||
.diag_write32 = ath6kl_usb_diag_write32,
|
||||
|
@ -1049,6 +1057,7 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = {
|
|||
.pipe_get_default = ath6kl_usb_get_default_pipe,
|
||||
.pipe_map_service = ath6kl_usb_map_service_pipe,
|
||||
.pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number,
|
||||
.cleanup_scatter = ath6kl_usb_cleanup_scatter,
|
||||
};
|
||||
|
||||
/* ath6kl usb driver registered functions */
|
||||
|
@ -1207,3 +1216,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);
|
|||
MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/in.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "testmode.h"
|
||||
|
@ -289,6 +290,13 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx,
|
|||
layer2_priority);
|
||||
} else
|
||||
usr_pri = layer2_priority & 0x7;
|
||||
|
||||
/*
|
||||
* Queue the EAPOL frames in the same WMM_AC_VO queue
|
||||
* as that of management frames.
|
||||
*/
|
||||
if (skb->protocol == cpu_to_be16(ETH_P_PAE))
|
||||
usr_pri = WMI_VOICE_USER_PRIORITY;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -460,8 +468,9 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
|
|||
freq, dur);
|
||||
chan = ieee80211_get_channel(ar->wiphy, freq);
|
||||
if (!chan) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel "
|
||||
"(freq=%u)\n", freq);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"remain_on_chnl: Unknown channel (freq=%u)\n",
|
||||
freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
id = vif->last_roc_id;
|
||||
|
@ -488,12 +497,14 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
|
|||
ev = (struct wmi_cancel_remain_on_chnl_event *) datap;
|
||||
freq = le32_to_cpu(ev->freq);
|
||||
dur = le32_to_cpu(ev->duration);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u "
|
||||
"status=%u\n", freq, dur, ev->status);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"cancel_remain_on_chnl: freq=%u dur=%u status=%u\n",
|
||||
freq, dur, ev->status);
|
||||
chan = ieee80211_get_channel(ar->wiphy, freq);
|
||||
if (!chan) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown "
|
||||
"channel (freq=%u)\n", freq);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"cancel_remain_on_chnl: Unknown channel (freq=%u)\n",
|
||||
freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (vif->last_cancel_roc_id &&
|
||||
|
@ -548,12 +559,12 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
freq = le32_to_cpu(ev->freq);
|
||||
dlen = le16_to_cpu(ev->len);
|
||||
if (datap + len < ev->data + dlen) {
|
||||
ath6kl_err("invalid wmi_p2p_rx_probe_req_event: "
|
||||
"len=%d dlen=%u\n", len, dlen);
|
||||
ath6kl_err("invalid wmi_p2p_rx_probe_req_event: len=%d dlen=%u\n",
|
||||
len, dlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u "
|
||||
"probe_req_report=%d\n",
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"rx_probe_req: len=%u freq=%u probe_req_report=%d\n",
|
||||
dlen, freq, vif->probe_req_report);
|
||||
|
||||
if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
|
||||
|
@ -592,8 +603,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
freq = le32_to_cpu(ev->freq);
|
||||
dlen = le16_to_cpu(ev->len);
|
||||
if (datap + len < ev->data + dlen) {
|
||||
ath6kl_err("invalid wmi_rx_action_event: "
|
||||
"len=%d dlen=%u\n", len, dlen);
|
||||
ath6kl_err("invalid wmi_rx_action_event: len=%d dlen=%u\n",
|
||||
len, dlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
|
||||
|
@ -687,7 +698,7 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
|
|||
|
||||
ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,
|
||||
le32_to_cpu(ev->sw_version),
|
||||
le32_to_cpu(ev->abi_version));
|
||||
le32_to_cpu(ev->abi_version), ev->phy_cap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -777,16 +788,15 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
/* AP mode start/STA connected event */
|
||||
struct net_device *dev = vif->ndev;
|
||||
if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM "
|
||||
"(AP started)\n",
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"%s: freq %d bssid %pM (AP started)\n",
|
||||
__func__, le16_to_cpu(ev->u.ap_bss.ch),
|
||||
ev->u.ap_bss.bssid);
|
||||
ath6kl_connect_ap_mode_bss(
|
||||
vif, le16_to_cpu(ev->u.ap_bss.ch));
|
||||
} else {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM "
|
||||
"auth=%u keymgmt=%u cipher=%u apsd_info=%u "
|
||||
"(STA connected)\n",
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"%s: aid %u mac_addr %pM auth=%u keymgmt=%u cipher=%u apsd_info=%u (STA connected)\n",
|
||||
__func__, ev->u.ap_sta.aid,
|
||||
ev->u.ap_sta.mac_addr,
|
||||
ev->u.ap_sta.auth,
|
||||
|
@ -1229,8 +1239,9 @@ static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,
|
|||
ev = (struct wmi_neighbor_report_event *) datap;
|
||||
if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info)
|
||||
> len) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event "
|
||||
"(num=%d len=%d)\n", ev->num_neighbors, len);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"truncated neighbor event (num=%d len=%d)\n",
|
||||
ev->num_neighbors, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < ev->num_neighbors; i++) {
|
||||
|
@ -1814,12 +1825,14 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
|||
u32 home_dwell_time, u32 force_scan_interval,
|
||||
s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct sk_buff *skb;
|
||||
struct wmi_begin_scan_cmd *sc;
|
||||
s8 size;
|
||||
s8 size, *supp_rates;
|
||||
int i, band, ret;
|
||||
struct ath6kl *ar = wmi->parent_dev;
|
||||
int num_rates;
|
||||
u32 ratemask;
|
||||
|
||||
size = sizeof(struct wmi_begin_scan_cmd);
|
||||
|
||||
|
@ -1846,10 +1859,13 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
|||
sc->num_ch = num_chan;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
struct ieee80211_supported_band *sband =
|
||||
ar->wiphy->bands[band];
|
||||
u32 ratemask = rates[band];
|
||||
u8 *supp_rates = sc->supp_rates[band].rates;
|
||||
sband = ar->wiphy->bands[band];
|
||||
|
||||
if (!sband)
|
||||
continue;
|
||||
|
||||
ratemask = rates[band];
|
||||
supp_rates = sc->supp_rates[band].rates;
|
||||
num_rates = 0;
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
|
@ -2129,8 +2145,8 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
|
|||
struct wmi_add_cipher_key_cmd *cmd;
|
||||
int ret;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d "
|
||||
"key_usage=%d key_len=%d key_op_ctrl=%d\n",
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"addkey cmd: key_index=%u key_type=%d key_usage=%d key_len=%d key_op_ctrl=%d\n",
|
||||
key_index, key_type, key_usage, key_len, key_op_ctrl);
|
||||
|
||||
if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
|
||||
|
@ -3047,8 +3063,8 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
|
|||
|
||||
res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u "
|
||||
"ctrl_flags=0x%x-> res=%d\n",
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"%s: nw_type=%u auth_mode=%u ch=%u ctrl_flags=0x%x-> res=%d\n",
|
||||
__func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch),
|
||||
le32_to_cpu(p->ctrl_flags), res);
|
||||
return res;
|
||||
|
@ -3208,8 +3224,9 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
|
|||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u "
|
||||
"ie_len=%u\n", mgmt_frm_type, ie_len);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"set_appie_cmd: mgmt_frm_type=%u ie_len=%u\n",
|
||||
mgmt_frm_type, ie_len);
|
||||
p = (struct wmi_set_appie_cmd *) skb->data;
|
||||
p->mgmt_frm_type = mgmt_frm_type;
|
||||
p->ie_len = ie_len;
|
||||
|
@ -3310,8 +3327,9 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
|||
wmi->last_mgmt_tx_frame = buf;
|
||||
wmi->last_mgmt_tx_frame_len = data_len;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u "
|
||||
"len=%u\n", id, freq, wait, data_len);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"send_action_cmd: id=%u freq=%u wait=%u len=%u\n",
|
||||
id, freq, wait, data_len);
|
||||
p = (struct wmi_send_action_cmd *) skb->data;
|
||||
p->id = cpu_to_le32(id);
|
||||
p->freq = cpu_to_le32(freq);
|
||||
|
@ -3348,8 +3366,9 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
|||
wmi->last_mgmt_tx_frame = buf;
|
||||
wmi->last_mgmt_tx_frame_len = data_len;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u "
|
||||
"len=%u\n", id, freq, wait, data_len);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"send_action_cmd: id=%u freq=%u wait=%u len=%u\n",
|
||||
id, freq, wait, data_len);
|
||||
p = (struct wmi_send_mgmt_cmd *) skb->data;
|
||||
p->id = cpu_to_le32(id);
|
||||
p->freq = cpu_to_le32(freq);
|
||||
|
@ -3402,8 +3421,9 @@ int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
|
|||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM "
|
||||
"len=%u\n", freq, dst, data_len);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"send_probe_response_cmd: freq=%u dst=%pM len=%u\n",
|
||||
freq, dst, data_len);
|
||||
p = (struct wmi_p2p_probe_response_cmd *) skb->data;
|
||||
p->freq = cpu_to_le32(freq);
|
||||
memcpy(p->destination_addr, dst, ETH_ALEN);
|
||||
|
|
|
@ -106,6 +106,8 @@ struct wmi_data_sync_bufs {
|
|||
#define WMM_AC_VI 2 /* video */
|
||||
#define WMM_AC_VO 3 /* voice */
|
||||
|
||||
#define WMI_VOICE_USER_PRIORITY 0x7
|
||||
|
||||
struct wmi {
|
||||
u16 stream_exist_for_ac[WMM_NUM_AC];
|
||||
u8 fat_pipe_exist;
|
||||
|
@ -1151,6 +1153,7 @@ enum wmi_phy_mode {
|
|||
WMI_11AG_MODE = 0x3,
|
||||
WMI_11B_MODE = 0x4,
|
||||
WMI_11GONLY_MODE = 0x5,
|
||||
WMI_11G_HT20 = 0x6,
|
||||
};
|
||||
|
||||
#define WMI_MAX_CHANNELS 32
|
||||
|
@ -1416,6 +1419,16 @@ struct wmi_ready_event_2 {
|
|||
u8 phy_cap;
|
||||
} __packed;
|
||||
|
||||
/* WMI_PHY_CAPABILITY */
|
||||
enum wmi_phy_cap {
|
||||
WMI_11A_CAP = 0x01,
|
||||
WMI_11G_CAP = 0x02,
|
||||
WMI_11AG_CAP = 0x03,
|
||||
WMI_11AN_CAP = 0x04,
|
||||
WMI_11GN_CAP = 0x05,
|
||||
WMI_11AGN_CAP = 0x06,
|
||||
};
|
||||
|
||||
/* Connect Event */
|
||||
struct wmi_connect_event {
|
||||
union {
|
||||
|
@ -1468,6 +1481,17 @@ enum wmi_disconnect_reason {
|
|||
IBSS_MERGE = 0xe,
|
||||
};
|
||||
|
||||
/* AP mode disconnect proto_reasons */
|
||||
enum ap_disconnect_reason {
|
||||
WMI_AP_REASON_STA_LEFT = 101,
|
||||
WMI_AP_REASON_FROM_HOST = 102,
|
||||
WMI_AP_REASON_COMM_TIMEOUT = 103,
|
||||
WMI_AP_REASON_MAX_STA = 104,
|
||||
WMI_AP_REASON_ACL = 105,
|
||||
WMI_AP_REASON_STA_ROAM = 106,
|
||||
WMI_AP_REASON_DFS_CHANNEL = 107,
|
||||
};
|
||||
|
||||
#define ATH6KL_COUNTRY_RD_SHIFT 16
|
||||
|
||||
struct ath6kl_wmi_regdomain {
|
||||
|
|
|
@ -892,34 +892,6 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
|
|||
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
|
||||
}
|
||||
|
||||
static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_rtt_hist *hist;
|
||||
u32 *table;
|
||||
int i;
|
||||
bool restore;
|
||||
|
||||
if (!ah->caldata)
|
||||
return false;
|
||||
|
||||
hist = &ah->caldata->rtt_hist;
|
||||
if (!hist->num_readings)
|
||||
return false;
|
||||
|
||||
ar9003_hw_rtt_enable(ah);
|
||||
ar9003_hw_rtt_set_mask(ah, 0x00);
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
||||
table = &hist->table[i][hist->num_readings][0];
|
||||
ar9003_hw_rtt_load_hist(ah, i, table);
|
||||
}
|
||||
restore = ar9003_hw_rtt_force_restore(ah);
|
||||
ar9003_hw_rtt_disable(ah);
|
||||
|
||||
return restore;
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
|
@ -942,9 +914,10 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
|||
if (!ar9003_hw_rtt_restore(ah, chan))
|
||||
run_rtt_cal = true;
|
||||
|
||||
ath_dbg(common, CALIBRATE, "RTT restore %s\n",
|
||||
run_rtt_cal ? "failed" : "succeed");
|
||||
if (run_rtt_cal)
|
||||
ath_dbg(common, CALIBRATE, "RTT calibration to be done\n");
|
||||
}
|
||||
|
||||
run_agc_cal = run_rtt_cal;
|
||||
|
||||
if (run_rtt_cal) {
|
||||
|
@ -1069,17 +1042,14 @@ skip_tx_iqcal:
|
|||
#undef CL_TAB_ENTRY
|
||||
|
||||
if (run_rtt_cal && caldata) {
|
||||
struct ath9k_rtt_hist *hist = &caldata->rtt_hist;
|
||||
if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) {
|
||||
u32 *table;
|
||||
if (is_reusable) {
|
||||
if (!ath9k_hw_rfbus_req(ah))
|
||||
ath_err(ath9k_hw_common(ah),
|
||||
"Could not stop baseband\n");
|
||||
else
|
||||
ar9003_hw_rtt_fill_hist(ah);
|
||||
|
||||
hist->num_readings++;
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
||||
table = &hist->table[i][hist->num_readings][0];
|
||||
ar9003_hw_rtt_fill_hist(ah, i, table);
|
||||
}
|
||||
ath9k_hw_rfbus_done(ah);
|
||||
}
|
||||
|
||||
ar9003_hw_rtt_disable(ah);
|
||||
|
|
|
@ -756,7 +756,7 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (caldata) {
|
||||
caldata->done_txiqcal_once = false;
|
||||
caldata->done_txclcal_once = false;
|
||||
caldata->rtt_hist.num_readings = 0;
|
||||
caldata->rtt_done = false;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_init_cal(ah, chan))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
#include "ar9003_phy.h"
|
||||
#include "ar9003_rtt.h"
|
||||
|
||||
|
@ -69,7 +70,7 @@ bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
|
|||
}
|
||||
|
||||
static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain,
|
||||
u32 index, u32 data28)
|
||||
u32 index, u32 data28)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
|
@ -100,12 +101,21 @@ static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain,
|
|||
RTT_ACCESS_TIMEOUT);
|
||||
}
|
||||
|
||||
void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table)
|
||||
void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
int chain, i;
|
||||
|
||||
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
|
||||
ar9003_hw_rtt_load_hist_entry(ah, chain, i, table[i]);
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
if (!(ah->rxchainmask & (1 << chain)))
|
||||
continue;
|
||||
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
|
||||
ar9003_hw_rtt_load_hist_entry(ah, chain, i,
|
||||
ah->caldata->rtt_table[chain][i]);
|
||||
ath_dbg(ath9k_hw_common(ah), CALIBRATE,
|
||||
"Load RTT value at idx %d, chain %d: 0x%x\n",
|
||||
i, chain, ah->caldata->rtt_table[chain][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
|
||||
|
@ -128,27 +138,71 @@ static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
|
|||
RTT_ACCESS_TIMEOUT))
|
||||
return RTT_BAD_VALUE;
|
||||
|
||||
val = REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain));
|
||||
val = MS(REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)),
|
||||
AR_PHY_RTT_SW_RTT_TABLE_DATA);
|
||||
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table)
|
||||
void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
int chain, i;
|
||||
|
||||
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
|
||||
table[i] = ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
if (!(ah->rxchainmask & (1 << chain)))
|
||||
continue;
|
||||
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
|
||||
ah->caldata->rtt_table[chain][i] =
|
||||
ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
|
||||
ath_dbg(ath9k_hw_common(ah), CALIBRATE,
|
||||
"RTT value at idx %d, chain %d is: 0x%x\n",
|
||||
i, chain, ah->caldata->rtt_table[chain][i]);
|
||||
}
|
||||
}
|
||||
|
||||
ah->caldata->rtt_done = true;
|
||||
}
|
||||
|
||||
void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
|
||||
{
|
||||
int i, j;
|
||||
int chain, i;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
if (!(ah->rxchainmask & (1 << chain)))
|
||||
continue;
|
||||
for (j = 0; j < MAX_RTT_TABLE_ENTRY; j++)
|
||||
ar9003_hw_rtt_load_hist_entry(ah, i, j, 0);
|
||||
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
|
||||
ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0);
|
||||
}
|
||||
|
||||
if (ah->caldata)
|
||||
ah->caldata->rtt_done = false;
|
||||
}
|
||||
|
||||
bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
bool restore;
|
||||
|
||||
if (!ah->caldata)
|
||||
return false;
|
||||
|
||||
if (!ah->caldata->rtt_done)
|
||||
return false;
|
||||
|
||||
ar9003_hw_rtt_enable(ah);
|
||||
ar9003_hw_rtt_set_mask(ah, 0x10);
|
||||
|
||||
if (!ath9k_hw_rfbus_req(ah)) {
|
||||
ath_err(ath9k_hw_common(ah), "Could not stop baseband\n");
|
||||
restore = false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ar9003_hw_rtt_load_hist(ah);
|
||||
restore = ar9003_hw_rtt_force_restore(ah);
|
||||
|
||||
fail:
|
||||
ath9k_hw_rfbus_done(ah);
|
||||
ar9003_hw_rtt_disable(ah);
|
||||
return restore;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ void ar9003_hw_rtt_enable(struct ath_hw *ah);
|
|||
void ar9003_hw_rtt_disable(struct ath_hw *ah);
|
||||
void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
|
||||
bool ar9003_hw_rtt_force_restore(struct ath_hw *ah);
|
||||
void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table);
|
||||
void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table);
|
||||
void ar9003_hw_rtt_load_hist(struct ath_hw *ah);
|
||||
void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
|
||||
void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
|
||||
bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1702,10 +1702,10 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
* For AR9462, make sure that calibration data for
|
||||
* re-using are present.
|
||||
*/
|
||||
if (AR_SREV_9462(ah) && (!ah->caldata ||
|
||||
!ah->caldata->done_txiqcal_once ||
|
||||
!ah->caldata->done_txclcal_once ||
|
||||
!ah->caldata->rtt_hist.num_readings))
|
||||
if (AR_SREV_9462(ah) && (ah->caldata &&
|
||||
(!ah->caldata->done_txiqcal_once ||
|
||||
!ah->caldata->done_txclcal_once ||
|
||||
!ah->caldata->rtt_done)))
|
||||
goto fail;
|
||||
|
||||
ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
|
||||
|
@ -1941,7 +1941,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (caldata) {
|
||||
caldata->done_txiqcal_once = false;
|
||||
caldata->done_txclcal_once = false;
|
||||
caldata->rtt_hist.num_readings = 0;
|
||||
}
|
||||
if (!ath9k_hw_init_cal(ah, chan))
|
||||
return -EIO;
|
||||
|
|
|
@ -348,12 +348,6 @@ enum ath9k_int {
|
|||
CHANNEL_HT40MINUS)
|
||||
|
||||
#define MAX_RTT_TABLE_ENTRY 6
|
||||
#define RTT_HIST_MAX 3
|
||||
struct ath9k_rtt_hist {
|
||||
u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY];
|
||||
u8 num_readings;
|
||||
};
|
||||
|
||||
#define MAX_IQCAL_MEASUREMENT 8
|
||||
#define MAX_CL_TAB_ENTRY 16
|
||||
|
||||
|
@ -363,6 +357,7 @@ struct ath9k_hw_cal_data {
|
|||
int32_t CalValid;
|
||||
int8_t iCoff;
|
||||
int8_t qCoff;
|
||||
bool rtt_done;
|
||||
bool paprd_done;
|
||||
bool nfcal_pending;
|
||||
bool nfcal_interference;
|
||||
|
@ -373,8 +368,8 @@ struct ath9k_hw_cal_data {
|
|||
u32 num_measures[AR9300_MAX_CHAINS];
|
||||
int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS];
|
||||
u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY];
|
||||
u32 rtt_table[AR9300_MAX_CHAINS][MAX_RTT_TABLE_ENTRY];
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
struct ath9k_rtt_hist rtt_hist;
|
||||
};
|
||||
|
||||
struct ath9k_channel {
|
||||
|
|
|
@ -107,11 +107,9 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
|
|||
dev->dma_dev = core->dma_dev;
|
||||
dev->irq = core->irq;
|
||||
|
||||
/*
|
||||
dev->board_vendor = core->bus->boardinfo.vendor;
|
||||
dev->board_type = core->bus->boardinfo.type;
|
||||
dev->board_rev = core->bus->boardinfo.rev;
|
||||
*/
|
||||
dev->board_rev = core->bus->sprom.board_rev;
|
||||
|
||||
dev->chip_id = core->bus->chipinfo.id;
|
||||
dev->chip_rev = core->bus->chipinfo.rev;
|
||||
|
@ -210,7 +208,7 @@ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
|
|||
|
||||
dev->board_vendor = sdev->bus->boardinfo.vendor;
|
||||
dev->board_type = sdev->bus->boardinfo.type;
|
||||
dev->board_rev = sdev->bus->boardinfo.rev;
|
||||
dev->board_rev = sdev->bus->sprom.board_rev;
|
||||
|
||||
dev->chip_id = sdev->bus->chip_id;
|
||||
dev->chip_rev = sdev->bus->chip_rev;
|
||||
|
|
|
@ -1109,7 +1109,7 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
|
|||
#ifdef CONFIG_B43_SSB
|
||||
if (dev->dev->bus_type == B43_BUS_SSB &&
|
||||
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
|
||||
!(dev->dev->sdev->bus->host_pci->is_pcie &&
|
||||
!(pci_is_pcie(dev->dev->sdev->bus->host_pci) &&
|
||||
ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
|
||||
return 1;
|
||||
#endif
|
||||
|
|
|
@ -5243,10 +5243,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
|
|||
|
||||
/* boardflags workarounds */
|
||||
if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
|
||||
bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
|
||||
bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74)
|
||||
bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
|
||||
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
|
||||
bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
|
||||
bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40)
|
||||
bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
|
||||
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
pdev = bus->host_pci;
|
||||
|
|
|
@ -1573,8 +1573,6 @@ static void b43legacy_request_firmware(struct work_struct *work)
|
|||
const char *filename;
|
||||
int err;
|
||||
|
||||
/* do dummy read */
|
||||
ssb_read32(dev->dev, SSB_TMSHIGH);
|
||||
if (!fw->ucode) {
|
||||
if (rev == 2)
|
||||
filename = "ucode2";
|
||||
|
@ -3781,7 +3779,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus)
|
|||
/* boardflags workarounds */
|
||||
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
|
||||
bus->boardinfo.type == 0x4E &&
|
||||
bus->boardinfo.rev > 0x40)
|
||||
bus->sprom.board_rev > 0x40)
|
||||
bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
|
||||
}
|
||||
|
||||
|
|
|
@ -408,7 +408,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
|
|||
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
(dev->dev->bus->boardinfo.type == 0x0416) &&
|
||||
(dev->dev->bus->boardinfo.rev == 0x0017))
|
||||
(dev->dev->bus->sprom.board_rev == 0x0017))
|
||||
return;
|
||||
|
||||
b43legacy_ilt_write(dev, 0x5001, 0x0002);
|
||||
|
@ -424,7 +424,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
|
|||
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
(dev->dev->bus->boardinfo.type == 0x0416) &&
|
||||
(dev->dev->bus->boardinfo.rev == 0x0017))
|
||||
(dev->dev->bus->sprom.board_rev == 0x0017))
|
||||
return;
|
||||
|
||||
b43legacy_ilt_write(dev, 0x0401, 0x0002);
|
||||
|
|
|
@ -1998,7 +1998,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
|
|||
if (phy->type == B43legacy_PHYTYPE_G) {
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type == 0x421 &&
|
||||
dev->dev->bus->boardinfo.rev >= 30)
|
||||
dev->dev->bus->sprom.board_rev >= 30)
|
||||
att = 3;
|
||||
else if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type == 0x416)
|
||||
|
@ -2008,7 +2008,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
|
|||
} else {
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type == 0x421 &&
|
||||
dev->dev->bus->boardinfo.rev >= 30)
|
||||
dev->dev->bus->sprom.board_rev >= 30)
|
||||
att = 7;
|
||||
else
|
||||
att = 6;
|
||||
|
@ -2018,7 +2018,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
|
|||
if (phy->type == B43legacy_PHYTYPE_G) {
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type == 0x421 &&
|
||||
dev->dev->bus->boardinfo.rev >= 30)
|
||||
dev->dev->bus->sprom.board_rev >= 30)
|
||||
att = 3;
|
||||
else if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type ==
|
||||
|
@ -2052,9 +2052,9 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
|
|||
}
|
||||
if (is_bcm_board_vendor(dev) &&
|
||||
dev->dev->bus->boardinfo.type == 0x421) {
|
||||
if (dev->dev->bus->boardinfo.rev < 0x43)
|
||||
if (dev->dev->bus->sprom.board_rev < 0x43)
|
||||
att = 2;
|
||||
else if (dev->dev->bus->boardinfo.rev < 0x51)
|
||||
else if (dev->dev->bus->sprom.board_rev < 0x51)
|
||||
att = 3;
|
||||
}
|
||||
if (att == 0xFFFF)
|
||||
|
|
|
@ -85,18 +85,15 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|||
sdiodev->irq_wake = true;
|
||||
|
||||
/* must configure SDIO_CCCR_IENx to enable irq */
|
||||
data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0,
|
||||
SDIO_CCCR_IENx, &ret);
|
||||
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
|
||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx,
|
||||
data, &ret);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
|
||||
|
||||
/* redirect, configure ane enable io for interrupt signal */
|
||||
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
|
||||
if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH)
|
||||
data |= SDIO_SEPINT_ACT_HI;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
|
||||
data, &ret);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,9 +102,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
|||
{
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
|
||||
0, NULL);
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
|
||||
|
||||
if (sdiodev->irq_wake) {
|
||||
disable_irq_wake(sdiodev->irq);
|
||||
|
@ -158,153 +154,147 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
|||
}
|
||||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
|
||||
int *err)
|
||||
{
|
||||
int status;
|
||||
s32 retry = 0;
|
||||
u8 data = 0;
|
||||
|
||||
do {
|
||||
if (retry) /* wait for 1 ms till bus get settled down */
|
||||
udelay(1000);
|
||||
status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
|
||||
addr, (u8 *) &data);
|
||||
} while (status != 0
|
||||
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
|
||||
if (err)
|
||||
*err = status;
|
||||
|
||||
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
|
||||
fnc_num, addr, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
|
||||
u8 data, int *err)
|
||||
{
|
||||
int status;
|
||||
s32 retry = 0;
|
||||
|
||||
do {
|
||||
if (retry) /* wait for 1 ms till bus get settled down */
|
||||
udelay(1000);
|
||||
status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
|
||||
addr, (u8 *) &data);
|
||||
} while (status != 0
|
||||
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
|
||||
if (err)
|
||||
*err = status;
|
||||
|
||||
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
|
||||
fnc_num, addr, data);
|
||||
}
|
||||
|
||||
int
|
||||
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
|
||||
{
|
||||
int err = 0;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
|
||||
(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
|
||||
if (!err)
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_SBADDRMID,
|
||||
(address >> 16) & SBSDIO_SBADDRMID_MASK,
|
||||
&err);
|
||||
if (!err)
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_SBADDRHIGH,
|
||||
(address >> 24) & SBSDIO_SBADDRHIGH_MASK,
|
||||
&err);
|
||||
int err = 0, i;
|
||||
u8 addr[3];
|
||||
s32 retry;
|
||||
|
||||
addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
|
||||
addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
|
||||
addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
retry = 0;
|
||||
do {
|
||||
if (retry)
|
||||
usleep_range(1000, 2000);
|
||||
err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE,
|
||||
SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i,
|
||||
&addr[i]);
|
||||
} while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
|
||||
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "failed at addr:0x%0x\n",
|
||||
SBSDIO_FUNC1_SBADDRLOW + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
|
||||
static int
|
||||
brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||
void *data, bool write)
|
||||
{
|
||||
int status;
|
||||
u32 word = 0;
|
||||
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
|
||||
u8 func_num, reg_size;
|
||||
u32 bar;
|
||||
s32 retry = 0;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
|
||||
|
||||
if (bar0 != sdiodev->sbwad) {
|
||||
if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
sdiodev->sbwad = bar0;
|
||||
}
|
||||
|
||||
addr &= SBSDIO_SB_OFT_ADDR_MASK;
|
||||
if (size == 4)
|
||||
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
||||
|
||||
status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
|
||||
addr, &word, size);
|
||||
|
||||
sdiodev->regfail = (status != 0);
|
||||
|
||||
brcmf_dbg(INFO, "u32data = 0x%x\n", word);
|
||||
|
||||
/* if ok, return appropriately masked word */
|
||||
if (status == 0) {
|
||||
switch (size) {
|
||||
case sizeof(u8):
|
||||
return word & 0xff;
|
||||
case sizeof(u16):
|
||||
return word & 0xffff;
|
||||
case sizeof(u32):
|
||||
return word;
|
||||
default:
|
||||
sdiodev->regfail = true;
|
||||
/*
|
||||
* figure out how to read the register based on address range
|
||||
* 0x00 ~ 0x7FF: function 0 CCCR and FBR
|
||||
* 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
|
||||
* The rest: function 1 silicon backplane core registers
|
||||
*/
|
||||
if ((addr & ~REG_F0_REG_MASK) == 0) {
|
||||
func_num = SDIO_FUNC_0;
|
||||
reg_size = 1;
|
||||
} else if ((addr & ~REG_F1_MISC_MASK) == 0) {
|
||||
func_num = SDIO_FUNC_1;
|
||||
reg_size = 1;
|
||||
} else {
|
||||
func_num = SDIO_FUNC_1;
|
||||
reg_size = 4;
|
||||
|
||||
/* Set the window for SB core register */
|
||||
bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
|
||||
if (bar != sdiodev->sbwad) {
|
||||
ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar);
|
||||
if (ret != 0) {
|
||||
memset(data, 0xFF, reg_size);
|
||||
return ret;
|
||||
}
|
||||
sdiodev->sbwad = bar;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise, bad sdio access or invalid size */
|
||||
brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
|
||||
u32 data)
|
||||
{
|
||||
int status;
|
||||
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
|
||||
int err = 0;
|
||||
|
||||
brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
|
||||
addr, size * 8, data);
|
||||
|
||||
if (bar0 != sdiodev->sbwad) {
|
||||
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sdiodev->sbwad = bar0;
|
||||
}
|
||||
|
||||
addr &= SBSDIO_SB_OFT_ADDR_MASK;
|
||||
if (size == 4)
|
||||
addr &= SBSDIO_SB_OFT_ADDR_MASK;
|
||||
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
||||
status =
|
||||
brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
|
||||
addr, &data, size);
|
||||
sdiodev->regfail = (status != 0);
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
return 0;
|
||||
do {
|
||||
if (!write)
|
||||
memset(data, 0, reg_size);
|
||||
if (retry) /* wait for 1 ms till bus get settled down */
|
||||
usleep_range(1000, 2000);
|
||||
if (reg_size == 1)
|
||||
ret = brcmf_sdioh_request_byte(sdiodev, write,
|
||||
func_num, addr, data);
|
||||
else
|
||||
ret = brcmf_sdioh_request_word(sdiodev, write,
|
||||
func_num, addr, data, 4);
|
||||
} while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
|
||||
|
||||
brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
|
||||
data, addr, size);
|
||||
return 0xFFFFFFFF;
|
||||
if (ret != 0)
|
||||
brcmf_dbg(ERROR, "failed with %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
|
||||
u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
||||
{
|
||||
return sdiodev->regfail;
|
||||
u8 data;
|
||||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
|
||||
brcmf_dbg(INFO, "data:0x%02x\n", data);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
||||
{
|
||||
u32 data;
|
||||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
|
||||
brcmf_dbg(INFO, "data:0x%08x\n", data);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||
u8 data, int *ret)
|
||||
{
|
||||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
}
|
||||
|
||||
void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||
u32 data, int *ret)
|
||||
{
|
||||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
}
|
||||
|
||||
static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
|
||||
|
|
|
@ -346,43 +346,17 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Read client card reg */
|
||||
static int
|
||||
brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr,
|
||||
int regsize, u32 *data)
|
||||
{
|
||||
|
||||
if ((func == 0) || (regsize == 1)) {
|
||||
u8 temp = 0;
|
||||
|
||||
brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr,
|
||||
&temp);
|
||||
*data = temp;
|
||||
*data &= 0xff;
|
||||
brcmf_dbg(DATA, "byte read data=0x%02x\n", *data);
|
||||
} else {
|
||||
brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr,
|
||||
data, regsize);
|
||||
if (regsize == 2)
|
||||
*data &= 0xffff;
|
||||
|
||||
brcmf_dbg(DATA, "word read data=0x%08x\n", *data);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
|
||||
{
|
||||
/* read 24 bits and return valid 17 bit addr */
|
||||
int i;
|
||||
int i, ret;
|
||||
u32 scratch, regdata;
|
||||
__le32 scratch_le;
|
||||
u8 *ptr = (u8 *)&scratch_le;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1,
|
||||
®data)) != SUCCESS)
|
||||
regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret);
|
||||
if (ret != 0)
|
||||
brcmf_dbg(ERROR, "Can't read!\n");
|
||||
|
||||
*ptr++ = (u8) regdata;
|
||||
|
|
|
@ -629,43 +629,29 @@ static bool data_ok(struct brcmf_sdio *bus)
|
|||
* Reads a register in the SDIO hardware block. This block occupies a series of
|
||||
* adresses on the 32 bit backplane bus.
|
||||
*/
|
||||
static void
|
||||
r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
|
||||
static int
|
||||
r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
|
||||
{
|
||||
u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
||||
*retryvar = 0;
|
||||
do {
|
||||
*regvar = brcmf_sdcard_reg_read(bus->sdiodev,
|
||||
bus->ci->c_inf[idx].base + reg_offset,
|
||||
sizeof(u32));
|
||||
} while (brcmf_sdcard_regfail(bus->sdiodev) &&
|
||||
(++(*retryvar) <= retry_limit));
|
||||
if (*retryvar) {
|
||||
bus->regfails += (*retryvar-1);
|
||||
if (*retryvar > retry_limit) {
|
||||
brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset);
|
||||
*regvar = 0;
|
||||
}
|
||||
}
|
||||
int ret;
|
||||
|
||||
*regvar = brcmf_sdio_regrl(bus->sdiodev,
|
||||
bus->ci->c_inf[idx].base + offset, &ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar)
|
||||
static int
|
||||
w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
|
||||
{
|
||||
u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
||||
*retryvar = 0;
|
||||
do {
|
||||
brcmf_sdcard_reg_write(bus->sdiodev,
|
||||
bus->ci->c_inf[idx].base + reg_offset,
|
||||
sizeof(u32), regval);
|
||||
} while (brcmf_sdcard_regfail(bus->sdiodev) &&
|
||||
(++(*retryvar) <= retry_limit));
|
||||
if (*retryvar) {
|
||||
bus->regfails += (*retryvar-1);
|
||||
if (*retryvar > retry_limit)
|
||||
brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n",
|
||||
reg_offset);
|
||||
}
|
||||
int ret;
|
||||
|
||||
brcmf_sdio_regwl(bus->sdiodev,
|
||||
bus->ci->c_inf[idx].base + reg_offset,
|
||||
regval, &ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
|
||||
|
@ -697,16 +683,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
|||
clkreq =
|
||||
bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
clkreq, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
/* Check current status */
|
||||
clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
clkctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "HT Avail read error: %d\n", err);
|
||||
return -EBADE;
|
||||
|
@ -715,9 +701,8 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
|||
/* Go to pending and await interrupt if appropriate */
|
||||
if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
|
||||
/* Allow only clock-available interrupt */
|
||||
devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "Devctl error setting CA: %d\n",
|
||||
err);
|
||||
|
@ -725,30 +710,28 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
|||
}
|
||||
|
||||
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, devctl, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||
devctl, &err);
|
||||
brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
|
||||
bus->clkstate = CLK_PENDING;
|
||||
|
||||
return 0;
|
||||
} else if (bus->clkstate == CLK_PENDING) {
|
||||
/* Cancel CA-only interrupt filter */
|
||||
devctl =
|
||||
brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
devctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, devctl, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||
devctl, &err);
|
||||
}
|
||||
|
||||
/* Otherwise, wait here (polling) for HT Avail */
|
||||
timeout = jiffies +
|
||||
msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
|
||||
while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
|
||||
clkctl = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
&err);
|
||||
clkctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
&err);
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
else
|
||||
|
@ -781,17 +764,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
|||
|
||||
if (bus->clkstate == CLK_PENDING) {
|
||||
/* Cancel CA-only interrupt filter */
|
||||
devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, devctl, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||
devctl, &err);
|
||||
}
|
||||
|
||||
bus->clkstate = CLK_SDONLY;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
clkreq, &err);
|
||||
brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "Failed access turning clock off: %d\n",
|
||||
|
@ -874,7 +856,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
|
|||
|
||||
static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep)
|
||||
{
|
||||
uint retries = 0;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(INFO, "request %s (currently %s)\n",
|
||||
sleep ? "SLEEP" : "WAKE",
|
||||
|
@ -894,22 +876,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep)
|
|||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
/* Tell device to start using OOB wakeup */
|
||||
w_sdreg32(bus, SMB_USE_OOB,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
|
||||
if (retries > retry_limit)
|
||||
ret = w_sdreg32(bus, SMB_USE_OOB,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox));
|
||||
if (ret != 0)
|
||||
brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n");
|
||||
|
||||
/* Turn off our contribution to the HT clock request */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
|
||||
|
||||
/* Isolate the bus */
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL,
|
||||
SBSDIO_DEVCTL_PADS_ISO, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||
SBSDIO_DEVCTL_PADS_ISO, NULL);
|
||||
|
||||
/* Change state */
|
||||
bus->sleeping = true;
|
||||
|
@ -917,21 +897,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep)
|
|||
} else {
|
||||
/* Waking up: bus power up is ok, set local state */
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
0, NULL);
|
||||
|
||||
/* Make sure the controller has the bus up */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
/* Send misc interrupt to indicate OOB not needed */
|
||||
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
|
||||
&retries);
|
||||
if (retries <= retry_limit)
|
||||
w_sdreg32(bus, SMB_DEV_INT,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox),
|
||||
&retries);
|
||||
ret = w_sdreg32(bus, 0,
|
||||
offsetof(struct sdpcmd_regs, tosbmailboxdata));
|
||||
if (ret == 0)
|
||||
ret = w_sdreg32(bus, SMB_DEV_INT,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox));
|
||||
|
||||
if (retries > retry_limit)
|
||||
if (ret != 0)
|
||||
brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n");
|
||||
|
||||
/* Make sure we have SD bus access */
|
||||
|
@ -955,17 +934,17 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
|
|||
u32 intstatus = 0;
|
||||
u32 hmb_data;
|
||||
u8 fcbits;
|
||||
uint retries = 0;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Read mailbox data and ack that we did so */
|
||||
r_sdreg32(bus, &hmb_data,
|
||||
offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
|
||||
ret = r_sdreg32(bus, &hmb_data,
|
||||
offsetof(struct sdpcmd_regs, tohostmailboxdata));
|
||||
|
||||
if (retries <= retry_limit)
|
||||
if (ret == 0)
|
||||
w_sdreg32(bus, SMB_INT_ACK,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox));
|
||||
bus->f1regdata += 2;
|
||||
|
||||
/* Dongle recomposed rx frames, accept them again */
|
||||
|
@ -1040,17 +1019,16 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
|
|||
if (abort)
|
||||
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_RF_TERM, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_RF_TERM, &err);
|
||||
bus->f1regdata++;
|
||||
|
||||
/* Wait until the packet has been flushed (device/FIFO stable) */
|
||||
for (lastrbc = retries = 0xffff; retries > 0; retries--) {
|
||||
hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_RFRAMEBCHI, NULL);
|
||||
lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_RFRAMEBCLO, NULL);
|
||||
hi = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_RFRAMEBCHI, &err);
|
||||
lo = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_RFRAMEBCLO, &err);
|
||||
bus->f1regdata += 2;
|
||||
|
||||
if ((hi == 0) && (lo == 0))
|
||||
|
@ -1070,11 +1048,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
|
|||
|
||||
if (rtx) {
|
||||
bus->rxrtx++;
|
||||
w_sdreg32(bus, SMB_NAK,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
|
||||
err = w_sdreg32(bus, SMB_NAK,
|
||||
offsetof(struct sdpcmd_regs, tosbmailbox));
|
||||
|
||||
bus->f1regdata++;
|
||||
if (retries <= retry_limit)
|
||||
if (err == 0)
|
||||
bus->rxskip = true;
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1060,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
|
|||
bus->nextlen = 0;
|
||||
|
||||
/* If we can't reach the device, signal failure */
|
||||
if (err || brcmf_sdcard_regfail(bus->sdiodev))
|
||||
if (err)
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
}
|
||||
|
||||
|
@ -2178,21 +2156,16 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
|
|||
bus->tx_sderrs++;
|
||||
|
||||
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
|
||||
NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_WF_TERM, NULL);
|
||||
bus->f1regdata++;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
u8 hi, lo;
|
||||
hi = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI,
|
||||
NULL);
|
||||
lo = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO,
|
||||
NULL);
|
||||
hi = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI, NULL);
|
||||
lo = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO, NULL);
|
||||
bus->f1regdata += 2;
|
||||
if ((hi == 0) && (lo == 0))
|
||||
break;
|
||||
|
@ -2219,7 +2192,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
|||
{
|
||||
struct sk_buff *pkt;
|
||||
u32 intstatus = 0;
|
||||
uint retries = 0;
|
||||
int ret = 0, prec_out;
|
||||
uint cnt = 0;
|
||||
uint datalen;
|
||||
|
@ -2249,11 +2221,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
|||
/* In poll mode, need to check for other events */
|
||||
if (!bus->intr && cnt) {
|
||||
/* Check device status, signal pending interrupt */
|
||||
r_sdreg32(bus, &intstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus),
|
||||
&retries);
|
||||
ret = r_sdreg32(bus, &intstatus,
|
||||
offsetof(struct sdpcmd_regs,
|
||||
intstatus));
|
||||
bus->f2txdata++;
|
||||
if (brcmf_sdcard_regfail(bus->sdiodev))
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (intstatus & bus->hostintmask)
|
||||
bus->ipend = true;
|
||||
|
@ -2275,7 +2247,6 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
{
|
||||
u32 local_hostintmask;
|
||||
u8 saveclk;
|
||||
uint retries;
|
||||
int err;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
@ -2303,7 +2274,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
/* Disable and clear interrupts at the chip level also */
|
||||
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
|
||||
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
|
||||
local_hostintmask = bus->hostintmask;
|
||||
bus->hostintmask = 0;
|
||||
|
||||
|
@ -2311,24 +2282,23 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
|
||||
/* Force clocks on backplane to be sure F2 interrupt propagates */
|
||||
saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
saveclk = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
if (!err) {
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
(saveclk | SBSDIO_FORCE_HT), &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
(saveclk | SBSDIO_FORCE_HT), &err);
|
||||
}
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
|
||||
|
||||
/* Turn off the bus (F2), free any pending packets */
|
||||
brcmf_dbg(INTR, "disable SDIO interrupts\n");
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
|
||||
SDIO_FUNC_ENABLE_1, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1,
|
||||
NULL);
|
||||
|
||||
/* Clear any pending interrupts now that F2 is disabled */
|
||||
w_sdreg32(bus, local_hostintmask,
|
||||
offsetof(struct sdpcmd_regs, intstatus), &retries);
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
|
||||
/* Turn off the backplane clock (only) */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
|
||||
|
@ -2373,12 +2343,12 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
|||
static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
||||
{
|
||||
u32 intstatus, newstatus = 0;
|
||||
uint retries = 0;
|
||||
uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
|
||||
uint txlimit = bus->txbound; /* Tx frames to send before resched */
|
||||
uint framecnt = 0; /* Temporary counter of tx/rx frames */
|
||||
bool rxdone = true; /* Flag for no more read data */
|
||||
bool resched = false; /* Flag indicating resched wanted */
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
|
@ -2389,13 +2359,12 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
|
||||
/* If waiting for HTAVAIL, check status */
|
||||
if (bus->clkstate == CLK_PENDING) {
|
||||
int err;
|
||||
u8 clkctl, devctl = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Check for inconsistent device control */
|
||||
devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
|
@ -2403,8 +2372,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
#endif /* DEBUG */
|
||||
|
||||
/* Read CSR, if clock on switch to AVAIL, else ignore */
|
||||
clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
clkctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "error reading CSR: %d\n",
|
||||
err);
|
||||
|
@ -2415,17 +2384,16 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
devctl, clkctl);
|
||||
|
||||
if (SBSDIO_HTAV(clkctl)) {
|
||||
devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
devctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_DEVICE_CTL, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
|
||||
err);
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
}
|
||||
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL, devctl, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
|
||||
devctl, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
|
||||
err);
|
||||
|
@ -2447,17 +2415,17 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
/* Pending interrupt indicates new device status */
|
||||
if (bus->ipend) {
|
||||
bus->ipend = false;
|
||||
r_sdreg32(bus, &newstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus), &retries);
|
||||
err = r_sdreg32(bus, &newstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
bus->f1regdata++;
|
||||
if (brcmf_sdcard_regfail(bus->sdiodev))
|
||||
if (err != 0)
|
||||
newstatus = 0;
|
||||
newstatus &= bus->hostintmask;
|
||||
bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
|
||||
if (newstatus) {
|
||||
w_sdreg32(bus, newstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus),
|
||||
&retries);
|
||||
err = w_sdreg32(bus, newstatus,
|
||||
offsetof(struct sdpcmd_regs,
|
||||
intstatus));
|
||||
bus->f1regdata++;
|
||||
}
|
||||
}
|
||||
|
@ -2472,11 +2440,11 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
*/
|
||||
if (intstatus & I_HMB_FC_CHANGE) {
|
||||
intstatus &= ~I_HMB_FC_CHANGE;
|
||||
w_sdreg32(bus, I_HMB_FC_CHANGE,
|
||||
offsetof(struct sdpcmd_regs, intstatus), &retries);
|
||||
err = w_sdreg32(bus, I_HMB_FC_CHANGE,
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
|
||||
r_sdreg32(bus, &newstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus), &retries);
|
||||
err = r_sdreg32(bus, &newstatus,
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
bus->f1regdata += 2;
|
||||
bus->fcstate =
|
||||
!!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
|
||||
|
@ -2546,21 +2514,18 @@ clkwait:
|
|||
|
||||
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
|
||||
NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_WF_TERM, &err);
|
||||
bus->f1regdata++;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
u8 hi, lo;
|
||||
hi = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI,
|
||||
NULL);
|
||||
lo = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO,
|
||||
NULL);
|
||||
hi = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI,
|
||||
&err);
|
||||
lo = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO,
|
||||
&err);
|
||||
bus->f1regdata += 2;
|
||||
if ((hi == 0) && (lo == 0))
|
||||
break;
|
||||
|
@ -2587,10 +2552,8 @@ clkwait:
|
|||
else await next interrupt */
|
||||
/* On failed register access, all bets are off:
|
||||
no resched or interrupts */
|
||||
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) ||
|
||||
brcmf_sdcard_regfail(bus->sdiodev)) {
|
||||
brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n",
|
||||
brcmf_sdcard_regfail(bus->sdiodev));
|
||||
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) {
|
||||
brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n");
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
bus->intstatus = 0;
|
||||
} else if (bus->clkstate == CLK_PENDING) {
|
||||
|
@ -2886,19 +2849,16 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
|
|||
|
||||
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_WF_TERM, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
|
||||
SFC_WF_TERM, NULL);
|
||||
bus->f1regdata++;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
u8 hi, lo;
|
||||
hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI,
|
||||
NULL);
|
||||
lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO,
|
||||
NULL);
|
||||
hi = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCHI, NULL);
|
||||
lo = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_WFRAMEBCLO, NULL);
|
||||
bus->f1regdata += 2;
|
||||
if (hi == 0 && lo == 0)
|
||||
break;
|
||||
|
@ -3188,7 +3148,6 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
|
|||
|
||||
static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
||||
{
|
||||
uint retries;
|
||||
int bcmerror = 0;
|
||||
struct chip_info *ci = bus->ci;
|
||||
|
||||
|
@ -3222,7 +3181,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
|||
}
|
||||
|
||||
w_sdreg32(bus, 0xFFFFFFFF,
|
||||
offsetof(struct sdpcmd_regs, intstatus), &retries);
|
||||
offsetof(struct sdpcmd_regs, intstatus));
|
||||
|
||||
ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
||||
|
||||
|
@ -3444,7 +3403,6 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
unsigned long timeout;
|
||||
uint retries = 0;
|
||||
u8 ready, enable;
|
||||
int err, ret = 0;
|
||||
u8 saveclk;
|
||||
|
@ -3472,13 +3430,11 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
goto exit;
|
||||
|
||||
/* Force clocks on backplane to be sure F2 interrupt propagates */
|
||||
saveclk =
|
||||
brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
saveclk = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
if (!err) {
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
(saveclk | SBSDIO_FORCE_HT), &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
(saveclk | SBSDIO_FORCE_HT), &err);
|
||||
}
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
|
||||
|
@ -3487,17 +3443,16 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
|
||||
/* Enable function 2 (frame transfers) */
|
||||
w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
|
||||
offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
|
||||
offsetof(struct sdpcmd_regs, tosbmailboxdata));
|
||||
enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
|
||||
enable, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY);
|
||||
ready = 0;
|
||||
while (enable != ready) {
|
||||
ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0,
|
||||
SDIO_CCCR_IORx, NULL);
|
||||
ready = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SDIO_CCCR_IORx, NULL);
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50))
|
||||
|
@ -3512,21 +3467,18 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
/* Set up the interrupt mask and enable interrupts */
|
||||
bus->hostintmask = HOSTINTMASK;
|
||||
w_sdreg32(bus, bus->hostintmask,
|
||||
offsetof(struct sdpcmd_regs, hostintmask), &retries);
|
||||
offsetof(struct sdpcmd_regs, hostintmask));
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_WATERMARK, 8, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err);
|
||||
} else {
|
||||
/* Disable F2 again */
|
||||
enable = SDIO_FUNC_ENABLE_1;
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0,
|
||||
SDIO_CCCR_IOEx, enable, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
/* Restore previous clock setting */
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = brcmf_sdio_intr_register(bus->sdiodev);
|
||||
|
@ -3606,9 +3558,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|||
|
||||
if (!bus->dpc_sched) {
|
||||
u8 devpend;
|
||||
devpend = brcmf_sdcard_cfg_read(bus->sdiodev,
|
||||
SDIO_FUNC_0, SDIO_CCCR_INTx,
|
||||
NULL);
|
||||
devpend = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SDIO_CCCR_INTx,
|
||||
NULL);
|
||||
intstatus =
|
||||
devpend & (INTR_STATUS_FUNC1 |
|
||||
INTR_STATUS_FUNC2);
|
||||
|
@ -3732,24 +3684,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|||
|
||||
bus->alp_only = true;
|
||||
|
||||
/* Return the window to backplane enumeration space for core access */
|
||||
if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE))
|
||||
brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n");
|
||||
|
||||
pr_debug("F1 signature read @0x18000000=0x%4x\n",
|
||||
brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4));
|
||||
brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
|
||||
|
||||
/*
|
||||
* Force PLL off until brcmf_sdio_chip_attach()
|
||||
* programs PLL control regs
|
||||
*/
|
||||
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
BRCMF_INIT_CLKCTL1, &err);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
||||
BRCMF_INIT_CLKCTL1, &err);
|
||||
if (!err)
|
||||
clkctl =
|
||||
brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
clkctl = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, &err);
|
||||
|
||||
if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
|
||||
|
@ -3782,9 +3728,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|||
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
||||
reg_addr = bus->ci->c_inf[idx].base +
|
||||
offsetof(struct sdpcmd_regs, corecontrol);
|
||||
reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32));
|
||||
brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32),
|
||||
reg_val | CC_BPRESEN);
|
||||
reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
|
||||
brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
|
||||
|
||||
brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
|
||||
|
||||
|
@ -3809,16 +3754,15 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
|
|||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Disable F2 to clear any intermediate frame state on the dongle */
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
|
||||
SDIO_FUNC_ENABLE_1, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
|
||||
SDIO_FUNC_ENABLE_1, NULL);
|
||||
|
||||
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
bus->sleeping = false;
|
||||
bus->rxflow = false;
|
||||
|
||||
/* Done with backplane-dependent accesses, can drop clock... */
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
|
||||
|
||||
/* ...and initialize clock/power states */
|
||||
bus->clkstate = CLK_SDONLY;
|
||||
|
|
|
@ -93,8 +93,9 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
|
|||
|
||||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbidhigh), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbidhigh),
|
||||
NULL);
|
||||
return SBCOREREV(regdata);
|
||||
}
|
||||
|
||||
|
@ -118,8 +119,9 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
|
|||
|
||||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
NULL);
|
||||
regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
|
||||
SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
|
||||
return (SSB_TMSLOW_CLOCK == regdata);
|
||||
|
@ -135,13 +137,13 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
|
|||
|
||||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
NULL);
|
||||
ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
|
||||
|
||||
return ret;
|
||||
|
@ -151,84 +153,85 @@ static void
|
|||
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci, u16 coreid)
|
||||
{
|
||||
u32 regdata;
|
||||
u32 regdata, base;
|
||||
u8 idx;
|
||||
|
||||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
base = ci->c_inf[idx].base;
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
|
||||
if (regdata & SSB_TMSLOW_RESET)
|
||||
return;
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
|
||||
if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
|
||||
/*
|
||||
* set target reject and spin until busy is clear
|
||||
* (preserve core-specific bits)
|
||||
*/
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
4, regdata | SSB_TMSLOW_REJECT);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
NULL);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
regdata | SSB_TMSLOW_REJECT, NULL);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
NULL);
|
||||
udelay(1);
|
||||
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) &
|
||||
SPINWAIT((brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbtmstatehigh),
|
||||
NULL) &
|
||||
SSB_TMSHIGH_BUSY), 100000);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbtmstatehigh),
|
||||
NULL);
|
||||
if (regdata & SSB_TMSHIGH_BUSY)
|
||||
brcmf_dbg(ERROR, "core state still busy\n");
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
|
||||
NULL);
|
||||
if (regdata & SSB_IDLOW_INITIATOR) {
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) |
|
||||
SSB_IMSTATE_REJECT;
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
|
||||
regdata);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbimstate),
|
||||
NULL);
|
||||
regdata |= SSB_IMSTATE_REJECT;
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
|
||||
regdata, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbimstate),
|
||||
NULL);
|
||||
udelay(1);
|
||||
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
|
||||
SPINWAIT((brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbimstate),
|
||||
NULL) &
|
||||
SSB_IMSTATE_BUSY), 100000);
|
||||
}
|
||||
|
||||
/* set reset and reject while enabling the clocks */
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
|
||||
(SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
|
||||
SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
|
||||
SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
regdata, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
NULL);
|
||||
udelay(10);
|
||||
|
||||
/* clear the initiator reject bit */
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
|
||||
NULL);
|
||||
if (regdata & SSB_IDLOW_INITIATOR) {
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
|
||||
~SSB_IMSTATE_REJECT;
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
|
||||
regdata);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(base, sbimstate),
|
||||
NULL);
|
||||
regdata &= ~SSB_IMSTATE_REJECT;
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
|
||||
regdata, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* leave reset and reject asserted */
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
|
||||
(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
|
||||
(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
|
@ -242,20 +245,19 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
|
|||
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
|
||||
|
||||
/* if core is already in reset, just return */
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
NULL);
|
||||
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
|
||||
return;
|
||||
|
||||
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
4, 0);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
udelay(10);
|
||||
|
||||
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
4, BCMA_RESET_CTL_RESET);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
BCMA_RESET_CTL_RESET, NULL);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
|
@ -279,41 +281,47 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
|
|||
* set reset while enabling the clock and
|
||||
* forcing them on throughout the core
|
||||
*/
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
|
||||
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
brcmf_sdio_regwl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
|
||||
NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
NULL);
|
||||
udelay(1);
|
||||
|
||||
/* clear any serror */
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
|
||||
NULL);
|
||||
if (regdata & SSB_TMSHIGH_SERR)
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0);
|
||||
brcmf_sdio_regwl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
|
||||
0, NULL);
|
||||
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate),
|
||||
NULL);
|
||||
if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
|
||||
regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
|
||||
brcmf_sdio_regwl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbimstate),
|
||||
regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
|
||||
NULL);
|
||||
|
||||
/* clear reset and allow it to propagate throughout the core */
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
|
||||
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
NULL);
|
||||
udelay(1);
|
||||
|
||||
/* leave clock enabled */
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
4, SSB_TMSLOW_CLOCK);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
SSB_TMSLOW_CLOCK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
|
||||
NULL);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
|
@ -330,18 +338,18 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
|
|||
brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
|
||||
|
||||
/* now do initialization sequence */
|
||||
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
|
||||
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
4, 0);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
|
||||
0, NULL);
|
||||
udelay(1);
|
||||
|
||||
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
4, BCMA_IOCTL_CLK);
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
|
||||
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
BCMA_IOCTL_CLK, NULL);
|
||||
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
|
||||
NULL);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
|
@ -358,8 +366,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
|
|||
*/
|
||||
ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
|
||||
ci->c_inf[0].base = regs;
|
||||
regdata = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
|
||||
regdata = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, chipid),
|
||||
NULL);
|
||||
ci->chip = regdata & CID_ID_MASK;
|
||||
ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
|
||||
ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
|
||||
|
@ -428,8 +437,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
/* Try forcing SDIO core to do ALPAvail request only */
|
||||
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
|
||||
brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "error writing for HT off\n");
|
||||
return err;
|
||||
|
@ -437,8 +445,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
/* If register supported, wait for ALPAvail and then force ALP */
|
||||
/* This may take up to 15 milliseconds */
|
||||
clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
|
||||
clkval = brcmf_sdio_regrb(sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
|
||||
|
||||
if ((clkval & ~SBSDIO_AVBITS) != clkset) {
|
||||
brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
|
||||
|
@ -446,8 +454,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
|
||||
SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
|
||||
!SBSDIO_ALPAV(clkval)),
|
||||
PMU_MAX_TRANSITION_DLY);
|
||||
if (!SBSDIO_ALPAV(clkval)) {
|
||||
|
@ -457,13 +465,11 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
|
|||
}
|
||||
|
||||
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
|
||||
brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
|
||||
udelay(65);
|
||||
|
||||
/* Also, disable the extra SDIO pull-ups */
|
||||
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -472,18 +478,22 @@ static void
|
|||
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
|
||||
struct chip_info *ci)
|
||||
{
|
||||
u32 base = ci->c_inf[0].base;
|
||||
|
||||
/* get chipcommon rev */
|
||||
ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
|
||||
|
||||
/* get chipcommon capabilites */
|
||||
ci->c_inf[0].caps =
|
||||
brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
|
||||
ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev,
|
||||
CORE_CC_REG(base, capabilities),
|
||||
NULL);
|
||||
|
||||
/* get pmu caps & rev */
|
||||
if (ci->c_inf[0].caps & CC_CAP_PMU) {
|
||||
ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
|
||||
ci->pmucaps =
|
||||
brcmf_sdio_regrl(sdiodev,
|
||||
CORE_CC_REG(base, pmucapabilities),
|
||||
NULL);
|
||||
ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
|
||||
}
|
||||
|
||||
|
@ -523,10 +533,10 @@ int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
|
|||
|
||||
brcmf_sdio_chip_buscoresetup(sdiodev, ci);
|
||||
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
|
||||
0, NULL);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
|
||||
0, NULL);
|
||||
|
||||
*ci_ptr = ci;
|
||||
return 0;
|
||||
|
@ -562,6 +572,7 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
|
|||
u32 str_mask = 0;
|
||||
u32 str_shift = 0;
|
||||
char chn[8];
|
||||
u32 base = ci->c_inf[0].base;
|
||||
|
||||
if (!(ci->c_inf[0].caps & CC_CAP_PMU))
|
||||
return;
|
||||
|
@ -591,17 +602,17 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
|
|||
}
|
||||
}
|
||||
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
|
||||
4, 1);
|
||||
cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
|
||||
1, NULL);
|
||||
cc_data_temp =
|
||||
brcmf_sdio_regrl(sdiodev,
|
||||
CORE_CC_REG(base, chipcontrol_addr),
|
||||
NULL);
|
||||
cc_data_temp &= ~str_mask;
|
||||
drivestrength_sel <<= str_shift;
|
||||
cc_data_temp |= drivestrength_sel;
|
||||
brcmf_sdcard_reg_write(sdiodev,
|
||||
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
|
||||
4, cc_data_temp);
|
||||
brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
|
||||
cc_data_temp, NULL);
|
||||
|
||||
brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
|
||||
drivestrength, cc_data_temp);
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
/* Maximum number of I/O funcs */
|
||||
#define SDIOD_MAX_IOFUNCS 7
|
||||
|
||||
/* mask of register map */
|
||||
#define REG_F0_REG_MASK 0x7FF
|
||||
#define REG_F1_MISC_MASK 0x1FFFF
|
||||
|
||||
/* as of sdiod rev 0, supports 3 functions */
|
||||
#define SBSDIO_NUM_FUNCTION 3
|
||||
|
||||
|
@ -142,7 +146,6 @@ struct brcmf_sdio_dev {
|
|||
u8 num_funcs; /* Supported funcs on client */
|
||||
u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
|
||||
u32 sbwad; /* Save backplane window address */
|
||||
bool regfail; /* status of last reg_r/w call */
|
||||
void *bus;
|
||||
atomic_t suspend; /* suspend flag */
|
||||
wait_queue_head_t request_byte_wait;
|
||||
|
@ -164,31 +167,13 @@ struct brcmf_sdio_dev {
|
|||
extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
|
||||
extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
|
||||
|
||||
/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
|
||||
* fn: function number
|
||||
* addr: unmodified SDIO-space address
|
||||
* data: data byte to write
|
||||
* err: pointer to error code (or NULL)
|
||||
*/
|
||||
extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func,
|
||||
u32 addr, int *err);
|
||||
extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func,
|
||||
u32 addr, u8 data, int *err);
|
||||
|
||||
/* Synchronous access to device (client) core registers via CMD53 to F1.
|
||||
* addr: backplane address (i.e. >= regsva from attach)
|
||||
* size: register width in bytes (2 or 4)
|
||||
* data: data for register write
|
||||
*/
|
||||
extern u32
|
||||
brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size);
|
||||
|
||||
extern u32
|
||||
brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
|
||||
u32 data);
|
||||
|
||||
/* Indicate if last reg read/write failed */
|
||||
extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev);
|
||||
/* sdio device register access interface */
|
||||
extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
|
||||
extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
|
||||
extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||
u8 data, int *ret);
|
||||
extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
||||
u32 data, int *ret);
|
||||
|
||||
/* Buffer transfer to/from device (client) core via cmd53.
|
||||
* fn: function number
|
||||
|
|
|
@ -39,10 +39,7 @@ BRCMSMAC_OFILES := \
|
|||
phy/phytbl_lcn.o \
|
||||
phy/phytbl_n.o \
|
||||
phy/phy_qmath.o \
|
||||
otp.o \
|
||||
srom.o \
|
||||
dma.o \
|
||||
nicpci.o \
|
||||
brcms_trace_events.o
|
||||
|
||||
MODULEPFX := brcmsmac
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <chipcommon.h>
|
||||
|
@ -29,8 +28,6 @@
|
|||
#include "types.h"
|
||||
#include "pub.h"
|
||||
#include "pmu.h"
|
||||
#include "srom.h"
|
||||
#include "nicpci.h"
|
||||
#include "aiutils.h"
|
||||
|
||||
/* slow_clk_ctl */
|
||||
|
@ -321,7 +318,6 @@
|
|||
#define IS_SIM(chippkg) \
|
||||
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
|
||||
|
||||
#define PCI(sih) (ai_get_buscoretype(sih) == PCI_CORE_ID)
|
||||
#define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID)
|
||||
|
||||
#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID))
|
||||
|
@ -454,36 +450,9 @@ struct aidmp {
|
|||
u32 componentid3; /* 0xffc */
|
||||
};
|
||||
|
||||
/* return true if PCIE capability exists in the pci config space */
|
||||
static bool ai_ispcie(struct si_info *sii)
|
||||
{
|
||||
u8 cap_ptr;
|
||||
|
||||
cap_ptr =
|
||||
pcicore_find_pci_capability(sii->pcibus, PCI_CAP_ID_EXP, NULL,
|
||||
NULL);
|
||||
if (!cap_ptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ai_buscore_prep(struct si_info *sii)
|
||||
{
|
||||
/* kludge to enable the clock on the 4306 which lacks a slowclock */
|
||||
if (!ai_ispcie(sii))
|
||||
ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
|
||||
{
|
||||
struct bcma_device *pci = NULL;
|
||||
struct bcma_device *pcie = NULL;
|
||||
struct bcma_device *core;
|
||||
|
||||
|
||||
/* no cores found, bail out */
|
||||
if (cc->bus->nr_cores == 0)
|
||||
return false;
|
||||
|
@ -492,8 +461,7 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
|
|||
sii->pub.ccrev = cc->id.rev;
|
||||
|
||||
/* get chipcommon chipstatus */
|
||||
if (ai_get_ccrev(&sii->pub) >= 11)
|
||||
sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
|
||||
sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
|
||||
|
||||
/* get chipcommon capabilites */
|
||||
sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
|
||||
|
@ -506,64 +474,18 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
|
|||
}
|
||||
|
||||
/* figure out buscore */
|
||||
list_for_each_entry(core, &cc->bus->cores, list) {
|
||||
uint cid, crev;
|
||||
|
||||
cid = core->id.id;
|
||||
crev = core->id.rev;
|
||||
|
||||
if (cid == PCI_CORE_ID) {
|
||||
pci = core;
|
||||
} else if (cid == PCIE_CORE_ID) {
|
||||
pcie = core;
|
||||
}
|
||||
}
|
||||
|
||||
if (pci && pcie) {
|
||||
if (ai_ispcie(sii))
|
||||
pci = NULL;
|
||||
else
|
||||
pcie = NULL;
|
||||
}
|
||||
if (pci) {
|
||||
sii->buscore = pci;
|
||||
} else if (pcie) {
|
||||
sii->buscore = pcie;
|
||||
}
|
||||
|
||||
/* fixup necessary chip/core configurations */
|
||||
if (!sii->pch) {
|
||||
sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core);
|
||||
if (sii->pch == NULL)
|
||||
return false;
|
||||
}
|
||||
if (ai_pci_fixcfg(&sii->pub))
|
||||
return false;
|
||||
sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* get boardtype and boardrev
|
||||
*/
|
||||
static __used void ai_nvram_process(struct si_info *sii)
|
||||
{
|
||||
uint w = 0;
|
||||
|
||||
/* do a pci config read to get subsystem id and subvendor id */
|
||||
pci_read_config_dword(sii->pcibus, PCI_SUBSYSTEM_VENDOR_ID, &w);
|
||||
|
||||
sii->pub.boardvendor = w & 0xffff;
|
||||
sii->pub.boardtype = (w >> 16) & 0xffff;
|
||||
}
|
||||
|
||||
static struct si_info *ai_doattach(struct si_info *sii,
|
||||
struct bcma_bus *pbus)
|
||||
{
|
||||
struct si_pub *sih = &sii->pub;
|
||||
u32 w, savewin;
|
||||
struct bcma_device *cc;
|
||||
uint socitype;
|
||||
struct ssb_sprom *sprom = &pbus->sprom;
|
||||
|
||||
savewin = 0;
|
||||
|
||||
|
@ -573,38 +495,15 @@ static struct si_info *ai_doattach(struct si_info *sii,
|
|||
/* switch to Chipcommon core */
|
||||
cc = pbus->drv_cc.core;
|
||||
|
||||
/* bus/core/clk setup for register access */
|
||||
if (!ai_buscore_prep(sii))
|
||||
return NULL;
|
||||
sih->chip = pbus->chipinfo.id;
|
||||
sih->chiprev = pbus->chipinfo.rev;
|
||||
sih->chippkg = pbus->chipinfo.pkg;
|
||||
sih->boardvendor = pbus->boardinfo.vendor;
|
||||
sih->boardtype = pbus->boardinfo.type;
|
||||
|
||||
/*
|
||||
* ChipID recognition.
|
||||
* We assume we can read chipid at offset 0 from the regs arg.
|
||||
* If we add other chiptypes (or if we need to support old sdio
|
||||
* hosts w/o chipcommon), some way of recognizing them needs to
|
||||
* be added here.
|
||||
*/
|
||||
w = bcma_read32(cc, CHIPCREGOFFS(chipid));
|
||||
socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
|
||||
/* Might as wll fill in chip id rev & pkg */
|
||||
sih->chip = w & CID_ID_MASK;
|
||||
sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
|
||||
sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
|
||||
|
||||
/* scan for cores */
|
||||
if (socitype != SOCI_AI)
|
||||
return NULL;
|
||||
|
||||
SI_MSG("Found chip type AI (0x%08x)\n", w);
|
||||
if (!ai_buscore_setup(sii, cc))
|
||||
goto exit;
|
||||
|
||||
/* Init nvram from sprom/otp if they exist */
|
||||
if (srom_var_init(&sii->pub))
|
||||
goto exit;
|
||||
|
||||
ai_nvram_process(sii);
|
||||
|
||||
/* === NVRAM, clock is ready === */
|
||||
bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
|
||||
bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
|
||||
|
@ -617,15 +516,13 @@ static struct si_info *ai_doattach(struct si_info *sii,
|
|||
}
|
||||
|
||||
/* setup the GPIO based LED powersave register */
|
||||
w = getintvar(sih, BRCMS_SROM_LEDDC);
|
||||
w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
|
||||
(sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT);
|
||||
if (w == 0)
|
||||
w = DEFAULT_GPIOTIMERVAL;
|
||||
ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval),
|
||||
~0, w);
|
||||
|
||||
if (PCIE(sih))
|
||||
pcicore_attach(sii->pch, SI_DOATTACH);
|
||||
|
||||
if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) {
|
||||
/*
|
||||
* enable 12 mA drive strenth for 43224 and
|
||||
|
@ -659,9 +556,6 @@ static struct si_info *ai_doattach(struct si_info *sii,
|
|||
return sii;
|
||||
|
||||
exit:
|
||||
if (sii->pch)
|
||||
pcicore_deinit(sii->pch);
|
||||
sii->pch = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -700,11 +594,6 @@ void ai_detach(struct si_pub *sih)
|
|||
if (sii == NULL)
|
||||
return;
|
||||
|
||||
if (sii->pch)
|
||||
pcicore_deinit(sii->pch);
|
||||
sii->pch = NULL;
|
||||
|
||||
srom_free_vars(sih);
|
||||
kfree(sii);
|
||||
}
|
||||
|
||||
|
@ -755,21 +644,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
|
|||
/* return the slow clock source - LPO, XTAL, or PCI */
|
||||
static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
|
||||
{
|
||||
struct si_info *sii;
|
||||
u32 val;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
if (ai_get_ccrev(&sii->pub) < 6) {
|
||||
pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT,
|
||||
&val);
|
||||
if (val & PCI_CFG_GPIO_SCS)
|
||||
return SCC_SS_PCI;
|
||||
return SCC_SS_XTAL;
|
||||
} else if (ai_get_ccrev(&sii->pub) < 10) {
|
||||
return bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) &
|
||||
SCC_SS_MASK;
|
||||
} else /* Insta-clock */
|
||||
return SCC_SS_XTAL;
|
||||
return SCC_SS_XTAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -779,36 +654,12 @@ static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
|
|||
static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
|
||||
struct bcma_device *cc)
|
||||
{
|
||||
u32 slowclk;
|
||||
uint div;
|
||||
|
||||
slowclk = ai_slowclk_src(sih, cc);
|
||||
if (ai_get_ccrev(sih) < 6) {
|
||||
if (slowclk == SCC_SS_PCI)
|
||||
return max_freq ? (PCIMAXFREQ / 64)
|
||||
: (PCIMINFREQ / 64);
|
||||
else
|
||||
return max_freq ? (XTALMAXFREQ / 32)
|
||||
: (XTALMINFREQ / 32);
|
||||
} else if (ai_get_ccrev(sih) < 10) {
|
||||
div = 4 *
|
||||
(((bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) &
|
||||
SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
|
||||
if (slowclk == SCC_SS_LPO)
|
||||
return max_freq ? LPOMAXFREQ : LPOMINFREQ;
|
||||
else if (slowclk == SCC_SS_XTAL)
|
||||
return max_freq ? (XTALMAXFREQ / div)
|
||||
: (XTALMINFREQ / div);
|
||||
else if (slowclk == SCC_SS_PCI)
|
||||
return max_freq ? (PCIMAXFREQ / div)
|
||||
: (PCIMINFREQ / div);
|
||||
} else {
|
||||
/* Chipc rev 10 is InstaClock */
|
||||
div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
|
||||
div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
|
||||
return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
|
||||
}
|
||||
return 0;
|
||||
/* Chipc rev 10 is InstaClock */
|
||||
div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
|
||||
div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
|
||||
return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -831,8 +682,7 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
|
|||
|
||||
/* Starting with 4318 it is ILP that is used for the delays */
|
||||
slowmaxfreq =
|
||||
ai_slowclk_freq(sih,
|
||||
(ai_get_ccrev(sih) >= 10) ? false : true, cc);
|
||||
ai_slowclk_freq(sih, false, cc);
|
||||
|
||||
pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
|
||||
fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
|
||||
|
@ -854,9 +704,8 @@ void ai_clkctl_init(struct si_pub *sih)
|
|||
return;
|
||||
|
||||
/* set all Instaclk chip ILP to 1 MHz */
|
||||
if (ai_get_ccrev(sih) >= 10)
|
||||
bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
|
||||
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
|
||||
bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
|
||||
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
|
||||
|
||||
ai_clkctl_setdelay(sih, cc);
|
||||
}
|
||||
|
@ -891,140 +740,6 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
|
|||
return fpdelay;
|
||||
}
|
||||
|
||||
/* turn primary xtal and/or pll off/on */
|
||||
int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
|
||||
{
|
||||
struct si_info *sii;
|
||||
u32 in, out, outen;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
/* pcie core doesn't have any mapping to control the xtal pu */
|
||||
if (PCIE(sih))
|
||||
return -1;
|
||||
|
||||
pci_read_config_dword(sii->pcibus, PCI_GPIO_IN, &in);
|
||||
pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, &out);
|
||||
pci_read_config_dword(sii->pcibus, PCI_GPIO_OUTEN, &outen);
|
||||
|
||||
/*
|
||||
* Avoid glitching the clock if GPRS is already using it.
|
||||
* We can't actually read the state of the PLLPD so we infer it
|
||||
* by the value of XTAL_PU which *is* readable via gpioin.
|
||||
*/
|
||||
if (on && (in & PCI_CFG_GPIO_XTAL))
|
||||
return 0;
|
||||
|
||||
if (what & XTAL)
|
||||
outen |= PCI_CFG_GPIO_XTAL;
|
||||
if (what & PLL)
|
||||
outen |= PCI_CFG_GPIO_PLL;
|
||||
|
||||
if (on) {
|
||||
/* turn primary xtal on */
|
||||
if (what & XTAL) {
|
||||
out |= PCI_CFG_GPIO_XTAL;
|
||||
if (what & PLL)
|
||||
out |= PCI_CFG_GPIO_PLL;
|
||||
pci_write_config_dword(sii->pcibus,
|
||||
PCI_GPIO_OUT, out);
|
||||
pci_write_config_dword(sii->pcibus,
|
||||
PCI_GPIO_OUTEN, outen);
|
||||
udelay(XTAL_ON_DELAY);
|
||||
}
|
||||
|
||||
/* turn pll on */
|
||||
if (what & PLL) {
|
||||
out &= ~PCI_CFG_GPIO_PLL;
|
||||
pci_write_config_dword(sii->pcibus,
|
||||
PCI_GPIO_OUT, out);
|
||||
mdelay(2);
|
||||
}
|
||||
} else {
|
||||
if (what & XTAL)
|
||||
out &= ~PCI_CFG_GPIO_XTAL;
|
||||
if (what & PLL)
|
||||
out |= PCI_CFG_GPIO_PLL;
|
||||
pci_write_config_dword(sii->pcibus,
|
||||
PCI_GPIO_OUT, out);
|
||||
pci_write_config_dword(sii->pcibus,
|
||||
PCI_GPIO_OUTEN, outen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clk control mechanism through chipcommon, no policy checking */
|
||||
static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
|
||||
{
|
||||
struct bcma_device *cc;
|
||||
u32 scc;
|
||||
|
||||
/* chipcommon cores prior to rev6 don't support dynamic clock control */
|
||||
if (ai_get_ccrev(&sii->pub) < 6)
|
||||
return false;
|
||||
|
||||
cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
|
||||
|
||||
if (!(ai_get_cccaps(&sii->pub) & CC_CAP_PWR_CTL) &&
|
||||
(ai_get_ccrev(&sii->pub) < 20))
|
||||
return mode == CLK_FAST;
|
||||
|
||||
switch (mode) {
|
||||
case CLK_FAST: /* FORCEHT, fast (pll) clock */
|
||||
if (ai_get_ccrev(&sii->pub) < 10) {
|
||||
/*
|
||||
* don't forget to force xtal back
|
||||
* on before we clear SCC_DYN_XTAL..
|
||||
*/
|
||||
ai_clkctl_xtal(&sii->pub, XTAL, ON);
|
||||
bcma_maskset32(cc, CHIPCREGOFFS(slow_clk_ctl),
|
||||
(SCC_XC | SCC_FS | SCC_IP), SCC_IP);
|
||||
} else if (ai_get_ccrev(&sii->pub) < 20) {
|
||||
bcma_set32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_HR);
|
||||
} else {
|
||||
bcma_set32(cc, CHIPCREGOFFS(clk_ctl_st), CCS_FORCEHT);
|
||||
}
|
||||
|
||||
/* wait for the PLL */
|
||||
if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
|
||||
u32 htavail = CCS_HTAVAIL;
|
||||
SPINWAIT(((bcma_read32(cc, CHIPCREGOFFS(clk_ctl_st)) &
|
||||
htavail) == 0), PMU_MAX_TRANSITION_DLY);
|
||||
} else {
|
||||
udelay(PLL_DELAY);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLK_DYNAMIC: /* enable dynamic clock control */
|
||||
if (ai_get_ccrev(&sii->pub) < 10) {
|
||||
scc = bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl));
|
||||
scc &= ~(SCC_FS | SCC_IP | SCC_XC);
|
||||
if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
|
||||
scc |= SCC_XC;
|
||||
bcma_write32(cc, CHIPCREGOFFS(slow_clk_ctl), scc);
|
||||
|
||||
/*
|
||||
* for dynamic control, we have to
|
||||
* release our xtal_pu "force on"
|
||||
*/
|
||||
if (scc & SCC_XC)
|
||||
ai_clkctl_xtal(&sii->pub, XTAL, OFF);
|
||||
} else if (ai_get_ccrev(&sii->pub) < 20) {
|
||||
/* Instaclock */
|
||||
bcma_mask32(cc, CHIPCREGOFFS(system_clk_ctl), ~SYCC_HR);
|
||||
} else {
|
||||
bcma_mask32(cc, CHIPCREGOFFS(clk_ctl_st), ~CCS_FORCEHT);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return mode == CLK_FAST;
|
||||
}
|
||||
|
||||
/*
|
||||
* clock control policy function throught chipcommon
|
||||
*
|
||||
|
@ -1033,133 +748,53 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
|
|||
* this is a wrapper over the next internal function
|
||||
* to allow flexible policy settings for outside caller
|
||||
*/
|
||||
bool ai_clkctl_cc(struct si_pub *sih, uint mode)
|
||||
bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct bcma_device *cc;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
/* chipcommon cores prior to rev6 don't support dynamic clock control */
|
||||
if (ai_get_ccrev(sih) < 6)
|
||||
return false;
|
||||
|
||||
if (PCI_FORCEHT(sih))
|
||||
return mode == CLK_FAST;
|
||||
return mode == BCMA_CLKMODE_FAST;
|
||||
|
||||
return _ai_clkctl_cc(sii, mode);
|
||||
cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_set_clockmode(cc, mode);
|
||||
return mode == BCMA_CLKMODE_FAST;
|
||||
}
|
||||
|
||||
void ai_pci_up(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct bcma_device *cc;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
if (PCI_FORCEHT(sih))
|
||||
_ai_clkctl_cc(sii, CLK_FAST);
|
||||
if (PCI_FORCEHT(sih)) {
|
||||
cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST);
|
||||
}
|
||||
|
||||
if (PCIE(sih))
|
||||
pcicore_up(sii->pch, SI_PCIUP);
|
||||
|
||||
}
|
||||
|
||||
/* Unconfigure and/or apply various WARs when system is going to sleep mode */
|
||||
void ai_pci_sleep(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
pcicore_sleep(sii->pch);
|
||||
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
|
||||
}
|
||||
|
||||
/* Unconfigure and/or apply various WARs when going down */
|
||||
void ai_pci_down(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct bcma_device *cc;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
/* release FORCEHT since chip is going to "down" state */
|
||||
if (PCI_FORCEHT(sih))
|
||||
_ai_clkctl_cc(sii, CLK_DYNAMIC);
|
||||
|
||||
pcicore_down(sii->pch, SI_PCIDOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the pci core for pci client (NIC) action
|
||||
* coremask is the bitvec of cores by index to be enabled.
|
||||
*/
|
||||
void ai_pci_setup(struct si_pub *sih, uint coremask)
|
||||
{
|
||||
struct si_info *sii;
|
||||
u32 w;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
/*
|
||||
* Enable sb->pci interrupts. Assume
|
||||
* PCI rev 2.3 support was added in pci core rev 6 and things changed..
|
||||
*/
|
||||
if (PCIE(sih) || (PCI(sih) && (ai_get_buscorerev(sih) >= 6))) {
|
||||
/* pci config write to set this core bit in PCIIntMask */
|
||||
pci_read_config_dword(sii->pcibus, PCI_INT_MASK, &w);
|
||||
w |= (coremask << PCI_SBIM_SHIFT);
|
||||
pci_write_config_dword(sii->pcibus, PCI_INT_MASK, w);
|
||||
if (PCI_FORCEHT(sih)) {
|
||||
cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC);
|
||||
}
|
||||
|
||||
if (PCI(sih)) {
|
||||
pcicore_pci_setup(sii->pch);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixup SROMless PCI device's configuration.
|
||||
* The current core may be changed upon return.
|
||||
*/
|
||||
int ai_pci_fixcfg(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii = (struct si_info *)sih;
|
||||
|
||||
/* Fixup PI in SROM shadow area to enable the correct PCI core access */
|
||||
/* check 'pi' is correct and fix it if not */
|
||||
pcicore_fixcfg(sii->pch);
|
||||
pcicore_hwup(sii->pch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mask&set gpiocontrol bits */
|
||||
u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority)
|
||||
{
|
||||
uint regoff;
|
||||
|
||||
regoff = offsetof(struct chipcregs, gpiocontrol);
|
||||
return ai_cc_reg(sih, regoff, mask, val);
|
||||
}
|
||||
|
||||
void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
|
||||
{
|
||||
struct bcma_device *cc;
|
||||
u32 val;
|
||||
|
||||
cc = ai_findcore(sih, CC_CORE_ID, 0);
|
||||
|
||||
if (on) {
|
||||
if (ai_get_chippkg(sih) == 9 || ai_get_chippkg(sih) == 0xb)
|
||||
/* Ext PA Controls for 4331 12x9 Package */
|
||||
bcma_set32(cc, CHIPCREGOFFS(chipcontrol),
|
||||
CCTRL4331_EXTPA_EN |
|
||||
CCTRL4331_EXTPA_ON_GPIO2_5);
|
||||
else
|
||||
/* Ext PA Controls for 4331 12x12 Package */
|
||||
bcma_set32(cc, CHIPCREGOFFS(chipcontrol),
|
||||
CCTRL4331_EXTPA_EN);
|
||||
} else {
|
||||
val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
|
||||
bcma_mask32(cc, CHIPCREGOFFS(chipcontrol),
|
||||
~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5));
|
||||
}
|
||||
if (PCIE(sih))
|
||||
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
|
||||
}
|
||||
|
||||
/* Enable BT-COEX & Ex-PA for 4313 */
|
||||
|
@ -1181,6 +816,9 @@ bool ai_deviceremoved(struct si_pub *sih)
|
|||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
|
||||
return false;
|
||||
|
||||
pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
|
||||
if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
|
||||
return true;
|
||||
|
@ -1188,45 +826,6 @@ bool ai_deviceremoved(struct si_pub *sih)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ai_is_sprom_available(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii = (struct si_info *)sih;
|
||||
|
||||
if (ai_get_ccrev(sih) >= 31) {
|
||||
struct bcma_device *cc;
|
||||
u32 sromctrl;
|
||||
|
||||
if ((ai_get_cccaps(sih) & CC_CAP_SROM) == 0)
|
||||
return false;
|
||||
|
||||
cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
|
||||
sromctrl = bcma_read32(cc, CHIPCREGOFFS(sromcontrol));
|
||||
return sromctrl & SRC_PRESENT;
|
||||
}
|
||||
|
||||
switch (ai_get_chip_id(sih)) {
|
||||
case BCM4313_CHIP_ID:
|
||||
return (sii->chipst & CST4313_SPROM_PRESENT) != 0;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ai_is_otp_disabled(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii = (struct si_info *)sih;
|
||||
|
||||
switch (ai_get_chip_id(sih)) {
|
||||
case BCM4313_CHIP_ID:
|
||||
return (sii->chipst & CST4313_OTP_PRESENT) == 0;
|
||||
/* These chips always have their OTP on */
|
||||
case BCM43224_CHIP_ID:
|
||||
case BCM43225_CHIP_ID:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint ai_get_buscoretype(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii = (struct si_info *)sih;
|
||||
|
|
|
@ -113,10 +113,6 @@
|
|||
#define XTAL 0x1 /* primary crystal oscillator (2050) */
|
||||
#define PLL 0x2 /* main chip pll */
|
||||
|
||||
/* clkctl clk mode */
|
||||
#define CLK_FAST 0 /* force fast (pll) clock */
|
||||
#define CLK_DYNAMIC 2 /* enable dynamic clock control */
|
||||
|
||||
/* GPIO usage priorities */
|
||||
#define GPIO_DRV_PRIORITY 0 /* Driver */
|
||||
#define GPIO_APP_PRIORITY 1 /* Application */
|
||||
|
@ -172,9 +168,7 @@ struct si_info {
|
|||
struct si_pub pub; /* back plane public state (must be first) */
|
||||
struct bcma_bus *icbus; /* handle to soc interconnect bus */
|
||||
struct pci_dev *pcibus; /* handle to pci bus */
|
||||
struct pcicore_info *pch; /* PCI/E core handle */
|
||||
struct bcma_device *buscore;
|
||||
struct list_head var_list; /* list of srom variables */
|
||||
|
||||
u32 chipst; /* chip status */
|
||||
};
|
||||
|
@ -197,38 +191,20 @@ extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
|
|||
extern struct si_pub *ai_attach(struct bcma_bus *pbus);
|
||||
extern void ai_detach(struct si_pub *sih);
|
||||
extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
|
||||
extern void ai_pci_setup(struct si_pub *sih, uint coremask);
|
||||
extern void ai_clkctl_init(struct si_pub *sih);
|
||||
extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
|
||||
extern bool ai_clkctl_cc(struct si_pub *sih, uint mode);
|
||||
extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on);
|
||||
extern bool ai_deviceremoved(struct si_pub *sih);
|
||||
extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val,
|
||||
u8 priority);
|
||||
|
||||
/* OTP status */
|
||||
extern bool ai_is_otp_disabled(struct si_pub *sih);
|
||||
|
||||
/* SPROM availability */
|
||||
extern bool ai_is_sprom_available(struct si_pub *sih);
|
||||
|
||||
extern void ai_pci_sleep(struct si_pub *sih);
|
||||
extern void ai_pci_down(struct si_pub *sih);
|
||||
extern void ai_pci_up(struct si_pub *sih);
|
||||
extern int ai_pci_fixcfg(struct si_pub *sih);
|
||||
|
||||
extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
|
||||
/* Enable Ex-PA for 4313 */
|
||||
extern void ai_epa_4313war(struct si_pub *sih);
|
||||
|
||||
extern uint ai_get_buscoretype(struct si_pub *sih);
|
||||
extern uint ai_get_buscorerev(struct si_pub *sih);
|
||||
|
||||
static inline int ai_get_ccrev(struct si_pub *sih)
|
||||
{
|
||||
return sih->ccrev;
|
||||
}
|
||||
|
||||
static inline u32 ai_get_cccaps(struct si_pub *sih)
|
||||
{
|
||||
return sih->cccaps;
|
||||
|
|
|
@ -108,7 +108,7 @@ brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
|
|||
struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
|
||||
{
|
||||
struct antsel_info *asi;
|
||||
struct si_pub *sih = wlc->hw->sih;
|
||||
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
|
||||
|
||||
asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
|
||||
if (!asi)
|
||||
|
@ -118,7 +118,7 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
|
|||
asi->pub = wlc->pub;
|
||||
asi->antsel_type = ANTSEL_NA;
|
||||
asi->antsel_avail = false;
|
||||
asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH);
|
||||
asi->antsel_antswitch = sprom->antswitch;
|
||||
|
||||
if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
|
||||
switch (asi->antsel_antswitch) {
|
||||
|
@ -128,12 +128,12 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
|
|||
/* 4321/2 board with 2x3 switch logic */
|
||||
asi->antsel_type = ANTSEL_2x3;
|
||||
/* Antenna selection availability */
|
||||
if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) ||
|
||||
((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) {
|
||||
if ((sprom->ant_available_bg == 7) ||
|
||||
(sprom->ant_available_a == 7)) {
|
||||
asi->antsel_avail = true;
|
||||
} else if (
|
||||
(u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 ||
|
||||
(u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) {
|
||||
sprom->ant_available_bg == 3 ||
|
||||
sprom->ant_available_a == 3) {
|
||||
asi->antsel_avail = false;
|
||||
} else {
|
||||
asi->antsel_avail = false;
|
||||
|
@ -146,8 +146,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
|
|||
break;
|
||||
}
|
||||
} else if ((asi->pub->sromrev == 4) &&
|
||||
((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) &&
|
||||
((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) {
|
||||
(sprom->ant_available_bg == 7) &&
|
||||
(sprom->ant_available_a == 0)) {
|
||||
/* hack to match old 4321CB2 cards with 2of3 antenna switch */
|
||||
asi->antsel_type = ANTSEL_2x3;
|
||||
asi->antsel_avail = true;
|
||||
|
|
|
@ -1110,7 +1110,7 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
|
|||
char country_abbrev[BRCM_CNTRY_BUF_SZ];
|
||||
const struct country_info *country;
|
||||
struct brcms_pub *pub = wlc->pub;
|
||||
char *ccode;
|
||||
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
|
||||
|
||||
|
@ -1122,9 +1122,8 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
|
|||
wlc->cmi = wlc_cm;
|
||||
|
||||
/* store the country code for passing up as a regulatory hint */
|
||||
ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
|
||||
if (ccode && brcms_c_country_valid(ccode))
|
||||
strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
|
||||
if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2))
|
||||
strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2));
|
||||
|
||||
/*
|
||||
* internal country information which must match
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/bcma/bcma.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <defs.h>
|
||||
#include "nicpci.h"
|
||||
#include "phy/phy_int.h"
|
||||
#include "d11.h"
|
||||
#include "channel.h"
|
||||
|
@ -770,7 +769,7 @@ void brcms_dpc(unsigned long data)
|
|||
* Precondition: Since this function is called in brcms_pci_probe() context,
|
||||
* no locking is required.
|
||||
*/
|
||||
static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
|
||||
static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
|
||||
{
|
||||
int status;
|
||||
struct device *device = &pdev->dev;
|
||||
|
@ -1022,7 +1021,7 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
|
|||
spin_lock_init(&wl->isr_lock);
|
||||
|
||||
/* prepare ucode */
|
||||
if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) {
|
||||
if (brcms_request_fw(wl, pdev) < 0) {
|
||||
wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
|
||||
"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
|
||||
brcms_release_fw(wl);
|
||||
|
@ -1043,12 +1042,12 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
|
|||
wl->pub->ieee_hw = hw;
|
||||
|
||||
/* register our interrupt handler */
|
||||
if (request_irq(pdev->bus->host_pci->irq, brcms_isr,
|
||||
if (request_irq(pdev->irq, brcms_isr,
|
||||
IRQF_SHARED, KBUILD_MODNAME, wl)) {
|
||||
wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
|
||||
goto fail;
|
||||
}
|
||||
wl->irq = pdev->bus->host_pci->irq;
|
||||
wl->irq = pdev->irq;
|
||||
|
||||
/* register module */
|
||||
brcms_c_module_register(wl->pub, "linux", wl, NULL);
|
||||
|
@ -1098,7 +1097,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
|
|||
|
||||
dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
|
||||
pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
|
||||
pdev->bus->host_pci->irq);
|
||||
pdev->irq);
|
||||
|
||||
if ((pdev->id.manuf != BCMA_MANUF_BCM) ||
|
||||
(pdev->id.id != BCMA_CORE_80211))
|
||||
|
|
|
@ -1219,7 +1219,7 @@ static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
|
|||
}
|
||||
|
||||
/* control chip clock to save power, enable dynamic clock or force fast clock */
|
||||
static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
|
||||
static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, enum bcma_clkmode mode)
|
||||
{
|
||||
if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) {
|
||||
/* new chips with PMU, CCS_FORCEHT will distribute the HT clock
|
||||
|
@ -1229,7 +1229,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
|
|||
*/
|
||||
|
||||
if (wlc_hw->clk) {
|
||||
if (mode == CLK_FAST) {
|
||||
if (mode == BCMA_CLKMODE_FAST) {
|
||||
bcma_set32(wlc_hw->d11core,
|
||||
D11REGOFFS(clk_ctl_st),
|
||||
CCS_FORCEHT);
|
||||
|
@ -1260,7 +1260,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
|
|||
~CCS_FORCEHT);
|
||||
}
|
||||
}
|
||||
wlc_hw->forcefastclk = (mode == CLK_FAST);
|
||||
wlc_hw->forcefastclk = (mode == BCMA_CLKMODE_FAST);
|
||||
} else {
|
||||
|
||||
/* old chips w/o PMU, force HT through cc,
|
||||
|
@ -1567,7 +1567,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
|
|||
/* request FAST clock if not on */
|
||||
fastclk = wlc_hw->forcefastclk;
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
|
||||
|
||||
|
@ -1576,7 +1576,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
|
|||
|
||||
/* restore the clk */
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
|
||||
}
|
||||
|
||||
static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
|
||||
|
@ -1882,27 +1882,20 @@ static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
|
|||
return true;
|
||||
}
|
||||
|
||||
static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
|
||||
static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ALEN])
|
||||
{
|
||||
enum brcms_srom_id var_id = BRCMS_SROM_MACADDR;
|
||||
char *macaddr;
|
||||
struct ssb_sprom *sprom = &wlc_hw->d11core->bus->sprom;
|
||||
|
||||
/* If macaddr exists, use it (Sromrev4, CIS, ...). */
|
||||
macaddr = getvar(wlc_hw->sih, var_id);
|
||||
if (macaddr != NULL)
|
||||
return macaddr;
|
||||
if (!is_zero_ether_addr(sprom->il0mac)) {
|
||||
memcpy(etheraddr, sprom->il0mac, 6);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wlc_hw->_nbands > 1)
|
||||
var_id = BRCMS_SROM_ET1MACADDR;
|
||||
memcpy(etheraddr, sprom->et1mac, 6);
|
||||
else
|
||||
var_id = BRCMS_SROM_IL0MACADDR;
|
||||
|
||||
macaddr = getvar(wlc_hw->sih, var_id);
|
||||
if (macaddr == NULL)
|
||||
wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
|
||||
"getvar(%d) not found\n", wlc_hw->unit, var_id);
|
||||
|
||||
return macaddr;
|
||||
memcpy(etheraddr, sprom->il0mac, 6);
|
||||
}
|
||||
|
||||
/* power both the pll and external oscillator on/off */
|
||||
|
@ -1917,9 +1910,6 @@ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
|
|||
if (!want && wlc_hw->pllreq)
|
||||
return;
|
||||
|
||||
if (wlc_hw->sih)
|
||||
ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
|
||||
|
||||
wlc_hw->sbclk = want;
|
||||
if (!wlc_hw->sbclk) {
|
||||
wlc_hw->clk = false;
|
||||
|
@ -2004,7 +1994,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
|
|||
/* request FAST clock if not on */
|
||||
fastclk = wlc_hw->forcefastclk;
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
/* reset the dma engines except first time thru */
|
||||
if (bcma_core_is_enabled(wlc_hw->d11core)) {
|
||||
|
@ -2053,7 +2043,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
|
|||
brcms_c_mctrl_reset(wlc_hw);
|
||||
|
||||
if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
brcms_b_phy_reset(wlc_hw);
|
||||
|
||||
|
@ -2065,7 +2055,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
|
|||
|
||||
/* restore the clk setting */
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
|
||||
}
|
||||
|
||||
/* txfifo sizes needs to be modified(increased) since the newer cores
|
||||
|
@ -2218,7 +2208,7 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc)
|
|||
gm |= gc |= BOARD_GPIO_PACTRL;
|
||||
|
||||
/* apply to gpiocontrol register */
|
||||
ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
|
||||
bcma_chipco_gpio_control(&wlc_hw->d11core->bus->drv_cc, gm, gc);
|
||||
}
|
||||
|
||||
static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
|
||||
|
@ -3371,7 +3361,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) {
|
|||
/* request FAST clock if not on */
|
||||
fastclk = wlc_hw->forcefastclk;
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
/* disable interrupts */
|
||||
macintmask = brcms_intrsoff(wlc->wl);
|
||||
|
@ -3405,7 +3395,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) {
|
|||
|
||||
/* restore the clk */
|
||||
if (!fastclk)
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
|
||||
}
|
||||
|
||||
static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
|
||||
|
@ -4436,17 +4426,22 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
uint unit, bool piomode)
|
||||
{
|
||||
struct brcms_hardware *wlc_hw;
|
||||
char *macaddr = NULL;
|
||||
uint err = 0;
|
||||
uint j;
|
||||
bool wme = false;
|
||||
struct shared_phy_params sha_params;
|
||||
struct wiphy *wiphy = wlc->wiphy;
|
||||
struct pci_dev *pcidev = core->bus->host_pci;
|
||||
struct ssb_sprom *sprom = &core->bus->sprom;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
|
||||
pcidev->vendor,
|
||||
pcidev->device);
|
||||
if (core->bus->hosttype == BCMA_HOSTTYPE_PCI)
|
||||
BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
|
||||
pcidev->vendor,
|
||||
pcidev->device);
|
||||
else
|
||||
BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
|
||||
core->bus->boardinfo.vendor,
|
||||
core->bus->boardinfo.type);
|
||||
|
||||
wme = true;
|
||||
|
||||
|
@ -4472,7 +4467,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
}
|
||||
|
||||
/* verify again the device is supported */
|
||||
if (!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) {
|
||||
if (core->bus->hosttype == BCMA_HOSTTYPE_PCI &&
|
||||
!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) {
|
||||
wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
|
||||
"vendor/device (0x%x/0x%x)\n",
|
||||
unit, pcidev->vendor, pcidev->device);
|
||||
|
@ -4480,8 +4476,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
wlc_hw->vendorid = pcidev->vendor;
|
||||
wlc_hw->deviceid = pcidev->device;
|
||||
if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
|
||||
wlc_hw->vendorid = pcidev->vendor;
|
||||
wlc_hw->deviceid = pcidev->device;
|
||||
} else {
|
||||
wlc_hw->vendorid = core->bus->boardinfo.vendor;
|
||||
wlc_hw->deviceid = core->bus->boardinfo.type;
|
||||
}
|
||||
|
||||
wlc_hw->d11core = core;
|
||||
wlc_hw->corerev = core->id.rev;
|
||||
|
@ -4501,7 +4502,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
* is still false; But it will be called again inside wlc_corereset,
|
||||
* after d11 is out of reset.
|
||||
*/
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
|
||||
|
||||
if (!brcms_b_validate_chip_access(wlc_hw)) {
|
||||
|
@ -4512,7 +4513,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
}
|
||||
|
||||
/* get the board rev, used just below */
|
||||
j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV);
|
||||
j = sprom->board_rev;
|
||||
/* promote srom boardrev of 0xFF to 1 */
|
||||
if (j == BOARDREV_PROMOTABLE)
|
||||
j = BOARDREV_PROMOTED;
|
||||
|
@ -4525,11 +4526,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
err = 15;
|
||||
goto fail;
|
||||
}
|
||||
wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV);
|
||||
wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih,
|
||||
BRCMS_SROM_BOARDFLAGS);
|
||||
wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih,
|
||||
BRCMS_SROM_BOARDFLAGS2);
|
||||
wlc_hw->sromrev = sprom->revision;
|
||||
wlc_hw->boardflags = sprom->boardflags_lo + (sprom->boardflags_hi << 16);
|
||||
wlc_hw->boardflags2 = sprom->boardflags2_lo + (sprom->boardflags2_hi << 16);
|
||||
|
||||
if (wlc_hw->boardflags & BFL_NOPLLDOWN)
|
||||
brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
|
||||
|
@ -4702,25 +4701,18 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
|
|||
*/
|
||||
|
||||
/* init etheraddr state variables */
|
||||
macaddr = brcms_c_get_macaddr(wlc_hw);
|
||||
if (macaddr == NULL) {
|
||||
wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
|
||||
unit);
|
||||
err = 21;
|
||||
goto fail;
|
||||
}
|
||||
if (!mac_pton(macaddr, wlc_hw->etheraddr) ||
|
||||
is_broadcast_ether_addr(wlc_hw->etheraddr) ||
|
||||
brcms_c_get_macaddr(wlc_hw, wlc_hw->etheraddr);
|
||||
|
||||
if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
|
||||
is_zero_ether_addr(wlc_hw->etheraddr)) {
|
||||
wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
|
||||
unit, macaddr);
|
||||
wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr\n",
|
||||
unit);
|
||||
err = 22;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
|
||||
wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih),
|
||||
macaddr);
|
||||
BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n",
|
||||
wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih));
|
||||
|
||||
return err;
|
||||
|
||||
|
@ -4770,16 +4762,16 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
|
|||
int aa;
|
||||
uint unit;
|
||||
int bandtype;
|
||||
struct si_pub *sih = wlc->hw->sih;
|
||||
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
|
||||
|
||||
unit = wlc->pub->unit;
|
||||
bandtype = wlc->band->bandtype;
|
||||
|
||||
/* get antennas available */
|
||||
if (bandtype == BRCM_BAND_5G)
|
||||
aa = (s8) getintvar(sih, BRCMS_SROM_AA5G);
|
||||
aa = sprom->ant_available_a;
|
||||
else
|
||||
aa = (s8) getintvar(sih, BRCMS_SROM_AA2G);
|
||||
aa = sprom->ant_available_bg;
|
||||
|
||||
if ((aa < 1) || (aa > 15)) {
|
||||
wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
|
||||
|
@ -4799,9 +4791,9 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
|
|||
|
||||
/* Compute Antenna Gain */
|
||||
if (bandtype == BRCM_BAND_5G)
|
||||
wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1);
|
||||
wlc->band->antgain = sprom->antenna_gain.a1;
|
||||
else
|
||||
wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0);
|
||||
wlc->band->antgain = sprom->antenna_gain.a0;
|
||||
|
||||
brcms_c_attach_antgain_init(wlc);
|
||||
|
||||
|
@ -4952,15 +4944,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc)
|
|||
|
||||
callbacks = 0;
|
||||
|
||||
if (wlc_hw->sih) {
|
||||
/*
|
||||
* detach interrupt sync mechanism since interrupt is disabled
|
||||
* and per-port interrupt object may has been freed. this must
|
||||
* be done before sb core switch
|
||||
*/
|
||||
ai_pci_sleep(wlc_hw->sih);
|
||||
}
|
||||
|
||||
brcms_b_detach_dmapio(wlc_hw);
|
||||
|
||||
band = wlc_hw->band;
|
||||
|
@ -5047,9 +5030,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
|
|||
*/
|
||||
brcms_b_xtal(wlc_hw, ON);
|
||||
ai_clkctl_init(wlc_hw->sih);
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
|
||||
ai_pci_fixcfg(wlc_hw->sih);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
/*
|
||||
* TODO: test suspend/resume
|
||||
|
@ -5078,8 +5059,6 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
|
|||
|
||||
static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
|
||||
{
|
||||
uint coremask;
|
||||
|
||||
BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
|
||||
|
||||
/*
|
||||
|
@ -5088,15 +5067,14 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
|
|||
*/
|
||||
brcms_b_xtal(wlc_hw, ON);
|
||||
ai_clkctl_init(wlc_hw->sih);
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
|
||||
/*
|
||||
* Configure pci/pcmcia here instead of in brcms_c_attach()
|
||||
* to allow mfg hotswap: down, hotswap (chip power cycle), up.
|
||||
*/
|
||||
coremask = (1 << wlc_hw->wlc->core->coreidx);
|
||||
|
||||
ai_pci_setup(wlc_hw->sih, coremask);
|
||||
bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
|
||||
true);
|
||||
|
||||
/*
|
||||
* Need to read the hwradio status here to cover the case where the
|
||||
|
@ -5126,7 +5104,7 @@ static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
|
|||
wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
|
||||
|
||||
/* FULLY enable dynamic power control and d11 core interrupt */
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
|
||||
brcms_intrson(wlc_hw->wlc->wl);
|
||||
return 0;
|
||||
}
|
||||
|
@ -5267,7 +5245,7 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
|
|||
brcms_intrsoff(wlc_hw->wlc->wl);
|
||||
|
||||
/* ensure we're running on the pll clock again */
|
||||
brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
|
||||
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
|
||||
}
|
||||
/* down phy at the last of this stage */
|
||||
callbacks += wlc_phy_down(wlc_hw->band->pi);
|
||||
|
|
|
@ -1,826 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <soc.h>
|
||||
#include <chipcommon.h>
|
||||
#include "aiutils.h"
|
||||
#include "pub.h"
|
||||
#include "nicpci.h"
|
||||
|
||||
/* SPROM offsets */
|
||||
#define SRSH_ASPM_OFFSET 4 /* word 4 */
|
||||
#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */
|
||||
#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */
|
||||
#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
|
||||
|
||||
#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */
|
||||
#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */
|
||||
#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */
|
||||
#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
|
||||
#define SRSH_BD_OFFSET 6 /* word 6 */
|
||||
|
||||
/* chipcontrol */
|
||||
#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */
|
||||
|
||||
/* MDIO control */
|
||||
#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
|
||||
#define MDIOCTL_DIVISOR_VAL 0x2
|
||||
#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
|
||||
#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */
|
||||
|
||||
/* MDIO Data */
|
||||
#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
|
||||
#define MDIODATA_TA 0x00020000 /* Turnaround */
|
||||
|
||||
#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
|
||||
#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
|
||||
#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
|
||||
#define MDIODATA_DEVADDR_MASK 0x0f800000
|
||||
/* Physmedia devaddr Mask */
|
||||
|
||||
/* MDIO Data for older revisions < 10 */
|
||||
#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */
|
||||
#define MDIODATA_REGADDR_MASK_OLD 0x003c0000
|
||||
/* Regaddr Mask */
|
||||
#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */
|
||||
#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000
|
||||
/* Physmedia devaddr Mask */
|
||||
|
||||
/* Transactions flags */
|
||||
#define MDIODATA_WRITE 0x10000000
|
||||
#define MDIODATA_READ 0x20000000
|
||||
#define MDIODATA_START 0x40000000
|
||||
|
||||
#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
|
||||
#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
|
||||
|
||||
/* serdes regs (rev < 10) */
|
||||
#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
|
||||
#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
|
||||
#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
|
||||
|
||||
/* SERDES RX registers */
|
||||
#define SERDES_RX_CTRL 1 /* Rx cntrl */
|
||||
#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
|
||||
#define SERDES_RX_CDR 6 /* CDR */
|
||||
#define SERDES_RX_CDRBW 7 /* CDR BW */
|
||||
/* SERDES RX control register */
|
||||
#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
|
||||
#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
|
||||
|
||||
/* SERDES PLL registers */
|
||||
#define SERDES_PLL_CTRL 1 /* PLL control reg */
|
||||
#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
|
||||
|
||||
/* Linkcontrol reg offset in PCIE Cap */
|
||||
#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */
|
||||
#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
|
||||
#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
|
||||
#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
|
||||
|
||||
#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
|
||||
#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
|
||||
#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
|
||||
#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
|
||||
|
||||
/* Power management threshold */
|
||||
#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */
|
||||
#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */
|
||||
#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */
|
||||
#define PCIE_ASPMTIMER_EXTEND 0x01000000
|
||||
/* > rev7:
|
||||
* enable extend ASPM timer
|
||||
*/
|
||||
|
||||
/* different register spaces to access thru pcie indirect access */
|
||||
#define PCIE_CONFIGREGS 1 /* Access to config space */
|
||||
#define PCIE_PCIEREGS 2 /* Access to pcie registers */
|
||||
|
||||
/* PCIE protocol PHY diagnostic registers */
|
||||
#define PCIE_PLP_STATUSREG 0x204 /* Status */
|
||||
|
||||
/* Status reg PCIE_PLP_STATUSREG */
|
||||
#define PCIE_PLP_POLARITYINV_STAT 0x10
|
||||
|
||||
/* PCIE protocol DLLP diagnostic registers */
|
||||
#define PCIE_DLLP_LCREG 0x100 /* Link Control */
|
||||
#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
|
||||
|
||||
/* PCIE protocol TLP diagnostic registers */
|
||||
#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
|
||||
|
||||
/* Sonics to PCI translation types */
|
||||
#define SBTOPCI_PREF 0x4 /* prefetch enable */
|
||||
#define SBTOPCI_BURST 0x8 /* burst enable */
|
||||
#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
|
||||
|
||||
#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
|
||||
|
||||
/* PCI core index in SROM shadow area */
|
||||
#define SRSH_PI_OFFSET 0 /* first word */
|
||||
#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
|
||||
#define SRSH_PI_SHIFT 12 /* bit 15:12 */
|
||||
|
||||
#define PCIREGOFFS(field) offsetof(struct sbpciregs, field)
|
||||
#define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field)
|
||||
|
||||
/* Sonics side: PCI core and host control registers */
|
||||
struct sbpciregs {
|
||||
u32 control; /* PCI control */
|
||||
u32 PAD[3];
|
||||
u32 arbcontrol; /* PCI arbiter control */
|
||||
u32 clkrun; /* Clkrun Control (>=rev11) */
|
||||
u32 PAD[2];
|
||||
u32 intstatus; /* Interrupt status */
|
||||
u32 intmask; /* Interrupt mask */
|
||||
u32 sbtopcimailbox; /* Sonics to PCI mailbox */
|
||||
u32 PAD[9];
|
||||
u32 bcastaddr; /* Sonics broadcast address */
|
||||
u32 bcastdata; /* Sonics broadcast data */
|
||||
u32 PAD[2];
|
||||
u32 gpioin; /* ro: gpio input (>=rev2) */
|
||||
u32 gpioout; /* rw: gpio output (>=rev2) */
|
||||
u32 gpioouten; /* rw: gpio output enable (>= rev2) */
|
||||
u32 gpiocontrol; /* rw: gpio control (>= rev2) */
|
||||
u32 PAD[36];
|
||||
u32 sbtopci0; /* Sonics to PCI translation 0 */
|
||||
u32 sbtopci1; /* Sonics to PCI translation 1 */
|
||||
u32 sbtopci2; /* Sonics to PCI translation 2 */
|
||||
u32 PAD[189];
|
||||
u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
|
||||
u16 sprom[36]; /* SPROM shadow Area */
|
||||
u32 PAD[46];
|
||||
};
|
||||
|
||||
/* SB side: PCIE core and host control registers */
|
||||
struct sbpcieregs {
|
||||
u32 control; /* host mode only */
|
||||
u32 PAD[2];
|
||||
u32 biststatus; /* bist Status: 0x00C */
|
||||
u32 gpiosel; /* PCIE gpio sel: 0x010 */
|
||||
u32 gpioouten; /* PCIE gpio outen: 0x14 */
|
||||
u32 PAD[2];
|
||||
u32 intstatus; /* Interrupt status: 0x20 */
|
||||
u32 intmask; /* Interrupt mask: 0x24 */
|
||||
u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
|
||||
u32 PAD[53];
|
||||
u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
|
||||
u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
|
||||
u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
|
||||
u32 PAD[5];
|
||||
|
||||
/* pcie core supports in direct access to config space */
|
||||
u32 configaddr; /* pcie config space access: Address field: 0x120 */
|
||||
u32 configdata; /* pcie config space access: Data field: 0x124 */
|
||||
|
||||
/* mdio access to serdes */
|
||||
u32 mdiocontrol; /* controls the mdio access: 0x128 */
|
||||
u32 mdiodata; /* Data to the mdio access: 0x12c */
|
||||
|
||||
/* pcie protocol phy/dllp/tlp register indirect access mechanism */
|
||||
u32 pcieindaddr; /* indirect access to
|
||||
* the internal register: 0x130
|
||||
*/
|
||||
u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */
|
||||
|
||||
u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */
|
||||
u32 PAD[177];
|
||||
u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */
|
||||
u16 sprom[64]; /* SPROM shadow Area */
|
||||
};
|
||||
|
||||
struct pcicore_info {
|
||||
struct bcma_device *core;
|
||||
struct si_pub *sih; /* System interconnect handle */
|
||||
struct pci_dev *dev;
|
||||
u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
|
||||
* in the config space
|
||||
*/
|
||||
bool pcie_pr42767;
|
||||
u8 pcie_polarity;
|
||||
u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */
|
||||
|
||||
u8 pmecap_offset; /* PM Capability offset in the config space */
|
||||
bool pmecap; /* Capable of generating PME */
|
||||
};
|
||||
|
||||
#define PCIE_ASPM(sih) \
|
||||
((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \
|
||||
((ai_get_buscorerev(sih) >= 3) && \
|
||||
(ai_get_buscorerev(sih) <= 5)))
|
||||
|
||||
|
||||
/* delay needed between the mdio control/ mdiodata register data access */
|
||||
static void pr28829_delay(void)
|
||||
{
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/* Initialize the PCI core.
|
||||
* It's caller's responsibility to make sure that this is done only once
|
||||
*/
|
||||
struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core)
|
||||
{
|
||||
struct pcicore_info *pi;
|
||||
|
||||
/* alloc struct pcicore_info */
|
||||
pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
|
||||
if (pi == NULL)
|
||||
return NULL;
|
||||
|
||||
pi->sih = sih;
|
||||
pi->dev = core->bus->host_pci;
|
||||
pi->core = core;
|
||||
|
||||
if (core->id.id == PCIE_CORE_ID) {
|
||||
u8 cap_ptr;
|
||||
cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
|
||||
NULL, NULL);
|
||||
pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
void pcicore_deinit(struct pcicore_info *pch)
|
||||
{
|
||||
kfree(pch);
|
||||
}
|
||||
|
||||
/* return cap_offset if requested capability exists in the PCI config space */
|
||||
/* Note that it's caller's responsibility to make sure it's a pci bus */
|
||||
u8
|
||||
pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
|
||||
unsigned char *buf, u32 *buflen)
|
||||
{
|
||||
u8 cap_id;
|
||||
u8 cap_ptr = 0;
|
||||
u32 bufsize;
|
||||
u8 byte_val;
|
||||
|
||||
/* check for Header type 0 */
|
||||
pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
|
||||
if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
|
||||
goto end;
|
||||
|
||||
/* check if the capability pointer field exists */
|
||||
pci_read_config_byte(dev, PCI_STATUS, &byte_val);
|
||||
if (!(byte_val & PCI_STATUS_CAP_LIST))
|
||||
goto end;
|
||||
|
||||
pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
|
||||
/* check if the capability pointer is 0x00 */
|
||||
if (cap_ptr == 0x00)
|
||||
goto end;
|
||||
|
||||
/* loop thru the capability list
|
||||
* and see if the pcie capability exists
|
||||
*/
|
||||
|
||||
pci_read_config_byte(dev, cap_ptr, &cap_id);
|
||||
|
||||
while (cap_id != req_cap_id) {
|
||||
pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
|
||||
if (cap_ptr == 0x00)
|
||||
break;
|
||||
pci_read_config_byte(dev, cap_ptr, &cap_id);
|
||||
}
|
||||
if (cap_id != req_cap_id)
|
||||
goto end;
|
||||
|
||||
/* found the caller requested capability */
|
||||
if (buf != NULL && buflen != NULL) {
|
||||
u8 cap_data;
|
||||
|
||||
bufsize = *buflen;
|
||||
if (!bufsize)
|
||||
goto end;
|
||||
*buflen = 0;
|
||||
/* copy the capability data excluding cap ID and next ptr */
|
||||
cap_data = cap_ptr + 2;
|
||||
if ((bufsize + cap_data) > PCI_SZPCR)
|
||||
bufsize = PCI_SZPCR - cap_data;
|
||||
*buflen = bufsize;
|
||||
while (bufsize--) {
|
||||
pci_read_config_byte(dev, cap_data, buf);
|
||||
cap_data++;
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
end:
|
||||
return cap_ptr;
|
||||
}
|
||||
|
||||
/* ***** Register Access API */
|
||||
static uint
|
||||
pcie_readreg(struct bcma_device *core, uint addrtype, uint offset)
|
||||
{
|
||||
uint retval = 0xFFFFFFFF;
|
||||
|
||||
switch (addrtype) {
|
||||
case PCIE_CONFIGREGS:
|
||||
bcma_write32(core, PCIEREGOFFS(configaddr), offset);
|
||||
(void)bcma_read32(core, PCIEREGOFFS(configaddr));
|
||||
retval = bcma_read32(core, PCIEREGOFFS(configdata));
|
||||
break;
|
||||
case PCIE_PCIEREGS:
|
||||
bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
|
||||
(void)bcma_read32(core, PCIEREGOFFS(pcieindaddr));
|
||||
retval = bcma_read32(core, PCIEREGOFFS(pcieinddata));
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static uint pcie_writereg(struct bcma_device *core, uint addrtype,
|
||||
uint offset, uint val)
|
||||
{
|
||||
switch (addrtype) {
|
||||
case PCIE_CONFIGREGS:
|
||||
bcma_write32(core, PCIEREGOFFS(configaddr), offset);
|
||||
bcma_write32(core, PCIEREGOFFS(configdata), val);
|
||||
break;
|
||||
case PCIE_PCIEREGS:
|
||||
bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
|
||||
bcma_write32(core, PCIEREGOFFS(pcieinddata), val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
|
||||
{
|
||||
uint mdiodata, i = 0;
|
||||
uint pcie_serdes_spinwait = 200;
|
||||
|
||||
mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
|
||||
(MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
|
||||
(MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
|
||||
(blk << 4));
|
||||
bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
|
||||
|
||||
pr28829_delay();
|
||||
/* retry till the transaction is complete */
|
||||
while (i < pcie_serdes_spinwait) {
|
||||
if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
|
||||
MDIOCTL_ACCESS_DONE)
|
||||
break;
|
||||
|
||||
udelay(1000);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= pcie_serdes_spinwait)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
|
||||
uint *val)
|
||||
{
|
||||
uint mdiodata;
|
||||
uint i = 0;
|
||||
uint pcie_serdes_spinwait = 10;
|
||||
|
||||
/* enable mdio access to SERDES */
|
||||
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol),
|
||||
MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
|
||||
|
||||
if (ai_get_buscorerev(pi->sih) >= 10) {
|
||||
/* new serdes is slower in rw,
|
||||
* using two layers of reg address mapping
|
||||
*/
|
||||
if (!pcie_mdiosetblock(pi, physmedia))
|
||||
return 1;
|
||||
mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
|
||||
(regaddr << MDIODATA_REGADDR_SHF));
|
||||
pcie_serdes_spinwait *= 20;
|
||||
} else {
|
||||
mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
|
||||
(regaddr << MDIODATA_REGADDR_SHF_OLD));
|
||||
}
|
||||
|
||||
if (!write)
|
||||
mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
|
||||
else
|
||||
mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
|
||||
*val);
|
||||
|
||||
bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
|
||||
|
||||
pr28829_delay();
|
||||
|
||||
/* retry till the transaction is complete */
|
||||
while (i < pcie_serdes_spinwait) {
|
||||
if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
|
||||
MDIOCTL_ACCESS_DONE) {
|
||||
if (!write) {
|
||||
pr28829_delay();
|
||||
*val = (bcma_read32(pi->core,
|
||||
PCIEREGOFFS(mdiodata)) &
|
||||
MDIODATA_MASK);
|
||||
}
|
||||
/* Disable mdio access to SERDES */
|
||||
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
|
||||
return 0;
|
||||
}
|
||||
udelay(1000);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Timed out. Disable mdio access to SERDES. */
|
||||
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* use the mdio interface to read from mdio slaves */
|
||||
static int
|
||||
pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
|
||||
uint *regval)
|
||||
{
|
||||
return pcie_mdioop(pi, physmedia, regaddr, false, regval);
|
||||
}
|
||||
|
||||
/* use the mdio interface to write to mdio slaves */
|
||||
static int
|
||||
pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
|
||||
{
|
||||
return pcie_mdioop(pi, physmedia, regaddr, true, &val);
|
||||
}
|
||||
|
||||
/* ***** Support functions ***** */
|
||||
static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
|
||||
{
|
||||
u32 reg_val;
|
||||
u8 offset;
|
||||
|
||||
offset = pi->pciecap_lcreg_offset;
|
||||
if (!offset)
|
||||
return 0;
|
||||
|
||||
pci_read_config_dword(pi->dev, offset, ®_val);
|
||||
/* set operation */
|
||||
if (mask) {
|
||||
if (val)
|
||||
reg_val |= PCIE_CLKREQ_ENAB;
|
||||
else
|
||||
reg_val &= ~PCIE_CLKREQ_ENAB;
|
||||
pci_write_config_dword(pi->dev, offset, reg_val);
|
||||
pci_read_config_dword(pi->dev, offset, ®_val);
|
||||
}
|
||||
if (reg_val & PCIE_CLKREQ_ENAB)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
|
||||
{
|
||||
u32 w;
|
||||
struct si_pub *sih = pi->sih;
|
||||
|
||||
if (ai_get_buscoretype(sih) != PCIE_CORE_ID ||
|
||||
ai_get_buscorerev(sih) < 7)
|
||||
return;
|
||||
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
|
||||
if (extend)
|
||||
w |= PCIE_ASPMTIMER_EXTEND;
|
||||
else
|
||||
w &= ~PCIE_ASPMTIMER_EXTEND;
|
||||
pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
|
||||
}
|
||||
|
||||
/* centralized clkreq control policy */
|
||||
static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
|
||||
{
|
||||
struct si_pub *sih = pi->sih;
|
||||
|
||||
switch (state) {
|
||||
case SI_DOATTACH:
|
||||
if (PCIE_ASPM(sih))
|
||||
pcie_clkreq(pi, 1, 0);
|
||||
break;
|
||||
case SI_PCIDOWN:
|
||||
/* turn on serdes PLL down */
|
||||
if (ai_get_buscorerev(sih) == 6) {
|
||||
ai_cc_reg(sih,
|
||||
offsetof(struct chipcregs, chipcontrol_addr),
|
||||
~0, 0);
|
||||
ai_cc_reg(sih,
|
||||
offsetof(struct chipcregs, chipcontrol_data),
|
||||
~0x40, 0);
|
||||
} else if (pi->pcie_pr42767) {
|
||||
pcie_clkreq(pi, 1, 1);
|
||||
}
|
||||
break;
|
||||
case SI_PCIUP:
|
||||
/* turn off serdes PLL down */
|
||||
if (ai_get_buscorerev(sih) == 6) {
|
||||
ai_cc_reg(sih,
|
||||
offsetof(struct chipcregs, chipcontrol_addr),
|
||||
~0, 0);
|
||||
ai_cc_reg(sih,
|
||||
offsetof(struct chipcregs, chipcontrol_data),
|
||||
~0x40, 0x40);
|
||||
} else if (PCIE_ASPM(sih)) { /* disable clkreq */
|
||||
pcie_clkreq(pi, 1, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ***** PCI core WARs ***** */
|
||||
/* Done only once at attach time */
|
||||
static void pcie_war_polarity(struct pcicore_info *pi)
|
||||
{
|
||||
u32 w;
|
||||
|
||||
if (pi->pcie_polarity != 0)
|
||||
return;
|
||||
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
|
||||
|
||||
/* Detect the current polarity at attach and force that polarity and
|
||||
* disable changing the polarity
|
||||
*/
|
||||
if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
|
||||
pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
|
||||
else
|
||||
pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
|
||||
SERDES_RX_CTRL_POLARITY);
|
||||
}
|
||||
|
||||
/* enable ASPM and CLKREQ if srom doesn't have it */
|
||||
/* Needs to happen when update to shadow SROM is needed
|
||||
* : Coming out of 'standby'/'hibernate'
|
||||
* : If pcie_war_aspm_ovr state changed
|
||||
*/
|
||||
static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
|
||||
{
|
||||
struct si_pub *sih = pi->sih;
|
||||
u16 val16;
|
||||
u32 w;
|
||||
|
||||
if (!PCIE_ASPM(sih))
|
||||
return;
|
||||
|
||||
/* bypass this on QT or VSIM */
|
||||
val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]));
|
||||
|
||||
val16 &= ~SRSH_ASPM_ENB;
|
||||
if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
|
||||
val16 |= SRSH_ASPM_ENB;
|
||||
else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
|
||||
val16 |= SRSH_ASPM_L1_ENB;
|
||||
else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
|
||||
val16 |= SRSH_ASPM_L0s_ENB;
|
||||
|
||||
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16);
|
||||
|
||||
pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
|
||||
w &= ~PCIE_ASPM_ENAB;
|
||||
w |= pi->pcie_war_aspm_ovr;
|
||||
pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
|
||||
|
||||
val16 = bcma_read16(pi->core,
|
||||
PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]));
|
||||
|
||||
if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
|
||||
val16 |= SRSH_CLKREQ_ENB;
|
||||
pi->pcie_pr42767 = true;
|
||||
} else
|
||||
val16 &= ~SRSH_CLKREQ_ENB;
|
||||
|
||||
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]),
|
||||
val16);
|
||||
}
|
||||
|
||||
/* Apply the polarity determined at the start */
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void pcie_war_serdes(struct pcicore_info *pi)
|
||||
{
|
||||
u32 w = 0;
|
||||
|
||||
if (pi->pcie_polarity != 0)
|
||||
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
|
||||
pi->pcie_polarity);
|
||||
|
||||
pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
|
||||
if (w & PLL_CTRL_FREQDET_EN) {
|
||||
w &= ~PLL_CTRL_FREQDET_EN;
|
||||
pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void pcie_misc_config_fixup(struct pcicore_info *pi)
|
||||
{
|
||||
u16 val16;
|
||||
|
||||
val16 = bcma_read16(pi->core,
|
||||
PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]));
|
||||
|
||||
if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
|
||||
val16 |= SRSH_L23READY_EXIT_NOPERST;
|
||||
bcma_write16(pi->core,
|
||||
PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16);
|
||||
}
|
||||
}
|
||||
|
||||
/* quick hack for testing */
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void pcie_war_noplldown(struct pcicore_info *pi)
|
||||
{
|
||||
/* turn off serdes PLL down */
|
||||
ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol),
|
||||
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
|
||||
|
||||
/* clear srom shadow backdoor */
|
||||
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0);
|
||||
}
|
||||
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void pcie_war_pci_setup(struct pcicore_info *pi)
|
||||
{
|
||||
struct si_pub *sih = pi->sih;
|
||||
u32 w;
|
||||
|
||||
if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) {
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS,
|
||||
PCIE_TLP_WORKAROUNDSREG);
|
||||
w |= 0x8;
|
||||
pcie_writereg(pi->core, PCIE_PCIEREGS,
|
||||
PCIE_TLP_WORKAROUNDSREG, w);
|
||||
}
|
||||
|
||||
if (ai_get_buscorerev(sih) == 1) {
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
|
||||
w |= 0x40;
|
||||
pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
|
||||
}
|
||||
|
||||
if (ai_get_buscorerev(sih) == 0) {
|
||||
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
|
||||
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
|
||||
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
|
||||
} else if (PCIE_ASPM(sih)) {
|
||||
/* Change the L1 threshold for better performance */
|
||||
w = pcie_readreg(pi->core, PCIE_PCIEREGS,
|
||||
PCIE_DLLP_PMTHRESHREG);
|
||||
w &= ~PCIE_L1THRESHOLDTIME_MASK;
|
||||
w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
|
||||
pcie_writereg(pi->core, PCIE_PCIEREGS,
|
||||
PCIE_DLLP_PMTHRESHREG, w);
|
||||
|
||||
pcie_war_serdes(pi);
|
||||
|
||||
pcie_war_aspm_clkreq(pi);
|
||||
} else if (ai_get_buscorerev(pi->sih) == 7)
|
||||
pcie_war_noplldown(pi);
|
||||
|
||||
/* Note that the fix is actually in the SROM,
|
||||
* that's why this is open-ended
|
||||
*/
|
||||
if (ai_get_buscorerev(pi->sih) >= 6)
|
||||
pcie_misc_config_fixup(pi);
|
||||
}
|
||||
|
||||
/* ***** Functions called during driver state changes ***** */
|
||||
void pcicore_attach(struct pcicore_info *pi, int state)
|
||||
{
|
||||
struct si_pub *sih = pi->sih;
|
||||
u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2);
|
||||
|
||||
/* Determine if this board needs override */
|
||||
if (PCIE_ASPM(sih)) {
|
||||
if (bfl2 & BFL2_PCIEWAR_OVR)
|
||||
pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
|
||||
else
|
||||
pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
|
||||
}
|
||||
|
||||
/* These need to happen in this order only */
|
||||
pcie_war_polarity(pi);
|
||||
|
||||
pcie_war_serdes(pi);
|
||||
|
||||
pcie_war_aspm_clkreq(pi);
|
||||
|
||||
pcie_clkreq_upd(pi, state);
|
||||
|
||||
}
|
||||
|
||||
void pcicore_hwup(struct pcicore_info *pi)
|
||||
{
|
||||
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
|
||||
return;
|
||||
|
||||
pcie_war_pci_setup(pi);
|
||||
}
|
||||
|
||||
void pcicore_up(struct pcicore_info *pi, int state)
|
||||
{
|
||||
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
|
||||
return;
|
||||
|
||||
/* Restore L1 timer for better performance */
|
||||
pcie_extendL1timer(pi, true);
|
||||
|
||||
pcie_clkreq_upd(pi, state);
|
||||
}
|
||||
|
||||
/* When the device is going to enter D3 state
|
||||
* (or the system is going to enter S3/S4 states)
|
||||
*/
|
||||
void pcicore_sleep(struct pcicore_info *pi)
|
||||
{
|
||||
u32 w;
|
||||
|
||||
if (!pi || !PCIE_ASPM(pi->sih))
|
||||
return;
|
||||
|
||||
pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
|
||||
w &= ~PCIE_CAP_LCREG_ASPML1;
|
||||
pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
|
||||
|
||||
pi->pcie_pr42767 = false;
|
||||
}
|
||||
|
||||
void pcicore_down(struct pcicore_info *pi, int state)
|
||||
{
|
||||
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
|
||||
return;
|
||||
|
||||
pcie_clkreq_upd(pi, state);
|
||||
|
||||
/* Reduce L1 timer for better power savings */
|
||||
pcie_extendL1timer(pi, false);
|
||||
}
|
||||
|
||||
void pcicore_fixcfg(struct pcicore_info *pi)
|
||||
{
|
||||
struct bcma_device *core = pi->core;
|
||||
u16 val16;
|
||||
uint regoff;
|
||||
|
||||
switch (pi->core->id.id) {
|
||||
case BCMA_CORE_PCI:
|
||||
regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]);
|
||||
break;
|
||||
|
||||
case BCMA_CORE_PCIE:
|
||||
regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
val16 = bcma_read16(pi->core, regoff);
|
||||
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) !=
|
||||
(u16)core->core_index) {
|
||||
val16 = ((u16)core->core_index << SRSH_PI_SHIFT) |
|
||||
(val16 & ~SRSH_PI_MASK);
|
||||
bcma_write16(pi->core, regoff, val16);
|
||||
}
|
||||
}
|
||||
|
||||
/* precondition: current core is pci core */
|
||||
void
|
||||
pcicore_pci_setup(struct pcicore_info *pi)
|
||||
{
|
||||
bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
|
||||
SBTOPCI_PREF | SBTOPCI_BURST);
|
||||
|
||||
if (pi->core->id.rev >= 11) {
|
||||
bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
|
||||
SBTOPCI_RC_READMULTI);
|
||||
bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL);
|
||||
(void)bcma_read32(pi->core, PCIREGOFFS(clkrun));
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _BRCM_NICPCI_H_
|
||||
#define _BRCM_NICPCI_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* PCI configuration address space size */
|
||||
#define PCI_SZPCR 256
|
||||
|
||||
/* Brcm PCI configuration registers */
|
||||
/* backplane address space accessed by BAR0 */
|
||||
#define PCI_BAR0_WIN 0x80
|
||||
/* sprom property control */
|
||||
#define PCI_SPROM_CONTROL 0x88
|
||||
/* mask of PCI and other cores interrupts */
|
||||
#define PCI_INT_MASK 0x94
|
||||
/* backplane core interrupt mask bits offset */
|
||||
#define PCI_SBIM_SHIFT 8
|
||||
/* backplane address space accessed by second 4KB of BAR0 */
|
||||
#define PCI_BAR0_WIN2 0xac
|
||||
/* pci config space gpio input (>=rev3) */
|
||||
#define PCI_GPIO_IN 0xb0
|
||||
/* pci config space gpio output (>=rev3) */
|
||||
#define PCI_GPIO_OUT 0xb4
|
||||
/* pci config space gpio output enable (>=rev3) */
|
||||
#define PCI_GPIO_OUTEN 0xb8
|
||||
|
||||
/* bar0 + 4K accesses external sprom */
|
||||
#define PCI_BAR0_SPROM_OFFSET (4 * 1024)
|
||||
/* bar0 + 6K accesses pci core registers */
|
||||
#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024)
|
||||
/*
|
||||
* pci core SB registers are at the end of the
|
||||
* 8KB window, so their address is the "regular"
|
||||
* address plus 4K
|
||||
*/
|
||||
#define PCI_BAR0_PCISBR_OFFSET (4 * 1024)
|
||||
/* bar0 window size Match with corerev 13 */
|
||||
#define PCI_BAR0_WINSZ (16 * 1024)
|
||||
/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
|
||||
/* bar0 + 8K accesses pci/pcie core registers */
|
||||
#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
|
||||
/* bar0 + 12K accesses chipc core registers */
|
||||
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
|
||||
|
||||
struct sbpciregs;
|
||||
struct sbpcieregs;
|
||||
|
||||
extern struct pcicore_info *pcicore_init(struct si_pub *sih,
|
||||
struct bcma_device *core);
|
||||
extern void pcicore_deinit(struct pcicore_info *pch);
|
||||
extern void pcicore_attach(struct pcicore_info *pch, int state);
|
||||
extern void pcicore_hwup(struct pcicore_info *pch);
|
||||
extern void pcicore_up(struct pcicore_info *pch, int state);
|
||||
extern void pcicore_sleep(struct pcicore_info *pch);
|
||||
extern void pcicore_down(struct pcicore_info *pch, int state);
|
||||
extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
|
||||
unsigned char *buf, u32 *buflen);
|
||||
extern void pcicore_fixcfg(struct pcicore_info *pch);
|
||||
extern void pcicore_pci_setup(struct pcicore_info *pch);
|
||||
|
||||
#endif /* _BRCM_NICPCI_H_ */
|
|
@ -1,410 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <brcm_hw_ids.h>
|
||||
#include <chipcommon.h>
|
||||
#include "aiutils.h"
|
||||
#include "otp.h"
|
||||
|
||||
#define OTPS_GUP_MASK 0x00000f00
|
||||
#define OTPS_GUP_SHIFT 8
|
||||
/* h/w subregion is programmed */
|
||||
#define OTPS_GUP_HW 0x00000100
|
||||
/* s/w subregion is programmed */
|
||||
#define OTPS_GUP_SW 0x00000200
|
||||
/* chipid/pkgopt subregion is programmed */
|
||||
#define OTPS_GUP_CI 0x00000400
|
||||
/* fuse subregion is programmed */
|
||||
#define OTPS_GUP_FUSE 0x00000800
|
||||
|
||||
/* Fields in otpprog in rev >= 21 */
|
||||
#define OTPP_COL_MASK 0x000000ff
|
||||
#define OTPP_COL_SHIFT 0
|
||||
#define OTPP_ROW_MASK 0x0000ff00
|
||||
#define OTPP_ROW_SHIFT 8
|
||||
#define OTPP_OC_MASK 0x0f000000
|
||||
#define OTPP_OC_SHIFT 24
|
||||
#define OTPP_READERR 0x10000000
|
||||
#define OTPP_VALUE_MASK 0x20000000
|
||||
#define OTPP_VALUE_SHIFT 29
|
||||
#define OTPP_START_BUSY 0x80000000
|
||||
#define OTPP_READ 0x40000000
|
||||
|
||||
/* Opcodes for OTPP_OC field */
|
||||
#define OTPPOC_READ 0
|
||||
#define OTPPOC_BIT_PROG 1
|
||||
#define OTPPOC_VERIFY 3
|
||||
#define OTPPOC_INIT 4
|
||||
#define OTPPOC_SET 5
|
||||
#define OTPPOC_RESET 6
|
||||
#define OTPPOC_OCST 7
|
||||
#define OTPPOC_ROW_LOCK 8
|
||||
#define OTPPOC_PRESCN_TEST 9
|
||||
|
||||
#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
|
||||
|
||||
#define OTPP_TRIES 10000000 /* # of tries for OTPP */
|
||||
|
||||
#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
|
||||
|
||||
/* Fixed size subregions sizes in words */
|
||||
#define OTPGU_CI_SZ 2
|
||||
|
||||
struct otpinfo;
|
||||
|
||||
/* OTP function struct */
|
||||
struct otp_fn_s {
|
||||
int (*init)(struct si_pub *sih, struct otpinfo *oi);
|
||||
int (*read_region)(struct otpinfo *oi, int region, u16 *data,
|
||||
uint *wlen);
|
||||
};
|
||||
|
||||
struct otpinfo {
|
||||
struct bcma_device *core; /* chipc core */
|
||||
const struct otp_fn_s *fn; /* OTP functions */
|
||||
struct si_pub *sih; /* Saved sb handle */
|
||||
|
||||
/* IPX OTP section */
|
||||
u16 wsize; /* Size of otp in words */
|
||||
u16 rows; /* Geometry */
|
||||
u16 cols; /* Geometry */
|
||||
u32 status; /* Flag bits (lock/prog/rv).
|
||||
* (Reflected only when OTP is power cycled)
|
||||
*/
|
||||
u16 hwbase; /* hardware subregion offset */
|
||||
u16 hwlim; /* hardware subregion boundary */
|
||||
u16 swbase; /* software subregion offset */
|
||||
u16 swlim; /* software subregion boundary */
|
||||
u16 fbase; /* fuse subregion offset */
|
||||
u16 flim; /* fuse subregion boundary */
|
||||
int otpgu_base; /* offset to General Use Region */
|
||||
};
|
||||
|
||||
/* OTP layout */
|
||||
/* CC revs 21, 24 and 27 OTP General Use Region word offset */
|
||||
#define REVA4_OTPGU_BASE 12
|
||||
|
||||
/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
|
||||
#define REVB8_OTPGU_BASE 20
|
||||
|
||||
/* CC rev 36 OTP General Use Region word offset */
|
||||
#define REV36_OTPGU_BASE 12
|
||||
|
||||
/* Subregion word offsets in General Use region */
|
||||
#define OTPGU_HSB_OFF 0
|
||||
#define OTPGU_SFB_OFF 1
|
||||
#define OTPGU_CI_OFF 2
|
||||
#define OTPGU_P_OFF 3
|
||||
#define OTPGU_SROM_OFF 4
|
||||
|
||||
/* Flag bit offsets in General Use region */
|
||||
#define OTPGU_HWP_OFF 60
|
||||
#define OTPGU_SWP_OFF 61
|
||||
#define OTPGU_CIP_OFF 62
|
||||
#define OTPGU_FUSEP_OFF 63
|
||||
#define OTPGU_CIP_MSK 0x4000
|
||||
#define OTPGU_P_MSK 0xf000
|
||||
#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
|
||||
|
||||
/* OTP Size */
|
||||
#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */
|
||||
#define OTP_SZ_FU_288 (288/8) /* 288 bits */
|
||||
#define OTP_SZ_FU_216 (216/8) /* 216 bits */
|
||||
#define OTP_SZ_FU_72 (72/8) /* 72 bits */
|
||||
#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
|
||||
#define OTP4315_SWREG_SZ 178 /* 178 bytes */
|
||||
#define OTP_SZ_FU_144 (144/8) /* 144 bits */
|
||||
|
||||
static u16
|
||||
ipxotp_otpr(struct otpinfo *oi, uint wn)
|
||||
{
|
||||
return bcma_read16(oi->core,
|
||||
CHIPCREGOFFS(sromotp[wn]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate max HW/SW region byte size by subtracting fuse region
|
||||
* and checksum size, osizew is oi->wsize (OTP size - GU size) in words
|
||||
*/
|
||||
static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (ai_get_chip_id(sih)) {
|
||||
case BCM43224_CHIP_ID:
|
||||
case BCM43225_CHIP_ID:
|
||||
ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
|
||||
break;
|
||||
case BCM4313_CHIP_ID:
|
||||
ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
|
||||
break;
|
||||
default:
|
||||
break; /* Don't know about this chip */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _ipxotp_init(struct otpinfo *oi)
|
||||
{
|
||||
uint k;
|
||||
u32 otpp, st;
|
||||
int ccrev = ai_get_ccrev(oi->sih);
|
||||
|
||||
|
||||
/*
|
||||
* record word offset of General Use Region
|
||||
* for various chipcommon revs
|
||||
*/
|
||||
if (ccrev == 21 || ccrev == 24
|
||||
|| ccrev == 27) {
|
||||
oi->otpgu_base = REVA4_OTPGU_BASE;
|
||||
} else if (ccrev == 36) {
|
||||
/*
|
||||
* OTP size greater than equal to 2KB (128 words),
|
||||
* otpgu_base is similar to rev23
|
||||
*/
|
||||
if (oi->wsize >= 128)
|
||||
oi->otpgu_base = REVB8_OTPGU_BASE;
|
||||
else
|
||||
oi->otpgu_base = REV36_OTPGU_BASE;
|
||||
} else if (ccrev == 23 || ccrev >= 25) {
|
||||
oi->otpgu_base = REVB8_OTPGU_BASE;
|
||||
}
|
||||
|
||||
/* First issue an init command so the status is up to date */
|
||||
otpp =
|
||||
OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
|
||||
|
||||
bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp);
|
||||
st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
|
||||
for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
|
||||
st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
|
||||
if (k >= OTPP_TRIES)
|
||||
return;
|
||||
|
||||
/* Read OTP lock bits and subregion programmed indication bits */
|
||||
oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus));
|
||||
|
||||
if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID)
|
||||
|| (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) {
|
||||
u32 p_bits;
|
||||
p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) &
|
||||
OTPGU_P_MSK) >> OTPGU_P_SHIFT;
|
||||
oi->status |= (p_bits << OTPS_GUP_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* h/w region base and fuse region limit are fixed to
|
||||
* the top and the bottom of the general use region.
|
||||
* Everything else can be flexible.
|
||||
*/
|
||||
oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
|
||||
oi->hwlim = oi->wsize;
|
||||
if (oi->status & OTPS_GUP_HW) {
|
||||
oi->hwlim =
|
||||
ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
|
||||
oi->swbase = oi->hwlim;
|
||||
} else
|
||||
oi->swbase = oi->hwbase;
|
||||
|
||||
/* subtract fuse and checksum from beginning */
|
||||
oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
|
||||
|
||||
if (oi->status & OTPS_GUP_SW) {
|
||||
oi->swlim =
|
||||
ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
|
||||
oi->fbase = oi->swlim;
|
||||
} else
|
||||
oi->fbase = oi->swbase;
|
||||
|
||||
oi->flim = oi->wsize;
|
||||
}
|
||||
|
||||
static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
|
||||
{
|
||||
/* Make sure we're running IPX OTP */
|
||||
if (!OTPTYPE_IPX(ai_get_ccrev(sih)))
|
||||
return -EBADE;
|
||||
|
||||
/* Make sure OTP is not disabled */
|
||||
if (ai_is_otp_disabled(sih))
|
||||
return -EBADE;
|
||||
|
||||
/* Check for otp size */
|
||||
switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
|
||||
case 0:
|
||||
/* Nothing there */
|
||||
return -EBADE;
|
||||
case 1: /* 32x64 */
|
||||
oi->rows = 32;
|
||||
oi->cols = 64;
|
||||
oi->wsize = 128;
|
||||
break;
|
||||
case 2: /* 64x64 */
|
||||
oi->rows = 64;
|
||||
oi->cols = 64;
|
||||
oi->wsize = 256;
|
||||
break;
|
||||
case 5: /* 96x64 */
|
||||
oi->rows = 96;
|
||||
oi->cols = 64;
|
||||
oi->wsize = 384;
|
||||
break;
|
||||
case 7: /* 16x64 *//* 1024 bits */
|
||||
oi->rows = 16;
|
||||
oi->cols = 64;
|
||||
oi->wsize = 64;
|
||||
break;
|
||||
default:
|
||||
/* Don't know the geometry */
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
/* Retrieve OTP region info */
|
||||
_ipxotp_init(oi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
|
||||
{
|
||||
uint base, i, sz;
|
||||
|
||||
/* Validate region selection */
|
||||
switch (region) {
|
||||
case OTP_HW_RGN:
|
||||
sz = (uint) oi->hwlim - oi->hwbase;
|
||||
if (!(oi->status & OTPS_GUP_HW)) {
|
||||
*wlen = sz;
|
||||
return -ENODATA;
|
||||
}
|
||||
if (*wlen < sz) {
|
||||
*wlen = sz;
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
base = oi->hwbase;
|
||||
break;
|
||||
case OTP_SW_RGN:
|
||||
sz = ((uint) oi->swlim - oi->swbase);
|
||||
if (!(oi->status & OTPS_GUP_SW)) {
|
||||
*wlen = sz;
|
||||
return -ENODATA;
|
||||
}
|
||||
if (*wlen < sz) {
|
||||
*wlen = sz;
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
base = oi->swbase;
|
||||
break;
|
||||
case OTP_CI_RGN:
|
||||
sz = OTPGU_CI_SZ;
|
||||
if (!(oi->status & OTPS_GUP_CI)) {
|
||||
*wlen = sz;
|
||||
return -ENODATA;
|
||||
}
|
||||
if (*wlen < sz) {
|
||||
*wlen = sz;
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
base = oi->otpgu_base + OTPGU_CI_OFF;
|
||||
break;
|
||||
case OTP_FUSE_RGN:
|
||||
sz = (uint) oi->flim - oi->fbase;
|
||||
if (!(oi->status & OTPS_GUP_FUSE)) {
|
||||
*wlen = sz;
|
||||
return -ENODATA;
|
||||
}
|
||||
if (*wlen < sz) {
|
||||
*wlen = sz;
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
base = oi->fbase;
|
||||
break;
|
||||
case OTP_ALL_RGN:
|
||||
sz = ((uint) oi->flim - oi->hwbase);
|
||||
if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
|
||||
*wlen = sz;
|
||||
return -ENODATA;
|
||||
}
|
||||
if (*wlen < sz) {
|
||||
*wlen = sz;
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
base = oi->hwbase;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Read the data */
|
||||
for (i = 0; i < sz; i++)
|
||||
data[i] = ipxotp_otpr(oi, base + i);
|
||||
|
||||
*wlen = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct otp_fn_s ipxotp_fn = {
|
||||
(int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
|
||||
(int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
|
||||
};
|
||||
|
||||
static int otp_init(struct si_pub *sih, struct otpinfo *oi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(oi, 0, sizeof(struct otpinfo));
|
||||
|
||||
oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
|
||||
|
||||
if (OTPTYPE_IPX(ai_get_ccrev(sih)))
|
||||
oi->fn = &ipxotp_fn;
|
||||
|
||||
if (oi->fn == NULL)
|
||||
return -EBADE;
|
||||
|
||||
oi->sih = sih;
|
||||
|
||||
ret = (oi->fn->init)(sih, oi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
|
||||
struct otpinfo otpinfo;
|
||||
struct otpinfo *oi = &otpinfo;
|
||||
int err = 0;
|
||||
|
||||
if (ai_is_otp_disabled(sih)) {
|
||||
err = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = otp_init(sih, oi);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ((oi)->fn->read_region)(oi, region, data, wlen);
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _BRCM_OTP_H_
|
||||
#define _BRCM_OTP_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* OTP regions */
|
||||
#define OTP_HW_RGN 1
|
||||
#define OTP_SW_RGN 2
|
||||
#define OTP_CI_RGN 4
|
||||
#define OTP_FUSE_RGN 8
|
||||
/* From h/w region to end of OTP including checksum */
|
||||
#define OTP_ALL_RGN 0xf
|
||||
|
||||
/* OTP Size */
|
||||
#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */
|
||||
|
||||
extern int otp_read_region(struct si_pub *sih, int region, u16 *data,
|
||||
uint *wlen);
|
||||
|
||||
#endif /* _BRCM_OTP_H_ */
|
|
@ -4817,28 +4817,23 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
s8 txpwr = 0;
|
||||
int i;
|
||||
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
|
||||
struct phy_shim_info *shim = pi->sh->physhim;
|
||||
struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
|
||||
|
||||
if (CHSPEC_IS2G(pi->radio_chanspec)) {
|
||||
u16 cckpo = 0;
|
||||
u32 offset_ofdm, offset_mcs;
|
||||
|
||||
pi_lcn->lcnphy_tr_isolation_mid =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
|
||||
pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso;
|
||||
|
||||
pi_lcn->lcnphy_rx_power_offset =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G);
|
||||
pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g;
|
||||
|
||||
pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0);
|
||||
pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1);
|
||||
pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2);
|
||||
pi->txpa_2g[0] = sprom->pa0b0;
|
||||
pi->txpa_2g[1] = sprom->pa0b1;
|
||||
pi->txpa_2g[2] = sprom->pa0b2;
|
||||
|
||||
pi_lcn->lcnphy_rssi_vf =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G);
|
||||
pi_lcn->lcnphy_rssi_vc =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G);
|
||||
pi_lcn->lcnphy_rssi_gs =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G);
|
||||
pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g;
|
||||
pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g;
|
||||
pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g;
|
||||
|
||||
pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
|
||||
pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
|
||||
|
@ -4848,7 +4843,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
|
||||
pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
|
||||
|
||||
txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0);
|
||||
txpwr = sprom->core_pwr_info[0].maxpwr_2g;
|
||||
pi->tx_srom_max_2g = txpwr;
|
||||
|
||||
for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
|
||||
|
@ -4856,8 +4851,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
|
||||
}
|
||||
|
||||
cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO);
|
||||
offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO);
|
||||
cckpo = sprom->cck2gpo;
|
||||
offset_ofdm = sprom->ofdm2gpo;
|
||||
if (cckpo) {
|
||||
uint max_pwr_chan = txpwr;
|
||||
|
||||
|
@ -4876,7 +4871,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
} else {
|
||||
u8 opo = 0;
|
||||
|
||||
opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO);
|
||||
opo = sprom->opo;
|
||||
|
||||
for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
|
||||
pi->tx_srom_max_rate_2g[i] = txpwr;
|
||||
|
@ -4886,12 +4881,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
((offset_ofdm & 0xf) * 2);
|
||||
offset_ofdm >>= 4;
|
||||
}
|
||||
offset_mcs =
|
||||
wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO1) << 16;
|
||||
offset_mcs |=
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO0);
|
||||
offset_mcs = sprom->mcs2gpo[1] << 16;
|
||||
offset_mcs |= sprom->mcs2gpo[0];
|
||||
pi_lcn->lcnphy_mcs20_po = offset_mcs;
|
||||
for (i = TXP_FIRST_SISO_MCS_20;
|
||||
i <= TXP_LAST_SISO_MCS_20; i++) {
|
||||
|
@ -4901,25 +4892,17 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
|
|||
}
|
||||
}
|
||||
|
||||
pi_lcn->lcnphy_rawtempsense =
|
||||
(u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE);
|
||||
pi_lcn->lcnphy_measPower =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER);
|
||||
pi_lcn->lcnphy_tempsense_slope =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE);
|
||||
pi_lcn->lcnphy_hw_iqcal_en =
|
||||
(bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN);
|
||||
pi_lcn->lcnphy_iqcal_swp_dis =
|
||||
(bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS);
|
||||
pi_lcn->lcnphy_tempcorrx =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX);
|
||||
pi_lcn->lcnphy_tempsense_option =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION);
|
||||
pi_lcn->lcnphy_freqoffset_corr =
|
||||
(u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR);
|
||||
if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1)
|
||||
pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense;
|
||||
pi_lcn->lcnphy_measPower = sprom->measpower;
|
||||
pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope;
|
||||
pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en;
|
||||
pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis;
|
||||
pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx;
|
||||
pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option;
|
||||
pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr;
|
||||
if (sprom->ant_available_bg > 1)
|
||||
wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
|
||||
(u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G));
|
||||
sprom->ant_available_bg);
|
||||
}
|
||||
pi_lcn->lcnphy_cck_dig_filt_type = -1;
|
||||
|
||||
|
|
|
@ -14386,30 +14386,30 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
|
|||
{
|
||||
u16 bw40po, cddpo, stbcpo, bwduppo;
|
||||
uint band_num;
|
||||
struct phy_shim_info *shim = pi->sh->physhim;
|
||||
struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
|
||||
|
||||
if (pi->sh->sromrev >= 9)
|
||||
return;
|
||||
|
||||
bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO);
|
||||
bw40po = sprom->bw40po;
|
||||
pi->bw402gpo = bw40po & 0xf;
|
||||
pi->bw405gpo = (bw40po & 0xf0) >> 4;
|
||||
pi->bw405glpo = (bw40po & 0xf00) >> 8;
|
||||
pi->bw405ghpo = (bw40po & 0xf000) >> 12;
|
||||
|
||||
cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO);
|
||||
cddpo = sprom->cddpo;
|
||||
pi->cdd2gpo = cddpo & 0xf;
|
||||
pi->cdd5gpo = (cddpo & 0xf0) >> 4;
|
||||
pi->cdd5glpo = (cddpo & 0xf00) >> 8;
|
||||
pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
|
||||
|
||||
stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO);
|
||||
stbcpo = sprom->stbcpo;
|
||||
pi->stbc2gpo = stbcpo & 0xf;
|
||||
pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
|
||||
pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
|
||||
pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
|
||||
|
||||
bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO);
|
||||
bwduppo = sprom->bwduppo;
|
||||
pi->bwdup2gpo = bwduppo & 0xf;
|
||||
pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
|
||||
pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
|
||||
|
@ -14419,242 +14419,137 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
|
|||
band_num++) {
|
||||
switch (band_num) {
|
||||
case 0:
|
||||
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP2GA0);
|
||||
sprom->core_pwr_info[0].maxpwr_2g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP2GA1);
|
||||
sprom->core_pwr_info[1].maxpwr_2g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW0A0);
|
||||
sprom->core_pwr_info[0].pa_2g[0];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW0A1);
|
||||
sprom->core_pwr_info[1].pa_2g[0];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW1A0);
|
||||
sprom->core_pwr_info[0].pa_2g[1];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW1A1);
|
||||
sprom->core_pwr_info[1].pa_2g[1];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW2A0);
|
||||
sprom->core_pwr_info[0].pa_2g[2];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA2GW2A1);
|
||||
sprom->core_pwr_info[1].pa_2g[2];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0);
|
||||
sprom->core_pwr_info[0].itssi_2g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1);
|
||||
sprom->core_pwr_info[1].itssi_2g;
|
||||
|
||||
pi->cck2gpo = (u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_CCK2GPO);
|
||||
pi->cck2gpo = sprom->cck2gpo;
|
||||
|
||||
pi->ofdm2gpo =
|
||||
(u32) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_OFDM2GPO);
|
||||
pi->ofdm2gpo = sprom->ofdm2gpo;
|
||||
|
||||
pi->mcs2gpo[0] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO0);
|
||||
pi->mcs2gpo[1] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO1);
|
||||
pi->mcs2gpo[2] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO2);
|
||||
pi->mcs2gpo[3] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO3);
|
||||
pi->mcs2gpo[4] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO4);
|
||||
pi->mcs2gpo[5] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO5);
|
||||
pi->mcs2gpo[6] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO6);
|
||||
pi->mcs2gpo[7] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS2GPO7);
|
||||
pi->mcs2gpo[0] = sprom->mcs2gpo[0];
|
||||
pi->mcs2gpo[1] = sprom->mcs2gpo[1];
|
||||
pi->mcs2gpo[2] = sprom->mcs2gpo[2];
|
||||
pi->mcs2gpo[3] = sprom->mcs2gpo[3];
|
||||
pi->mcs2gpo[4] = sprom->mcs2gpo[4];
|
||||
pi->mcs2gpo[5] = sprom->mcs2gpo[5];
|
||||
pi->mcs2gpo[6] = sprom->mcs2gpo[6];
|
||||
pi->mcs2gpo[7] = sprom->mcs2gpo[7];
|
||||
break;
|
||||
case 1:
|
||||
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
|
||||
sprom->core_pwr_info[0].maxpwr_5g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GA1);
|
||||
sprom->core_pwr_info[1].maxpwr_5g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW0A0);
|
||||
sprom->core_pwr_info[0].pa_5g[0];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW0A1);
|
||||
sprom->core_pwr_info[1].pa_5g[0];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW1A0);
|
||||
sprom->core_pwr_info[0].pa_5g[1];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW1A1);
|
||||
sprom->core_pwr_info[1].pa_5g[1];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW2A0);
|
||||
sprom->core_pwr_info[0].pa_5g[2];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GW2A1);
|
||||
sprom->core_pwr_info[1].pa_5g[2];
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0);
|
||||
sprom->core_pwr_info[0].itssi_5g;
|
||||
pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1);
|
||||
sprom->core_pwr_info[1].itssi_5g;
|
||||
|
||||
pi->ofdm5gpo =
|
||||
(u32) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_OFDM5GPO);
|
||||
pi->ofdm5gpo = sprom->ofdm5gpo;
|
||||
|
||||
pi->mcs5gpo[0] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO0);
|
||||
pi->mcs5gpo[1] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO1);
|
||||
pi->mcs5gpo[2] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO2);
|
||||
pi->mcs5gpo[3] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO3);
|
||||
pi->mcs5gpo[4] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO4);
|
||||
pi->mcs5gpo[5] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO5);
|
||||
pi->mcs5gpo[6] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO6);
|
||||
pi->mcs5gpo[7] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GPO7);
|
||||
pi->mcs5gpo[0] = sprom->mcs5gpo[0];
|
||||
pi->mcs5gpo[1] = sprom->mcs5gpo[1];
|
||||
pi->mcs5gpo[2] = sprom->mcs5gpo[2];
|
||||
pi->mcs5gpo[3] = sprom->mcs5gpo[3];
|
||||
pi->mcs5gpo[4] = sprom->mcs5gpo[4];
|
||||
pi->mcs5gpo[5] = sprom->mcs5gpo[5];
|
||||
pi->mcs5gpo[6] = sprom->mcs5gpo[6];
|
||||
pi->mcs5gpo[7] = sprom->mcs5gpo[7];
|
||||
break;
|
||||
case 2:
|
||||
|
||||
pi->nphy_pwrctrl_info[0].max_pwr_5gl =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GLA0);
|
||||
sprom->core_pwr_info[0].maxpwr_5gl;
|
||||
pi->nphy_pwrctrl_info[1].max_pwr_5gl =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GLA1);
|
||||
sprom->core_pwr_info[1].maxpwr_5gl;
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW0A0);
|
||||
sprom->core_pwr_info[0].pa_5gl[0];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW0A1);
|
||||
sprom->core_pwr_info[1].pa_5gl[0];
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW1A0);
|
||||
sprom->core_pwr_info[0].pa_5gl[1];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW1A1);
|
||||
sprom->core_pwr_info[1].pa_5gl[1];
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW2A0);
|
||||
sprom->core_pwr_info[0].pa_5gl[2];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GLW2A1);
|
||||
sprom->core_pwr_info[1].pa_5gl[2];
|
||||
pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
|
||||
pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
|
||||
|
||||
pi->ofdm5glpo =
|
||||
(u32) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_OFDM5GLPO);
|
||||
pi->ofdm5glpo = sprom->ofdm5glpo;
|
||||
|
||||
pi->mcs5glpo[0] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO0);
|
||||
pi->mcs5glpo[1] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO1);
|
||||
pi->mcs5glpo[2] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO2);
|
||||
pi->mcs5glpo[3] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO3);
|
||||
pi->mcs5glpo[4] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO4);
|
||||
pi->mcs5glpo[5] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO5);
|
||||
pi->mcs5glpo[6] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO6);
|
||||
pi->mcs5glpo[7] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GLPO7);
|
||||
pi->mcs5glpo[0] = sprom->mcs5glpo[0];
|
||||
pi->mcs5glpo[1] = sprom->mcs5glpo[1];
|
||||
pi->mcs5glpo[2] = sprom->mcs5glpo[2];
|
||||
pi->mcs5glpo[3] = sprom->mcs5glpo[3];
|
||||
pi->mcs5glpo[4] = sprom->mcs5glpo[4];
|
||||
pi->mcs5glpo[5] = sprom->mcs5glpo[5];
|
||||
pi->mcs5glpo[6] = sprom->mcs5glpo[6];
|
||||
pi->mcs5glpo[7] = sprom->mcs5glpo[7];
|
||||
break;
|
||||
case 3:
|
||||
|
||||
pi->nphy_pwrctrl_info[0].max_pwr_5gh =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GHA0);
|
||||
sprom->core_pwr_info[0].maxpwr_5gh;
|
||||
pi->nphy_pwrctrl_info[1].max_pwr_5gh =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GHA1);
|
||||
sprom->core_pwr_info[1].maxpwr_5gh;
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW0A0);
|
||||
sprom->core_pwr_info[0].pa_5gh[0];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW0A1);
|
||||
sprom->core_pwr_info[1].pa_5gh[0];
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW1A0);
|
||||
sprom->core_pwr_info[0].pa_5gh[1];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW1A1);
|
||||
sprom->core_pwr_info[1].pa_5gh[1];
|
||||
pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW2A0);
|
||||
sprom->core_pwr_info[0].pa_5gh[2];
|
||||
pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
|
||||
(s16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PA5GHW2A1);
|
||||
sprom->core_pwr_info[1].pa_5gh[2];
|
||||
pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
|
||||
pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
|
||||
|
||||
pi->ofdm5ghpo =
|
||||
(u32) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_OFDM5GHPO);
|
||||
pi->ofdm5ghpo = sprom->ofdm5ghpo;
|
||||
|
||||
pi->mcs5ghpo[0] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO0);
|
||||
pi->mcs5ghpo[1] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO1);
|
||||
pi->mcs5ghpo[2] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO2);
|
||||
pi->mcs5ghpo[3] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO3);
|
||||
pi->mcs5ghpo[4] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO4);
|
||||
pi->mcs5ghpo[5] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO5);
|
||||
pi->mcs5ghpo[6] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO6);
|
||||
pi->mcs5ghpo[7] =
|
||||
(u16) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MCS5GHPO7);
|
||||
pi->mcs5ghpo[0] = sprom->mcs5ghpo[0];
|
||||
pi->mcs5ghpo[1] = sprom->mcs5ghpo[1];
|
||||
pi->mcs5ghpo[2] = sprom->mcs5ghpo[2];
|
||||
pi->mcs5ghpo[3] = sprom->mcs5ghpo[3];
|
||||
pi->mcs5ghpo[4] = sprom->mcs5ghpo[4];
|
||||
pi->mcs5ghpo[5] = sprom->mcs5ghpo[5];
|
||||
pi->mcs5ghpo[6] = sprom->mcs5ghpo[6];
|
||||
pi->mcs5ghpo[7] = sprom->mcs5ghpo[7];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -14664,45 +14559,34 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
|
|||
|
||||
static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
|
||||
{
|
||||
struct phy_shim_info *shim = pi->sh->physhim;
|
||||
struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
|
||||
|
||||
pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH);
|
||||
pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G);
|
||||
pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G);
|
||||
pi->antswitch = sprom->antswitch;
|
||||
pi->aa2g = sprom->ant_available_bg;
|
||||
pi->aa5g = sprom->ant_available_a;
|
||||
|
||||
pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_TSSIPOS2G);
|
||||
pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_EXTPAGAIN2G);
|
||||
pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PDETRANGE2G);
|
||||
pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
|
||||
pi->srom_fem2g.antswctrllut =
|
||||
(u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
|
||||
pi->srom_fem2g.tssipos = sprom->fem.ghz2.tssipos;
|
||||
pi->srom_fem2g.extpagain = sprom->fem.ghz2.extpa_gain;
|
||||
pi->srom_fem2g.pdetrange = sprom->fem.ghz2.pdet_range;
|
||||
pi->srom_fem2g.triso = sprom->fem.ghz2.tr_iso;
|
||||
pi->srom_fem2g.antswctrllut = sprom->fem.ghz2.antswlut;
|
||||
|
||||
pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_TSSIPOS5G);
|
||||
pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_EXTPAGAIN5G);
|
||||
pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_PDETRANGE5G);
|
||||
pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G);
|
||||
if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G))
|
||||
pi->srom_fem5g.antswctrllut =
|
||||
(u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G);
|
||||
pi->srom_fem5g.tssipos = sprom->fem.ghz5.tssipos;
|
||||
pi->srom_fem5g.extpagain = sprom->fem.ghz5.extpa_gain;
|
||||
pi->srom_fem5g.pdetrange = sprom->fem.ghz5.pdet_range;
|
||||
pi->srom_fem5g.triso = sprom->fem.ghz5.tr_iso;
|
||||
if (sprom->fem.ghz5.antswlut)
|
||||
pi->srom_fem5g.antswctrllut = sprom->fem.ghz5.antswlut;
|
||||
else
|
||||
pi->srom_fem5g.antswctrllut =
|
||||
(u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
|
||||
pi->srom_fem5g.antswctrllut = sprom->fem.ghz2.antswlut;
|
||||
|
||||
wlc_phy_txpower_ipa_upd(pi);
|
||||
|
||||
pi->phy_txcore_disable_temp =
|
||||
(s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH);
|
||||
pi->phy_txcore_disable_temp = sprom->tempthresh;
|
||||
if (pi->phy_txcore_disable_temp == 0)
|
||||
pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
|
||||
|
||||
pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_TEMPOFFSET);
|
||||
pi->phy_tempsense_offset = sprom->tempoffset;
|
||||
if (pi->phy_tempsense_offset != 0) {
|
||||
if (pi->phy_tempsense_offset >
|
||||
(NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET))
|
||||
|
@ -14717,8 +14601,7 @@ static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
|
|||
pi->phy_txcore_enable_temp =
|
||||
pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
|
||||
|
||||
pi->phycal_tempdelta =
|
||||
(u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA);
|
||||
pi->phycal_tempdelta = sprom->phycal_tempdelta;
|
||||
if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA)
|
||||
pi->phycal_tempdelta = 0;
|
||||
|
||||
|
@ -21460,7 +21343,7 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
|
|||
write_phy_reg(pi, 0xc8, 0x0);
|
||||
write_phy_reg(pi, 0xc9, 0x0);
|
||||
|
||||
ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
|
||||
bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, mask, mask);
|
||||
|
||||
mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
|
||||
mc &= ~MCTL_GPOUT_SEL_MASK;
|
||||
|
|
|
@ -214,12 +214,3 @@ wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
|
|||
{
|
||||
brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
|
||||
}
|
||||
|
||||
char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
|
||||
{
|
||||
return getvar(physhim->wlc_hw->sih, id);
|
||||
}
|
||||
int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
|
||||
{
|
||||
return getintvar(physhim->wlc_hw->sih, id);
|
||||
}
|
||||
|
|
|
@ -175,8 +175,5 @@ extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
|
|||
extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
|
||||
u32 phy_mode);
|
||||
extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
|
||||
extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id);
|
||||
extern int wlapi_getintvar(struct phy_shim_info *physhim,
|
||||
enum brcms_srom_id id);
|
||||
|
||||
#endif /* _BRCM_PHY_SHIM_H_ */
|
||||
|
|
|
@ -22,232 +22,6 @@
|
|||
#include "types.h"
|
||||
#include "defs.h"
|
||||
|
||||
enum brcms_srom_id {
|
||||
BRCMS_SROM_NULL,
|
||||
BRCMS_SROM_CONT,
|
||||
BRCMS_SROM_AA2G,
|
||||
BRCMS_SROM_AA5G,
|
||||
BRCMS_SROM_AG0,
|
||||
BRCMS_SROM_AG1,
|
||||
BRCMS_SROM_AG2,
|
||||
BRCMS_SROM_AG3,
|
||||
BRCMS_SROM_ANTSWCTL2G,
|
||||
BRCMS_SROM_ANTSWCTL5G,
|
||||
BRCMS_SROM_ANTSWITCH,
|
||||
BRCMS_SROM_BOARDFLAGS2,
|
||||
BRCMS_SROM_BOARDFLAGS,
|
||||
BRCMS_SROM_BOARDNUM,
|
||||
BRCMS_SROM_BOARDREV,
|
||||
BRCMS_SROM_BOARDTYPE,
|
||||
BRCMS_SROM_BW40PO,
|
||||
BRCMS_SROM_BWDUPPO,
|
||||
BRCMS_SROM_BXA2G,
|
||||
BRCMS_SROM_BXA5G,
|
||||
BRCMS_SROM_CC,
|
||||
BRCMS_SROM_CCK2GPO,
|
||||
BRCMS_SROM_CCKBW202GPO,
|
||||
BRCMS_SROM_CCKBW20UL2GPO,
|
||||
BRCMS_SROM_CCODE,
|
||||
BRCMS_SROM_CDDPO,
|
||||
BRCMS_SROM_DEVID,
|
||||
BRCMS_SROM_ET1MACADDR,
|
||||
BRCMS_SROM_EXTPAGAIN2G,
|
||||
BRCMS_SROM_EXTPAGAIN5G,
|
||||
BRCMS_SROM_FREQOFFSET_CORR,
|
||||
BRCMS_SROM_HW_IQCAL_EN,
|
||||
BRCMS_SROM_IL0MACADDR,
|
||||
BRCMS_SROM_IQCAL_SWP_DIS,
|
||||
BRCMS_SROM_LEDBH0,
|
||||
BRCMS_SROM_LEDBH1,
|
||||
BRCMS_SROM_LEDBH2,
|
||||
BRCMS_SROM_LEDBH3,
|
||||
BRCMS_SROM_LEDDC,
|
||||
BRCMS_SROM_LEGOFDM40DUPPO,
|
||||
BRCMS_SROM_LEGOFDMBW202GPO,
|
||||
BRCMS_SROM_LEGOFDMBW205GHPO,
|
||||
BRCMS_SROM_LEGOFDMBW205GLPO,
|
||||
BRCMS_SROM_LEGOFDMBW205GMPO,
|
||||
BRCMS_SROM_LEGOFDMBW20UL2GPO,
|
||||
BRCMS_SROM_LEGOFDMBW20UL5GHPO,
|
||||
BRCMS_SROM_LEGOFDMBW20UL5GLPO,
|
||||
BRCMS_SROM_LEGOFDMBW20UL5GMPO,
|
||||
BRCMS_SROM_MACADDR,
|
||||
BRCMS_SROM_MCS2GPO0,
|
||||
BRCMS_SROM_MCS2GPO1,
|
||||
BRCMS_SROM_MCS2GPO2,
|
||||
BRCMS_SROM_MCS2GPO3,
|
||||
BRCMS_SROM_MCS2GPO4,
|
||||
BRCMS_SROM_MCS2GPO5,
|
||||
BRCMS_SROM_MCS2GPO6,
|
||||
BRCMS_SROM_MCS2GPO7,
|
||||
BRCMS_SROM_MCS32PO,
|
||||
BRCMS_SROM_MCS5GHPO0,
|
||||
BRCMS_SROM_MCS5GHPO1,
|
||||
BRCMS_SROM_MCS5GHPO2,
|
||||
BRCMS_SROM_MCS5GHPO3,
|
||||
BRCMS_SROM_MCS5GHPO4,
|
||||
BRCMS_SROM_MCS5GHPO5,
|
||||
BRCMS_SROM_MCS5GHPO6,
|
||||
BRCMS_SROM_MCS5GHPO7,
|
||||
BRCMS_SROM_MCS5GLPO0,
|
||||
BRCMS_SROM_MCS5GLPO1,
|
||||
BRCMS_SROM_MCS5GLPO2,
|
||||
BRCMS_SROM_MCS5GLPO3,
|
||||
BRCMS_SROM_MCS5GLPO4,
|
||||
BRCMS_SROM_MCS5GLPO5,
|
||||
BRCMS_SROM_MCS5GLPO6,
|
||||
BRCMS_SROM_MCS5GLPO7,
|
||||
BRCMS_SROM_MCS5GPO0,
|
||||
BRCMS_SROM_MCS5GPO1,
|
||||
BRCMS_SROM_MCS5GPO2,
|
||||
BRCMS_SROM_MCS5GPO3,
|
||||
BRCMS_SROM_MCS5GPO4,
|
||||
BRCMS_SROM_MCS5GPO5,
|
||||
BRCMS_SROM_MCS5GPO6,
|
||||
BRCMS_SROM_MCS5GPO7,
|
||||
BRCMS_SROM_MCSBW202GPO,
|
||||
BRCMS_SROM_MCSBW205GHPO,
|
||||
BRCMS_SROM_MCSBW205GLPO,
|
||||
BRCMS_SROM_MCSBW205GMPO,
|
||||
BRCMS_SROM_MCSBW20UL2GPO,
|
||||
BRCMS_SROM_MCSBW20UL5GHPO,
|
||||
BRCMS_SROM_MCSBW20UL5GLPO,
|
||||
BRCMS_SROM_MCSBW20UL5GMPO,
|
||||
BRCMS_SROM_MCSBW402GPO,
|
||||
BRCMS_SROM_MCSBW405GHPO,
|
||||
BRCMS_SROM_MCSBW405GLPO,
|
||||
BRCMS_SROM_MCSBW405GMPO,
|
||||
BRCMS_SROM_MEASPOWER,
|
||||
BRCMS_SROM_OFDM2GPO,
|
||||
BRCMS_SROM_OFDM5GHPO,
|
||||
BRCMS_SROM_OFDM5GLPO,
|
||||
BRCMS_SROM_OFDM5GPO,
|
||||
BRCMS_SROM_OPO,
|
||||
BRCMS_SROM_PA0B0,
|
||||
BRCMS_SROM_PA0B1,
|
||||
BRCMS_SROM_PA0B2,
|
||||
BRCMS_SROM_PA0ITSSIT,
|
||||
BRCMS_SROM_PA0MAXPWR,
|
||||
BRCMS_SROM_PA1B0,
|
||||
BRCMS_SROM_PA1B1,
|
||||
BRCMS_SROM_PA1B2,
|
||||
BRCMS_SROM_PA1HIB0,
|
||||
BRCMS_SROM_PA1HIB1,
|
||||
BRCMS_SROM_PA1HIB2,
|
||||
BRCMS_SROM_PA1HIMAXPWR,
|
||||
BRCMS_SROM_PA1ITSSIT,
|
||||
BRCMS_SROM_PA1LOB0,
|
||||
BRCMS_SROM_PA1LOB1,
|
||||
BRCMS_SROM_PA1LOB2,
|
||||
BRCMS_SROM_PA1LOMAXPWR,
|
||||
BRCMS_SROM_PA1MAXPWR,
|
||||
BRCMS_SROM_PDETRANGE2G,
|
||||
BRCMS_SROM_PDETRANGE5G,
|
||||
BRCMS_SROM_PHYCAL_TEMPDELTA,
|
||||
BRCMS_SROM_RAWTEMPSENSE,
|
||||
BRCMS_SROM_REGREV,
|
||||
BRCMS_SROM_REV,
|
||||
BRCMS_SROM_RSSISAV2G,
|
||||
BRCMS_SROM_RSSISAV5G,
|
||||
BRCMS_SROM_RSSISMC2G,
|
||||
BRCMS_SROM_RSSISMC5G,
|
||||
BRCMS_SROM_RSSISMF2G,
|
||||
BRCMS_SROM_RSSISMF5G,
|
||||
BRCMS_SROM_RXCHAIN,
|
||||
BRCMS_SROM_RXPO2G,
|
||||
BRCMS_SROM_RXPO5G,
|
||||
BRCMS_SROM_STBCPO,
|
||||
BRCMS_SROM_TEMPCORRX,
|
||||
BRCMS_SROM_TEMPOFFSET,
|
||||
BRCMS_SROM_TEMPSENSE_OPTION,
|
||||
BRCMS_SROM_TEMPSENSE_SLOPE,
|
||||
BRCMS_SROM_TEMPTHRESH,
|
||||
BRCMS_SROM_TRI2G,
|
||||
BRCMS_SROM_TRI5GH,
|
||||
BRCMS_SROM_TRI5GL,
|
||||
BRCMS_SROM_TRI5G,
|
||||
BRCMS_SROM_TRISO2G,
|
||||
BRCMS_SROM_TRISO5G,
|
||||
BRCMS_SROM_TSSIPOS2G,
|
||||
BRCMS_SROM_TSSIPOS5G,
|
||||
BRCMS_SROM_TXCHAIN,
|
||||
/*
|
||||
* per-path identifiers (see srom.c)
|
||||
*/
|
||||
BRCMS_SROM_ITT2GA0,
|
||||
BRCMS_SROM_ITT2GA1,
|
||||
BRCMS_SROM_ITT2GA2,
|
||||
BRCMS_SROM_ITT2GA3,
|
||||
BRCMS_SROM_ITT5GA0,
|
||||
BRCMS_SROM_ITT5GA1,
|
||||
BRCMS_SROM_ITT5GA2,
|
||||
BRCMS_SROM_ITT5GA3,
|
||||
BRCMS_SROM_MAXP2GA0,
|
||||
BRCMS_SROM_MAXP2GA1,
|
||||
BRCMS_SROM_MAXP2GA2,
|
||||
BRCMS_SROM_MAXP2GA3,
|
||||
BRCMS_SROM_MAXP5GA0,
|
||||
BRCMS_SROM_MAXP5GA1,
|
||||
BRCMS_SROM_MAXP5GA2,
|
||||
BRCMS_SROM_MAXP5GA3,
|
||||
BRCMS_SROM_MAXP5GHA0,
|
||||
BRCMS_SROM_MAXP5GHA1,
|
||||
BRCMS_SROM_MAXP5GHA2,
|
||||
BRCMS_SROM_MAXP5GHA3,
|
||||
BRCMS_SROM_MAXP5GLA0,
|
||||
BRCMS_SROM_MAXP5GLA1,
|
||||
BRCMS_SROM_MAXP5GLA2,
|
||||
BRCMS_SROM_MAXP5GLA3,
|
||||
BRCMS_SROM_PA2GW0A0,
|
||||
BRCMS_SROM_PA2GW0A1,
|
||||
BRCMS_SROM_PA2GW0A2,
|
||||
BRCMS_SROM_PA2GW0A3,
|
||||
BRCMS_SROM_PA2GW1A0,
|
||||
BRCMS_SROM_PA2GW1A1,
|
||||
BRCMS_SROM_PA2GW1A2,
|
||||
BRCMS_SROM_PA2GW1A3,
|
||||
BRCMS_SROM_PA2GW2A0,
|
||||
BRCMS_SROM_PA2GW2A1,
|
||||
BRCMS_SROM_PA2GW2A2,
|
||||
BRCMS_SROM_PA2GW2A3,
|
||||
BRCMS_SROM_PA5GHW0A0,
|
||||
BRCMS_SROM_PA5GHW0A1,
|
||||
BRCMS_SROM_PA5GHW0A2,
|
||||
BRCMS_SROM_PA5GHW0A3,
|
||||
BRCMS_SROM_PA5GHW1A0,
|
||||
BRCMS_SROM_PA5GHW1A1,
|
||||
BRCMS_SROM_PA5GHW1A2,
|
||||
BRCMS_SROM_PA5GHW1A3,
|
||||
BRCMS_SROM_PA5GHW2A0,
|
||||
BRCMS_SROM_PA5GHW2A1,
|
||||
BRCMS_SROM_PA5GHW2A2,
|
||||
BRCMS_SROM_PA5GHW2A3,
|
||||
BRCMS_SROM_PA5GLW0A0,
|
||||
BRCMS_SROM_PA5GLW0A1,
|
||||
BRCMS_SROM_PA5GLW0A2,
|
||||
BRCMS_SROM_PA5GLW0A3,
|
||||
BRCMS_SROM_PA5GLW1A0,
|
||||
BRCMS_SROM_PA5GLW1A1,
|
||||
BRCMS_SROM_PA5GLW1A2,
|
||||
BRCMS_SROM_PA5GLW1A3,
|
||||
BRCMS_SROM_PA5GLW2A0,
|
||||
BRCMS_SROM_PA5GLW2A1,
|
||||
BRCMS_SROM_PA5GLW2A2,
|
||||
BRCMS_SROM_PA5GLW2A3,
|
||||
BRCMS_SROM_PA5GW0A0,
|
||||
BRCMS_SROM_PA5GW0A1,
|
||||
BRCMS_SROM_PA5GW0A2,
|
||||
BRCMS_SROM_PA5GW0A3,
|
||||
BRCMS_SROM_PA5GW1A0,
|
||||
BRCMS_SROM_PA5GW1A1,
|
||||
BRCMS_SROM_PA5GW1A2,
|
||||
BRCMS_SROM_PA5GW1A3,
|
||||
BRCMS_SROM_PA5GW2A0,
|
||||
BRCMS_SROM_PA5GW2A1,
|
||||
BRCMS_SROM_PA5GW2A2,
|
||||
BRCMS_SROM_PA5GW2A3,
|
||||
};
|
||||
|
||||
#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
|
||||
|
||||
/* phy types */
|
||||
|
@ -565,8 +339,6 @@ extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
|
|||
struct ieee80211_sta *sta, u16 tid);
|
||||
extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
|
||||
u8 ba_wsize, uint max_rx_ampdu_bytes);
|
||||
extern char *getvar(struct si_pub *sih, enum brcms_srom_id id);
|
||||
extern int getintvar(struct si_pub *sih, enum brcms_srom_id id);
|
||||
extern int brcms_c_module_register(struct brcms_pub *pub,
|
||||
const char *name, struct brcms_info *hdl,
|
||||
int (*down_fn)(void *handle));
|
||||
|
|
|
@ -1,980 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/crc8.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <chipcommon.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "pub.h"
|
||||
#include "nicpci.h"
|
||||
#include "aiutils.h"
|
||||
#include "otp.h"
|
||||
#include "srom.h"
|
||||
#include "soc.h"
|
||||
|
||||
/*
|
||||
* SROM CRC8 polynomial value:
|
||||
*
|
||||
* x^8 + x^7 +x^6 + x^4 + x^2 + 1
|
||||
*/
|
||||
#define SROM_CRC8_POLY 0xAB
|
||||
|
||||
/* Maximum srom: 6 Kilobits == 768 bytes */
|
||||
#define SROM_MAX 768
|
||||
|
||||
/* PCI fields */
|
||||
#define PCI_F0DEVID 48
|
||||
|
||||
#define SROM_WORDS 64
|
||||
|
||||
#define SROM_SSID 2
|
||||
|
||||
#define SROM_WL1LHMAXP 29
|
||||
|
||||
#define SROM_WL1LPAB0 30
|
||||
#define SROM_WL1LPAB1 31
|
||||
#define SROM_WL1LPAB2 32
|
||||
|
||||
#define SROM_WL1HPAB0 33
|
||||
#define SROM_WL1HPAB1 34
|
||||
#define SROM_WL1HPAB2 35
|
||||
|
||||
#define SROM_MACHI_IL0 36
|
||||
#define SROM_MACMID_IL0 37
|
||||
#define SROM_MACLO_IL0 38
|
||||
#define SROM_MACHI_ET1 42
|
||||
#define SROM_MACMID_ET1 43
|
||||
#define SROM_MACLO_ET1 44
|
||||
|
||||
#define SROM_BXARSSI2G 40
|
||||
#define SROM_BXARSSI5G 41
|
||||
|
||||
#define SROM_TRI52G 42
|
||||
#define SROM_TRI5GHL 43
|
||||
|
||||
#define SROM_RXPO52G 45
|
||||
|
||||
#define SROM_AABREV 46
|
||||
/* Fields in AABREV */
|
||||
#define SROM_BR_MASK 0x00ff
|
||||
#define SROM_CC_MASK 0x0f00
|
||||
#define SROM_CC_SHIFT 8
|
||||
#define SROM_AA0_MASK 0x3000
|
||||
#define SROM_AA0_SHIFT 12
|
||||
#define SROM_AA1_MASK 0xc000
|
||||
#define SROM_AA1_SHIFT 14
|
||||
|
||||
#define SROM_WL0PAB0 47
|
||||
#define SROM_WL0PAB1 48
|
||||
#define SROM_WL0PAB2 49
|
||||
|
||||
#define SROM_LEDBH10 50
|
||||
#define SROM_LEDBH32 51
|
||||
|
||||
#define SROM_WL10MAXP 52
|
||||
|
||||
#define SROM_WL1PAB0 53
|
||||
#define SROM_WL1PAB1 54
|
||||
#define SROM_WL1PAB2 55
|
||||
|
||||
#define SROM_ITT 56
|
||||
|
||||
#define SROM_BFL 57
|
||||
#define SROM_BFL2 28
|
||||
|
||||
#define SROM_AG10 58
|
||||
|
||||
#define SROM_CCODE 59
|
||||
|
||||
#define SROM_OPO 60
|
||||
|
||||
#define SROM_CRCREV 63
|
||||
|
||||
#define SROM4_WORDS 220
|
||||
|
||||
#define SROM4_TXCHAIN_MASK 0x000f
|
||||
#define SROM4_RXCHAIN_MASK 0x00f0
|
||||
#define SROM4_SWITCH_MASK 0xff00
|
||||
|
||||
/* Per-path fields */
|
||||
#define MAX_PATH_SROM 4
|
||||
|
||||
#define SROM4_CRCREV 219
|
||||
|
||||
/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
|
||||
* This is acombined srom for both MIMO and SISO boards, usable in
|
||||
* the .130 4Kilobit OTP with hardware redundancy.
|
||||
*/
|
||||
#define SROM8_BREV 65
|
||||
|
||||
#define SROM8_BFL0 66
|
||||
#define SROM8_BFL1 67
|
||||
#define SROM8_BFL2 68
|
||||
#define SROM8_BFL3 69
|
||||
|
||||
#define SROM8_MACHI 70
|
||||
#define SROM8_MACMID 71
|
||||
#define SROM8_MACLO 72
|
||||
|
||||
#define SROM8_CCODE 73
|
||||
#define SROM8_REGREV 74
|
||||
|
||||
#define SROM8_LEDBH10 75
|
||||
#define SROM8_LEDBH32 76
|
||||
|
||||
#define SROM8_LEDDC 77
|
||||
|
||||
#define SROM8_AA 78
|
||||
|
||||
#define SROM8_AG10 79
|
||||
#define SROM8_AG32 80
|
||||
|
||||
#define SROM8_TXRXC 81
|
||||
|
||||
#define SROM8_BXARSSI2G 82
|
||||
#define SROM8_BXARSSI5G 83
|
||||
#define SROM8_TRI52G 84
|
||||
#define SROM8_TRI5GHL 85
|
||||
#define SROM8_RXPO52G 86
|
||||
|
||||
#define SROM8_FEM2G 87
|
||||
#define SROM8_FEM5G 88
|
||||
#define SROM8_FEM_ANTSWLUT_MASK 0xf800
|
||||
#define SROM8_FEM_ANTSWLUT_SHIFT 11
|
||||
#define SROM8_FEM_TR_ISO_MASK 0x0700
|
||||
#define SROM8_FEM_TR_ISO_SHIFT 8
|
||||
#define SROM8_FEM_PDET_RANGE_MASK 0x00f8
|
||||
#define SROM8_FEM_PDET_RANGE_SHIFT 3
|
||||
#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
|
||||
#define SROM8_FEM_EXTPA_GAIN_SHIFT 1
|
||||
#define SROM8_FEM_TSSIPOS_MASK 0x0001
|
||||
#define SROM8_FEM_TSSIPOS_SHIFT 0
|
||||
|
||||
#define SROM8_THERMAL 89
|
||||
|
||||
/* Temp sense related entries */
|
||||
#define SROM8_MPWR_RAWTS 90
|
||||
#define SROM8_TS_SLP_OPT_CORRX 91
|
||||
/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable,
|
||||
* IQSWP: IQ CAL swap disable */
|
||||
#define SROM8_FOC_HWIQ_IQSWP 92
|
||||
|
||||
/* Temperature delta for PHY calibration */
|
||||
#define SROM8_PHYCAL_TEMPDELTA 93
|
||||
|
||||
/* Per-path offsets & fields */
|
||||
#define SROM8_PATH0 96
|
||||
#define SROM8_PATH1 112
|
||||
#define SROM8_PATH2 128
|
||||
#define SROM8_PATH3 144
|
||||
|
||||
#define SROM8_2G_ITT_MAXP 0
|
||||
#define SROM8_2G_PA 1
|
||||
#define SROM8_5G_ITT_MAXP 4
|
||||
#define SROM8_5GLH_MAXP 5
|
||||
#define SROM8_5G_PA 6
|
||||
#define SROM8_5GL_PA 9
|
||||
#define SROM8_5GH_PA 12
|
||||
|
||||
/* All the miriad power offsets */
|
||||
#define SROM8_2G_CCKPO 160
|
||||
|
||||
#define SROM8_2G_OFDMPO 161
|
||||
#define SROM8_5G_OFDMPO 163
|
||||
#define SROM8_5GL_OFDMPO 165
|
||||
#define SROM8_5GH_OFDMPO 167
|
||||
|
||||
#define SROM8_2G_MCSPO 169
|
||||
#define SROM8_5G_MCSPO 177
|
||||
#define SROM8_5GL_MCSPO 185
|
||||
#define SROM8_5GH_MCSPO 193
|
||||
|
||||
#define SROM8_CDDPO 201
|
||||
#define SROM8_STBCPO 202
|
||||
#define SROM8_BW40PO 203
|
||||
#define SROM8_BWDUPPO 204
|
||||
|
||||
/* SISO PA parameters are in the path0 spaces */
|
||||
#define SROM8_SISO 96
|
||||
|
||||
/* Legacy names for SISO PA paramters */
|
||||
#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
|
||||
#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
|
||||
#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
|
||||
#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
|
||||
#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
|
||||
#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
|
||||
#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
|
||||
#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
|
||||
#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
|
||||
#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
|
||||
#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
|
||||
#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
|
||||
#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
|
||||
#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
|
||||
#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
|
||||
|
||||
/* SROM REV 9 */
|
||||
#define SROM9_2GPO_CCKBW20 160
|
||||
#define SROM9_2GPO_CCKBW20UL 161
|
||||
#define SROM9_2GPO_LOFDMBW20 162
|
||||
#define SROM9_2GPO_LOFDMBW20UL 164
|
||||
|
||||
#define SROM9_5GLPO_LOFDMBW20 166
|
||||
#define SROM9_5GLPO_LOFDMBW20UL 168
|
||||
#define SROM9_5GMPO_LOFDMBW20 170
|
||||
#define SROM9_5GMPO_LOFDMBW20UL 172
|
||||
#define SROM9_5GHPO_LOFDMBW20 174
|
||||
#define SROM9_5GHPO_LOFDMBW20UL 176
|
||||
|
||||
#define SROM9_2GPO_MCSBW20 178
|
||||
#define SROM9_2GPO_MCSBW20UL 180
|
||||
#define SROM9_2GPO_MCSBW40 182
|
||||
|
||||
#define SROM9_5GLPO_MCSBW20 184
|
||||
#define SROM9_5GLPO_MCSBW20UL 186
|
||||
#define SROM9_5GLPO_MCSBW40 188
|
||||
#define SROM9_5GMPO_MCSBW20 190
|
||||
#define SROM9_5GMPO_MCSBW20UL 192
|
||||
#define SROM9_5GMPO_MCSBW40 194
|
||||
#define SROM9_5GHPO_MCSBW20 196
|
||||
#define SROM9_5GHPO_MCSBW20UL 198
|
||||
#define SROM9_5GHPO_MCSBW40 200
|
||||
|
||||
#define SROM9_PO_MCS32 202
|
||||
#define SROM9_PO_LOFDM40DUP 203
|
||||
|
||||
/* SROM flags (see sromvar_t) */
|
||||
|
||||
/* value continues as described by the next entry */
|
||||
#define SRFL_MORE 1
|
||||
#define SRFL_NOFFS 2 /* value bits can't be all one's */
|
||||
#define SRFL_PRHEX 4 /* value is in hexdecimal format */
|
||||
#define SRFL_PRSIGN 8 /* value is in signed decimal format */
|
||||
#define SRFL_CCODE 0x10 /* value is in country code format */
|
||||
#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
|
||||
#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
|
||||
/* do not generate a nvram param, entry is for mfgc */
|
||||
#define SRFL_NOVAR 0x80
|
||||
|
||||
/* Max. nvram variable table size */
|
||||
#define MAXSZ_NVRAM_VARS 4096
|
||||
|
||||
/*
|
||||
* indicates type of value.
|
||||
*/
|
||||
enum brcms_srom_var_type {
|
||||
BRCMS_SROM_STRING,
|
||||
BRCMS_SROM_SNUMBER,
|
||||
BRCMS_SROM_UNUMBER
|
||||
};
|
||||
|
||||
/*
|
||||
* storage type for srom variable.
|
||||
*
|
||||
* var_list: for linked list operations.
|
||||
* varid: identifier of the variable.
|
||||
* var_type: type of variable.
|
||||
* buf: variable value when var_type == BRCMS_SROM_STRING.
|
||||
* uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER.
|
||||
* sval: signed variable value when var_type == BRCMS_SROM_SNUMBER.
|
||||
*/
|
||||
struct brcms_srom_list_head {
|
||||
struct list_head var_list;
|
||||
enum brcms_srom_id varid;
|
||||
enum brcms_srom_var_type var_type;
|
||||
union {
|
||||
char buf[0];
|
||||
u32 uval;
|
||||
s32 sval;
|
||||
};
|
||||
};
|
||||
|
||||
struct brcms_sromvar {
|
||||
enum brcms_srom_id varid;
|
||||
u32 revmask;
|
||||
u32 flags;
|
||||
u16 off;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
struct brcms_varbuf {
|
||||
char *base; /* pointer to buffer base */
|
||||
char *buf; /* pointer to current position */
|
||||
unsigned int size; /* current (residual) size in bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* Assumptions:
|
||||
* - Ethernet address spans across 3 consecutive words
|
||||
*
|
||||
* Table rules:
|
||||
* - Add multiple entries next to each other if a value spans across multiple
|
||||
* words (even multiple fields in the same word) with each entry except the
|
||||
* last having it's SRFL_MORE bit set.
|
||||
* - Ethernet address entry does not follow above rule and must not have
|
||||
* SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
|
||||
* - The last entry's name field must be NULL to indicate the end of the table.
|
||||
* Other entries must have non-NULL name.
|
||||
*/
|
||||
static const struct brcms_sromvar pci_sromvars[] = {
|
||||
{BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
|
||||
0xffff},
|
||||
{BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
|
||||
{BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
|
||||
{BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
|
||||
{BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
|
||||
{BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
|
||||
{BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
|
||||
{BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
|
||||
{BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
|
||||
{BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
|
||||
{BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
|
||||
{BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
|
||||
{BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
|
||||
{BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
|
||||
{BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
|
||||
{BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
|
||||
{BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
|
||||
{BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
|
||||
{BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
|
||||
{BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
|
||||
{BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
|
||||
{BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
|
||||
{BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
|
||||
{BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
|
||||
{BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
|
||||
{BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
|
||||
{BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
|
||||
{BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
|
||||
{BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
|
||||
{BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
|
||||
{BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
|
||||
{BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
|
||||
{BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
|
||||
{BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
|
||||
{BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
|
||||
{BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
|
||||
{BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
|
||||
{BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
|
||||
{BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
|
||||
{BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
|
||||
{BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
|
||||
{BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
|
||||
{BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
|
||||
{BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
|
||||
{BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
|
||||
{BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
|
||||
{BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
|
||||
{BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
|
||||
{BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
|
||||
{BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
|
||||
{BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
|
||||
SROM4_TXCHAIN_MASK},
|
||||
{BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
|
||||
SROM4_RXCHAIN_MASK},
|
||||
{BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
|
||||
SROM4_SWITCH_MASK},
|
||||
{BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G,
|
||||
SROM8_FEM_TSSIPOS_MASK},
|
||||
{BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G,
|
||||
SROM8_FEM_EXTPA_GAIN_MASK},
|
||||
{BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G,
|
||||
SROM8_FEM_PDET_RANGE_MASK},
|
||||
{BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
|
||||
{BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G,
|
||||
SROM8_FEM_ANTSWLUT_MASK},
|
||||
{BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G,
|
||||
SROM8_FEM_TSSIPOS_MASK},
|
||||
{BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G,
|
||||
SROM8_FEM_EXTPA_GAIN_MASK},
|
||||
{BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G,
|
||||
SROM8_FEM_PDET_RANGE_MASK},
|
||||
{BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
|
||||
{BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G,
|
||||
SROM8_FEM_ANTSWLUT_MASK},
|
||||
{BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
|
||||
{BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
|
||||
|
||||
{BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
|
||||
{BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
|
||||
{BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
|
||||
0xffff},
|
||||
{BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
|
||||
0x01ff},
|
||||
{BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
|
||||
0xfe00},
|
||||
{BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX,
|
||||
SROM8_TS_SLP_OPT_CORRX, 0x00ff},
|
||||
{BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
|
||||
0xfc00},
|
||||
{BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX,
|
||||
SROM8_TS_SLP_OPT_CORRX, 0x0300},
|
||||
{BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX,
|
||||
SROM8_FOC_HWIQ_IQSWP, 0x000f},
|
||||
{BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
|
||||
0x0010},
|
||||
{BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
|
||||
0x0020},
|
||||
{BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
|
||||
0x00ff},
|
||||
|
||||
{BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
|
||||
{BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
|
||||
{BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
|
||||
{BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
|
||||
{BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
|
||||
{BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
|
||||
{BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
|
||||
{BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
|
||||
{BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
|
||||
{BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
|
||||
{BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
|
||||
{BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
|
||||
{BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
|
||||
|
||||
/* power per rate from sromrev 9 */
|
||||
{BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
|
||||
{BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_2GPO_LOFDMBW20, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_2GPO_LOFDMBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GLPO_LOFDMBW20, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GLPO_LOFDMBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GMPO_LOFDMBW20, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GMPO_LOFDMBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GHPO_LOFDMBW20, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GHPO_LOFDMBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GLPO_MCSBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GMPO_MCSBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
|
||||
SROM9_5GHPO_MCSBW20UL, 0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
|
||||
{BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
|
||||
{BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
|
||||
{BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
|
||||
|
||||
{BRCMS_SROM_NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const struct brcms_sromvar perpath_pci_sromvars[] = {
|
||||
{BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
|
||||
{BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
|
||||
{BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
|
||||
{BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
|
||||
{BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
|
||||
{BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
|
||||
{BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
|
||||
{BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
|
||||
{BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
|
||||
{BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
|
||||
{BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
|
||||
{BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
|
||||
{BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
|
||||
{BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1,
|
||||
0xffff},
|
||||
{BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2,
|
||||
0xffff},
|
||||
{BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
|
||||
{BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1,
|
||||
0xffff},
|
||||
{BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2,
|
||||
0xffff},
|
||||
{BRCMS_SROM_NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* crc table has the same contents for every device instance, so it can be
|
||||
* shared between devices. */
|
||||
static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
|
||||
|
||||
static uint mask_shift(u16 mask)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < (sizeof(mask) << 3); i++) {
|
||||
if (mask & (1 << i))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint mask_width(u16 mask)
|
||||
{
|
||||
int i;
|
||||
for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
|
||||
if (mask & (1 << i))
|
||||
return (uint) (i - mask_shift(mask) + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void le16_to_cpu_buf(u16 *buf, uint nwords)
|
||||
{
|
||||
while (nwords--)
|
||||
*(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords));
|
||||
}
|
||||
|
||||
static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
|
||||
{
|
||||
while (nwords--)
|
||||
*(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords));
|
||||
}
|
||||
|
||||
/*
|
||||
* convert binary srom data into linked list of srom variable items.
|
||||
*/
|
||||
static int
|
||||
_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
|
||||
{
|
||||
struct brcms_srom_list_head *entry;
|
||||
enum brcms_srom_id id;
|
||||
u16 w;
|
||||
u32 val = 0;
|
||||
const struct brcms_sromvar *srv;
|
||||
uint width;
|
||||
uint flags;
|
||||
u32 sr = (1 << sromrev);
|
||||
uint p;
|
||||
uint pb = SROM8_PATH0;
|
||||
const uint psz = SROM8_PATH1 - SROM8_PATH0;
|
||||
|
||||
/* first store the srom revision */
|
||||
entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->varid = BRCMS_SROM_REV;
|
||||
entry->var_type = BRCMS_SROM_UNUMBER;
|
||||
entry->uval = sromrev;
|
||||
list_add(&entry->var_list, var_list);
|
||||
|
||||
for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) {
|
||||
enum brcms_srom_var_type type;
|
||||
u8 ea[ETH_ALEN];
|
||||
u8 extra_space = 0;
|
||||
|
||||
if ((srv->revmask & sr) == 0)
|
||||
continue;
|
||||
|
||||
flags = srv->flags;
|
||||
id = srv->varid;
|
||||
|
||||
/* This entry is for mfgc only. Don't generate param for it, */
|
||||
if (flags & SRFL_NOVAR)
|
||||
continue;
|
||||
|
||||
if (flags & SRFL_ETHADDR) {
|
||||
/*
|
||||
* stored in string format XX:XX:XX:XX:XX:XX (17 chars)
|
||||
*/
|
||||
ea[0] = (srom[srv->off] >> 8) & 0xff;
|
||||
ea[1] = srom[srv->off] & 0xff;
|
||||
ea[2] = (srom[srv->off + 1] >> 8) & 0xff;
|
||||
ea[3] = srom[srv->off + 1] & 0xff;
|
||||
ea[4] = (srom[srv->off + 2] >> 8) & 0xff;
|
||||
ea[5] = srom[srv->off + 2] & 0xff;
|
||||
/* 17 characters + string terminator - union size */
|
||||
extra_space = 18 - sizeof(s32);
|
||||
type = BRCMS_SROM_STRING;
|
||||
} else {
|
||||
w = srom[srv->off];
|
||||
val = (w & srv->mask) >> mask_shift(srv->mask);
|
||||
width = mask_width(srv->mask);
|
||||
|
||||
while (srv->flags & SRFL_MORE) {
|
||||
srv++;
|
||||
if (srv->off == 0)
|
||||
continue;
|
||||
|
||||
w = srom[srv->off];
|
||||
val +=
|
||||
((w & srv->mask) >> mask_shift(srv->
|
||||
mask)) <<
|
||||
width;
|
||||
width += mask_width(srv->mask);
|
||||
}
|
||||
|
||||
if ((flags & SRFL_NOFFS)
|
||||
&& ((int)val == (1 << width) - 1))
|
||||
continue;
|
||||
|
||||
if (flags & SRFL_CCODE) {
|
||||
type = BRCMS_SROM_STRING;
|
||||
} else if (flags & SRFL_LEDDC) {
|
||||
/* LED Powersave duty cycle has to be scaled:
|
||||
*(oncount >> 24) (offcount >> 8)
|
||||
*/
|
||||
u32 w32 = /* oncount */
|
||||
(((val >> 8) & 0xff) << 24) |
|
||||
/* offcount */
|
||||
(((val & 0xff)) << 8);
|
||||
type = BRCMS_SROM_UNUMBER;
|
||||
val = w32;
|
||||
} else if ((flags & SRFL_PRSIGN)
|
||||
&& (val & (1 << (width - 1)))) {
|
||||
type = BRCMS_SROM_SNUMBER;
|
||||
val |= ~0 << width;
|
||||
} else
|
||||
type = BRCMS_SROM_UNUMBER;
|
||||
}
|
||||
|
||||
entry = kzalloc(sizeof(struct brcms_srom_list_head) +
|
||||
extra_space, GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
entry->varid = id;
|
||||
entry->var_type = type;
|
||||
if (flags & SRFL_ETHADDR) {
|
||||
snprintf(entry->buf, 18, "%pM", ea);
|
||||
} else if (flags & SRFL_CCODE) {
|
||||
if (val == 0)
|
||||
entry->buf[0] = '\0';
|
||||
else
|
||||
snprintf(entry->buf, 3, "%c%c",
|
||||
(val >> 8), (val & 0xff));
|
||||
} else {
|
||||
entry->uval = val;
|
||||
}
|
||||
|
||||
list_add(&entry->var_list, var_list);
|
||||
}
|
||||
|
||||
for (p = 0; p < MAX_PATH_SROM; p++) {
|
||||
for (srv = perpath_pci_sromvars;
|
||||
srv->varid != BRCMS_SROM_NULL; srv++) {
|
||||
if ((srv->revmask & sr) == 0)
|
||||
continue;
|
||||
|
||||
if (srv->flags & SRFL_NOVAR)
|
||||
continue;
|
||||
|
||||
w = srom[pb + srv->off];
|
||||
val = (w & srv->mask) >> mask_shift(srv->mask);
|
||||
width = mask_width(srv->mask);
|
||||
|
||||
/* Cheating: no per-path var is more than
|
||||
* 1 word */
|
||||
if ((srv->flags & SRFL_NOFFS)
|
||||
&& ((int)val == (1 << width) - 1))
|
||||
continue;
|
||||
|
||||
entry =
|
||||
kzalloc(sizeof(struct brcms_srom_list_head),
|
||||
GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
entry->varid = srv->varid+p;
|
||||
entry->var_type = BRCMS_SROM_UNUMBER;
|
||||
entry->uval = val;
|
||||
list_add(&entry->var_list, var_list);
|
||||
}
|
||||
pb += psz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The crc check is done on a little-endian array, we need
|
||||
* to switch the bytes around before checking crc (and
|
||||
* then switch it back).
|
||||
*/
|
||||
static int do_crc_check(u16 *buf, unsigned nwords)
|
||||
{
|
||||
u8 crc;
|
||||
|
||||
cpu_to_le16_buf(buf, nwords);
|
||||
crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE);
|
||||
le16_to_cpu_buf(buf, nwords);
|
||||
|
||||
return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in and validate sprom.
|
||||
* Return 0 on success, nonzero on error.
|
||||
*/
|
||||
static int
|
||||
sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
|
||||
{
|
||||
int err = 0;
|
||||
uint i;
|
||||
struct bcma_device *core;
|
||||
uint sprom_offset;
|
||||
|
||||
/* determine core to read */
|
||||
if (ai_get_ccrev(sih) < 32) {
|
||||
core = ai_findcore(sih, BCMA_CORE_80211, 0);
|
||||
sprom_offset = PCI_BAR0_SPROM_OFFSET;
|
||||
} else {
|
||||
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
|
||||
sprom_offset = CHIPCREGOFFS(sromotp);
|
||||
}
|
||||
|
||||
/* read the sprom */
|
||||
for (i = 0; i < nwords; i++)
|
||||
buf[i] = bcma_read16(core, sprom_offset+i*2);
|
||||
|
||||
if (buf[0] == 0xffff)
|
||||
/*
|
||||
* The hardware thinks that an srom that starts with
|
||||
* 0xffff is blank, regardless of the rest of the
|
||||
* content, so declare it bad.
|
||||
*/
|
||||
return -ENODATA;
|
||||
|
||||
if (check_crc && !do_crc_check(buf, nwords))
|
||||
err = -EIO;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
|
||||
{
|
||||
u8 *otp;
|
||||
uint sz = OTP_SZ_MAX / 2; /* size in words */
|
||||
int err = 0;
|
||||
|
||||
otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
|
||||
if (otp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
|
||||
|
||||
sz = min_t(uint, sz, nwords);
|
||||
memcpy(buf, otp, sz * 2);
|
||||
|
||||
kfree(otp);
|
||||
|
||||
/* Check CRC */
|
||||
if (buf[0] == 0xffff)
|
||||
/* The hardware thinks that an srom that starts with 0xffff
|
||||
* is blank, regardless of the rest of the content, so declare
|
||||
* it bad.
|
||||
*/
|
||||
return -ENODATA;
|
||||
|
||||
/* fixup the endianness so crc8 will pass */
|
||||
cpu_to_le16_buf(buf, sz);
|
||||
if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2,
|
||||
CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
|
||||
err = -EIO;
|
||||
else
|
||||
/* now correct the endianness of the byte array */
|
||||
le16_to_cpu_buf(buf, sz);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize nonvolatile variable table from sprom.
|
||||
* Return 0 on success, nonzero on error.
|
||||
*/
|
||||
int srom_var_init(struct si_pub *sih)
|
||||
{
|
||||
u16 *srom;
|
||||
u8 sromrev = 0;
|
||||
u32 sr;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Apply CRC over SROM content regardless SROM is present or not.
|
||||
*/
|
||||
srom = kmalloc(SROM_MAX, GFP_ATOMIC);
|
||||
if (!srom)
|
||||
return -ENOMEM;
|
||||
|
||||
crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
|
||||
if (ai_is_sprom_available(sih)) {
|
||||
err = sprom_read_pci(sih, srom, SROM4_WORDS, true);
|
||||
|
||||
if (err == 0)
|
||||
/* srom read and passed crc */
|
||||
/* top word of sprom contains version and crc8 */
|
||||
sromrev = srom[SROM4_CRCREV] & 0xff;
|
||||
} else {
|
||||
/* Use OTP if SPROM not available */
|
||||
err = otp_read_pci(sih, srom, SROM4_WORDS);
|
||||
if (err == 0)
|
||||
/* OTP only contain SROM rev8/rev9 for now */
|
||||
sromrev = srom[SROM4_CRCREV] & 0xff;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
struct si_info *sii = (struct si_info *)sih;
|
||||
|
||||
/* Bitmask for the sromrev */
|
||||
sr = 1 << sromrev;
|
||||
|
||||
/*
|
||||
* srom version check: Current valid versions: 8, 9
|
||||
*/
|
||||
if ((sr & 0x300) == 0) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sii->var_list);
|
||||
|
||||
/* parse SROM into name=value pairs. */
|
||||
err = _initvars_srom_pci(sromrev, srom, &sii->var_list);
|
||||
if (err)
|
||||
srom_free_vars(sih);
|
||||
}
|
||||
|
||||
errout:
|
||||
kfree(srom);
|
||||
return err;
|
||||
}
|
||||
|
||||
void srom_free_vars(struct si_pub *sih)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct brcms_srom_list_head *entry, *next;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
list_for_each_entry_safe(entry, next, &sii->var_list, var_list) {
|
||||
list_del(&entry->var_list);
|
||||
kfree(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the name=value vars for a specific one and return its value.
|
||||
* Returns NULL if not found.
|
||||
*/
|
||||
char *getvar(struct si_pub *sih, enum brcms_srom_id id)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct brcms_srom_list_head *entry;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
list_for_each_entry(entry, &sii->var_list, var_list)
|
||||
if (entry->varid == id)
|
||||
return &entry->buf[0];
|
||||
|
||||
/* nothing found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the vars for a specific one and return its value as
|
||||
* an integer. Returns 0 if not found.-
|
||||
*/
|
||||
int getintvar(struct si_pub *sih, enum brcms_srom_id id)
|
||||
{
|
||||
struct si_info *sii;
|
||||
struct brcms_srom_list_head *entry;
|
||||
unsigned long res;
|
||||
|
||||
sii = (struct si_info *)sih;
|
||||
|
||||
list_for_each_entry(entry, &sii->var_list, var_list)
|
||||
if (entry->varid == id) {
|
||||
if (entry->var_type == BRCMS_SROM_SNUMBER ||
|
||||
entry->var_type == BRCMS_SROM_UNUMBER)
|
||||
return (int)entry->sval;
|
||||
else if (!kstrtoul(&entry->buf[0], 0, &res))
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _BRCM_SROM_H_
|
||||
#define _BRCM_SROM_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* Prototypes */
|
||||
extern int srom_var_init(struct si_pub *sih);
|
||||
extern void srom_free_vars(struct si_pub *sih);
|
||||
|
||||
extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
|
||||
uint byteoff, uint nbytes, u16 *buf, bool check_crc);
|
||||
|
||||
#endif /* _BRCM_SROM_H_ */
|
|
@ -370,9 +370,11 @@ void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
|
|||
|
||||
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
|
||||
{
|
||||
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
|
||||
|
||||
/* get available rx/tx chains */
|
||||
wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN);
|
||||
wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN);
|
||||
wlc->stf->hw_txchain = sprom->txchain;
|
||||
wlc->stf->hw_rxchain = sprom->rxchain;
|
||||
|
||||
/* these parameter are intended to be used for all PHY types */
|
||||
if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
|
@ -273,9 +274,20 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Possible situations when BT needs to take over for receive,
|
||||
* at the same time where STA needs to response to AP's frame(s),
|
||||
* reduce the tx power of the required response frames, by that,
|
||||
* allow the concurrent BT receive & WiFi transmit
|
||||
* (BT - ANT A, WiFi -ANT B), without interference to one another
|
||||
*
|
||||
* Reduced tx power apply to control frames only (ACK/Back/CTS)
|
||||
* when indicated by the BT config command
|
||||
*/
|
||||
basic.kill_ack_mask = priv->kill_ack_mask;
|
||||
basic.kill_cts_mask = priv->kill_cts_mask;
|
||||
basic.reduce_txpower = priv->reduced_txpower;
|
||||
if (priv->reduced_txpower)
|
||||
basic.reduce_txpower = IWLAGN_BT_REDUCED_TX_PWR;
|
||||
basic.valid = priv->bt_valid;
|
||||
|
||||
/*
|
||||
|
@ -589,13 +601,31 @@ static bool iwlagn_set_kill_msk(struct iwl_priv *priv,
|
|||
return need_update;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon RSSI changes, sends a bt config command with following changes
|
||||
* 1. enable/disable "reduced control frames tx power
|
||||
* 2. update the "kill)ack_mask" and "kill_cts_mask"
|
||||
*
|
||||
* If "reduced tx power" is enabled, uCode shall
|
||||
* 1. ACK/Back/CTS rate shall reduced to 6Mbps
|
||||
* 2. not use duplciate 20/40MHz mode
|
||||
*/
|
||||
static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
|
||||
struct iwl_bt_uart_msg *uart_msg)
|
||||
{
|
||||
bool need_update = false;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int ave_rssi;
|
||||
|
||||
ave_rssi = ieee80211_ave_rssi(ctx->vif);
|
||||
if (!ave_rssi) {
|
||||
/* no rssi data, no changes to reduce tx power */
|
||||
IWL_DEBUG_COEX(priv, "no rssi data available\n");
|
||||
return need_update;
|
||||
}
|
||||
if (!priv->reduced_txpower &&
|
||||
!iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
|
||||
(ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) &&
|
||||
(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
|
||||
BT_UART_MSG_FRAME3OBEX_MSK)) &&
|
||||
!(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
|
||||
|
@ -606,13 +636,14 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
|
|||
need_update = true;
|
||||
} else if (priv->reduced_txpower &&
|
||||
(iwl_is_associated(priv, IWL_RXON_CTX_PAN) ||
|
||||
(ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) ||
|
||||
(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
|
||||
BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) ||
|
||||
!(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
|
||||
BT_UART_MSG_FRAME3OBEX_MSK)))) {
|
||||
/* disable reduced tx power */
|
||||
priv->reduced_txpower = false;
|
||||
priv->bt_valid &= ~IWLAGN_BT_VALID_REDUCED_TX_PWR;
|
||||
priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,10 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
|||
RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
ctx->staging.dev_type = RXON_DEV_TYPE_SNIFFER;
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "Unsupported interface type %d\n",
|
||||
ctx->vif->type);
|
||||
|
|
|
@ -590,11 +590,17 @@ turn_off:
|
|||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
if (test_bit(txq_id, priv->agg_q_alloc)) {
|
||||
/* If the transport didn't know that we wanted to start
|
||||
* agreggation, don't tell it that we want to stop them
|
||||
/*
|
||||
* If the transport didn't know that we wanted to start
|
||||
* agreggation, don't tell it that we want to stop them.
|
||||
* This can happen when we don't get the addBA response on
|
||||
* time, or we hadn't time to drain the AC queues.
|
||||
*/
|
||||
if (agg_state != IWL_AGG_STARTING)
|
||||
if (agg_state == IWL_AGG_ON)
|
||||
iwl_trans_tx_agg_disable(priv->trans, txq_id);
|
||||
else
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
|
||||
agg_state);
|
||||
iwlagn_dealloc_agg_txq(priv, txq_id);
|
||||
}
|
||||
|
||||
|
@ -1300,10 +1306,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
(u8 *) &ba_resp->sta_addr_lo32,
|
||||
ba_resp->sta_id);
|
||||
IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
|
||||
"scd_flow = %d, scd_ssn = %d\n",
|
||||
"scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n",
|
||||
ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl),
|
||||
(unsigned long long)le64_to_cpu(ba_resp->bitmap),
|
||||
scd_flow, ba_resp_scd_ssn);
|
||||
scd_flow, ba_resp_scd_ssn, ba_resp->txed,
|
||||
ba_resp->txed_2_done);
|
||||
|
||||
/* Mark that the expected block-ack response arrived */
|
||||
agg->wait_for_ba = false;
|
||||
|
@ -1319,8 +1326,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
*/
|
||||
ba_resp->txed = ba_resp->txed_2_done;
|
||||
}
|
||||
IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
|
||||
ba_resp->txed, ba_resp->txed_2_done);
|
||||
|
||||
priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn;
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
|||
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
|
||||
|
|
|
@ -1910,6 +1910,8 @@ enum iwl_bt_kill_idx {
|
|||
IWLAGN_BT_VALID_REDUCED_TX_PWR | \
|
||||
IWLAGN_BT_VALID_3W_LUT)
|
||||
|
||||
#define IWLAGN_BT_REDUCED_TX_PWR BIT(0)
|
||||
|
||||
#define IWLAGN_BT_DECISION_LUT_SIZE 12
|
||||
|
||||
struct iwl_basic_bt_cmd {
|
||||
|
@ -1923,6 +1925,10 @@ struct iwl_basic_bt_cmd {
|
|||
u8 bt3_timer_t2_value;
|
||||
__le16 bt4_reaction_time; /* unused */
|
||||
__le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE];
|
||||
/*
|
||||
* bit 0: use reduced tx power for control frame
|
||||
* bit 1 - 7: reserved
|
||||
*/
|
||||
u8 reduce_txpower;
|
||||
u8 reserved;
|
||||
__le16 valid;
|
||||
|
@ -2272,7 +2278,6 @@ struct iwl_ssid_ie {
|
|||
#define IWL_GOOD_CRC_TH_DISABLED 0
|
||||
#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)
|
||||
#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff)
|
||||
#define IWL_MAX_SCAN_SIZE 1024
|
||||
#define IWL_MAX_CMD_SIZE 4096
|
||||
|
||||
/*
|
||||
|
|
|
@ -150,6 +150,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||
IEEE80211_HW_SCAN_WHILE_IDLE;
|
||||
|
||||
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
|
||||
|
@ -223,8 +224,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2;
|
||||
/* we create the 802.11 header and a max-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 34;
|
||||
|
||||
/*
|
||||
* We don't use all queues: 4 and 9 are unused and any
|
||||
|
|
|
@ -253,6 +253,8 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||
|
||||
IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
|
||||
skip, period);
|
||||
/* The power level here is 0-4 (used as array index), but user expects
|
||||
to see 1-5 (according to spec). */
|
||||
IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
|
||||
}
|
||||
|
||||
|
@ -308,10 +310,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
|||
priv->power_data.debug_sleep_level_override,
|
||||
dtimper);
|
||||
else {
|
||||
/* Note that the user parameter is 1-5 (according to spec),
|
||||
but we pass 0-4 because it acts as an array index. */
|
||||
if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 &&
|
||||
iwlwifi_mod_params.power_level <= IWL_POWER_INDEX_5)
|
||||
iwlwifi_mod_params.power_level <= IWL_POWER_NUM)
|
||||
iwl_static_sleep_cmd(priv, cmd,
|
||||
iwlwifi_mod_params.power_level, dtimper);
|
||||
iwlwifi_mod_params.power_level - 1, dtimper);
|
||||
else
|
||||
iwl_static_sleep_cmd(priv, cmd,
|
||||
IWL_POWER_INDEX_1, dtimper);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#define IWL_PASSIVE_DWELL_TIME_52 (10)
|
||||
#define IWL_PASSIVE_DWELL_BASE (100)
|
||||
#define IWL_CHANNEL_TUNE_TIME 5
|
||||
#define MAX_SCAN_CHANNEL 50
|
||||
|
||||
static int iwl_send_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -616,7 +617,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
|||
*/
|
||||
|
||||
static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
|
||||
const u8 *ies, int ie_len, int left)
|
||||
const u8 *ies, int ie_len, const u8 *ssid,
|
||||
u8 ssid_len, int left)
|
||||
{
|
||||
int len = 0;
|
||||
u8 *pos = NULL;
|
||||
|
@ -638,14 +640,18 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
|
|||
/* ...next IE... */
|
||||
pos = &frame->u.probe_req.variable[0];
|
||||
|
||||
/* fill in our indirect SSID IE */
|
||||
left -= 2;
|
||||
/* fill in our SSID IE */
|
||||
left -= ssid_len + 2;
|
||||
if (left < 0)
|
||||
return 0;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = 0;
|
||||
*pos++ = ssid_len;
|
||||
if (ssid && ssid_len) {
|
||||
memcpy(pos, ssid, ssid_len);
|
||||
pos += ssid_len;
|
||||
}
|
||||
|
||||
len += 2;
|
||||
len += ssid_len + 2;
|
||||
|
||||
if (WARN_ON(left < ie_len))
|
||||
return len;
|
||||
|
@ -679,6 +685,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
u8 active_chains;
|
||||
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
|
||||
int ret;
|
||||
int scan_cmd_size = sizeof(struct iwl_scan_cmd) +
|
||||
MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) +
|
||||
priv->fw->ucode_capa.max_probe_length;
|
||||
const u8 *ssid = NULL;
|
||||
u8 ssid_len = 0;
|
||||
|
||||
if (WARN_ON_ONCE(priv->scan_request &&
|
||||
priv->scan_request->n_channels > MAX_SCAN_CHANNEL))
|
||||
return -EINVAL;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
|
@ -686,8 +701,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
if (!priv->scan_cmd) {
|
||||
priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
|
||||
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
|
||||
priv->scan_cmd = kmalloc(scan_cmd_size, GFP_KERNEL);
|
||||
if (!priv->scan_cmd) {
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"fail to allocate memory for scan\n");
|
||||
|
@ -695,7 +709,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
}
|
||||
}
|
||||
scan = priv->scan_cmd;
|
||||
memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
|
||||
memset(scan, 0, scan_cmd_size);
|
||||
|
||||
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
|
||||
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
|
||||
|
@ -746,10 +760,18 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
if (priv->scan_request->n_ssids) {
|
||||
int i, p = 0;
|
||||
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
|
||||
for (i = 0; i < priv->scan_request->n_ssids; i++) {
|
||||
/* always does wildcard anyway */
|
||||
if (!priv->scan_request->ssids[i].ssid_len)
|
||||
continue;
|
||||
/*
|
||||
* The highest priority SSID is inserted to the
|
||||
* probe request template.
|
||||
*/
|
||||
ssid_len = priv->scan_request->ssids[0].ssid_len;
|
||||
ssid = priv->scan_request->ssids[0].ssid;
|
||||
|
||||
/*
|
||||
* Invert the order of ssids, the firmware will invert
|
||||
* it back.
|
||||
*/
|
||||
for (i = priv->scan_request->n_ssids - 1; i >= 1; i--) {
|
||||
scan->direct_scan[p].id = WLAN_EID_SSID;
|
||||
scan->direct_scan[p].len =
|
||||
priv->scan_request->ssids[i].ssid_len;
|
||||
|
@ -883,7 +905,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
ssid, ssid_len,
|
||||
scan_cmd_size - sizeof(*scan));
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
case IWL_SCAN_ROC:
|
||||
|
@ -891,7 +914,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
cmd_len = iwl_fill_probe_req(
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
NULL, 0,
|
||||
scan_cmd_size - sizeof(*scan));
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
|
|
@ -746,6 +746,11 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
hwsim_check_sta_magic(txi->control.sta);
|
||||
|
||||
ieee80211_tx_info_clear_status(txi);
|
||||
|
||||
/* frame was transmitted at most favorable rate at first attempt */
|
||||
txi->control.rates[0].count = 1;
|
||||
txi->control.rates[1].idx = -1;
|
||||
|
||||
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
|
||||
txi->flags |= IEEE80211_TX_STAT_ACK;
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
|
|
|
@ -29,6 +29,8 @@ mwifiex-y += scan.o
|
|||
mwifiex-y += join.o
|
||||
mwifiex-y += sta_ioctl.o
|
||||
mwifiex-y += sta_cmd.o
|
||||
mwifiex-y += uap_cmd.o
|
||||
mwifiex-y += ie.o
|
||||
mwifiex-y += sta_cmdresp.o
|
||||
mwifiex-y += sta_event.o
|
||||
mwifiex-y += sta_tx.o
|
||||
|
|
|
@ -20,6 +20,23 @@
|
|||
#include "cfg80211.h"
|
||||
#include "main.h"
|
||||
|
||||
static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
|
||||
{
|
||||
.max = 1, .types = BIT(NL80211_IFTYPE_STATION),
|
||||
},
|
||||
{
|
||||
.max = 1, .types = BIT(NL80211_IFTYPE_AP),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
|
||||
.limits = mwifiex_ap_sta_limits,
|
||||
.num_different_channels = 1,
|
||||
.n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
|
||||
.max_interfaces = MWIFIEX_MAX_BSS_NUM,
|
||||
.beacon_int_infra_match = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* This function maps the nl802.11 channel type into driver channel type.
|
||||
*
|
||||
|
@ -67,7 +84,7 @@ mwifiex_is_alg_wep(u32 cipher)
|
|||
/*
|
||||
* This function retrieves the private structure from kernel wiphy structure.
|
||||
*/
|
||||
static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy)
|
||||
static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
|
||||
{
|
||||
return (void *) (*(unsigned long *) wiphy_priv(wiphy));
|
||||
}
|
||||
|
@ -80,8 +97,10 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
|
|||
u8 key_index, bool pairwise, const u8 *mac_addr)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(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, 1)) {
|
||||
if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) {
|
||||
wiphy_err(wiphy, "deleting the crypto keys\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -98,7 +117,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
|
|||
enum nl80211_tx_power_setting type,
|
||||
int mbm)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
|
||||
struct mwifiex_private *priv;
|
||||
struct mwifiex_power_cfg power_cfg;
|
||||
int dbm = MBM_TO_DBM(mbm);
|
||||
|
||||
|
@ -109,6 +129,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
|
|||
power_cfg.is_power_auto = 1;
|
||||
}
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
|
||||
return mwifiex_set_tx_power(priv, &power_cfg);
|
||||
}
|
||||
|
||||
|
@ -148,7 +170,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
|
|||
if (!priv->sec_info.wep_enabled)
|
||||
return 0;
|
||||
|
||||
if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) {
|
||||
if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
|
||||
wiphy_err(wiphy, "set default Tx key index\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -165,9 +187,11 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
|
|||
struct key_params *params)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(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, params->key, params->key_len,
|
||||
key_index, 0)) {
|
||||
key_index, peer_mac, 0)) {
|
||||
wiphy_err(wiphy, "crypto keys added\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -192,13 +216,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
|||
enum ieee80211_band band;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *ch;
|
||||
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
|
||||
struct mwifiex_private *priv;
|
||||
struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
|
||||
|
||||
/* Set country code */
|
||||
domain_info->country_code[0] = priv->country_code[0];
|
||||
domain_info->country_code[1] = priv->country_code[1];
|
||||
domain_info->country_code[0] = adapter->country_code[0];
|
||||
domain_info->country_code[1] = adapter->country_code[1];
|
||||
domain_info->country_code[2] = ' ';
|
||||
|
||||
band = mwifiex_band_to_radio_type(adapter->config_bands);
|
||||
|
@ -250,6 +274,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
|||
|
||||
domain_info->no_of_triplet = no_of_triplet;
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
|
||||
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL)) {
|
||||
wiphy_err(wiphy, "11D: setting domain info in FW\n");
|
||||
|
@ -272,12 +298,12 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
|||
static int mwifiex_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
|
||||
|
||||
wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain"
|
||||
" %c%c\n", request->alpha2[0], request->alpha2[1]);
|
||||
wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n",
|
||||
request->alpha2[0], request->alpha2[1]);
|
||||
|
||||
memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2));
|
||||
memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2));
|
||||
|
||||
switch (request->initiator) {
|
||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
|
@ -361,33 +387,10 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
|
|||
if (mwifiex_bss_set_channel(priv, &cfp))
|
||||
return -EFAULT;
|
||||
|
||||
return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
|
||||
}
|
||||
|
||||
/*
|
||||
* CFG802.11 operation handler to set channel.
|
||||
*
|
||||
* This function can only be used when station is not connected.
|
||||
*/
|
||||
static int
|
||||
mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct mwifiex_private *priv;
|
||||
|
||||
if (dev)
|
||||
priv = mwifiex_netdev_get_priv(dev);
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
|
||||
return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
|
||||
else
|
||||
priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
|
||||
if (priv->media_connected) {
|
||||
wiphy_err(wiphy, "This setting is valid only when station "
|
||||
"is not connected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mwifiex_set_rf_channel(priv, chan, channel_type);
|
||||
return mwifiex_uap_set_channel(priv, cfp.channel);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -399,18 +402,13 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
|||
static int
|
||||
mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
|
||||
frag_thr > MWIFIEX_FRAG_MAX_VALUE)
|
||||
return -EINVAL;
|
||||
frag_thr = MWIFIEX_FRAG_MAX_VALUE;
|
||||
|
||||
/* Send request to firmware */
|
||||
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
|
||||
HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
|
||||
&frag_thr);
|
||||
|
||||
return ret;
|
||||
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
|
||||
HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
|
||||
&frag_thr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -439,19 +437,85 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
|
|||
static int
|
||||
mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
int ret = 0;
|
||||
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
|
||||
struct mwifiex_private *priv;
|
||||
struct mwifiex_uap_bss_param *bss_cfg;
|
||||
int ret, bss_started, i;
|
||||
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
|
||||
ret = mwifiex_set_rts(priv, wiphy->rts_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
priv = adapter->priv[i];
|
||||
|
||||
switch (priv->bss_role) {
|
||||
case MWIFIEX_BSS_ROLE_UAP:
|
||||
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param),
|
||||
GFP_KERNEL);
|
||||
if (!bss_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
mwifiex_set_sys_config_invalid_data(bss_cfg);
|
||||
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
|
||||
bss_cfg->rts_threshold = wiphy->rts_threshold;
|
||||
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
|
||||
bss_cfg->frag_threshold = wiphy->frag_threshold;
|
||||
if (changed & WIPHY_PARAM_RETRY_LONG)
|
||||
bss_cfg->retry_limit = wiphy->retry_long;
|
||||
|
||||
bss_started = priv->bss_started;
|
||||
|
||||
ret = mwifiex_send_cmd_sync(priv,
|
||||
HostCmd_CMD_UAP_BSS_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
NULL);
|
||||
if (ret) {
|
||||
wiphy_err(wiphy, "Failed to stop the BSS\n");
|
||||
kfree(bss_cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_UAP_SYS_CONFIG,
|
||||
HostCmd_ACT_GEN_SET,
|
||||
UAP_BSS_PARAMS_I, bss_cfg);
|
||||
|
||||
kfree(bss_cfg);
|
||||
|
||||
if (ret) {
|
||||
wiphy_err(wiphy, "Failed to set bss config\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!bss_started)
|
||||
break;
|
||||
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_UAP_BSS_START,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
NULL);
|
||||
if (ret) {
|
||||
wiphy_err(wiphy, "Failed to start BSS\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
case MWIFIEX_BSS_ROLE_STA:
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
|
||||
ret = mwifiex_set_rts(priv,
|
||||
wiphy->rts_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
|
||||
ret = mwifiex_set_frag(priv,
|
||||
wiphy->frag_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
|
||||
ret = mwifiex_set_frag(priv, wiphy->frag_threshold);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -466,31 +530,59 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
|
|||
int ret;
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
if (priv->bss_mode == type) {
|
||||
wiphy_warn(wiphy, "already set to required type\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->bss_mode = type;
|
||||
|
||||
switch (type) {
|
||||
switch (dev->ieee80211_ptr->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC;
|
||||
wiphy_dbg(wiphy, "info: setting interface type to adhoc\n");
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name);
|
||||
case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */
|
||||
return 0;
|
||||
case NL80211_IFTYPE_AP:
|
||||
default:
|
||||
wiphy_err(wiphy, "%s: changing to %d not supported\n",
|
||||
dev->name, type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
|
||||
wiphy_dbg(wiphy, "info: setting interface type to managed\n");
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
|
||||
case NL80211_IFTYPE_STATION: /* This shouldn't happen */
|
||||
return 0;
|
||||
case NL80211_IFTYPE_AP:
|
||||
default:
|
||||
wiphy_err(wiphy, "%s: changing to %d not supported\n",
|
||||
dev->name, type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name);
|
||||
case NL80211_IFTYPE_AP: /* This shouldn't happen */
|
||||
return 0;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
default:
|
||||
wiphy_err(wiphy, "%s: changing to %d not supported\n",
|
||||
dev->name, type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
|
||||
wiphy_dbg(wiphy, "info: setting interface type to auto\n");
|
||||
return 0;
|
||||
default:
|
||||
wiphy_err(wiphy, "unknown interface type: %d\n", type);
|
||||
return -EINVAL;
|
||||
wiphy_err(wiphy, "%s: unknown iftype: %d\n",
|
||||
dev->name, dev->ieee80211_ptr->iftype);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
dev->ieee80211_ptr->iftype = type;
|
||||
priv->bss_mode = type;
|
||||
mwifiex_deauthenticate(priv, NULL);
|
||||
|
||||
priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
||||
|
@ -804,6 +896,90 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* cfg80211 operation handler for stop ap.
|
||||
* Function stops BSS running at uAP interface.
|
||||
*/
|
||||
static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
if (mwifiex_del_mgmt_ies(priv))
|
||||
wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
|
||||
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cfg80211 operation handler for start_ap.
|
||||
* Function sets beacon period, DTIM period, SSID and security into
|
||||
* AP config structure.
|
||||
* AP is configured with these settings and BSS is started.
|
||||
*/
|
||||
static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
struct mwifiex_uap_bss_param *bss_cfg;
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
|
||||
return -1;
|
||||
if (mwifiex_set_mgmt_ies(priv, params))
|
||||
return -1;
|
||||
|
||||
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
|
||||
if (!bss_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
mwifiex_set_sys_config_invalid_data(bss_cfg);
|
||||
|
||||
if (params->beacon_interval)
|
||||
bss_cfg->beacon_period = params->beacon_interval;
|
||||
if (params->dtim_period)
|
||||
bss_cfg->dtim_period = params->dtim_period;
|
||||
|
||||
if (params->ssid && params->ssid_len) {
|
||||
memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
|
||||
bss_cfg->ssid.ssid_len = params->ssid_len;
|
||||
}
|
||||
|
||||
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
|
||||
kfree(bss_cfg);
|
||||
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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");
|
||||
kfree(bss_cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
|
||||
HostCmd_ACT_GEN_SET,
|
||||
UAP_BSS_PARAMS_I, bss_cfg)) {
|
||||
wiphy_err(wiphy, "Failed to set the SSID\n");
|
||||
kfree(bss_cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kfree(bss_cfg);
|
||||
|
||||
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL)) {
|
||||
wiphy_err(wiphy, "Failed to start the BSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CFG802.11 operation handler for disconnection request.
|
||||
*
|
||||
|
@ -923,7 +1099,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, 1);
|
||||
ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1);
|
||||
|
||||
if (mode == NL80211_IFTYPE_ADHOC) {
|
||||
/* "privacy" is set only for ad-hoc mode */
|
||||
|
@ -971,7 +1147,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
|||
" 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, 0);
|
||||
sme->key_idx, NULL, 0);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
@ -1050,6 +1226,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (priv->bss_mode == NL80211_IFTYPE_AP) {
|
||||
wiphy_err(wiphy, "skip association request for AP interface\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
|
||||
(char *) sme->ssid, sme->bssid);
|
||||
|
||||
|
@ -1283,15 +1464,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
u32 *flags,
|
||||
struct vif_params *params)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
|
||||
struct mwifiex_private *priv;
|
||||
struct net_device *dev;
|
||||
void *mdev_priv;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
if (!priv)
|
||||
return NULL;
|
||||
|
||||
adapter = priv->adapter;
|
||||
if (!adapter)
|
||||
return NULL;
|
||||
|
||||
|
@ -1299,12 +1477,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
|
||||
if (priv->bss_mode) {
|
||||
wiphy_err(wiphy, "cannot create multiple"
|
||||
" station/adhoc interfaces\n");
|
||||
wiphy_err(wiphy,
|
||||
"cannot create multiple sta/adhoc ifaces\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
|
||||
if (!wdev)
|
||||
return NULL;
|
||||
|
||||
wdev->wiphy = wiphy;
|
||||
priv->wdev = wdev;
|
||||
wdev->iftype = NL80211_IFTYPE_STATION;
|
||||
|
||||
if (type == NL80211_IFTYPE_UNSPECIFIED)
|
||||
priv->bss_mode = NL80211_IFTYPE_STATION;
|
||||
else
|
||||
|
@ -1312,10 +1499,35 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
|
||||
priv->bss_type = MWIFIEX_BSS_TYPE_STA;
|
||||
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
|
||||
priv->bss_priority = 0;
|
||||
priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
|
||||
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
|
||||
priv->bss_num = 0;
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP];
|
||||
|
||||
if (priv->bss_mode) {
|
||||
wiphy_err(wiphy, "Can't create multiple AP interfaces");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
|
||||
if (!wdev)
|
||||
return NULL;
|
||||
|
||||
priv->wdev = wdev;
|
||||
wdev->wiphy = wiphy;
|
||||
wdev->iftype = NL80211_IFTYPE_AP;
|
||||
|
||||
priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
|
||||
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
|
||||
priv->bss_priority = MWIFIEX_BSS_ROLE_UAP;
|
||||
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
|
||||
priv->bss_started = 0;
|
||||
priv->bss_num = 0;
|
||||
priv->bss_mode = type;
|
||||
|
||||
break;
|
||||
default:
|
||||
wiphy_err(wiphy, "type not supported\n");
|
||||
|
@ -1329,6 +1541,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
goto error;
|
||||
}
|
||||
|
||||
mwifiex_init_priv_params(priv, dev);
|
||||
priv->netdev = dev;
|
||||
|
||||
mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
|
||||
|
||||
if (adapter->config_bands & BAND_A)
|
||||
mwifiex_setup_ht_caps(
|
||||
&wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
|
||||
|
||||
dev_net_set(dev, wiphy_net(wiphy));
|
||||
dev->ieee80211_ptr = priv->wdev;
|
||||
dev->ieee80211_ptr->iftype = priv->bss_mode;
|
||||
|
@ -1343,9 +1564,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
mdev_priv = netdev_priv(dev);
|
||||
*((unsigned long *) mdev_priv) = (unsigned long) priv;
|
||||
|
||||
priv->netdev = dev;
|
||||
mwifiex_init_priv_params(priv, dev);
|
||||
|
||||
SET_NETDEV_DEV(dev, adapter->dev);
|
||||
|
||||
/* Register network device */
|
||||
|
@ -1417,7 +1635,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|||
.get_station = mwifiex_cfg80211_get_station,
|
||||
.dump_station = mwifiex_cfg80211_dump_station,
|
||||
.set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
|
||||
.set_channel = mwifiex_cfg80211_set_channel,
|
||||
.join_ibss = mwifiex_cfg80211_join_ibss,
|
||||
.leave_ibss = mwifiex_cfg80211_leave_ibss,
|
||||
.add_key = mwifiex_cfg80211_add_key,
|
||||
|
@ -1426,6 +1643,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|||
.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
|
||||
.set_tx_power = mwifiex_cfg80211_set_tx_power,
|
||||
.set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
|
||||
.start_ap = mwifiex_cfg80211_start_ap,
|
||||
.stop_ap = mwifiex_cfg80211_stop_ap,
|
||||
.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
|
||||
};
|
||||
|
||||
|
@ -1436,82 +1655,67 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|||
* default parameters and handler function pointers, and finally
|
||||
* registers the device.
|
||||
*/
|
||||
int mwifiex_register_cfg80211(struct mwifiex_private *priv)
|
||||
|
||||
int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
int ret;
|
||||
void *wdev_priv;
|
||||
struct wireless_dev *wdev;
|
||||
struct ieee80211_sta_ht_cap *ht_info;
|
||||
struct wiphy *wiphy;
|
||||
struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
|
||||
u8 *country_code;
|
||||
|
||||
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
|
||||
if (!wdev) {
|
||||
dev_err(priv->adapter->dev, "%s: allocating wireless device\n",
|
||||
__func__);
|
||||
/* create a new wiphy for use with cfg80211 */
|
||||
wiphy = wiphy_new(&mwifiex_cfg80211_ops,
|
||||
sizeof(struct mwifiex_adapter *));
|
||||
if (!wiphy) {
|
||||
dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
wdev->wiphy =
|
||||
wiphy_new(&mwifiex_cfg80211_ops,
|
||||
sizeof(struct mwifiex_private *));
|
||||
if (!wdev->wiphy) {
|
||||
kfree(wdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
wdev->iftype = NL80211_IFTYPE_STATION;
|
||||
wdev->wiphy->max_scan_ssids = 10;
|
||||
wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
|
||||
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
|
||||
wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
|
||||
ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap;
|
||||
mwifiex_setup_ht_caps(ht_info, priv);
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
|
||||
if (adapter->config_bands & BAND_A)
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
|
||||
else
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
|
||||
|
||||
if (priv->adapter->config_bands & BAND_A) {
|
||||
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
|
||||
ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap;
|
||||
mwifiex_setup_ht_caps(ht_info, priv);
|
||||
} else {
|
||||
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
|
||||
}
|
||||
wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
|
||||
wiphy->n_iface_combinations = 1;
|
||||
|
||||
/* Initialize cipher suits */
|
||||
wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
|
||||
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
|
||||
wiphy->cipher_suites = mwifiex_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
|
||||
|
||||
memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
|
||||
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY;
|
||||
|
||||
/* Reserve space for mwifiex specific private data for BSS */
|
||||
wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
|
||||
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
|
||||
|
||||
wdev->wiphy->reg_notifier = mwifiex_reg_notifier;
|
||||
wiphy->reg_notifier = mwifiex_reg_notifier;
|
||||
|
||||
/* Set struct mwifiex_private pointer in wiphy_priv */
|
||||
wdev_priv = wiphy_priv(wdev->wiphy);
|
||||
/* Set struct mwifiex_adapter pointer in wiphy_priv */
|
||||
wdev_priv = wiphy_priv(wiphy);
|
||||
*(unsigned long *)wdev_priv = (unsigned long)adapter;
|
||||
|
||||
*(unsigned long *) wdev_priv = (unsigned long) priv;
|
||||
set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev);
|
||||
|
||||
set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev);
|
||||
|
||||
ret = wiphy_register(wdev->wiphy);
|
||||
ret = wiphy_register(wiphy);
|
||||
if (ret < 0) {
|
||||
dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
|
||||
__func__);
|
||||
wiphy_free(wdev->wiphy);
|
||||
kfree(wdev);
|
||||
dev_err(adapter->dev,
|
||||
"%s: wiphy_register failed: %d\n", __func__, ret);
|
||||
wiphy_free(wiphy);
|
||||
return ret;
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: successfully registered wiphy device\n");
|
||||
}
|
||||
|
||||
country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
|
||||
if (country_code && regulatory_hint(wdev->wiphy, country_code))
|
||||
dev_err(priv->adapter->dev,
|
||||
"%s: regulatory_hint failed\n", __func__);
|
||||
|
||||
priv->wdev = wdev;
|
||||
if (country_code && regulatory_hint(wiphy, country_code))
|
||||
dev_err(adapter->dev, "regulatory_hint() failed\n");
|
||||
|
||||
adapter->wiphy = wiphy;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,6 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
int mwifiex_register_cfg80211(struct mwifiex_private *);
|
||||
int mwifiex_register_cfg80211(struct mwifiex_adapter *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -440,6 +440,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
|
|||
do_gettimeofday(&tstamp);
|
||||
dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n",
|
||||
tstamp.tv_sec, tstamp.tv_usec, eventcause);
|
||||
} else {
|
||||
/* Handle PS_SLEEP/AWAKE events on STA */
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
|
||||
if (!priv)
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
}
|
||||
|
||||
ret = mwifiex_process_sta_event(priv);
|
||||
|
@ -540,8 +545,20 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
|
|||
|
||||
/* Prepare command */
|
||||
if (cmd_no) {
|
||||
ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action,
|
||||
cmd_oid, data_buf, cmd_ptr);
|
||||
switch (cmd_no) {
|
||||
case HostCmd_CMD_UAP_SYS_CONFIG:
|
||||
case HostCmd_CMD_UAP_BSS_START:
|
||||
case HostCmd_CMD_UAP_BSS_STOP:
|
||||
ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
|
||||
cmd_oid, data_buf,
|
||||
cmd_ptr);
|
||||
break;
|
||||
default:
|
||||
ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action,
|
||||
cmd_oid, data_buf,
|
||||
cmd_ptr);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf);
|
||||
cmd_node->cmd_flag |= CMD_F_HOSTCMD;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/ieee80211.h>
|
||||
|
||||
|
||||
#define MWIFIEX_MAX_BSS_NUM (1)
|
||||
#define MWIFIEX_MAX_BSS_NUM (2)
|
||||
|
||||
#define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd)
|
||||
* + 4 byte alignment
|
||||
|
@ -55,11 +55,17 @@
|
|||
#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024)
|
||||
#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024)
|
||||
|
||||
#define MAX_BEACON_PERIOD (4000)
|
||||
#define MIN_BEACON_PERIOD (50)
|
||||
#define MAX_DTIM_PERIOD (100)
|
||||
#define MIN_DTIM_PERIOD (1)
|
||||
|
||||
#define MWIFIEX_RTS_MIN_VALUE (0)
|
||||
#define MWIFIEX_RTS_MAX_VALUE (2347)
|
||||
#define MWIFIEX_FRAG_MIN_VALUE (256)
|
||||
#define MWIFIEX_FRAG_MAX_VALUE (2346)
|
||||
|
||||
#define MWIFIEX_RETRY_LIMIT 14
|
||||
#define MWIFIEX_SDIO_BLOCK_SIZE 256
|
||||
|
||||
#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0)
|
||||
|
@ -92,6 +98,11 @@ struct mwifiex_fw_image {
|
|||
u32 fw_len;
|
||||
};
|
||||
|
||||
struct mwifiex_802_11_ssid {
|
||||
u32 ssid_len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
};
|
||||
|
||||
struct mwifiex_wait_queue {
|
||||
wait_queue_head_t wait;
|
||||
int status;
|
||||
|
|
|
@ -93,6 +93,20 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
|
||||
#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF)))
|
||||
|
||||
#define UAP_BSS_PARAMS_I 0
|
||||
#define UAP_CUSTOM_IE_I 1
|
||||
#define MWIFIEX_AUTO_IDX_MASK 0xffff
|
||||
#define MWIFIEX_DELETE_MASK 0x0000
|
||||
#define MGMT_MASK_ASSOC_REQ 0x01
|
||||
#define MGMT_MASK_REASSOC_REQ 0x04
|
||||
#define MGMT_MASK_ASSOC_RESP 0x02
|
||||
#define MGMT_MASK_REASSOC_RESP 0x08
|
||||
#define MGMT_MASK_PROBE_REQ 0x10
|
||||
#define MGMT_MASK_PROBE_RESP 0x20
|
||||
#define MGMT_MASK_BEACON 0x100
|
||||
|
||||
#define TLV_TYPE_UAP_SSID 0x0000
|
||||
|
||||
#define PROPRIETARY_TLV_BASE_ID 0x0100
|
||||
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
|
||||
#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1)
|
||||
|
@ -104,14 +118,26 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
|
||||
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
|
||||
#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31)
|
||||
#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32)
|
||||
#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42)
|
||||
#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44)
|
||||
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
|
||||
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
|
||||
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
|
||||
#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
|
||||
#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65)
|
||||
#define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70)
|
||||
#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82)
|
||||
#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83)
|
||||
#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84)
|
||||
#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93)
|
||||
#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94)
|
||||
#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104)
|
||||
#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105)
|
||||
#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113)
|
||||
#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114)
|
||||
#define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145)
|
||||
#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146)
|
||||
|
||||
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
|
||||
|
||||
|
@ -209,6 +235,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define HostCmd_CMD_RSSI_INFO 0x00a4
|
||||
#define HostCmd_CMD_FUNC_INIT 0x00a9
|
||||
#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
|
||||
#define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0
|
||||
#define HostCmd_CMD_UAP_BSS_START 0x00b1
|
||||
#define HostCmd_CMD_UAP_BSS_STOP 0x00b2
|
||||
#define HostCmd_CMD_11N_CFG 0x00cd
|
||||
#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce
|
||||
#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf
|
||||
|
@ -223,6 +252,19 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define HostCmd_CMD_SET_BSS_MODE 0x00f7
|
||||
#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
|
||||
|
||||
#define PROTOCOL_NO_SECURITY 0x01
|
||||
#define PROTOCOL_STATIC_WEP 0x02
|
||||
#define PROTOCOL_WPA 0x08
|
||||
#define PROTOCOL_WPA2 0x20
|
||||
#define PROTOCOL_WPA2_MIXED 0x28
|
||||
#define PROTOCOL_EAP 0x40
|
||||
#define KEY_MGMT_NONE 0x04
|
||||
#define KEY_MGMT_PSK 0x02
|
||||
#define KEY_MGMT_EAP 0x01
|
||||
#define CIPHER_TKIP 0x04
|
||||
#define CIPHER_AES_CCMP 0x08
|
||||
#define VALID_CIPHER_BITMAP 0x0c
|
||||
|
||||
enum ENH_PS_MODES {
|
||||
EN_PS = 1,
|
||||
DIS_PS = 2,
|
||||
|
@ -313,15 +355,20 @@ enum ENH_PS_MODES {
|
|||
#define EVENT_DATA_SNR_HIGH 0x00000027
|
||||
#define EVENT_LINK_QUALITY 0x00000028
|
||||
#define EVENT_PORT_RELEASE 0x0000002b
|
||||
#define EVENT_UAP_STA_DEAUTH 0x0000002c
|
||||
#define EVENT_UAP_STA_ASSOC 0x0000002d
|
||||
#define EVENT_UAP_BSS_START 0x0000002e
|
||||
#define EVENT_PRE_BEACON_LOST 0x00000031
|
||||
#define EVENT_ADDBA 0x00000033
|
||||
#define EVENT_DELBA 0x00000034
|
||||
#define EVENT_BA_STREAM_TIEMOUT 0x00000037
|
||||
#define EVENT_AMSDU_AGGR_CTRL 0x00000042
|
||||
#define EVENT_UAP_BSS_IDLE 0x00000043
|
||||
#define EVENT_UAP_BSS_ACTIVE 0x00000044
|
||||
#define EVENT_WEP_ICV_ERR 0x00000046
|
||||
#define EVENT_HS_ACT_REQ 0x00000047
|
||||
#define EVENT_BW_CHANGE 0x00000048
|
||||
|
||||
#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c
|
||||
#define EVENT_HOSTWAKE_STAIE 0x0000004d
|
||||
|
||||
#define EVENT_ID_MASK 0xffff
|
||||
|
@ -1103,6 +1150,101 @@ struct host_cmd_ds_802_11_eeprom_access {
|
|||
u8 value;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_assoc_event {
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
__le16 frame_control;
|
||||
__le16 cap_info;
|
||||
__le16 listen_interval;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_sys_config {
|
||||
__le16 action;
|
||||
u8 tlv[0];
|
||||
};
|
||||
|
||||
struct host_cmd_tlv_akmp {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 key_mgmt;
|
||||
__le16 key_mgmt_operation;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_pwk_cipher {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 proto;
|
||||
u8 cipher;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_gwk_cipher {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 cipher;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_passphrase {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 passphrase[0];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_auth_type {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 auth_type;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_encrypt_protocol {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 proto;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_ssid {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 ssid[0];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_beacon_period {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 period;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_dtim_period {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 period;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_frag_threshold {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 frag_thr;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_rts_threshold {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 rts_thr;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_retry_limit {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 limit;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_mac_addr {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_channel_band {
|
||||
struct host_cmd_tlv tlv;
|
||||
u8 band_config;
|
||||
u8 channel;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_802_11_rf_channel {
|
||||
__le16 action;
|
||||
__le16 current_channel;
|
||||
|
@ -1167,6 +1309,20 @@ struct host_cmd_ds_802_11_subsc_evt {
|
|||
__le16 events;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie {
|
||||
__le16 ie_index;
|
||||
__le16 mgmt_subtype_mask;
|
||||
__le16 ie_length;
|
||||
u8 ie_buffer[IEEE_MAX_IE_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define MAX_MGMT_IE_INDEX 16
|
||||
struct mwifiex_ie_list {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_command {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
|
@ -1217,6 +1373,7 @@ struct host_cmd_ds_command {
|
|||
struct host_cmd_ds_pcie_details pcie_host_spec;
|
||||
struct host_cmd_ds_802_11_eeprom_access eeprom;
|
||||
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
|
||||
struct host_cmd_ds_sys_config uap_sys_config;
|
||||
} params;
|
||||
} __packed;
|
||||
|
||||
|
|
396
drivers/net/wireless/mwifiex/ie.c
Normal file
396
drivers/net/wireless/mwifiex/ie.c
Normal file
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* Marvell Wireless LAN device driver: management IE handling- setting and
|
||||
* deleting IE.
|
||||
*
|
||||
* 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 "main.h"
|
||||
|
||||
/* This function checks if current IE index is used by any on other interface.
|
||||
* Return: -1: yes, current IE index is used by someone else.
|
||||
* 0: no, current IE index is NOT used by other interface.
|
||||
*/
|
||||
static int
|
||||
mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
|
||||
{
|
||||
int i;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_ie *ie;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
if (adapter->priv[i] != priv) {
|
||||
ie = &adapter->priv[i]->mgmt_ie[idx];
|
||||
if (ie->mgmt_subtype_mask && ie->ie_length)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get unused IE index. This index will be used for setting new IE */
|
||||
static int
|
||||
mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
|
||||
struct mwifiex_ie *ie, u16 *index)
|
||||
{
|
||||
u16 mask, len, i;
|
||||
|
||||
for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
|
||||
mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
|
||||
len = le16_to_cpu(priv->mgmt_ie[i].ie_length) +
|
||||
le16_to_cpu(ie->ie_length);
|
||||
|
||||
if (mask == MWIFIEX_AUTO_IDX_MASK)
|
||||
continue;
|
||||
|
||||
if (mask == subtype_mask) {
|
||||
if (len > IEEE_MAX_IE_SIZE)
|
||||
continue;
|
||||
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!priv->mgmt_ie[i].ie_length) {
|
||||
if (mwifiex_ie_index_used_by_other_intf(priv, i))
|
||||
continue;
|
||||
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This function prepares IE data buffer for command to be sent to FW */
|
||||
static int
|
||||
mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
|
||||
struct mwifiex_ie_list *ie_list)
|
||||
{
|
||||
u16 travel_len, index, mask;
|
||||
s16 input_len;
|
||||
struct mwifiex_ie *ie;
|
||||
u8 *tmp;
|
||||
|
||||
input_len = le16_to_cpu(ie_list->len);
|
||||
travel_len = sizeof(struct host_cmd_tlv);
|
||||
|
||||
ie_list->len = 0;
|
||||
|
||||
while (input_len > 0) {
|
||||
ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len);
|
||||
input_len -= le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
|
||||
travel_len += le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
|
||||
|
||||
index = le16_to_cpu(ie->ie_index);
|
||||
mask = le16_to_cpu(ie->mgmt_subtype_mask);
|
||||
|
||||
if (index == MWIFIEX_AUTO_IDX_MASK) {
|
||||
/* automatic addition */
|
||||
if (mwifiex_ie_get_autoidx(priv, mask, ie, &index))
|
||||
return -1;
|
||||
if (index == MWIFIEX_AUTO_IDX_MASK)
|
||||
return -1;
|
||||
|
||||
tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
|
||||
tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length);
|
||||
memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
|
||||
le16_add_cpu(&priv->mgmt_ie[index].ie_length,
|
||||
le16_to_cpu(ie->ie_length));
|
||||
priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
|
||||
priv->mgmt_ie[index].mgmt_subtype_mask =
|
||||
cpu_to_le16(mask);
|
||||
|
||||
ie->ie_index = cpu_to_le16(index);
|
||||
ie->ie_length = priv->mgmt_ie[index].ie_length;
|
||||
memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer,
|
||||
le16_to_cpu(priv->mgmt_ie[index].ie_length));
|
||||
} else {
|
||||
if (mask != MWIFIEX_DELETE_MASK)
|
||||
return -1;
|
||||
/*
|
||||
* Check if this index is being used on any
|
||||
* other interface.
|
||||
*/
|
||||
if (mwifiex_ie_index_used_by_other_intf(priv, index))
|
||||
return -1;
|
||||
|
||||
ie->ie_length = 0;
|
||||
memcpy(&priv->mgmt_ie[index], ie,
|
||||
sizeof(struct mwifiex_ie));
|
||||
}
|
||||
|
||||
le16_add_cpu(&ie_list->len,
|
||||
le16_to_cpu(priv->mgmt_ie[index].ie_length) +
|
||||
MWIFIEX_IE_HDR_SIZE);
|
||||
}
|
||||
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
|
||||
return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
|
||||
HostCmd_ACT_GEN_SET,
|
||||
UAP_CUSTOM_IE_I, ie_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy individual custom IEs for beacon, probe response and assoc response
|
||||
* and prepare single structure for IE setting.
|
||||
* This function also updates allocated IE indices from driver.
|
||||
*/
|
||||
static int
|
||||
mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
|
||||
struct mwifiex_ie *beacon_ie, u16 *beacon_idx,
|
||||
struct mwifiex_ie *pr_ie, u16 *probe_idx,
|
||||
struct mwifiex_ie *ar_ie, u16 *assoc_idx)
|
||||
{
|
||||
struct mwifiex_ie_list *ap_custom_ie;
|
||||
u8 *pos;
|
||||
u16 len;
|
||||
int ret;
|
||||
|
||||
ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!ap_custom_ie)
|
||||
return -ENOMEM;
|
||||
|
||||
ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
|
||||
pos = (u8 *)ap_custom_ie->ie_list;
|
||||
|
||||
if (beacon_ie) {
|
||||
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
|
||||
le16_to_cpu(beacon_ie->ie_length);
|
||||
memcpy(pos, beacon_ie, len);
|
||||
pos += len;
|
||||
le16_add_cpu(&ap_custom_ie->len, len);
|
||||
}
|
||||
if (pr_ie) {
|
||||
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
|
||||
le16_to_cpu(pr_ie->ie_length);
|
||||
memcpy(pos, pr_ie, len);
|
||||
pos += len;
|
||||
le16_add_cpu(&ap_custom_ie->len, len);
|
||||
}
|
||||
if (ar_ie) {
|
||||
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
|
||||
le16_to_cpu(ar_ie->ie_length);
|
||||
memcpy(pos, ar_ie, len);
|
||||
pos += len;
|
||||
le16_add_cpu(&ap_custom_ie->len, len);
|
||||
}
|
||||
|
||||
ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie);
|
||||
|
||||
pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index);
|
||||
if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) {
|
||||
/* save beacon ie index after auto-indexing */
|
||||
*beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index);
|
||||
len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE +
|
||||
le16_to_cpu(beacon_ie->ie_length);
|
||||
pos += len;
|
||||
}
|
||||
if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) {
|
||||
/* save probe resp ie index after auto-indexing */
|
||||
*probe_idx = *((u16 *)pos);
|
||||
len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE +
|
||||
le16_to_cpu(pr_ie->ie_length);
|
||||
pos += len;
|
||||
}
|
||||
if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK)
|
||||
/* save assoc resp ie index after auto-indexing */
|
||||
*assoc_idx = *((u16 *)pos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs,
|
||||
* association response IEs from cfg80211_ap_settings function and sets these IE
|
||||
* to FW.
|
||||
*/
|
||||
int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
|
||||
struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
|
||||
struct ieee_types_header *ie = NULL;
|
||||
u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
u16 mask;
|
||||
int ret = 0;
|
||||
|
||||
if (params->beacon.tail && params->beacon.tail_len) {
|
||||
ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail,
|
||||
params->beacon.tail_len);
|
||||
if (ie) {
|
||||
rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!rsn_ie)
|
||||
return -ENOMEM;
|
||||
|
||||
rsn_ie->ie_index = cpu_to_le16(rsn_idx);
|
||||
mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP |
|
||||
MGMT_MASK_ASSOC_RESP;
|
||||
rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask);
|
||||
rsn_ie->ie_length = cpu_to_le16(ie->len + 2);
|
||||
memcpy(rsn_ie->ie_buffer, ie, ie->len + 2);
|
||||
|
||||
if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx,
|
||||
NULL, NULL,
|
||||
NULL, NULL)) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->rsn_idx = rsn_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
|
||||
beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!beacon_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
beacon_ie->ie_index = cpu_to_le16(beacon_idx);
|
||||
beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON);
|
||||
beacon_ie->ie_length =
|
||||
cpu_to_le16(params->beacon.beacon_ies_len);
|
||||
memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies,
|
||||
params->beacon.beacon_ies_len);
|
||||
}
|
||||
|
||||
if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) {
|
||||
pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!pr_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pr_ie->ie_index = cpu_to_le16(pr_idx);
|
||||
pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP);
|
||||
pr_ie->ie_length =
|
||||
cpu_to_le16(params->beacon.proberesp_ies_len);
|
||||
memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies,
|
||||
params->beacon.proberesp_ies_len);
|
||||
}
|
||||
|
||||
if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) {
|
||||
ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!ar_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ar_ie->ie_index = cpu_to_le16(ar_idx);
|
||||
mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP;
|
||||
ar_ie->mgmt_subtype_mask = cpu_to_le16(mask);
|
||||
ar_ie->ie_length =
|
||||
cpu_to_le16(params->beacon.assocresp_ies_len);
|
||||
memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies,
|
||||
params->beacon.assocresp_ies_len);
|
||||
}
|
||||
|
||||
if (beacon_ie || pr_ie || ar_ie) {
|
||||
ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
|
||||
&beacon_idx, pr_ie,
|
||||
&pr_idx, ar_ie, &ar_idx);
|
||||
if (ret)
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->beacon_idx = beacon_idx;
|
||||
priv->proberesp_idx = pr_idx;
|
||||
priv->assocresp_idx = ar_idx;
|
||||
|
||||
done:
|
||||
kfree(beacon_ie);
|
||||
kfree(pr_ie);
|
||||
kfree(ar_ie);
|
||||
kfree(rsn_ie);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function removes management IE set */
|
||||
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
|
||||
struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) {
|
||||
rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!rsn_ie)
|
||||
return -ENOMEM;
|
||||
|
||||
rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx);
|
||||
rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
|
||||
rsn_ie->ie_length = 0;
|
||||
if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx,
|
||||
NULL, &priv->proberesp_idx,
|
||||
NULL, &priv->assocresp_idx)) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
}
|
||||
|
||||
if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) {
|
||||
beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!beacon_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx);
|
||||
beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
|
||||
beacon_ie->ie_length = 0;
|
||||
}
|
||||
if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) {
|
||||
pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!pr_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx);
|
||||
pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
|
||||
pr_ie->ie_length = 0;
|
||||
}
|
||||
if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) {
|
||||
ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
|
||||
if (!ar_ie) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx);
|
||||
ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
|
||||
ar_ie->ie_length = 0;
|
||||
}
|
||||
|
||||
if (beacon_ie || pr_ie || ar_ie)
|
||||
ret = mwifiex_update_uap_custom_ie(priv,
|
||||
beacon_ie, &priv->beacon_idx,
|
||||
pr_ie, &priv->proberesp_idx,
|
||||
ar_ie, &priv->assocresp_idx);
|
||||
|
||||
done:
|
||||
kfree(beacon_ie);
|
||||
kfree(pr_ie);
|
||||
kfree(ar_ie);
|
||||
kfree(rsn_ie);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -279,6 +279,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->channel_type = NL80211_CHAN_HT20;
|
||||
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -62,6 +62,36 @@ enum {
|
|||
BAND_AN = 16,
|
||||
};
|
||||
|
||||
#define MWIFIEX_WPA_PASSHPHRASE_LEN 64
|
||||
struct wpa_param {
|
||||
u8 pairwise_cipher_wpa;
|
||||
u8 pairwise_cipher_wpa2;
|
||||
u8 group_cipher;
|
||||
u32 length;
|
||||
u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN];
|
||||
};
|
||||
|
||||
#define KEY_MGMT_ON_HOST 0x03
|
||||
#define MWIFIEX_AUTH_MODE_AUTO 0xFF
|
||||
#define BAND_CONFIG_MANUAL 0x00
|
||||
struct mwifiex_uap_bss_param {
|
||||
u8 channel;
|
||||
u8 band_cfg;
|
||||
u16 rts_threshold;
|
||||
u16 frag_threshold;
|
||||
u8 retry_limit;
|
||||
struct mwifiex_802_11_ssid ssid;
|
||||
u8 bcast_ssid_ctl;
|
||||
u8 radio_ctl;
|
||||
u8 dtim_period;
|
||||
u16 beacon_period;
|
||||
u16 auth_mode;
|
||||
u16 protocol;
|
||||
u16 key_mgmt;
|
||||
u16 key_mgmt_operation;
|
||||
struct wpa_param wpa_cfg;
|
||||
};
|
||||
|
||||
enum {
|
||||
ADHOC_IDLE,
|
||||
ADHOC_STARTED,
|
||||
|
@ -269,6 +299,8 @@ struct mwifiex_ds_read_eeprom {
|
|||
|
||||
#define IEEE_MAX_IE_SIZE 256
|
||||
|
||||
#define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
|
||||
|
||||
struct mwifiex_ds_misc_gen_ie {
|
||||
u32 type;
|
||||
u32 len;
|
||||
|
|
|
@ -1374,22 +1374,28 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
|
|||
*
|
||||
* In case of infra made, it sends deauthentication request, and
|
||||
* in case of ad-hoc mode, a stop network request is sent to the firmware.
|
||||
* In AP mode, a command to stop bss is sent to firmware.
|
||||
*/
|
||||
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!priv->media_connected)
|
||||
return 0;
|
||||
|
||||
if (priv->media_connected) {
|
||||
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
|
||||
ret = mwifiex_deauthenticate_infra(priv, mac);
|
||||
} else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
|
||||
ret = mwifiex_send_cmd_sync(priv,
|
||||
HostCmd_CMD_802_11_AD_HOC_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL);
|
||||
}
|
||||
switch (priv->bss_mode) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
return mwifiex_deauthenticate_infra(priv, mac);
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return mwifiex_send_cmd_sync(priv,
|
||||
HostCmd_CMD_802_11_AD_HOC_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL);
|
||||
case NL80211_IFTYPE_AP:
|
||||
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);
|
||||
|
||||
|
|
|
@ -64,17 +64,17 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
|
|||
|
||||
adapter->priv_num = 0;
|
||||
|
||||
/* Allocate memory for private structure */
|
||||
adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
|
||||
if (!adapter->priv[0]) {
|
||||
dev_err(adapter->dev,
|
||||
"%s: failed to alloc priv[0]\n", __func__);
|
||||
goto error;
|
||||
for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
|
||||
/* Allocate memory for private structure */
|
||||
adapter->priv[i] =
|
||||
kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
|
||||
if (!adapter->priv[i])
|
||||
goto error;
|
||||
|
||||
adapter->priv[i]->adapter = adapter;
|
||||
adapter->priv[i]->bss_priority = i;
|
||||
adapter->priv_num++;
|
||||
}
|
||||
|
||||
adapter->priv_num++;
|
||||
|
||||
adapter->priv[0]->adapter = adapter;
|
||||
mwifiex_init_lock_list(adapter);
|
||||
|
||||
init_timer(&adapter->cmd_timer);
|
||||
|
@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
|||
if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
|
||||
goto done;
|
||||
|
||||
priv = adapter->priv[0];
|
||||
if (mwifiex_register_cfg80211(priv) != 0) {
|
||||
priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
|
||||
if (mwifiex_register_cfg80211(adapter)) {
|
||||
dev_err(adapter->dev, "cannot register with cfg80211\n");
|
||||
goto err_init_fw;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
/* Create station interface by default */
|
||||
if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
|
||||
if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
|
||||
NL80211_IFTYPE_STATION, NULL, NULL)) {
|
||||
dev_err(adapter->dev, "cannot create default STA interface\n");
|
||||
goto err_add_intf;
|
||||
}
|
||||
|
||||
/* Create AP interface by default */
|
||||
if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
|
||||
NL80211_IFTYPE_AP, NULL, NULL)) {
|
||||
dev_err(adapter->dev, "cannot create default AP interface\n");
|
||||
goto err_add_intf;
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
|
||||
|
@ -369,7 +376,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
|||
goto done;
|
||||
|
||||
err_add_intf:
|
||||
mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
|
||||
mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
|
||||
rtnl_unlock();
|
||||
err_init_fw:
|
||||
pr_debug("info: %s: unregister device\n", __func__);
|
||||
|
@ -633,6 +640,12 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
|
|||
priv->current_key_index = 0;
|
||||
priv->media_connected = false;
|
||||
memset(&priv->nick_name, 0, sizeof(priv->nick_name));
|
||||
memset(priv->mgmt_ie, 0,
|
||||
sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
|
||||
priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
|
||||
priv->num_tx_timeout = 0;
|
||||
memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
|
||||
}
|
||||
|
@ -830,19 +843,21 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
|||
|
||||
rtnl_lock();
|
||||
if (priv->wdev && priv->netdev)
|
||||
mwifiex_del_virtual_intf(priv->wdev->wiphy,
|
||||
priv->netdev);
|
||||
mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
priv = adapter->priv[0];
|
||||
if (!priv)
|
||||
if (!priv || !priv->wdev)
|
||||
goto exit_remove;
|
||||
|
||||
if (priv->wdev) {
|
||||
wiphy_unregister(priv->wdev->wiphy);
|
||||
wiphy_free(priv->wdev->wiphy);
|
||||
kfree(priv->wdev);
|
||||
wiphy_unregister(priv->wdev->wiphy);
|
||||
wiphy_free(priv->wdev->wiphy);
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
priv = adapter->priv[i];
|
||||
if (priv)
|
||||
kfree(priv->wdev);
|
||||
}
|
||||
|
||||
mwifiex_terminate_workqueue(adapter);
|
||||
|
|
|
@ -116,6 +116,7 @@ enum {
|
|||
#define MAX_FREQUENCY_BAND_BG 2484
|
||||
|
||||
#define MWIFIEX_EVENT_HEADER_LEN 4
|
||||
#define MWIFIEX_UAP_EVENT_EXTRA_HEADER 2
|
||||
|
||||
#define MWIFIEX_TYPE_LEN 4
|
||||
#define MWIFIEX_USB_TYPE_CMD 0xF00DFACE
|
||||
|
@ -370,6 +371,7 @@ struct mwifiex_private {
|
|||
u8 bss_role;
|
||||
u8 bss_priority;
|
||||
u8 bss_num;
|
||||
u8 bss_started;
|
||||
u8 frame_type;
|
||||
u8 curr_addr[ETH_ALEN];
|
||||
u8 media_connected;
|
||||
|
@ -470,12 +472,16 @@ struct mwifiex_private {
|
|||
struct cfg80211_scan_request *scan_request;
|
||||
struct mwifiex_user_scan_cfg *user_scan_cfg;
|
||||
u8 cfg_bssid[6];
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
struct wps wps;
|
||||
u8 scan_block;
|
||||
s32 cqm_rssi_thold;
|
||||
u32 cqm_rssi_hyst;
|
||||
u8 subsc_evt_rssi_state;
|
||||
struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
|
||||
u16 beacon_idx;
|
||||
u16 proberesp_idx;
|
||||
u16 assocresp_idx;
|
||||
u16 rsn_idx;
|
||||
};
|
||||
|
||||
enum mwifiex_ba_status {
|
||||
|
@ -571,6 +577,7 @@ struct mwifiex_adapter {
|
|||
char fw_name[32];
|
||||
int winner;
|
||||
struct device *dev;
|
||||
struct wiphy *wiphy;
|
||||
bool surprise_removed;
|
||||
u32 fw_release_number;
|
||||
u16 init_wait_q_woken;
|
||||
|
@ -677,6 +684,8 @@ struct mwifiex_adapter {
|
|||
struct cmd_ctrl_node *cmd_queued;
|
||||
spinlock_t queue_lock; /* lock for tx queues */
|
||||
struct completion fw_load;
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
u16 max_mgmt_ie_index;
|
||||
};
|
||||
|
||||
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
|
||||
|
@ -760,6 +769,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
|||
int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
|
||||
u16 cmd_action, u32 cmd_oid,
|
||||
void *data_buf, void *cmd_buf);
|
||||
int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
|
||||
u16 cmd_action, u32 cmd_oid,
|
||||
void *data_buf, void *cmd_buf);
|
||||
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 *,
|
||||
|
@ -820,6 +832,9 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
|
|||
int is_command_pending(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_init_priv_params(struct mwifiex_private *priv,
|
||||
struct net_device *dev);
|
||||
int mwifiex_set_secure_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_config,
|
||||
struct cfg80211_ap_settings *params);
|
||||
|
||||
/*
|
||||
* This function checks if the queuing is RA based or not.
|
||||
|
@ -933,7 +948,8 @@ int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
|
|||
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
|
||||
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index, int disable);
|
||||
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);
|
||||
|
||||
|
@ -969,6 +985,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
|
|||
|
||||
int mwifiex_main_process(struct mwifiex_adapter *);
|
||||
|
||||
int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel);
|
||||
int mwifiex_bss_set_channel(struct mwifiex_private *,
|
||||
struct mwifiex_chan_freq_power *cfp);
|
||||
int mwifiex_get_bss_info(struct mwifiex_private *,
|
||||
|
@ -986,6 +1003,11 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
u32 *flags, struct vif_params *params);
|
||||
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
|
||||
|
||||
void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
|
||||
|
||||
int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
|
||||
struct cfg80211_ap_settings *params);
|
||||
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
|
||||
u8 *mwifiex_11d_code_2_region(u8 code);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
|
|
@ -498,7 +498,8 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
|||
{
|
||||
struct host_cmd_ds_802_11_key_material *key_material =
|
||||
&cmd->params.key_material;
|
||||
u16 key_param_len = 0;
|
||||
struct host_cmd_tlv_mac_addr *tlv_mac;
|
||||
u16 key_param_len = 0, cmd_size;
|
||||
int ret = 0;
|
||||
const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
|
@ -614,11 +615,26 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
|||
cpu_to_le16((u16) enc_key->key_len +
|
||||
KEYPARAMSET_FIXED_LEN);
|
||||
|
||||
key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN)
|
||||
key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
|
||||
+ sizeof(struct mwifiex_ie_types_header);
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
|
||||
+ key_param_len);
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
|
||||
tlv_mac = (void *)((u8 *)&key_material->key_param_set +
|
||||
key_param_len);
|
||||
tlv_mac->tlv.type = cpu_to_le16(TLV_TYPE_STA_MAC_ADDR);
|
||||
tlv_mac->tlv.len = cpu_to_le16(ETH_ALEN);
|
||||
memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN);
|
||||
cmd_size = key_param_len + S_DS_GEN +
|
||||
sizeof(key_material->action) +
|
||||
sizeof(struct host_cmd_tlv_mac_addr);
|
||||
} else {
|
||||
cmd_size = key_param_len + S_DS_GEN +
|
||||
sizeof(key_material->action);
|
||||
}
|
||||
cmd->size = cpu_to_le16(cmd_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1248,13 +1264,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
|||
if (ret)
|
||||
return -1;
|
||||
|
||||
/* Enable IEEE PS by default */
|
||||
priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_802_11_PS_MODE_ENH,
|
||||
EN_AUTO_PS, BITMAP_STA_PS, NULL);
|
||||
if (ret)
|
||||
return -1;
|
||||
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
|
||||
/* Enable IEEE PS by default */
|
||||
priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
|
||||
ret = mwifiex_send_cmd_async(
|
||||
priv, HostCmd_CMD_802_11_PS_MODE_ENH,
|
||||
EN_AUTO_PS, BITMAP_STA_PS, NULL);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get tx rate */
|
||||
|
@ -1270,12 +1288,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
|||
if (ret)
|
||||
return -1;
|
||||
|
||||
/* set ibss coalescing_status */
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
|
||||
HostCmd_ACT_GEN_SET, 0, &enable);
|
||||
if (ret)
|
||||
return -1;
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
|
||||
/* set ibss coalescing_status */
|
||||
ret = mwifiex_send_cmd_async(
|
||||
priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
|
||||
HostCmd_ACT_GEN_SET, 0, &enable);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
|
||||
amsdu_aggr_ctrl.enable = true;
|
||||
|
@ -1293,7 +1313,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
|||
if (ret)
|
||||
return -1;
|
||||
|
||||
if (first_sta && (priv->adapter->iface_type != MWIFIEX_USB)) {
|
||||
if (first_sta && priv->adapter->iface_type != MWIFIEX_USB &&
|
||||
priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
|
||||
/* Enable auto deep sleep */
|
||||
auto_ds.auto_ds = DEEP_SLEEP_ON;
|
||||
auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
|
||||
|
@ -1305,12 +1326,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Send cmd to FW to enable/disable 11D function */
|
||||
state_11d = ENABLE_11D;
|
||||
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB,
|
||||
HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d);
|
||||
if (ret)
|
||||
dev_err(priv->adapter->dev, "11D: failed to enable 11D\n");
|
||||
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
|
||||
/* Send cmd to FW to enable/disable 11D function */
|
||||
state_11d = ENABLE_11D;
|
||||
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB,
|
||||
HostCmd_ACT_GEN_SET, DOT11D_I,
|
||||
&state_11d);
|
||||
if (ret)
|
||||
dev_err(priv->adapter->dev,
|
||||
"11D: failed to enable 11D\n");
|
||||
}
|
||||
|
||||
/* Send cmd to FW to configure 11n specific configuration
|
||||
* (Short GI, Channel BW, Green field support etc.) for transmit
|
||||
|
|
|
@ -944,6 +944,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
|||
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
|
||||
ret = mwifiex_ret_subsc_evt(priv, resp, data_buf);
|
||||
break;
|
||||
case HostCmd_CMD_UAP_SYS_CONFIG:
|
||||
break;
|
||||
case HostCmd_CMD_UAP_BSS_START:
|
||||
priv->bss_started = 1;
|
||||
break;
|
||||
case HostCmd_CMD_UAP_BSS_STOP:
|
||||
priv->bss_started = 0;
|
||||
break;
|
||||
default:
|
||||
dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
|
||||
resp->command);
|
||||
|
|
|
@ -184,8 +184,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
|
|||
int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
int len, ret = 0;
|
||||
u32 eventcause = adapter->event_cause;
|
||||
struct station_info sinfo;
|
||||
struct mwifiex_assoc_event *event;
|
||||
|
||||
switch (eventcause) {
|
||||
case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
|
||||
|
@ -402,6 +404,53 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
|||
case EVENT_HOSTWAKE_STAIE:
|
||||
dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
|
||||
break;
|
||||
|
||||
case EVENT_UAP_STA_ASSOC:
|
||||
skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
event = (struct mwifiex_assoc_event *)adapter->event_skb->data;
|
||||
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 = (u8 *)&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:
|
||||
skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
cfg80211_del_sta(priv->netdev, adapter->event_skb->data,
|
||||
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);
|
||||
|
|
|
@ -462,7 +462,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
|
|||
|
||||
info->bss_chan = bss_desc->channel;
|
||||
|
||||
memcpy(info->country_code, priv->country_code,
|
||||
memcpy(info->country_code, adapter->country_code,
|
||||
IEEE80211_COUNTRY_STRING_LEN);
|
||||
|
||||
info->media_connected = priv->media_connected;
|
||||
|
@ -1219,7 +1219,8 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
|
|||
* 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, int disable)
|
||||
int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable)
|
||||
{
|
||||
struct mwifiex_ds_encrypt_key encrypt_key;
|
||||
|
||||
|
@ -1229,8 +1230,12 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
|||
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);
|
||||
} else {
|
||||
encrypt_key.key_disable = true;
|
||||
if (mac_addr)
|
||||
memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key);
|
||||
|
|
432
drivers/net/wireless/mwifiex/uap_cmd.c
Normal file
432
drivers/net/wireless/mwifiex/uap_cmd.c
Normal file
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* Marvell Wireless LAN device driver: AP specific command 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 "main.h"
|
||||
|
||||
/* This function parses security related parameters from cfg80211_ap_settings
|
||||
* and sets into FW understandable bss_config structure.
|
||||
*/
|
||||
int mwifiex_set_secure_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_config,
|
||||
struct cfg80211_ap_settings *params) {
|
||||
int i;
|
||||
|
||||
switch (params->auth_type) {
|
||||
case NL80211_AUTHTYPE_OPEN_SYSTEM:
|
||||
bss_config->auth_mode = WLAN_AUTH_OPEN;
|
||||
break;
|
||||
case NL80211_AUTHTYPE_SHARED_KEY:
|
||||
bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
|
||||
break;
|
||||
case NL80211_AUTHTYPE_NETWORK_EAP:
|
||||
bss_config->auth_mode = WLAN_AUTH_LEAP;
|
||||
break;
|
||||
default:
|
||||
bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO;
|
||||
break;
|
||||
}
|
||||
|
||||
bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
|
||||
|
||||
for (i = 0; i < params->crypto.n_akm_suites; i++) {
|
||||
switch (params->crypto.akm_suites[i]) {
|
||||
case WLAN_AKM_SUITE_8021X:
|
||||
if (params->crypto.wpa_versions &
|
||||
NL80211_WPA_VERSION_1) {
|
||||
bss_config->protocol = PROTOCOL_WPA;
|
||||
bss_config->key_mgmt = KEY_MGMT_EAP;
|
||||
}
|
||||
if (params->crypto.wpa_versions &
|
||||
NL80211_WPA_VERSION_2) {
|
||||
bss_config->protocol = PROTOCOL_WPA2;
|
||||
bss_config->key_mgmt = KEY_MGMT_EAP;
|
||||
}
|
||||
break;
|
||||
case WLAN_AKM_SUITE_PSK:
|
||||
if (params->crypto.wpa_versions &
|
||||
NL80211_WPA_VERSION_1) {
|
||||
bss_config->protocol = PROTOCOL_WPA;
|
||||
bss_config->key_mgmt = KEY_MGMT_PSK;
|
||||
}
|
||||
if (params->crypto.wpa_versions &
|
||||
NL80211_WPA_VERSION_2) {
|
||||
bss_config->protocol = PROTOCOL_WPA2;
|
||||
bss_config->key_mgmt = KEY_MGMT_PSK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
|
||||
switch (params->crypto.ciphers_pairwise[i]) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
bss_config->wpa_cfg.pairwise_cipher_wpa2 =
|
||||
CIPHER_AES_CCMP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (params->crypto.cipher_group) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function initializes some of mwifiex_uap_bss_param variables.
|
||||
* This helps FW in ignoring invalid values. These values may or may not
|
||||
* be get updated to valid ones at later stage.
|
||||
*/
|
||||
void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
|
||||
{
|
||||
config->bcast_ssid_ctl = 0x7F;
|
||||
config->radio_ctl = 0x7F;
|
||||
config->dtim_period = 0x7F;
|
||||
config->beacon_period = 0x7FFF;
|
||||
config->auth_mode = 0x7F;
|
||||
config->rts_threshold = 0x7FFF;
|
||||
config->frag_threshold = 0x7FFF;
|
||||
config->retry_limit = 0x7F;
|
||||
}
|
||||
|
||||
/* This function parses BSS related parameters from structure
|
||||
* and prepares TLVs. These TLVs are appended to command buffer.
|
||||
*/
|
||||
static int
|
||||
mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
||||
{
|
||||
struct host_cmd_tlv_dtim_period *dtim_period;
|
||||
struct host_cmd_tlv_beacon_period *beacon_period;
|
||||
struct host_cmd_tlv_ssid *ssid;
|
||||
struct host_cmd_tlv_channel_band *chan_band;
|
||||
struct host_cmd_tlv_frag_threshold *frag_threshold;
|
||||
struct host_cmd_tlv_rts_threshold *rts_threshold;
|
||||
struct host_cmd_tlv_retry_limit *retry_limit;
|
||||
struct host_cmd_tlv_pwk_cipher *pwk_cipher;
|
||||
struct host_cmd_tlv_gwk_cipher *gwk_cipher;
|
||||
struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
|
||||
struct host_cmd_tlv_auth_type *auth_type;
|
||||
struct host_cmd_tlv_passphrase *passphrase;
|
||||
struct host_cmd_tlv_akmp *tlv_akmp;
|
||||
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
|
||||
u16 cmd_size = *param_size;
|
||||
|
||||
if (bss_cfg->ssid.ssid_len) {
|
||||
ssid = (struct host_cmd_tlv_ssid *)tlv;
|
||||
ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
|
||||
ssid->tlv.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
|
||||
memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
|
||||
cmd_size += sizeof(struct host_cmd_tlv) +
|
||||
bss_cfg->ssid.ssid_len;
|
||||
tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len;
|
||||
}
|
||||
if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) {
|
||||
chan_band = (struct host_cmd_tlv_channel_band *)tlv;
|
||||
chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
|
||||
chan_band->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
chan_band->band_config = bss_cfg->band_cfg;
|
||||
chan_band->channel = bss_cfg->channel;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_channel_band);
|
||||
tlv += sizeof(struct host_cmd_tlv_channel_band);
|
||||
}
|
||||
if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
|
||||
bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
|
||||
beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
|
||||
beacon_period->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
|
||||
beacon_period->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
|
||||
cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
|
||||
tlv += sizeof(struct host_cmd_tlv_beacon_period);
|
||||
}
|
||||
if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
|
||||
bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
|
||||
dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
|
||||
dtim_period->tlv.type = cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
|
||||
dtim_period->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
dtim_period->period = bss_cfg->dtim_period;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
|
||||
tlv += sizeof(struct host_cmd_tlv_dtim_period);
|
||||
}
|
||||
if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
|
||||
rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
|
||||
rts_threshold->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
|
||||
rts_threshold->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
|
||||
cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
|
||||
tlv += sizeof(struct host_cmd_tlv_frag_threshold);
|
||||
}
|
||||
if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
|
||||
(bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
|
||||
frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
|
||||
frag_threshold->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
|
||||
frag_threshold->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
|
||||
cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
|
||||
tlv += sizeof(struct host_cmd_tlv_frag_threshold);
|
||||
}
|
||||
if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
|
||||
retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
|
||||
retry_limit->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
|
||||
retry_limit->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
retry_limit->limit = (u8)bss_cfg->retry_limit;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
|
||||
tlv += sizeof(struct host_cmd_tlv_retry_limit);
|
||||
}
|
||||
if ((bss_cfg->protocol & PROTOCOL_WPA) ||
|
||||
(bss_cfg->protocol & PROTOCOL_WPA2) ||
|
||||
(bss_cfg->protocol & PROTOCOL_EAP)) {
|
||||
tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
|
||||
tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
|
||||
tlv_akmp->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
tlv_akmp->key_mgmt_operation =
|
||||
cpu_to_le16(bss_cfg->key_mgmt_operation);
|
||||
tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
|
||||
cmd_size += sizeof(struct host_cmd_tlv_akmp);
|
||||
tlv += sizeof(struct host_cmd_tlv_akmp);
|
||||
|
||||
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa &
|
||||
VALID_CIPHER_BITMAP) {
|
||||
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
|
||||
pwk_cipher->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_PWK_CIPHER);
|
||||
pwk_cipher->tlv.len = cpu_to_le16(
|
||||
sizeof(struct host_cmd_tlv_pwk_cipher) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
|
||||
pwk_cipher->cipher =
|
||||
bss_cfg->wpa_cfg.pairwise_cipher_wpa;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
|
||||
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
|
||||
}
|
||||
if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 &
|
||||
VALID_CIPHER_BITMAP) {
|
||||
pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
|
||||
pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
|
||||
pwk_cipher->tlv.len = cpu_to_le16(
|
||||
sizeof(struct host_cmd_tlv_pwk_cipher) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
|
||||
pwk_cipher->cipher =
|
||||
bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
|
||||
tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
|
||||
}
|
||||
if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
|
||||
gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
|
||||
gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
|
||||
gwk_cipher->tlv.len = cpu_to_le16(
|
||||
sizeof(struct host_cmd_tlv_gwk_cipher) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
|
||||
tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
|
||||
}
|
||||
if (bss_cfg->wpa_cfg.length) {
|
||||
passphrase = (struct host_cmd_tlv_passphrase *)tlv;
|
||||
passphrase->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
|
||||
passphrase->tlv.len =
|
||||
cpu_to_le16(bss_cfg->wpa_cfg.length);
|
||||
memcpy(passphrase->passphrase,
|
||||
bss_cfg->wpa_cfg.passphrase,
|
||||
bss_cfg->wpa_cfg.length);
|
||||
cmd_size += sizeof(struct host_cmd_tlv) +
|
||||
bss_cfg->wpa_cfg.length;
|
||||
tlv += sizeof(struct host_cmd_tlv) +
|
||||
bss_cfg->wpa_cfg.length;
|
||||
}
|
||||
}
|
||||
if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
|
||||
(bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
|
||||
auth_type = (struct host_cmd_tlv_auth_type *)tlv;
|
||||
auth_type->tlv.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
|
||||
auth_type->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
|
||||
sizeof(struct host_cmd_tlv));
|
||||
auth_type->auth_type = (u8)bss_cfg->auth_mode;
|
||||
cmd_size += sizeof(struct host_cmd_tlv_auth_type);
|
||||
tlv += sizeof(struct host_cmd_tlv_auth_type);
|
||||
}
|
||||
if (bss_cfg->protocol) {
|
||||
encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
|
||||
encrypt_protocol->tlv.type =
|
||||
cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
|
||||
encrypt_protocol->tlv.len =
|
||||
cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
|
||||
- sizeof(struct host_cmd_tlv));
|
||||
encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
|
||||
cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
|
||||
tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
|
||||
}
|
||||
|
||||
*param_size = cmd_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function parses custom IEs from IE list and prepares command buffer */
|
||||
static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
|
||||
{
|
||||
struct mwifiex_ie_list *ap_ie = cmd_buf;
|
||||
struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv;
|
||||
|
||||
if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
|
||||
return -1;
|
||||
|
||||
*ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv);
|
||||
|
||||
tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
|
||||
tlv_ie->len = ap_ie->len;
|
||||
tlv += sizeof(struct host_cmd_tlv);
|
||||
|
||||
memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse AP config structure and prepare TLV based command structure
|
||||
* to be sent to FW for uAP configuration
|
||||
*/
|
||||
static int
|
||||
mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
|
||||
u32 type, void *cmd_buf)
|
||||
{
|
||||
u8 *tlv;
|
||||
u16 cmd_size, param_size, ie_size;
|
||||
struct host_cmd_ds_sys_config *sys_cfg;
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
|
||||
cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
|
||||
sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config;
|
||||
sys_cfg->action = cpu_to_le16(cmd_action);
|
||||
tlv = sys_cfg->tlv;
|
||||
|
||||
switch (type) {
|
||||
case UAP_BSS_PARAMS_I:
|
||||
param_size = cmd_size;
|
||||
if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, ¶m_size))
|
||||
return -1;
|
||||
cmd->size = cpu_to_le16(param_size);
|
||||
break;
|
||||
case UAP_CUSTOM_IE_I:
|
||||
ie_size = cmd_size;
|
||||
if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
|
||||
return -1;
|
||||
cmd->size = cpu_to_le16(ie_size);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function prepares the AP specific commands before sending them
|
||||
* to the firmware.
|
||||
* This is a generic function which calls specific command preparation
|
||||
* routines based upon the command number.
|
||||
*/
|
||||
int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
|
||||
u16 cmd_action, u32 type,
|
||||
void *data_buf, void *cmd_buf)
|
||||
{
|
||||
struct host_cmd_ds_command *cmd = cmd_buf;
|
||||
|
||||
switch (cmd_no) {
|
||||
case HostCmd_CMD_UAP_SYS_CONFIG:
|
||||
if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf))
|
||||
return -1;
|
||||
break;
|
||||
case HostCmd_CMD_UAP_BSS_START:
|
||||
case HostCmd_CMD_UAP_BSS_STOP:
|
||||
cmd->command = cpu_to_le16(cmd_no);
|
||||
cmd->size = cpu_to_le16(S_DS_GEN);
|
||||
break;
|
||||
default:
|
||||
dev_err(priv->adapter->dev,
|
||||
"PREP_CMD: unknown cmd %#x\n", cmd_no);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function sets the RF channel for AP.
|
||||
*
|
||||
* This function populates channel information in AP config structure
|
||||
* and sends command to configure channel information in AP.
|
||||
*/
|
||||
int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel)
|
||||
{
|
||||
struct mwifiex_uap_bss_param *bss_cfg;
|
||||
struct wiphy *wiphy = priv->wdev->wiphy;
|
||||
|
||||
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
|
||||
if (!bss_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
|
||||
bss_cfg->channel = channel;
|
||||
|
||||
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
|
||||
HostCmd_ACT_GEN_SET,
|
||||
UAP_BSS_PARAMS_I, bss_cfg)) {
|
||||
wiphy_err(wiphy, "Failed to set the uAP channel\n");
|
||||
kfree(bss_cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kfree(bss_cfg);
|
||||
return 0;
|
||||
}
|
|
@ -885,6 +885,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
|
|||
tid_ptr = &(priv_tmp)->wmm.
|
||||
tid_tbl_ptr[tos_to_tid[i]];
|
||||
|
||||
/* For non-STA ra_list_curr may be NULL */
|
||||
if (!tid_ptr->ra_list_curr)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&tid_ptr->tid_tbl_lock,
|
||||
flags);
|
||||
is_list_empty =
|
||||
|
|
|
@ -505,9 +505,6 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
|
||||
|
||||
static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
|
||||
|
||||
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
u8 key_index, bool pairwise, const u8 *mac_addr,
|
||||
struct key_params *params);
|
||||
|
@ -549,7 +546,6 @@ static const struct cfg80211_ops rndis_config_ops = {
|
|||
.disconnect = rndis_disconnect,
|
||||
.join_ibss = rndis_join_ibss,
|
||||
.leave_ibss = rndis_leave_ibss,
|
||||
.set_channel = rndis_set_channel,
|
||||
.add_key = rndis_add_key,
|
||||
.del_key = rndis_del_key,
|
||||
.set_default_key = rndis_set_default_key,
|
||||
|
@ -2398,16 +2394,6 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
|
|||
return deauthenticate(usbdev);
|
||||
}
|
||||
|
||||
static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
|
||||
return set_channel(usbdev,
|
||||
ieee80211_frequency_to_channel(chan->center_freq));
|
||||
}
|
||||
|
||||
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
u8 key_index, bool pairwise, const u8 *mac_addr,
|
||||
struct key_params *params)
|
||||
|
|
|
@ -1192,6 +1192,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
|||
{ PCI_DEVICE(0x1814, 0x5390) },
|
||||
{ PCI_DEVICE(0x1814, 0x5392) },
|
||||
{ PCI_DEVICE(0x1814, 0x539a) },
|
||||
{ PCI_DEVICE(0x1814, 0x539b) },
|
||||
{ PCI_DEVICE(0x1814, 0x539f) },
|
||||
#endif
|
||||
{ 0, }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
config WL12XX
|
||||
tristate "TI wl12xx support"
|
||||
depends on MAC80211
|
||||
select WLCORE
|
||||
---help---
|
||||
This module adds support for wireless adapters based on TI wl1271,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config WLCORE
|
||||
tristate "TI wlcore support"
|
||||
depends on WL_TI && GENERIC_HARDIRQS
|
||||
depends on WL_TI && GENERIC_HARDIRQS && MAC80211
|
||||
depends on INET
|
||||
select FW_LOADER
|
||||
---help---
|
||||
|
|
|
@ -1714,3 +1714,83 @@ out:
|
|||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Set the global behaviour of RX filters - On/Off + default action */
|
||||
int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
|
||||
enum rx_filter_action action)
|
||||
{
|
||||
struct acx_default_rx_filter *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx default rx filter en: %d act: %d",
|
||||
enable, action);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx)
|
||||
return -ENOMEM;
|
||||
|
||||
acx->enable = enable;
|
||||
acx->default_action = action;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_ENABLE_RX_DATA_FILTER, acx,
|
||||
sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx default rx filter enable failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure or disable a specific RX filter pattern */
|
||||
int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable,
|
||||
struct wl12xx_rx_filter *filter)
|
||||
{
|
||||
struct acx_rx_filter_cfg *acx;
|
||||
int fields_size = 0;
|
||||
int acx_size;
|
||||
int ret;
|
||||
|
||||
WARN_ON(enable && !filter);
|
||||
WARN_ON(index >= WL1271_MAX_RX_FILTERS);
|
||||
|
||||
wl1271_debug(DEBUG_ACX,
|
||||
"acx set rx filter idx: %d enable: %d filter: %p",
|
||||
index, enable, filter);
|
||||
|
||||
if (enable) {
|
||||
fields_size = wl1271_rx_filter_get_fields_size(filter);
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "act: %d num_fields: %d field_size: %d",
|
||||
filter->action, filter->num_fields, fields_size);
|
||||
}
|
||||
|
||||
acx_size = ALIGN(sizeof(*acx) + fields_size, 4);
|
||||
acx = kzalloc(acx_size, GFP_KERNEL);
|
||||
|
||||
if (!acx)
|
||||
return -ENOMEM;
|
||||
|
||||
acx->enable = enable;
|
||||
acx->index = index;
|
||||
|
||||
if (enable) {
|
||||
acx->num_fields = filter->num_fields;
|
||||
acx->action = filter->action;
|
||||
wl1271_rx_filter_flatten_fields(filter, acx->fields);
|
||||
}
|
||||
|
||||
wl1271_dump(DEBUG_ACX, "RX_FILTER: ", acx, acx_size);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SET_RX_DATA_FILTER, acx, acx_size);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("setting rx filter failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1147,6 +1147,32 @@ struct wl12xx_acx_config_hangover {
|
|||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct acx_default_rx_filter {
|
||||
struct acx_header header;
|
||||
u8 enable;
|
||||
|
||||
/* action of type FILTER_XXX */
|
||||
u8 default_action;
|
||||
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct acx_rx_filter_cfg {
|
||||
struct acx_header header;
|
||||
|
||||
u8 enable;
|
||||
|
||||
/* 0 - WL1271_MAX_RX_FILTERS-1 */
|
||||
u8 index;
|
||||
|
||||
u8 action;
|
||||
|
||||
u8 num_fields;
|
||||
u8 fields[0];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0000,
|
||||
ACX_MEM_CFG = 0x0001,
|
||||
|
@ -1304,5 +1330,9 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
|||
int wl1271_acx_fm_coex(struct wl1271 *wl);
|
||||
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
|
||||
int wl12xx_acx_config_hangover(struct wl1271 *wl);
|
||||
int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
|
||||
enum rx_filter_action action);
|
||||
int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable,
|
||||
struct wl12xx_rx_filter *filter);
|
||||
|
||||
#endif /* __WL1271_ACX_H__ */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue