You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
This commit is contained in:
@@ -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)
|
What: setitimer accepts user NULL pointer (value)
|
||||||
When: 3.6
|
When: 3.6
|
||||||
Why: setitimer is not returning -EFAULT if user pointer is NULL. This
|
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
|
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.
|
and a translation will be forwarded to NFC Core as needed.
|
||||||
HCI uses 2 execution contexts:
|
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.
|
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:
|
HCI Session initialization:
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -52,18 +52,42 @@ entry points:
|
|||||||
struct nfc_hci_ops {
|
struct nfc_hci_ops {
|
||||||
int (*open)(struct nfc_hci_dev *hdev);
|
int (*open)(struct nfc_hci_dev *hdev);
|
||||||
void (*close)(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 (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||||
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
|
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
|
||||||
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
|
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
|
||||||
struct nfc_target *target);
|
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
|
- open() and close() shall turn the hardware on and off.
|
||||||
write a frame to the chip. start_poll() is an optional entrypoint that shall
|
- hci_ready() is an optional entry point that is called right after the hci
|
||||||
set the hardware in polling mode. This must be implemented only if the hardware
|
session has been set up. The driver can use it to do additional initialization
|
||||||
uses proprietary gates or a mechanism slightly different from the HCI standard.
|
that must be performed using HCI commands.
|
||||||
target_from_gate() is another optional entrypoint to return the protocols
|
- 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.
|
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
|
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
|
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.
|
handles shdlc rx & tx queues. Dispatches HCI cmd responses.
|
||||||
|
|
||||||
- HCI Tx Cmd worker (MSGTXWQ)
|
- 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)
|
- HCI Rx worker (MSGRXWQ)
|
||||||
Dispatches incoming HCI commands or events.
|
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
|
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
|
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.
|
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.
|
form complete HCI frames, which can be a response, command, or event.
|
||||||
|
|
||||||
HCI Responses are dispatched immediately from this context to unblock
|
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.
|
callback that was provided by nfc_hci_msg_tx_work() when it sent the command.
|
||||||
The completion callback will then wake the syscall context.
|
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];
|
char prefix[10];
|
||||||
|
|
||||||
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||||
|
memset(out, 0, sizeof(struct ssb_sprom));
|
||||||
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
||||||
bus->host_pci->bus->number + 1,
|
bus->host_pci->bus->number + 1,
|
||||||
PCI_SLOT(bus->host_pci->devfn));
|
PCI_SLOT(bus->host_pci->devfn));
|
||||||
@@ -109,15 +110,9 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
|
|||||||
/* Fill boardinfo structure */
|
/* Fill boardinfo structure */
|
||||||
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
|
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
|
||||||
|
|
||||||
if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
|
bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
|
||||||
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);
|
|
||||||
|
|
||||||
|
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
|
||||||
bcm47xx_fill_sprom(&iv->sprom, NULL);
|
bcm47xx_fill_sprom(&iv->sprom, NULL);
|
||||||
|
|
||||||
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
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) {
|
switch (bus->hosttype) {
|
||||||
case BCMA_HOSTTYPE_PCI:
|
case BCMA_HOSTTYPE_PCI:
|
||||||
|
memset(out, 0, sizeof(struct ssb_sprom));
|
||||||
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
||||||
bus->host_pci->bus->number + 1,
|
bus->host_pci->bus->number + 1,
|
||||||
PCI_SLOT(bus->host_pci->devfn));
|
PCI_SLOT(bus->host_pci->devfn));
|
||||||
bcm47xx_fill_sprom(out, prefix);
|
bcm47xx_fill_sprom(out, prefix);
|
||||||
return 0;
|
return 0;
|
||||||
case BCMA_HOSTTYPE_SOC:
|
case BCMA_HOSTTYPE_SOC:
|
||||||
|
memset(out, 0, sizeof(struct ssb_sprom));
|
||||||
bcm47xx_fill_sprom_ethernet(out, NULL);
|
bcm47xx_fill_sprom_ethernet(out, NULL);
|
||||||
core = bcma_find_core(bus, BCMA_CORE_80211);
|
core = bcma_find_core(bus, BCMA_CORE_80211);
|
||||||
if (core) {
|
if (core) {
|
||||||
@@ -197,6 +194,8 @@ static void __init bcm47xx_register_bcma(void)
|
|||||||
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
|
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
|
||||||
if (err)
|
if (err)
|
||||||
panic("Failed to initialize BCMA bus (err %d)", err);
|
panic("Failed to initialize BCMA bus (err %d)", err);
|
||||||
|
|
||||||
|
bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
|
|||||||
const char *prefix)
|
const char *prefix)
|
||||||
{
|
{
|
||||||
nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
|
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_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
|
||||||
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
|
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
|
||||||
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 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)
|
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
|
||||||
{
|
{
|
||||||
memset(sprom, 0, sizeof(struct ssb_sprom));
|
|
||||||
|
|
||||||
bcm47xx_fill_sprom_ethernet(sprom, prefix);
|
bcm47xx_fill_sprom_ethernet(sprom, prefix);
|
||||||
|
|
||||||
nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
|
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);
|
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(struct ssb_sprom *sprom, const char *prefix);
|
||||||
void bcm47xx_fill_sprom_ethernet(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 */
|
#endif /* __ASM_BCM47XX_H */
|
||||||
|
|||||||
+2
-1
@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_device *core, u32 flags)
|
|||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
||||||
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
||||||
|
bcma_aread32(core, BCMA_RESET_CTL);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bcma_core_disable);
|
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");
|
pr_err("HT force timeout\n");
|
||||||
break;
|
break;
|
||||||
case BCMA_CLKMODE_DYNAMIC:
|
case BCMA_CLKMODE_DYNAMIC:
|
||||||
pr_warn("Dynamic clockmode not supported yet!\n");
|
bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
|
||||||
break;
|
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);
|
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)
|
static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
|
||||||
{
|
{
|
||||||
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
|
||||||
pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
|
||||||
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
|
pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
|
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);
|
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.
|
* Init.
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||||
{
|
{
|
||||||
|
bcma_core_pci_fixcfg(pc);
|
||||||
bcma_pcicore_serdes_workaround(pc);
|
bcma_pcicore_serdes_workaround(pc);
|
||||||
|
bcma_core_pci_config_fixup(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||||
@@ -224,3 +259,17 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
|
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))
|
if (unlikely(!addr))
|
||||||
goto out;
|
goto out;
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
mmio = ioremap_nocache(addr, len);
|
mmio = ioremap_nocache(addr, sizeof(val));
|
||||||
if (!mmio)
|
if (!mmio)
|
||||||
goto out;
|
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 = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
||||||
addr |= (func << 8);
|
addr |= (func << 8);
|
||||||
addr |= (off & 0xfc);
|
addr |= (off & 0xfc);
|
||||||
mmio = ioremap_nocache(addr, len);
|
mmio = ioremap_nocache(addr, sizeof(val));
|
||||||
if (!mmio)
|
if (!mmio)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||||||
if (unlikely(!addr))
|
if (unlikely(!addr))
|
||||||
goto out;
|
goto out;
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
mmio = ioremap_nocache(addr, len);
|
mmio = ioremap_nocache(addr, sizeof(val));
|
||||||
if (!mmio)
|
if (!mmio)
|
||||||
goto out;
|
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.
|
/* Ok, ready to run, register it to the system.
|
||||||
* The following needs change, if we want to port hostmode
|
* The following needs change, if we want to port hostmode
|
||||||
* to non-MIPS platform. */
|
* to non-MIPS platform. */
|
||||||
io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
|
io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
|
||||||
0x04000000);
|
resource_size(&pc_host->mem_resource));
|
||||||
pc_host->pci_controller.io_map_base = io_map_base;
|
pc_host->pci_controller.io_map_base = io_map_base;
|
||||||
set_io_port_base(pc_host->pci_controller.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
|
/* 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->hosttype = BCMA_HOSTTYPE_PCI;
|
||||||
bus->ops = &bcma_host_pci_ops;
|
bus->ops = &bcma_host_pci_ops;
|
||||||
|
|
||||||
|
bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
|
||||||
|
bus->boardinfo.type = bus->host_pci->subsystem_device;
|
||||||
|
|
||||||
/* Register */
|
/* Register */
|
||||||
err = bcma_bus_register(bus);
|
err = bcma_bus_register(bus);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -222,7 +225,7 @@ err_kfree_bus:
|
|||||||
return err;
|
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);
|
struct bcma_bus *bus = pci_get_drvdata(dev);
|
||||||
|
|
||||||
@@ -277,7 +280,7 @@ static struct pci_driver bcma_pci_bridge_driver = {
|
|||||||
.name = "bcma-pci-bridge",
|
.name = "bcma-pci-bridge",
|
||||||
.id_table = bcma_pci_bridge_tbl,
|
.id_table = bcma_pci_bridge_tbl,
|
||||||
.probe = bcma_host_pci_probe,
|
.probe = bcma_host_pci_probe,
|
||||||
.remove = bcma_host_pci_remove,
|
.remove = __devexit_p(bcma_host_pci_remove),
|
||||||
.driver.pm = BCMA_PM_OPS,
|
.driver.pm = BCMA_PM_OPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+40
-14
@@ -19,7 +19,14 @@ struct bcma_device_id_name {
|
|||||||
u16 id;
|
u16 id;
|
||||||
const char *name;
|
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_OOB_ROUTER, "OOB Router" },
|
||||||
{ BCMA_CORE_INVALID, "Invalid" },
|
{ BCMA_CORE_INVALID, "Invalid" },
|
||||||
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
|
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
|
||||||
@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_names[] = {
|
|||||||
{ BCMA_CORE_SRAM, "SRAM" },
|
{ BCMA_CORE_SRAM, "SRAM" },
|
||||||
{ BCMA_CORE_SDRAM, "SDRAM" },
|
{ BCMA_CORE_SDRAM, "SDRAM" },
|
||||||
{ BCMA_CORE_PCI, "PCI" },
|
{ BCMA_CORE_PCI, "PCI" },
|
||||||
{ BCMA_CORE_MIPS, "MIPS" },
|
|
||||||
{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
|
{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
|
||||||
{ BCMA_CORE_V90, "V90" },
|
{ BCMA_CORE_V90, "V90" },
|
||||||
{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
|
{ 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_A, "PHY A" },
|
||||||
{ BCMA_CORE_PHY_B, "PHY B" },
|
{ BCMA_CORE_PHY_B, "PHY B" },
|
||||||
{ BCMA_CORE_PHY_G, "PHY G" },
|
{ BCMA_CORE_PHY_G, "PHY G" },
|
||||||
{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
|
|
||||||
{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
|
{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
|
||||||
{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
|
{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
|
||||||
{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
|
{ 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_PHY_N, "PHY N" },
|
||||||
{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
|
{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
|
||||||
{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
|
{ 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_PHY_LP, "PHY LP" },
|
||||||
{ BCMA_CORE_PMU, "PMU" },
|
{ BCMA_CORE_PMU, "PMU" },
|
||||||
{ BCMA_CORE_PHY_SSN, "PHY SSN" },
|
{ BCMA_CORE_PHY_SSN, "PHY SSN" },
|
||||||
{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
|
{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
|
||||||
{ BCMA_CORE_ARM_CM3, "ARM CM3" },
|
|
||||||
{ BCMA_CORE_PHY_HT, "PHY HT" },
|
{ BCMA_CORE_PHY_HT, "PHY HT" },
|
||||||
{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
|
|
||||||
{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
|
{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
|
||||||
{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
|
{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
|
||||||
{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
|
{ 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_SHIM, "SHIM" },
|
||||||
{ BCMA_CORE_DEFAULT, "Default" },
|
{ BCMA_CORE_DEFAULT, "Default" },
|
||||||
};
|
};
|
||||||
const char *bcma_device_name(struct bcma_device_id *id)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (id->manuf == BCMA_MANUF_BCM) {
|
static const struct bcma_device_id_name bcma_mips_device_names[] = {
|
||||||
for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
|
{ BCMA_CORE_MIPS, "MIPS" },
|
||||||
if (bcma_device_names[i].id == id->id)
|
{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
|
||||||
return bcma_device_names[i].name;
|
{ 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";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+148
-1
@@ -181,6 +181,22 @@ static int bcma_sprom_valid(const u16 *sprom)
|
|||||||
#define SPEX(_field, _offset, _mask, _shift) \
|
#define SPEX(_field, _offset, _mask, _shift) \
|
||||||
bus->sprom._field = ((sprom[SPOFF(_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)
|
static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
||||||
{
|
{
|
||||||
u16 v, o;
|
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_lo, SSB_SPROM8_BFL2LO, ~0, 0);
|
||||||
SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~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 */
|
/* Extract cores power info info */
|
||||||
for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
|
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);
|
SSB_SROM8_FEM_TR_ISO_SHIFT);
|
||||||
SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
|
SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
|
||||||
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
|
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 */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||||
|
|
||||||
|
/* Atheros AR5BBU22 with sflash firmware */
|
||||||
|
{ USB_DEVICE(0x0489, 0xE03C) },
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
|||||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe004), .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 */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ struct btmrvl_adapter {
|
|||||||
u8 wakeup_tries;
|
u8 wakeup_tries;
|
||||||
wait_queue_head_t cmd_wait_q;
|
wait_queue_head_t cmd_wait_q;
|
||||||
u8 cmd_complete;
|
u8 cmd_complete;
|
||||||
|
bool is_suspended;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct btmrvl_private {
|
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_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_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_enable_ps(struct btmrvl_private *priv);
|
||||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||||
|
int btmrvl_enable_hs(struct btmrvl_private *priv);
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
void btmrvl_debugfs_init(struct hci_dev *hdev);
|
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);
|
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)
|
int btmrvl_enable_ps(struct btmrvl_private *priv)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
@@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
|
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 sk_buff *skb;
|
||||||
struct btmrvl_cmd *cmd;
|
struct btmrvl_cmd *cmd;
|
||||||
@@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(btmrvl_enable_hs);
|
||||||
|
|
||||||
int btmrvl_prepare_command(struct btmrvl_private *priv)
|
int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = NULL;
|
|
||||||
struct btmrvl_cmd *cmd;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (priv->btmrvl_dev.hscfgcmd) {
|
if (priv->btmrvl_dev.hscfgcmd) {
|
||||||
priv->btmrvl_dev.hscfgcmd = 0;
|
priv->btmrvl_dev.hscfgcmd = 0;
|
||||||
|
btmrvl_send_hscfg_cmd(priv);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->btmrvl_dev.pscmd) {
|
if (priv->btmrvl_dev.pscmd) {
|
||||||
|
|||||||
@@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
kfree(tmphlprbuf);
|
kfree(tmphlprbuf);
|
||||||
if (fw_helper)
|
|
||||||
release_firmware(fw_helper);
|
release_firmware(fw_helper);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
kfree(tmpfwbuf);
|
kfree(tmpfwbuf);
|
||||||
|
|
||||||
if (fw_firmware)
|
|
||||||
release_firmware(fw_firmware);
|
release_firmware(fw_firmware);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
|||||||
priv->btmrvl_dev.psmode = 1;
|
priv->btmrvl_dev.psmode = 1;
|
||||||
btmrvl_enable_ps(priv);
|
btmrvl_enable_ps(priv);
|
||||||
|
|
||||||
|
priv->btmrvl_dev.gpio_gap = 0xffff;
|
||||||
|
btmrvl_send_hscfg_cmd(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
disable_host_int:
|
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 = {
|
static struct sdio_driver bt_mrvl_sdio = {
|
||||||
.name = "btmrvl_sdio",
|
.name = "btmrvl_sdio",
|
||||||
.id_table = btmrvl_sdio_ids,
|
.id_table = btmrvl_sdio_ids,
|
||||||
.probe = btmrvl_sdio_probe,
|
.probe = btmrvl_sdio_probe,
|
||||||
.remove = btmrvl_sdio_remove,
|
.remove = btmrvl_sdio_remove,
|
||||||
|
.drv = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &btmrvl_sdio_pm_ops,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init btmrvl_sdio_init_module(void)
|
static int __init btmrvl_sdio_init_module(void)
|
||||||
|
|||||||
@@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = {
|
|||||||
/* Atheros AR5BBU12 with sflash firmware */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||||
|
|
||||||
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
|
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||||
|
|
||||||
/* Broadcom BCM2035 */
|
/* Broadcom BCM2035 */
|
||||||
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||||
{ USB_DEVICE(0x0a5c, 0x200a), .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 btusb_data *data = container_of(work, struct btusb_data, work);
|
||||||
struct hci_dev *hdev = data->hdev;
|
struct hci_dev *hdev = data->hdev;
|
||||||
|
int new_alts;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (hdev->conn_hash.sco_num > 0) {
|
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);
|
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);
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||||
|
|
||||||
if (__set_isoc_interface(hdev, 2) < 0)
|
if (__set_isoc_interface(hdev, new_alts) < 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
|||||||
hdev->close = hci_uart_close;
|
hdev->close = hci_uart_close;
|
||||||
hdev->flush = hci_uart_flush;
|
hdev->flush = hci_uart_flush;
|
||||||
hdev->send = hci_uart_send_frame;
|
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))
|
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
||||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
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;
|
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)
|
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,
|
ie, 2 + vif->ssid_len + beacon_ie_len,
|
||||||
0, GFP_KERNEL);
|
0, GFP_KERNEL);
|
||||||
if (bss)
|
if (bss)
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
|
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||||
"cfg80211\n", bssid);
|
"added bss %pM to cfg80211\n", bssid);
|
||||||
kfree(ie);
|
kfree(ie);
|
||||||
} else
|
} else
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
|
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;
|
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,
|
static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
struct cfg80211_scan_request *request)
|
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) {
|
if (!ar->usr_bss_filter) {
|
||||||
clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
|
clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
|
||||||
ret = ath6kl_wmi_bssfilter_cmd(
|
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||||
ar->wmi, vif->fw_vif_idx,
|
ALL_BSS_FILTER, 0);
|
||||||
(test_bit(CONNECTED, &vif->flags) ?
|
|
||||||
ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath6kl_err("couldn't set bss filtering\n");
|
ath6kl_err("couldn't set bss filtering\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->n_ssids && request->ssids[0].ssid_len) {
|
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||||
u8 i;
|
request->n_ssids);
|
||||||
|
if (ret < 0)
|
||||||
if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
|
return ret;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this also clears IE in fw if it's not set */
|
/* this also clears IE in fw if it's not set */
|
||||||
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
|
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
|
||||||
WMI_FRAME_PROBE_REQ,
|
WMI_FRAME_PROBE_REQ,
|
||||||
request->ie, request->ie_len);
|
request->ie, request->ie_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath6kl_err("failed to set Probe Request appie for "
|
ath6kl_err("failed to set Probe Request appie for scan");
|
||||||
"scan");
|
|
||||||
return ret;
|
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);
|
channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
|
||||||
if (channels == NULL) {
|
if (channels == NULL) {
|
||||||
ath6kl_warn("failed to set scan channels, "
|
ath6kl_warn("failed to set scan channels, scan all channels");
|
||||||
"scan all channels");
|
|
||||||
n_channels = 0;
|
n_channels = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,6 +1032,20 @@ out:
|
|||||||
vif->scan_req = NULL;
|
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,
|
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
u8 key_index, bool pairwise,
|
u8 key_index, bool pairwise,
|
||||||
const u8 *mac_addr,
|
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;
|
ar->ap_mode_bkey.key_len = key->key_len;
|
||||||
memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
|
memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
|
||||||
if (!test_bit(CONNECTED, &vif->flags)) {
|
if (!test_bit(CONNECTED, &vif->flags)) {
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
|
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||||
"key configuration until AP mode has been "
|
"Delay initial group key configuration until AP mode has been started\n");
|
||||||
"started\n");
|
|
||||||
/*
|
/*
|
||||||
* The key will be set in ath6kl_connect_ap_mode() once
|
* The key will be set in ath6kl_connect_ap_mode() once
|
||||||
* the connected event is received from the target.
|
* 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
|
* the AP mode has properly started
|
||||||
* (ath6kl_install_statioc_wep_keys).
|
* (ath6kl_install_statioc_wep_keys).
|
||||||
*/
|
*/
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
|
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||||
"until AP mode has been started\n");
|
"Delay WEP key configuration until AP mode has been started\n");
|
||||||
vif->wep_key_list[key_index].key_len = key->key_len;
|
vif->wep_key_list[key_index].key_len = key->key_len;
|
||||||
memcpy(vif->wep_key_list[key_index].key, key->key,
|
memcpy(vif->wep_key_list[key_index].key, key->key,
|
||||||
key->key_len);
|
key->key_len);
|
||||||
@@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
|
|||||||
sizeof(discvr_pattern), discvr_offset,
|
sizeof(discvr_pattern), discvr_offset,
|
||||||
discvr_pattern, discvr_mask);
|
discvr_pattern, discvr_mask);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
|
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
|
||||||
"pattern\n");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||||||
u8 index = 0;
|
u8 index = 0;
|
||||||
__be32 ips[MAX_IP_ADDRS];
|
__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);
|
vif = ath6kl_vif_first(ar);
|
||||||
if (!vif)
|
if (!vif)
|
||||||
return -EIO;
|
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))
|
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
|
||||||
return -EINVAL;
|
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 */
|
/* Clear existing WOW patterns */
|
||||||
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
|
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
|
||||||
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
|
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,
|
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||||
ATH6KL_HOST_MODE_AWAKE);
|
ATH6KL_HOST_MODE_AWAKE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath6kl_warn("Failed to configure host sleep mode for "
|
ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
|
||||||
"wow resume: %d\n", ret);
|
ret);
|
||||||
ar->state = ATH6KL_STATE_WOW;
|
ar->state = ATH6KL_STATE_WOW;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||||||
|
|
||||||
ar->state = ATH6KL_STATE_ON;
|
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);
|
netif_wake_queue(vif->ndev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
|
|||||||
if (!vif)
|
if (!vif)
|
||||||
return -EIO;
|
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;
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
ath6kl_cfg80211_stop_all(ar);
|
ath6kl_cfg80211_stop_all(ar);
|
||||||
|
|
||||||
@@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
|
|||||||
band, htcap);
|
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)
|
static bool ath6kl_is_p2p_ie(const u8 *pos)
|
||||||
{
|
{
|
||||||
return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
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 */
|
/* skip element id and length */
|
||||||
rsn_ie += 2;
|
rsn_ie += 2;
|
||||||
|
|
||||||
/* skip version, group cipher */
|
/* skip version */
|
||||||
if (rsn_ie_len < 6)
|
if (rsn_ie_len < 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
rsn_ie += 6;
|
rsn_ie += 2;
|
||||||
rsn_ie_len -= 6;
|
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 */
|
/* skip pairwise cipher suite */
|
||||||
if (rsn_ie_len < 2)
|
if (rsn_ie_len < 2)
|
||||||
return -EINVAL;
|
return 0;
|
||||||
cnt = *((u16 *) rsn_ie);
|
cnt = get_unaligned_le16(rsn_ie);
|
||||||
rsn_ie += (2 + cnt * 4);
|
rsn_ie += (2 + cnt * 4);
|
||||||
rsn_ie_len -= (2 + cnt * 4);
|
rsn_ie_len -= (2 + cnt * 4);
|
||||||
|
|
||||||
/* skip akm suite */
|
/* skip akm suite */
|
||||||
if (rsn_ie_len < 2)
|
if (rsn_ie_len < 2)
|
||||||
return -EINVAL;
|
return 0;
|
||||||
cnt = *((u16 *) rsn_ie);
|
cnt = get_unaligned_le16(rsn_ie);
|
||||||
rsn_ie += (2 + cnt * 4);
|
rsn_ie += (2 + cnt * 4);
|
||||||
rsn_ie_len -= (2 + cnt * 4);
|
rsn_ie_len -= (2 + cnt * 4);
|
||||||
|
|
||||||
if (rsn_ie_len < 2)
|
if (rsn_ie_len < 2)
|
||||||
return -EINVAL;
|
return 0;
|
||||||
|
|
||||||
memcpy(rsn_capab, rsn_ie, 2);
|
memcpy(rsn_capab, rsn_ie, 2);
|
||||||
|
|
||||||
@@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&vif->profile, &p, sizeof(p));
|
||||||
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||||||
clear_bit(CONNECTED, &vif->flags);
|
clear_bit(CONNECTED, &vif->flags);
|
||||||
|
|
||||||
/* Restore ht setting in firmware */
|
/* Restore ht setting in firmware */
|
||||||
if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true))
|
return ath6kl_restore_htcap(vif);
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
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);
|
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||||
u16 interval;
|
u16 interval;
|
||||||
int ret;
|
int ret;
|
||||||
u8 i;
|
|
||||||
|
|
||||||
if (ar->state != ATH6KL_STATE_ON)
|
if (ar->state != ATH6KL_STATE_ON)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||||||
if (vif->sme_state != SME_DISCONNECTED)
|
if (vif->sme_state != SME_DISCONNECTED)
|
||||||
return -EBUSY;
|
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);
|
ath6kl_cfg80211_scan_complete_event(vif, true);
|
||||||
|
|
||||||
for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
|
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
|
request->n_ssids);
|
||||||
i, DISABLE_SSID_FLAG,
|
if (ret < 0)
|
||||||
0, NULL);
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
/* fw uses seconds, also make sure that it's >0 */
|
/* fw uses seconds, also make sure that it's >0 */
|
||||||
interval = max_t(u16, 1, request->interval / 1000);
|
interval = max_t(u16, 1, request->interval / 1000);
|
||||||
|
|
||||||
ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
|
ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
|
||||||
interval, interval,
|
interval, interval,
|
||||||
10, 0, 0, 0, 3, 0, 0, 0);
|
vif->bg_scan_period, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||||
ATH6KL_WOW_MODE_ENABLE,
|
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;
|
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
|
||||||
|
|
||||||
if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
|
if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
|
||||||
ath6kl_warn("ath6kl_deep_sleep_enable: "
|
ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n");
|
||||||
"wmi_powermode_cmd failed\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
|||||||
vif->next_mode = nw_type;
|
vif->next_mode = nw_type;
|
||||||
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
||||||
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
||||||
|
vif->bg_scan_period = 0;
|
||||||
vif->htcap.ht_enable = true;
|
vif->htcap.ht_enable = true;
|
||||||
|
|
||||||
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
||||||
@@ -3393,6 +3451,7 @@ err:
|
|||||||
int ath6kl_cfg80211_init(struct ath6kl *ar)
|
int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = ar->wiphy;
|
struct wiphy *wiphy = ar->wiphy;
|
||||||
|
bool band_2gig = false, band_5gig = false, ht = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
|
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 */
|
/* max num of ssids that can be probed during scanning */
|
||||||
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
|
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
|
||||||
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
|
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
|
||||||
|
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;
|
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
|
||||||
|
if (band_5gig)
|
||||||
wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
|
wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
|
||||||
|
|
||||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||||
|
|
||||||
wiphy->cipher_suites = cipher_suites;
|
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_min_len = 1;
|
||||||
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
|
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 |
|
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
|
||||||
WIPHY_FLAG_HAVE_AP_SME |
|
WIPHY_FLAG_HAVE_AP_SME |
|
||||||
@@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||||||
ar->wiphy->probe_resp_offload =
|
ar->wiphy->probe_resp_offload =
|
||||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
|
||||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
|
||||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
|
||||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
|
|
||||||
|
|
||||||
ret = wiphy_register(wiphy);
|
ret = wiphy_register(wiphy);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode {
|
|||||||
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
||||||
enum nl80211_iftype type,
|
enum nl80211_iftype type,
|
||||||
u8 fw_vif_idx, u8 nw_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_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
|
||||||
|
|
||||||
void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user