diff options
Diffstat (limited to 'drivers/net')
329 files changed, 26373 insertions, 10434 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 77c1fab7d774..f6668cdaac85 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -883,14 +883,6 @@ config BFIN_RX_DESC_NUM help Set the number of buffer packets used in driver. -config BFIN_MAC_RMII - bool "RMII PHY Interface" - depends on BFIN_MAC - default y if BFIN527_EZKIT - default n if BFIN537_STAMP - help - Use Reduced PHY MII Interface - config BFIN_MAC_USE_HWSTAMP bool "Use IEEE 1588 hwstamp" depends on BFIN_MAC && BF518 @@ -954,6 +946,8 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select TI_DAVINCI_MDIO + select TI_DAVINCI_CPDMA select PHYLIB help This driver supports TI's DaVinci Ethernet . @@ -961,6 +955,25 @@ config TI_DAVINCI_EMAC To compile this driver as a module, choose M here: the module will be called davinci_emac_driver. This is recommended. +config TI_DAVINCI_MDIO + tristate "TI DaVinci MDIO Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select PHYLIB + help + This driver supports TI's DaVinci MDIO module. + + To compile this driver as a module, choose M here: the module + will be called davinci_mdio. This is recommended. + +config TI_DAVINCI_CPDMA + tristate "TI DaVinci CPDMA Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + help + This driver supports TI's DaVinci CPDMA dma engine. + + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS @@ -1028,7 +1041,7 @@ config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on ARM || SUPERH + depends on ARM || SUPERH || MN10300 help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -1042,7 +1055,7 @@ config SMC911X config SMSC911X tristate "SMSC LAN911x/LAN921x families embedded ethernet support" - depends on ARM || SUPERH || BLACKFIN || MIPS + depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300 select CRC32 select MII select PHYLIB @@ -1054,6 +1067,14 @@ config SMSC911X <file:Documentation/networking/net-modules.txt>. The module will be called smsc911x. +config SMSC911X_ARCH_HOOKS + def_bool n + depends on SMSC911X + help + If the arch enables this, it allows the arch to implement various + hooks for more comprehensive interrupt control and also to override + the source of the MAC address. + config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" depends on ISA @@ -2520,6 +2541,7 @@ source "drivers/net/stmmac/Kconfig" config PCH_GBE tristate "PCH Gigabit Ethernet" depends on PCI + select MII ---help--- This is a gigabit ethernet driver for Topcliff PCH. Topcliff PCH is the platform controller hub that is used in Intel's diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b8bf93d4a132..652fc6b98039 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,8 @@ obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o +obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o +obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index 3134e5326231..8cb27cb7bca1 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -407,7 +407,7 @@ static noinline int __init addr_accessible(volatile void *regp, int wordflag, int writeflag) { int ret; - long flags; + unsigned long flags; long *vbr, save_berr; local_irq_save(flags); diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index ef4115b897bf..9ab58097fa2e 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -631,8 +631,6 @@ struct atl1c_adapter { extern char atl1c_driver_name[]; extern char atl1c_driver_version[]; -extern int atl1c_up(struct atl1c_adapter *adapter); -extern void atl1c_down(struct atl1c_adapter *adapter); extern void atl1c_reinit_locked(struct atl1c_adapter *adapter); extern s32 atl1c_reset_hw(struct atl1c_hw *hw); extern void atl1c_set_ethtool_ops(struct net_device *netdev); diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 99ffcf667d1f..09b099bfab2b 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -66,6 +66,8 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, int *work_done, int work_to_do); +static int atl1c_up(struct atl1c_adapter *adapter); +static void atl1c_down(struct atl1c_adapter *adapter); static const u16 atl1c_pay_load_size[] = { 128, 256, 512, 1024, 2048, 4096, @@ -2309,7 +2311,7 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) return err; } -int atl1c_up(struct atl1c_adapter *adapter) +static int atl1c_up(struct atl1c_adapter *adapter) { struct net_device *netdev = adapter->netdev; int num; @@ -2351,7 +2353,7 @@ err_alloc_rx: return err; } -void atl1c_down(struct atl1c_adapter *adapter) +static void atl1c_down(struct atl1c_adapter *adapter) { struct net_device *netdev = adapter->netdev; diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index dbd27b8e66bd..43579b3b24ac 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -91,6 +91,8 @@ MODULE_VERSION(ATLX_DRIVER_VERSION); /* Temporary hack for merging atl1 and atl2 */ #include "atlx.c" +static const struct ethtool_ops atl1_ethtool_ops; + /* * This is the only thing that needs to be changed to adjust the * maximum number of ports that the driver can manage. @@ -353,7 +355,7 @@ static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value) * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to read */ -s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data) +static s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data) { u32 val; int i; @@ -553,7 +555,7 @@ static s32 atl1_read_mac_addr(struct atl1_hw *hw) * 1. calcu 32bit CRC for multicast address * 2. reverse crc with MSB to LSB */ -u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) +static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) { u32 crc32, value = 0; int i; @@ -570,7 +572,7 @@ u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) * hw - Struct containing variables accessed by shared code * hash_value - Multicast address hash value */ -void atl1_hash_set(struct atl1_hw *hw, u32 hash_value) +static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value) { u32 hash_bit, hash_reg; u32 mta; @@ -914,7 +916,7 @@ static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex return 0; } -void atl1_set_mac_addr(struct atl1_hw *hw) +static void atl1_set_mac_addr(struct atl1_hw *hw) { u32 value; /* @@ -3658,7 +3660,7 @@ static int atl1_nway_reset(struct net_device *netdev) return 0; } -const struct ethtool_ops atl1_ethtool_ops = { +static const struct ethtool_ops atl1_ethtool_ops = { .get_settings = atl1_get_settings, .set_settings = atl1_set_settings, .get_drvinfo = atl1_get_drvinfo, diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index 9c0ddb273ac8..68de8cbfb3ec 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -56,16 +56,13 @@ struct atl1_adapter; struct atl1_hw; /* function prototypes needed by multiple files */ -u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr); -void atl1_hash_set(struct atl1_hw *hw, u32 hash_value); -s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data); -void atl1_set_mac_addr(struct atl1_hw *hw); +static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr); +static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value); +static void atl1_set_mac_addr(struct atl1_hw *hw); static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static u32 atl1_check_link(struct atl1_adapter *adapter); -extern const struct ethtool_ops atl1_ethtool_ops; - /* hardware definitions specific to L1 */ /* Block IDLE Status Register */ diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index f979ea2d6d3c..afb7f7dd1bb1 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c @@ -41,6 +41,10 @@ #include "atlx.h" +static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data); +static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr); +static void atlx_set_mac_addr(struct atl1_hw *hw); + static struct atlx_spi_flash_dev flash_table[] = { /* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SEC_ERS CHIP_ERS */ {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62}, diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 1e7f305ed00b..36eca1ce75d4 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1471,42 +1471,6 @@ err: return status; } -/* Uses sync mcc */ -int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, - u8 *connector) -{ - struct be_mcc_wrb *wrb; - struct be_cmd_req_port_type *req; - int status; - - spin_lock_bh(&adapter->mcc_lock); - - wrb = wrb_from_mccq(adapter); - if (!wrb) { - status = -EBUSY; - goto err; - } - req = embedded_payload(wrb); - - be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0, - OPCODE_COMMON_READ_TRANSRECV_DATA); - - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_READ_TRANSRECV_DATA, sizeof(*req)); - - req->port = cpu_to_le32(port); - req->page_num = cpu_to_le32(TR_PAGE_A0); - status = be_mcc_notify_wait(adapter); - if (!status) { - struct be_cmd_resp_port_type *resp = embedded_payload(wrb); - *connector = resp->data.connector; - } - -err: - spin_unlock_bh(&adapter->mcc_lock); - return status; -} - int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_type, u32 flash_opcode, u32 buf_size) { diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index c7f6cdfe1c73..8469ff061f30 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -1022,8 +1022,6 @@ extern int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon, u8 status, u8 state); extern int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state); -extern int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, - u8 *connector); extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 45b1f6635282..c36cd2ffbadc 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -849,20 +849,16 @@ static void be_rx_stats_update(struct be_rx_obj *rxo, stats->rx_mcast_pkts++; } -static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) +static inline bool csum_passed(struct be_eth_rx_compl *rxcp) { - u8 l4_cksm, ip_version, ipcksm, tcpf = 0, udpf = 0, ipv6_chk; + u8 l4_cksm, ipv6, ipcksm; l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp); - ip_version = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp); - if (ip_version) { - tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); - udpf = AMAP_GET_BITS(struct amap_eth_rx_compl, udpf, rxcp); - } - ipv6_chk = (ip_version && (tcpf || udpf)); + ipv6 = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp); - return ((l4_cksm && ipv6_chk && ipcksm) && cso) ? false : true; + /* Ignore ipcksm for ipv6 pkts */ + return l4_cksm && (ipcksm || ipv6); } static struct be_rx_page_info * @@ -1017,10 +1013,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd); - if (do_pkt_csum(rxcp, adapter->rx_csum)) - skb_checksum_none_assert(skb); - else + if (likely(adapter->rx_csum && csum_passed(rxcp))) skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, adapter->netdev); @@ -1674,7 +1670,7 @@ static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo, return (tcp_frame && !err) ? true : false; } -int be_poll_rx(struct napi_struct *napi, int budget) +static int be_poll_rx(struct napi_struct *napi, int budget) { struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq); @@ -1806,6 +1802,20 @@ static void be_worker(struct work_struct *work) struct be_rx_obj *rxo; int i; + /* when interrupts are not yet enabled, just reap any pending + * mcc completions */ + if (!netif_running(adapter->netdev)) { + int mcc_compl, status = 0; + + mcc_compl = be_process_mcc(adapter, &status); + + if (mcc_compl) { + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); + } + goto reschedule; + } + if (!adapter->stats_ioctl_sent) be_cmd_get_stats(adapter, &adapter->stats_cmd); @@ -1824,6 +1834,7 @@ static void be_worker(struct work_struct *work) if (!adapter->ue_detected) be_detect_dump_ue(adapter); +reschedule: schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } @@ -2019,8 +2030,6 @@ static int be_close(struct net_device *netdev) struct be_eq_obj *tx_eq = &adapter->tx_eq; int vec, i; - cancel_delayed_work_sync(&adapter->work); - be_async_mcc_disable(adapter); netif_stop_queue(netdev); @@ -2085,8 +2094,6 @@ static int be_open(struct net_device *netdev) /* Now that interrupts are on we can process async mcc */ be_async_mcc_enable(adapter); - schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); - status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); if (status) @@ -2299,9 +2306,6 @@ static int be_clear(struct be_adapter *adapter) #define FW_FILE_HDR_SIGN "ServerEngines Corp. " -char flash_cookie[2][16] = {"*** SE FLAS", - "H DIRECTORY *** "}; - static bool be_flash_redboot(struct be_adapter *adapter, const u8 *p, u32 img_start, int image_size, int hdr_size) @@ -2559,7 +2563,6 @@ static void be_netdev_init(struct net_device *netdev) netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, BE_NAPI_WEIGHT); - netif_carrier_off(netdev); netif_stop_queue(netdev); } @@ -2715,6 +2718,8 @@ static void __devexit be_remove(struct pci_dev *pdev) if (!adapter) return; + cancel_delayed_work_sync(&adapter->work); + unregister_netdev(adapter->netdev); be_clear(adapter); @@ -2868,8 +2873,10 @@ static int __devinit be_probe(struct pci_dev *pdev, status = register_netdev(netdev); if (status != 0) goto unsetup; + netif_carrier_off(netdev); dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); return 0; unsetup: diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index f7233191162b..ce1e5e9d06f6 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -1,7 +1,7 @@ /* * Blackfin On-Chip MAC Driver * - * Copyright 2004-2007 Analog Devices Inc. + * Copyright 2004-2010 Analog Devices Inc. * * Enter bugs at http://blackfin.uclinux.org/ * @@ -23,7 +23,6 @@ #include <linux/device.h> #include <linux/spinlock.h> #include <linux/mii.h> -#include <linux/phy.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> @@ -76,12 +75,6 @@ static struct net_dma_desc_tx *current_tx_ptr; static struct net_dma_desc_tx *tx_desc; static struct net_dma_desc_rx *rx_desc; -#if defined(CONFIG_BFIN_MAC_RMII) -static u16 pin_req[] = P_RMII0; -#else -static u16 pin_req[] = P_MII0; -#endif - static void desc_list_free(void) { struct net_dma_desc_rx *r; @@ -347,23 +340,23 @@ static void bfin_mac_adjust_link(struct net_device *dev) } if (phydev->speed != lp->old_speed) { -#if defined(CONFIG_BFIN_MAC_RMII) - u32 opmode = bfin_read_EMAC_OPMODE(); - switch (phydev->speed) { - case 10: - opmode |= RMII_10; - break; - case 100: - opmode &= ~(RMII_10); - break; - default: - printk(KERN_WARNING - "%s: Ack! Speed (%d) is not 10/100!\n", - DRV_NAME, phydev->speed); - break; + if (phydev->interface == PHY_INTERFACE_MODE_RMII) { + u32 opmode = bfin_read_EMAC_OPMODE(); + switch (phydev->speed) { + case 10: + opmode |= RMII_10; + break; + case 100: + opmode &= ~RMII_10; + break; + default: + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not 10/100!\n", + DRV_NAME, phydev->speed); + break; + } + bfin_write_EMAC_OPMODE(opmode); } - bfin_write_EMAC_OPMODE(opmode); -#endif new_state = 1; lp->old_speed = phydev->speed; @@ -392,7 +385,7 @@ static void bfin_mac_adjust_link(struct net_device *dev) /* MDC = 2.5 MHz */ #define MDC_CLK 2500000 -static int mii_probe(struct net_device *dev) +static int mii_probe(struct net_device *dev, int phy_mode) { struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev = NULL; @@ -411,8 +404,8 @@ static int mii_probe(struct net_device *dev) sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div); bfin_write_EMAC_SYSCTL(sysctl); - /* search for connect PHY device */ - for (i = 0; i < PHY_MAX_ADDR; i++) { + /* search for connected PHY device */ + for (i = 0; i < PHY_MAX_ADDR; ++i) { struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i]; if (!tmp_phydev) @@ -429,13 +422,14 @@ static int mii_probe(struct net_device *dev) return -ENODEV; } -#if defined(CONFIG_BFIN_MAC_RMII) - phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, - 0, PHY_INTERFACE_MODE_RMII); -#else + if (phy_mode != PHY_INTERFACE_MODE_RMII && + phy_mode != PHY_INTERFACE_MODE_MII) { + printk(KERN_INFO "%s: Invalid phy interface mode\n", dev->name); + return -EINVAL; + } + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, - 0, PHY_INTERFACE_MODE_MII); -#endif + 0, phy_mode); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); @@ -570,6 +564,8 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = { /**************************************************************************/ void setup_system_regs(struct net_device *dev) { + struct bfin_mac_local *lp = netdev_priv(dev); + int i; unsigned short sysctl; /* @@ -577,6 +573,15 @@ void setup_system_regs(struct net_device *dev) * Configure checksum support and rcve frame word alignment */ sysctl = bfin_read_EMAC_SYSCTL(); + /* + * check if interrupt is requested for any PHY, + * enable PHY interrupt only if needed + */ + for (i = 0; i < PHY_MAX_ADDR; ++i) + if (lp->mii_bus->irq[i] != PHY_POLL) + break; + if (i < PHY_MAX_ADDR) + sysctl |= PHYIE; sysctl |= RXDWA; #if defined(BFIN_MAC_CSUM_OFFLOAD) sysctl |= RXCKS; @@ -1203,7 +1208,7 @@ static void bfin_mac_disable(void) /* * Enable Interrupts, Receive, and Transmit */ -static int bfin_mac_enable(void) +static int bfin_mac_enable(struct phy_device *phydev) { int ret; u32 opmode; @@ -1233,12 +1238,13 @@ static int bfin_mac_enable(void) opmode |= DRO | DC | PSF; opmode |= RE; -#if defined(CONFIG_BFIN_MAC_RMII) - opmode |= RMII; /* For Now only 100MBit are supported */ + if (phydev->interface == PHY_INTERFACE_MODE_RMII) { + opmode |= RMII; /* For Now only 100MBit are supported */ #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2 - opmode |= TE; -#endif + opmode |= TE; #endif + } + /* Turn on the EMAC rx */ bfin_write_EMAC_OPMODE(opmode); @@ -1270,7 +1276,7 @@ static void bfin_mac_timeout(struct net_device *dev) if (netif_queue_stopped(lp->ndev)) netif_wake_queue(lp->ndev); - bfin_mac_enable(); + bfin_mac_enable(lp->phydev); /* We can accept TX packets again */ dev->trans_start = jiffies; /* prevent tx timeout */ @@ -1342,11 +1348,19 @@ static void bfin_mac_set_multicast_list(struct net_device *dev) static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { + struct bfin_mac_local *lp = netdev_priv(netdev); + + if (!netif_running(netdev)) + return -EINVAL; + switch (cmd) { case SIOCSHWTSTAMP: return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); default: - return -EOPNOTSUPP; + if (lp->phydev) + return phy_mii_ioctl(lp->phydev, ifr, cmd); + else + return -EOPNOTSUPP; } } @@ -1394,7 +1408,7 @@ static int bfin_mac_open(struct net_device *dev) setup_mac_addr(dev->dev_addr); bfin_mac_disable(); - ret = bfin_mac_enable(); + ret = bfin_mac_enable(lp->phydev); if (ret) return ret; pr_debug("hardware init finished\n"); @@ -1450,6 +1464,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) struct net_device *ndev; struct bfin_mac_local *lp; struct platform_device *pd; + struct bfin_mii_bus_platform_data *mii_bus_data; int rc; ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); @@ -1501,11 +1516,12 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) if (!lp->mii_bus) { dev_err(&pdev->dev, "Cannot get mii_bus!\n"); rc = -ENODEV; - goto out_err_mii_bus_probe; + goto out_err_probe_mac; } lp->mii_bus->priv = ndev; + mii_bus_data = pd->dev.platform_data; - rc = mii_probe(ndev); + rc = mii_probe(ndev, mii_bus_data->phy_mode); if (rc) { dev_err(&pdev->dev, "MII Probe failed!\n"); goto out_err_mii_probe; @@ -1552,8 +1568,6 @@ out_err_request_irq: out_err_mii_probe: mdiobus_unregister(lp->mii_bus); mdiobus_free(lp->mii_bus); -out_err_mii_bus_probe: - peripheral_free_list(pin_req); out_err_probe_mac: platform_set_drvdata(pdev, NULL); free_netdev(ndev); @@ -1576,8 +1590,6 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev) free_netdev(ndev); - peripheral_free_list(pin_req); - return 0; } @@ -1623,12 +1635,21 @@ static int bfin_mac_resume(struct platform_device *pdev) static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) { struct mii_bus *miibus; + struct bfin_mii_bus_platform_data *mii_bus_pd; + const unsigned short *pin_req; int rc, i; + mii_bus_pd = dev_get_platdata(&pdev->dev); + if (!mii_bus_pd) { + dev_err(&pdev->dev, "No peripherals in platform data!\n"); + return -EINVAL; + } + /* * We are setting up a network card, * so set the GPIO pins to Ethernet mode */ + pin_req = mii_bus_pd->mac_peripherals; rc = peripheral_request_list(pin_req, DRV_NAME); if (rc) { dev_err(&pdev->dev, "Requesting peripherals failed!\n"); @@ -1645,13 +1666,30 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) miibus->parent = &pdev->dev; miibus->name = "bfin_mii_bus"; + miibus->phy_mask = mii_bus_pd->phy_mask; + snprintf(miibus->id, MII_BUS_ID_SIZE, "0"); miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - if (miibus->irq == NULL) - goto out_err_alloc; - for (i = 0; i < PHY_MAX_ADDR; ++i) + if (!miibus->irq) + goto out_err_irq_alloc; + + for (i = rc; i < PHY_MAX_ADDR; ++i) miibus->irq[i] = PHY_POLL; + rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR); + if (rc != mii_bus_pd->phydev_number) + dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n", + mii_bus_pd->phydev_number); + for (i = 0; i < rc; ++i) { + unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr; + if (phyaddr < PHY_MAX_ADDR) + miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq; + else + dev_err(&pdev->dev, + "Invalid PHY address %i for phydev %i\n", + phyaddr, i); + } + rc = mdiobus_register(miibus); if (rc) { dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); @@ -1663,6 +1701,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) out_err_mdiobus_register: kfree(miibus->irq); +out_err_irq_alloc: mdiobus_free(miibus); out_err_alloc: peripheral_free_list(pin_req); @@ -1673,11 +1712,15 @@ out_err_alloc: static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) { struct mii_bus *miibus = platform_get_drvdata(pdev); + struct bfin_mii_bus_platform_data *mii_bus_pd = + dev_get_platdata(&pdev->dev); + platform_set_drvdata(pdev, NULL); mdiobus_unregister(miibus); kfree(miibus->irq); mdiobus_free(miibus); - peripheral_free_list(pin_req); + peripheral_free_list(mii_bus_pd->mac_peripherals); + return 0; } diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h index 04e4050df18b..aed68bed2365 100644 --- a/drivers/net/bfin_mac.h +++ b/drivers/net/bfin_mac.h @@ -14,6 +14,8 @@ #include <linux/clocksource.h> #include <linux/timecompare.h> #include <linux/timer.h> +#include <linux/etherdevice.h> +#include <linux/bfin_mac.h> #define BFIN_MAC_CSUM_OFFLOAD diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 9571ecf48f35..9eea225decaf 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1288,15 +1288,11 @@ struct bnx2x_func_init_params { #define WAIT_RAMROD_POLL 0x01 #define WAIT_RAMROD_COMMON 0x02 -int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, - int *state_p, int flags); /* dmae */ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, u32 len32); -void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, - u32 addr, u32 len); void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx); u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type); u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode); @@ -1307,7 +1303,6 @@ int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port); int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port); u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param); -void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); void bnx2x_calc_fc_adv(struct bnx2x *bp); int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index bc5837514074..459614d2d7bc 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -25,6 +25,7 @@ #include "bnx2x_init.h" +static int bnx2x_setup_irqs(struct bnx2x *bp); /* free skb in the packet ring at pos idx * return idx of last bd freed @@ -2187,7 +2188,7 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p) } -int bnx2x_setup_irqs(struct bnx2x *bp) +static int bnx2x_setup_irqs(struct bnx2x *bp) { int rc = 0; if (bp->flags & USING_MSIX_FLAG) { diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 5bfe0ab1d2d4..6b28739c5302 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -117,13 +117,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); void bnx2x_int_enable(struct bnx2x *bp); /** - * Disable HW interrupts. - * - * @param bp - */ -void bnx2x_int_disable(struct bnx2x *bp); - -/** * Disable interrupts. This function ensures that there are no * ISRs or SP DPCs (sp_task) are running after it returns. * @@ -192,17 +185,6 @@ int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp, int is_leading); /** - * Bring down an eth client. - * - * @param bp - * @param p - * - * @return int - */ -int bnx2x_stop_fw_client(struct bnx2x *bp, - struct bnx2x_client_ramrod_params *p); - -/** * Set number of queues according to mode * * @param bp @@ -250,34 +232,6 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource); */ void bnx2x_set_eth_mac(struct bnx2x *bp, int set); -#ifdef BCM_CNIC -/** - * Set iSCSI MAC(s) at the next enties in the CAM after the ETH - * MAC(s). The function will wait until the ramrod completion - * returns. - * - * @param bp driver handle - * @param set set or clear the CAM entry - * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. - */ -int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set); -#endif - -/** - * Initialize status block in FW and HW - * - * @param bp driver handle - * @param dma_addr_t mapping - * @param int sb_id - * @param int vfid - * @param u8 vf_valid - * @param int fw_sb_id - * @param int igu_sb_id - */ -void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, - u8 vf_valid, int fw_sb_id, int igu_sb_id); - /** * Set MAC filtering configurations. * @@ -326,7 +280,6 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe); * @return int */ int bnx2x_func_start(struct bnx2x *bp); -int bnx2x_func_stop(struct bnx2x *bp); /** * Prepare ILT configurations according to current driver @@ -396,14 +349,6 @@ int bnx2x_enable_msix(struct bnx2x *bp); int bnx2x_enable_msi(struct bnx2x *bp); /** - * Request IRQ vectors from OS. - * - * @param bp - * - * @return int - */ -int bnx2x_setup_irqs(struct bnx2x *bp); -/** * NAPI callback * * @param napi diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h index e65de784182c..a306b0e46b61 100644 --- a/drivers/net/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/bnx2x/bnx2x_init_ops.h @@ -16,7 +16,9 @@ #define BNX2X_INIT_OPS_H static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len); - +static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); +static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, + u32 addr, u32 len); static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, u32 len) @@ -589,7 +591,7 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop) return rc; } -int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop) +static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop) { int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop); if (!rc) @@ -635,7 +637,7 @@ static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt, } } -void bnx2x_ilt_boundry_init_op(struct bnx2x *bp, +static void bnx2x_ilt_boundry_init_op(struct bnx2x *bp, struct ilt_client_info *ilt_cli, u32 ilt_start, u8 initop) { @@ -688,8 +690,10 @@ void bnx2x_ilt_boundry_init_op(struct bnx2x *bp, } } -void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, struct bnx2x_ilt *ilt, - struct ilt_client_info *ilt_cli, u8 initop) +static void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, + struct bnx2x_ilt *ilt, + struct ilt_client_info *ilt_cli, + u8 initop) { int i; @@ -703,8 +707,8 @@ void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, struct bnx2x_ilt *ilt, bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop); } -void bnx2x_ilt_client_init_op(struct bnx2x *bp, - struct ilt_client_info *ilt_cli, u8 initop) +static void bnx2x_ilt_client_init_op(struct bnx2x *bp, + struct ilt_client_info *ilt_cli, u8 initop) { struct bnx2x_ilt *ilt = BP_ILT(bp); @@ -720,7 +724,7 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp, bnx2x_ilt_client_init_op(bp, ilt_cli, initop); } -void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop) +static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop) { bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop); bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop); @@ -752,7 +756,7 @@ static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num, * called during init common stage, ilt clients should be initialized * prioir to calling this function */ -void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop) +static void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop) { bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU, PXP2_REG_RQ_CDU_P_SIZE, initop); @@ -772,8 +776,8 @@ void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop) #define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT) /* called during init port stage */ -void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count, - u8 initop) +static void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count, + u8 initop) { int port = BP_PORT(bp); @@ -814,8 +818,8 @@ static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count) } /* called during init common stage */ -void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, - u8 initop) +static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, + u8 initop) { if (!QM_INIT(qm_cid_count)) return; @@ -836,8 +840,8 @@ void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, ****************************************************************************/ /* called during init func stage */ -void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, - dma_addr_t t2_mapping, int src_cid_count) +static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, + dma_addr_t t2_mapping, int src_cid_count) { int i; int port = BP_PORT(bp); diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 3e99bf9c42b9..2326774df843 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -181,6 +181,12 @@ (_bank + (_addr & 0xf)), \ _val) +static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, + u8 devad, u16 reg, u16 *ret_val); + +static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, + u8 devad, u16 reg, u16 val); + static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits) { u32 val = REG_RD(bp, reg); @@ -594,7 +600,7 @@ static u8 bnx2x_bmac2_enable(struct link_params *params, return 0; } -u8 bnx2x_bmac_enable(struct link_params *params, +static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars, u8 is_lb) { @@ -2537,122 +2543,6 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy, } } -/* - *------------------------------------------------------------------------ - * bnx2x_override_led_value - - * - * Override the led value of the requested led - * - *------------------------------------------------------------------------ - */ -u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, - u32 led_idx, u32 value) -{ - u32 reg_val; - - /* If port 0 then use EMAC0, else use EMAC1*/ - u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - - DP(NETIF_MSG_LINK, - "bnx2x_override_led_value() port %x led_idx %d value %d\n", - port, led_idx, value); - - switch (led_idx) { - case 0: /* 10MB led */ - /* Read the current value of the LED register in - the EMAC block */ - reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); - /* Set the OVERRIDE bit to 1 */ - reg_val |= EMAC_LED_OVERRIDE; - /* If value is 1, set the 10M_OVERRIDE bit, - otherwise reset it.*/ - reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) : - (reg_val & ~EMAC_LED_10MB_OVERRIDE); - REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); - break; - case 1: /*100MB led */ - /*Read the current value of the LED register in - the EMAC block */ - reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); - /* Set the OVERRIDE bit to 1 */ - reg_val |= EMAC_LED_OVERRIDE; - /* If value is 1, set the 100M_OVERRIDE bit, - otherwise reset it.*/ - reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) : - (reg_val & ~EMAC_LED_100MB_OVERRIDE); - REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); - break; - case 2: /* 1000MB led */ - /* Read the current value of the LED register in the - EMAC block */ - reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); - /* Set the OVERRIDE bit to 1 */ - reg_val |= EMAC_LED_OVERRIDE; - /* If value is 1, set the 1000M_OVERRIDE bit, otherwise - reset it. */ - reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : - (reg_val & ~EMAC_LED_1000MB_OVERRIDE); - REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); - break; - case 3: /* 2500MB led */ - /* Read the current value of the LED register in the - EMAC block*/ - reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); - /* Set the OVERRIDE bit to 1 */ - reg_val |= EMAC_LED_OVERRIDE; - /* If value is 1, set the 2500M_OVERRIDE bit, otherwise - reset it.*/ - reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : - (reg_val & ~EMAC_LED_2500MB_OVERRIDE); - REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); - break; - case 4: /*10G led */ - if (port == 0) { - REG_WR(bp, NIG_REG_LED_10G_P0, - value); - } else { - REG_WR(bp, NIG_REG_LED_10G_P1, - value); - } - break; - case 5: /* TRAFFIC led */ - /* Find if the traffic control is via BMAC or EMAC */ - if (port == 0) - reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN); - else - reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN); - - /* Override the traffic led in the EMAC:*/ - if (reg_val == 1) { - /* Read the current value of the LED register in - the EMAC block */ - reg_val = REG_RD(bp, emac_base + - EMAC_REG_EMAC_LED); - /* Set the TRAFFIC_OVERRIDE bit to 1 */ - reg_val |= EMAC_LED_OVERRIDE; - /* If value is 1, set the TRAFFIC bit, otherwise - reset it.*/ - reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) : - (reg_val & ~EMAC_LED_TRAFFIC); - REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); - } else { /* Override the traffic led in the BMAC: */ - REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 - + port*4, 1); - REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4, - value); - } - break; - default: - DP(NETIF_MSG_LINK, - "bnx2x_override_led_value() unknown led index %d " - "(should be 0-5)\n", led_idx); - return -EINVAL; - } - - return 0; -} - - u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars, u8 mode, u32 speed) { @@ -4099,9 +3989,9 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy, return -EINVAL; } -u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, - struct link_params *params, u16 addr, - u8 byte_cnt, u8 *o_buf) +static u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, + struct link_params *params, u16 addr, + u8 byte_cnt, u8 *o_buf) { if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr, @@ -6819,13 +6709,6 @@ u8 bnx2x_phy_probe(struct link_params *params) return 0; } -u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx) -{ - if (phy_idx < params->num_phys) - return params->phy[phy_idx].supported; - return 0; -} - static void set_phy_vars(struct link_params *params) { struct bnx2x *bp = params->bp; diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h index 58a4c7199276..171abf8097ee 100644 --- a/drivers/net/bnx2x/bnx2x_link.h +++ b/drivers/net/bnx2x/bnx2x_link.h @@ -279,12 +279,6 @@ u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr, u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr, u8 devad, u16 reg, u16 val); - -u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, - u8 devad, u16 reg, u16 *ret_val); - -u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, - u8 devad, u16 reg, u16 val); /* Reads the link_status from the shmem, and update the link vars accordingly */ void bnx2x_link_status_update(struct link_params *input, @@ -304,8 +298,6 @@ u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars, #define LED_MODE_OPER 2 #define LED_MODE_FRONT_PANEL_OFF 3 -u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, u32 led_idx, u32 value); - /* bnx2x_handle_module_detect_int should be called upon module detection interrupt */ void bnx2x_handle_module_detect_int(struct link_params *params); @@ -325,19 +317,12 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port); /* Reset the external of SFX7101 */ void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy); -u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, - struct link_params *params, u16 addr, - u8 byte_cnt, u8 *o_buf); - void bnx2x_hw_reset_phy(struct link_params *params); /* Checks if HW lock is required for this phy/board type */ u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base); -/* Returns the aggregative supported attributes of the phys on board */ -u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx); - /* Check swap bit and adjust PHY order */ u32 bnx2x_phy_selection(struct link_params *params); diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index ff99a2fc0426..e9ad16f00b56 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -403,7 +403,7 @@ static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port, /* used only at init * locking is done by mcp */ -void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val) +static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val) { pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, addr); pci_write_config_dword(bp->pdev, PCICFG_GRC_DATA, val); @@ -429,7 +429,8 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) #define DMAE_DP_DST_PCI "pci dst_addr [%x:%08x]" #define DMAE_DP_DST_NONE "dst_addr [none]" -void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl) +static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, + int msglvl) { u32 src_type = dmae->opcode & DMAE_COMMAND_SRC; @@ -551,8 +552,9 @@ u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type, return opcode; } -void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae, - u8 src_type, u8 dst_type) +static void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, + struct dmae_command *dmae, + u8 src_type, u8 dst_type) { memset(dmae, 0, sizeof(struct dmae_command)); @@ -567,7 +569,8 @@ void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae, } /* issue a dmae command over the init-channel and wailt for completion */ -int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae) +static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, + struct dmae_command *dmae) { u32 *wb_comp = bnx2x_sp(bp, wb_comp); int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 40; @@ -674,8 +677,8 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) bnx2x_issue_dmae_with_comp(bp, &dmae); } -void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, - u32 addr, u32 len) +static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, + u32 addr, u32 len) { int dmae_wr_max = DMAE_LEN32_WR_MAX(bp); int offset = 0; @@ -1267,7 +1270,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp) BNX2X_ERR("BUG! proper val not read from IGU!\n"); } -void bnx2x_int_disable(struct bnx2x *bp) +static void bnx2x_int_disable(struct bnx2x *bp) { if (bp->common.int_block == INT_BLOCK_HC) bnx2x_hc_int_disable(bp); @@ -2236,7 +2239,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) } /* must be called under rtnl_lock */ -void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) +static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) { u32 mask = (1 << cl_id); @@ -2303,7 +2306,7 @@ void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) bp->mac_filters.unmatched_unicast & ~mask; } -void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) +static void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) { struct tstorm_eth_function_common_config tcfg = {0}; u16 rss_flgs; @@ -2460,7 +2463,7 @@ static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp, txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0; } -void bnx2x_pf_init(struct bnx2x *bp) +static void bnx2x_pf_init(struct bnx2x *bp) { struct bnx2x_func_init_params func_init = {0}; struct bnx2x_rss_params rss = {0}; @@ -3928,7 +3931,7 @@ void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm, hc_sm->time_to_expire = 0xFFFFFFFF; } -void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, +static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, u8 vf_valid, int fw_sb_id, int igu_sb_id) { int igu_seg_id; @@ -6021,6 +6024,9 @@ alloc_mem_err: /* * Init service functions */ +static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, + int *state_p, int flags); + int bnx2x_func_start(struct bnx2x *bp) { bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1); @@ -6030,7 +6036,7 @@ int bnx2x_func_start(struct bnx2x *bp) WAIT_RAMROD_COMMON); } -int bnx2x_func_stop(struct bnx2x *bp) +static int bnx2x_func_stop(struct bnx2x *bp) { bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1); @@ -6103,8 +6109,8 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, u8 *mac, bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags); } -int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, - int *state_p, int flags) +static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, + int *state_p, int flags) { /* can take a while if any port is running */ int cnt = 5000; @@ -6154,7 +6160,7 @@ int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, return -EBUSY; } -u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset) +static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset) { if (CHIP_IS_E1H(bp)) return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp); @@ -6273,7 +6279,7 @@ static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp) * * @return 0 if cussess, -ENODEV if ramrod doesn't return. */ -int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) +static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) { u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) : bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE)); @@ -6383,11 +6389,11 @@ static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid) ETH_CONNECTION_TYPE); } -int bnx2x_setup_fw_client(struct bnx2x *bp, - struct bnx2x_client_init_params *params, - u8 activate, - struct client_init_ramrod_data *data, - dma_addr_t data_mapping) +static int bnx2x_setup_fw_client(struct bnx2x *bp, + struct bnx2x_client_init_params *params, + u8 activate, + struct client_init_ramrod_data *data, + dma_addr_t data_mapping) { u16 hc_usec; int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP; @@ -6633,7 +6639,8 @@ int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp, return rc; } -int bnx2x_stop_fw_client(struct bnx2x *bp, struct bnx2x_client_ramrod_params *p) +static int bnx2x_stop_fw_client(struct bnx2x *bp, + struct bnx2x_client_ramrod_params *p) { int rc; @@ -7440,7 +7447,7 @@ reset_task_exit: * Init service functions */ -u32 bnx2x_get_pretend_reg(struct bnx2x *bp) +static u32 bnx2x_get_pretend_reg(struct bnx2x *bp) { u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0; u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index beb3b7cecd52..bdb68a600382 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -493,9 +493,9 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct slave *slave; int i; - write_lock(&bond->lock); + write_lock_bh(&bond->lock); bond->vlgrp = grp; - write_unlock(&bond->lock); + write_unlock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { struct net_device *slave_dev = slave->dev; diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig index 75bfc3a9d95f..09ed3f42d673 100644 --- a/drivers/net/caif/Kconfig +++ b/drivers/net/caif/Kconfig @@ -31,3 +31,10 @@ config CAIF_SPI_SYNC Putting the next command and length in the start of the frame can help to synchronize to the next transfer in case of over or under-runs. This option also needs to be enabled on the modem. + +config CAIF_SHM + tristate "CAIF shared memory protocol driver" + depends on CAIF && U5500_MBOX + default n + ---help--- + The CAIF shared memory protocol driver for the STE UX5500 platform. diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile index 3a11d619452b..b38d987da67d 100644 --- a/drivers/net/caif/Makefile +++ b/drivers/net/caif/Makefile @@ -8,3 +8,7 @@ obj-$(CONFIG_CAIF_TTY) += caif_serial.o # SPI slave physical interfaces module cfspi_slave-objs := caif_spi.o caif_spi_slave.o obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o + +# Shared memory +caif_shm-objs := caif_shmcore.o caif_shm_u5500.o +obj-$(CONFIG_CAIF_SHM) += caif_shm.o diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c new file mode 100644 index 000000000000..1cd90da86f13 --- /dev/null +++ b/drivers/net/caif/caif_shm_u5500.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com + * Author: Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt + +#include <linux/version.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <mach/mbox.h> +#include <net/caif/caif_shm.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CAIF Shared Memory protocol driver"); + +#define MAX_SHM_INSTANCES 1 + +enum { + MBX_ACC0, + MBX_ACC1, + MBX_DSP +}; + +static struct shmdev_layer shmdev_lyr[MAX_SHM_INSTANCES]; + +static unsigned int shm_start; +static unsigned int shm_size; + +module_param(shm_size, uint , 0440); +MODULE_PARM_DESC(shm_total_size, "Start of SHM shared memory"); + +module_param(shm_start, uint , 0440); +MODULE_PARM_DESC(shm_total_start, "Total Size of SHM shared memory"); + +static int shmdev_send_msg(u32 dev_id, u32 mbx_msg) +{ + /* Always block until msg is written successfully */ + mbox_send(shmdev_lyr[dev_id].hmbx, mbx_msg, true); + return 0; +} + +static int shmdev_mbx_setup(void *pshmdrv_cb, struct shmdev_layer *pshm_dev, + void *pshm_drv) +{ + /* + * For UX5500, we have only 1 SHM instance which uses MBX0 + * for communication with the peer modem + */ + pshm_dev->hmbx = mbox_setup(MBX_ACC0, pshmdrv_cb, pshm_drv); + + if (!pshm_dev->hmbx) + return -ENODEV; + else + return 0; +} + +static int __init caif_shmdev_init(void) +{ + int i, result; + + /* Loop is currently overkill, there is only one instance */ + for (i = 0; i < MAX_SHM_INSTANCES; i++) { + + shmdev_lyr[i].shm_base_addr = shm_start; + shmdev_lyr[i].shm_total_sz = shm_size; + + if (((char *)shmdev_lyr[i].shm_base_addr == NULL) + || (shmdev_lyr[i].shm_total_sz <= 0)) { + pr_warn("ERROR," + "Shared memory Address and/or Size incorrect" + ", Bailing out ...\n"); + result = -EINVAL; + goto clean; + } + + pr_info("SHM AREA (instance %d) STARTS" + " AT %p\n", i, (char *)shmdev_lyr[i].shm_base_addr); + + shmdev_lyr[i].shm_id = i; + shmdev_lyr[i].pshmdev_mbxsend = shmdev_send_msg; + shmdev_lyr[i].pshmdev_mbxsetup = shmdev_mbx_setup; + + /* + * Finally, CAIF core module is called with details in place: + * 1. SHM base address + * 2. SHM size + * 3. MBX handle + */ + result = caif_shmcore_probe(&shmdev_lyr[i]); + if (result) { + pr_warn("ERROR[%d]," + "Could not probe SHM core (instance %d)" + " Bailing out ...\n", result, i); + goto clean; + } + } + + return 0; + +clean: + /* + * For now, we assume that even if one instance of SHM fails, we bail + * out of the driver support completely. For this, we need to release + * any memory allocated and unregister any instance of SHM net device. + */ + for (i = 0; i < MAX_SHM_INSTANCES; i++) { + if (shmdev_lyr[i].pshm_netdev) + unregister_netdev(shmdev_lyr[i].pshm_netdev); + } + return result; +} + +static void __exit caif_shmdev_exit(void) +{ + int i; + + for (i = 0; i < MAX_SHM_INSTANCES; i++) { + caif_shmcore_remove(shmdev_lyr[i].pshm_netdev); + kfree((void *)shmdev_lyr[i].shm_base_addr); + } + +} + +module_init(caif_shmdev_init); +module_exit(caif_shmdev_exit); diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c new file mode 100644 index 000000000000..19f9c0656667 --- /dev/null +++ b/drivers/net/caif/caif_shmcore.c @@ -0,0 +1,744 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com + * Authors: Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com, + * Daniel Martensson / daniel.martensson@stericsson.com + * License terms: GNU General Public License (GPL) version 2 + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt + +#include <linux/spinlock.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/netdevice.h> +#include <linux/if_arp.h> + +#include <net/caif/caif_device.h> +#include <net/caif/caif_shm.h> + +#define NR_TX_BUF 6 +#define NR_RX_BUF 6 +#define TX_BUF_SZ 0x2000 +#define RX_BUF_SZ 0x2000 + +#define CAIF_NEEDED_HEADROOM 32 + +#define CAIF_FLOW_ON 1 +#define CAIF_FLOW_OFF 0 + +#define LOW_WATERMARK 3 +#define HIGH_WATERMARK 4 + +/* Maximum number of CAIF buffers per shared memory buffer. */ +#define SHM_MAX_FRMS_PER_BUF 10 + +/* + * Size in bytes of the descriptor area + * (With end of descriptor signalling) + */ +#define SHM_CAIF_DESC_SIZE ((SHM_MAX_FRMS_PER_BUF + 1) * \ + sizeof(struct shm_pck_desc)) + +/* + * Offset to the first CAIF frame within a shared memory buffer. + * Aligned on 32 bytes. + */ +#define SHM_CAIF_FRM_OFS (SHM_CAIF_DESC_SIZE + (SHM_CAIF_DESC_SIZE % 32)) + +/* Number of bytes for CAIF shared memory header. */ +#define SHM_HDR_LEN 1 + +/* Number of padding bytes for the complete CAIF frame. */ +#define SHM_FRM_PAD_LEN 4 + +#define CAIF_MAX_MTU 4096 + +#define SHM_SET_FULL(x) (((x+1) & 0x0F) << 0) +#define SHM_GET_FULL(x) (((x >> 0) & 0x0F) - 1) + +#define SHM_SET_EMPTY(x) (((x+1) & 0x0F) << 4) +#define SHM_GET_EMPTY(x) (((x >> 4) & 0x0F) - 1) + +#define SHM_FULL_MASK (0x0F << 0) +#define SHM_EMPTY_MASK (0x0F << 4) + +struct shm_pck_desc { + /* + * Offset from start of shared memory area to start of + * shared memory CAIF frame. + */ + u32 frm_ofs; + u32 frm_len; +}; + +struct buf_list { + unsigned char *desc_vptr; + u32 phy_addr; + u32 index; + u32 len; + u32 frames; + u32 frm_ofs; + struct list_head list; +}; + +struct shm_caif_frm { + /* Number of bytes of padding before the CAIF frame. */ + u8 hdr_ofs; +}; + +struct shmdrv_layer { + /* caif_dev_common must always be first in the structure*/ + struct caif_dev_common cfdev; + + u32 shm_tx_addr; + u32 shm_rx_addr; + u32 shm_base_addr; + u32 tx_empty_available; + spinlock_t lock; + + struct list_head tx_empty_list; + struct list_head tx_pend_list; + struct list_head tx_full_list; + struct list_head rx_empty_list; + struct list_head rx_pend_list; + struct list_head rx_full_list; + + struct workqueue_struct *pshm_tx_workqueue; + struct workqueue_struct *pshm_rx_workqueue; + + struct work_struct shm_tx_work; + struct work_struct shm_rx_work; + + struct sk_buff_head sk_qhead; + struct shmdev_layer *pshm_dev; +}; + +static int shm_netdev_open(struct net_device *shm_netdev) +{ + netif_wake_queue(shm_netdev); + return 0; +} + +static int shm_netdev_close(struct net_device *shm_netdev) +{ + netif_stop_queue(shm_netdev); + return 0; +} + +int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv) +{ + struct buf_list *pbuf; + struct shmdrv_layer *pshm_drv; + struct list_head *pos; + u32 avail_emptybuff = 0; + unsigned long flags = 0; + + pshm_drv = (struct shmdrv_layer *)priv; + + /* Check for received buffers. */ + if (mbx_msg & SHM_FULL_MASK) { + int idx; + + spin_lock_irqsave(&pshm_drv->lock, flags); + + /* Check whether we have any outstanding buffers. */ + if (list_empty(&pshm_drv->rx_empty_list)) { + + /* Release spin lock. */ + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* We print even in IRQ context... */ + pr_warn("No empty Rx buffers to fill: " + "mbx_msg:%x\n", mbx_msg); + + /* Bail out. */ + goto err_sync; + } + + pbuf = + list_entry(pshm_drv->rx_empty_list.next, + struct buf_list, list); + idx = pbuf->index; + + /* Check buffer synchronization. */ + if (idx != SHM_GET_FULL(mbx_msg)) { + + /* We print even in IRQ context... */ + pr_warn( + "phyif_shm_mbx_msg_cb: RX full out of sync:" + " idx:%d, msg:%x SHM_GET_FULL(mbx_msg):%x\n", + idx, mbx_msg, SHM_GET_FULL(mbx_msg)); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* Bail out. */ + goto err_sync; + } + + list_del_init(&pbuf->list); + list_add_tail(&pbuf->list, &pshm_drv->rx_full_list); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* Schedule RX work queue. */ + if (!work_pending(&pshm_drv->shm_rx_work)) + queue_work(pshm_drv->pshm_rx_workqueue, + &pshm_drv->shm_rx_work); + } + + /* Check for emptied buffers. */ + if (mbx_msg & SHM_EMPTY_MASK) { + int idx; + + spin_lock_irqsave(&pshm_drv->lock, flags); + + /* Check whether we have any outstanding buffers. */ + if (list_empty(&pshm_drv->tx_full_list)) { + + /* We print even in IRQ context... */ + pr_warn("No TX to empty: msg:%x\n", mbx_msg); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* Bail out. */ + goto err_sync; + } + + pbuf = + list_entry(pshm_drv->tx_full_list.next, + struct buf_list, list); + idx = pbuf->index; + + /* Check buffer synchronization. */ + if (idx != SHM_GET_EMPTY(mbx_msg)) { + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* We print even in IRQ context... */ + pr_warn("TX empty " + "out of sync:idx:%d, msg:%x\n", idx, mbx_msg); + + /* Bail out. */ + goto err_sync; + } + list_del_init(&pbuf->list); + + /* Reset buffer parameters. */ + pbuf->frames = 0; + pbuf->frm_ofs = SHM_CAIF_FRM_OFS; + + list_add_tail(&pbuf->list, &pshm_drv->tx_empty_list); + + /* Check the available no. of buffers in the empty list */ + list_for_each(pos, &pshm_drv->tx_empty_list) + avail_emptybuff++; + + /* Check whether we have to wake up the transmitter. */ + if ((avail_emptybuff > HIGH_WATERMARK) && + (!pshm_drv->tx_empty_available)) { + pshm_drv->tx_empty_available = 1; + pshm_drv->cfdev.flowctrl + (pshm_drv->pshm_dev->pshm_netdev, + CAIF_FLOW_ON); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* Schedule the work queue. if required */ + if (!work_pending(&pshm_drv->shm_tx_work)) + queue_work(pshm_drv->pshm_tx_workqueue, + &pshm_drv->shm_tx_work); + } else + spin_unlock_irqrestore(&pshm_drv->lock, flags); + } + + return 0; + +err_sync: + return -EIO; +} + +static void shm_rx_work_func(struct work_struct *rx_work) +{ + struct shmdrv_layer *pshm_drv; + struct buf_list *pbuf; + unsigned long flags = 0; + struct sk_buff *skb; + char *p; + int ret; + + pshm_drv = container_of(rx_work, struct shmdrv_layer, shm_rx_work); + + while (1) { + + struct shm_pck_desc *pck_desc; + + spin_lock_irqsave(&pshm_drv->lock, flags); + + /* Check for received buffers. */ + if (list_empty(&pshm_drv->rx_full_list)) { + spin_unlock_irqrestore(&pshm_drv->lock, flags); + break; + } + + pbuf = + list_entry(pshm_drv->rx_full_list.next, struct buf_list, + list); + list_del_init(&pbuf->list); + + /* Retrieve pointer to start of the packet descriptor area. */ + pck_desc = (struct shm_pck_desc *) pbuf->desc_vptr; + + /* + * Check whether descriptor contains a CAIF shared memory + * frame. + */ + while (pck_desc->frm_ofs) { + unsigned int frm_buf_ofs; + unsigned int frm_pck_ofs; + unsigned int frm_pck_len; + /* + * Check whether offset is within buffer limits + * (lower). + */ + if (pck_desc->frm_ofs < + (pbuf->phy_addr - pshm_drv->shm_base_addr)) + break; + /* + * Check whether offset is within buffer limits + * (higher). + */ + if (pck_desc->frm_ofs > + ((pbuf->phy_addr - pshm_drv->shm_base_addr) + + pbuf->len)) + break; + + /* Calculate offset from start of buffer. */ + frm_buf_ofs = + pck_desc->frm_ofs - (pbuf->phy_addr - + pshm_drv->shm_base_addr); + + /* + * Calculate offset and length of CAIF packet while + * taking care of the shared memory header. + */ + frm_pck_ofs = + frm_buf_ofs + SHM_HDR_LEN + + (*(pbuf->desc_vptr + frm_buf_ofs)); + frm_pck_len = + (pck_desc->frm_len - SHM_HDR_LEN - + (*(pbuf->desc_vptr + frm_buf_ofs))); + + /* Check whether CAIF packet is within buffer limits */ + if ((frm_pck_ofs + pck_desc->frm_len) > pbuf->len) + break; + + /* Get a suitable CAIF packet and copy in data. */ + skb = netdev_alloc_skb(pshm_drv->pshm_dev->pshm_netdev, + frm_pck_len + 1); + BUG_ON(skb == NULL); + + p = skb_put(skb, frm_pck_len); + memcpy(p, pbuf->desc_vptr + frm_pck_ofs, frm_pck_len); + + skb->protocol = htons(ETH_P_CAIF); + skb_reset_mac_header(skb); + skb->dev = pshm_drv->pshm_dev->pshm_netdev; + + /* Push received packet up the stack. */ + ret = netif_rx_ni(skb); + + if (!ret) { + pshm_drv->pshm_dev->pshm_netdev->stats. + rx_packets++; + pshm_drv->pshm_dev->pshm_netdev->stats. + rx_bytes += pck_desc->frm_len; + } else + ++pshm_drv->pshm_dev->pshm_netdev->stats. + rx_dropped; + /* Move to next packet descriptor. */ + pck_desc++; + } + + list_add_tail(&pbuf->list, &pshm_drv->rx_pend_list); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + } + + /* Schedule the work queue. if required */ + if (!work_pending(&pshm_drv->shm_tx_work)) + queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work); + +} + +static void shm_tx_work_func(struct work_struct *tx_work) +{ + u32 mbox_msg; + unsigned int frmlen, avail_emptybuff, append = 0; + unsigned long flags = 0; + struct buf_list *pbuf = NULL; + struct shmdrv_layer *pshm_drv; + struct shm_caif_frm *frm; + struct sk_buff *skb; + struct shm_pck_desc *pck_desc; + struct list_head *pos; + + pshm_drv = container_of(tx_work, struct shmdrv_layer, shm_tx_work); + + do { + /* Initialize mailbox message. */ + mbox_msg = 0x00; + avail_emptybuff = 0; + + spin_lock_irqsave(&pshm_drv->lock, flags); + + /* Check for pending receive buffers. */ + if (!list_empty(&pshm_drv->rx_pend_list)) { + + pbuf = list_entry(pshm_drv->rx_pend_list.next, + struct buf_list, list); + + list_del_init(&pbuf->list); + list_add_tail(&pbuf->list, &pshm_drv->rx_empty_list); + /* + * Value index is never changed, + * so read access should be safe. + */ + mbox_msg |= SHM_SET_EMPTY(pbuf->index); + } + + skb = skb_peek(&pshm_drv->sk_qhead); + + if (skb == NULL) + goto send_msg; + + /* Check the available no. of buffers in the empty list */ + list_for_each(pos, &pshm_drv->tx_empty_list) + avail_emptybuff++; + + if ((avail_emptybuff < LOW_WATERMARK) && + pshm_drv->tx_empty_available) { + /* Update blocking condition. */ + pshm_drv->tx_empty_available = 0; + pshm_drv->cfdev.flowctrl + (pshm_drv->pshm_dev->pshm_netdev, + CAIF_FLOW_OFF); + } + /* + * We simply return back to the caller if we do not have space + * either in Tx pending list or Tx empty list. In this case, + * we hold the received skb in the skb list, waiting to + * be transmitted once Tx buffers become available + */ + if (list_empty(&pshm_drv->tx_empty_list)) + goto send_msg; + + /* Get the first free Tx buffer. */ + pbuf = list_entry(pshm_drv->tx_empty_list.next, + struct buf_list, list); + do { + if (append) { + skb = skb_peek(&pshm_drv->sk_qhead); + if (skb == NULL) + break; + } + + frm = (struct shm_caif_frm *) + (pbuf->desc_vptr + pbuf->frm_ofs); + + frm->hdr_ofs = 0; + frmlen = 0; + frmlen += SHM_HDR_LEN + frm->hdr_ofs + skb->len; + + /* Add tail padding if needed. */ + if (frmlen % SHM_FRM_PAD_LEN) + frmlen += SHM_FRM_PAD_LEN - + (frmlen % SHM_FRM_PAD_LEN); + + /* + * Verify that packet, header and additional padding + * can fit within the buffer frame area. + */ + if (frmlen >= (pbuf->len - pbuf->frm_ofs)) + break; + + if (!append) { + list_del_init(&pbuf->list); + append = 1; + } + + skb = skb_dequeue(&pshm_drv->sk_qhead); + /* Copy in CAIF frame. */ + skb_copy_bits(skb, 0, pbuf->desc_vptr + + pbuf->frm_ofs + SHM_HDR_LEN + + frm->hdr_ofs, skb->len); + + pshm_drv->pshm_dev->pshm_netdev->stats.tx_packets++; + pshm_drv->pshm_dev->pshm_netdev->stats.tx_bytes += + frmlen; + dev_kfree_skb(skb); + + /* Fill in the shared memory packet descriptor area. */ + pck_desc = (struct shm_pck_desc *) (pbuf->desc_vptr); + /* Forward to current frame. */ + pck_desc += pbuf->frames; + pck_desc->frm_ofs = (pbuf->phy_addr - + pshm_drv->shm_base_addr) + + pbuf->frm_ofs; + pck_desc->frm_len = frmlen; + /* Terminate packet descriptor area. */ + pck_desc++; + pck_desc->frm_ofs = 0; + /* Update buffer parameters. */ + pbuf->frames++; + pbuf->frm_ofs += frmlen + (frmlen % 32); + + } while (pbuf->frames < SHM_MAX_FRMS_PER_BUF); + + /* Assign buffer as full. */ + list_add_tail(&pbuf->list, &pshm_drv->tx_full_list); + append = 0; + mbox_msg |= SHM_SET_FULL(pbuf->index); +send_msg: + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + if (mbox_msg) + pshm_drv->pshm_dev->pshmdev_mbxsend + (pshm_drv->pshm_dev->shm_id, mbox_msg); + } while (mbox_msg); +} + +static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev) +{ + struct shmdrv_layer *pshm_drv; + unsigned long flags = 0; + + pshm_drv = netdev_priv(shm_netdev); + + spin_lock_irqsave(&pshm_drv->lock, flags); + + skb_queue_tail(&pshm_drv->sk_qhead, skb); + + spin_unlock_irqrestore(&pshm_drv->lock, flags); + + /* Schedule Tx work queue. for deferred processing of skbs*/ + if (!work_pending(&pshm_drv->shm_tx_work)) + queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work); + + return 0; +} + +static const struct net_device_ops netdev_ops = { + .ndo_open = shm_netdev_open, + .ndo_stop = shm_netdev_close, + .ndo_start_xmit = shm_netdev_tx, +}; + +static void shm_netdev_setup(struct net_device *pshm_netdev) +{ + struct shmdrv_layer *pshm_drv; + pshm_netdev->netdev_ops = &netdev_ops; + + pshm_netdev->mtu = CAIF_MAX_MTU; + pshm_netdev->type = ARPHRD_CAIF; + pshm_netdev->hard_header_len = CAIF_NEEDED_HEADROOM; + pshm_netdev->tx_queue_len = 0; + pshm_netdev->destructor = free_netdev; + + pshm_drv = netdev_priv(pshm_netdev); + + /* Initialize structures in a clean state. */ + memset(pshm_drv, 0, sizeof(struct shmdrv_layer)); + + pshm_drv->cfdev.link_select = CAIF_LINK_LOW_LATENCY; +} + +int caif_shmcore_probe(struct shmdev_layer *pshm_dev) +{ + int result, j; + struct shmdrv_layer *pshm_drv = NULL; + + pshm_dev->pshm_netdev = alloc_netdev(sizeof(struct shmdrv_layer), + "cfshm%d", shm_netdev_setup); + if (!pshm_dev->pshm_netdev) + return -ENOMEM; + + pshm_drv = netdev_priv(pshm_dev->pshm_netdev); + pshm_drv->pshm_dev = pshm_dev; + + /* + * Initialization starts with the verification of the + * availability of MBX driver by calling its setup function. + * MBX driver must be available by this time for proper + * functioning of SHM driver. + */ + if ((pshm_dev->pshmdev_mbxsetup + (caif_shmdrv_rx_cb, pshm_dev, pshm_drv)) != 0) { + pr_warn("Could not config. SHM Mailbox," + " Bailing out.....\n"); + free_netdev(pshm_dev->pshm_netdev); + return -ENODEV; + } + + skb_queue_head_init(&pshm_drv->sk_qhead); + + pr_info("SHM DEVICE[%d] PROBED BY DRIVER, NEW SHM DRIVER" + " INSTANCE AT pshm_drv =0x%p\n", + pshm_drv->pshm_dev->shm_id, pshm_drv); + + if (pshm_dev->shm_total_sz < + (NR_TX_BUF * TX_BUF_SZ + NR_RX_BUF * RX_BUF_SZ)) { + + pr_warn("ERROR, Amount of available" + " Phys. SHM cannot accomodate current SHM " + "driver configuration, Bailing out ...\n"); + free_netdev(pshm_dev->pshm_netdev); + return -ENOMEM; + } + + pshm_drv->shm_base_addr = pshm_dev->shm_base_addr; + pshm_drv->shm_tx_addr = pshm_drv->shm_base_addr; + + if (pshm_dev->shm_loopback) + pshm_drv->shm_rx_addr = pshm_drv->shm_tx_addr; + else + pshm_drv->shm_rx_addr = pshm_dev->shm_base_addr + + (NR_TX_BUF * TX_BUF_SZ); + + INIT_LIST_HEAD(&pshm_drv->tx_empty_list); + INIT_LIST_HEAD(&pshm_drv->tx_pend_list); + INIT_LIST_HEAD(&pshm_drv->tx_full_list); + + INIT_LIST_HEAD(&pshm_drv->rx_empty_list); + INIT_LIST_HEAD(&pshm_drv->rx_pend_list); + INIT_LIST_HEAD(&pshm_drv->rx_full_list); + + INIT_WORK(&pshm_drv->shm_tx_work, shm_tx_work_func); + INIT_WORK(&pshm_drv->shm_rx_work, shm_rx_work_func); + + pshm_drv->pshm_tx_workqueue = + create_singlethread_workqueue("shm_tx_work"); + pshm_drv->pshm_rx_workqueue = + create_singlethread_workqueue("shm_rx_work"); + + for (j = 0; j < NR_TX_BUF; j++) { + struct buf_list *tx_buf = + kmalloc(sizeof(struct buf_list), GFP_KERNEL); + + if (tx_buf == NULL) { + pr_warn("ERROR, Could not" + " allocate dynamic mem. for tx_buf," + " Bailing out ...\n"); + free_netdev(pshm_dev->pshm_netdev); + return -ENOMEM; + } + tx_buf->index = j; + tx_buf->phy_addr = pshm_drv->shm_tx_addr + (TX_BUF_SZ * j); + tx_buf->len = TX_BUF_SZ; + tx_buf->frames = 0; + tx_buf->frm_ofs = SHM_CAIF_FRM_OFS; + + if (pshm_dev->shm_loopback) + tx_buf->desc_vptr = (char *)tx_buf->phy_addr; + else + tx_buf->desc_vptr = + ioremap(tx_buf->phy_addr, TX_BUF_SZ); + + list_add_tail(&tx_buf->list, &pshm_drv->tx_empty_list); + } + + for (j = 0; j < NR_RX_BUF; j++) { + struct buf_list *rx_buf = + kmalloc(sizeof(struct buf_list), GFP_KERNEL); + + if (rx_buf == NULL) { + pr_warn("ERROR, Could not" + " allocate dynamic mem.for rx_buf," + " Bailing out ...\n"); + free_netdev(pshm_dev->pshm_netdev); + return -ENOMEM; + } + rx_buf->index = j; + rx_buf->phy_addr = pshm_drv->shm_rx_addr + (RX_BUF_SZ * j); + rx_buf->len = RX_BUF_SZ; + + if (pshm_dev->shm_loopback) + rx_buf->desc_vptr = (char *)rx_buf->phy_addr; + else + rx_buf->desc_vptr = + ioremap(rx_buf->phy_addr, RX_BUF_SZ); + list_add_tail(&rx_buf->list, &pshm_drv->rx_empty_list); + } + + pshm_drv->tx_empty_available = 1; + result = register_netdev(pshm_dev->pshm_netdev); + if (result) + pr_warn("ERROR[%d], SHM could not, " + "register with NW FRMWK Bailing out ...\n", result); + + return result; +} + +void caif_shmcore_remove(struct net_device *pshm_netdev) +{ + struct buf_list *pbuf; + struct shmdrv_layer *pshm_drv = NULL; + + pshm_drv = netdev_priv(pshm_netdev); + + while (!(list_empty(&pshm_drv->tx_pend_list))) { + pbuf = + list_entry(pshm_drv->tx_pend_list.next, + struct buf_list, list); + + list_del(&pbuf->list); + kfree(pbuf); + } + + while (!(list_empty(&pshm_drv->tx_full_list))) { + pbuf = + list_entry(pshm_drv->tx_full_list.next, + struct buf_list, list); + list_del(&pbuf->list); + kfree(pbuf); + } + + while (!(list_empty(&pshm_drv->tx_empty_list))) { + pbuf = + list_entry(pshm_drv->tx_empty_list.next, + struct buf_list, list); + list_del(&pbuf->list); + kfree(pbuf); + } + + while (!(list_empty(&pshm_drv->rx_full_list))) { + pbuf = + list_entry(pshm_drv->tx_full_list.next, + struct buf_list, list); + list_del(&pbuf->list); + kfree(pbuf); + } + + while (!(list_empty(&pshm_drv->rx_pend_list))) { + pbuf = + list_entry(pshm_drv->tx_pend_list.next, + struct buf_list, list); + list_del(&pbuf->list); + kfree(pbuf); + } + + while (!(list_empty(&pshm_drv->rx_empty_list))) { + pbuf = + list_entry(pshm_drv->rx_empty_list.next, + struct buf_list, list); + list_del(&pbuf->list); + kfree(pbuf); + } + + /* Destroy work queues. */ + destroy_workqueue(pshm_drv->pshm_tx_workqueue); + destroy_workqueue(pshm_drv->pshm_rx_workqueue); + + unregister_netdev(pshm_netdev); +} diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 9d9e45394433..080574b0fff0 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -82,6 +82,14 @@ config CAN_FLEXCAN ---help--- Say Y here if you want to support for Freescale FlexCAN. +config PCH_CAN + tristate "PCH CAN" + depends on CAN_DEV && PCI + ---help--- + This driver is for PCH CAN of Topcliff which is an IOH for x86 + embedded processor. + This driver can access CAN bus. + source "drivers/net/can/mscan/Kconfig" source "drivers/net/can/sja1000/Kconfig" diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 00575373bbd0..90af15a4f106 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -17,5 +17,6 @@ obj-$(CONFIG_CAN_MCP251X) += mcp251x.o obj-$(CONFIG_CAN_BFIN) += bfin_can.o obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o +obj-$(CONFIG_PCH_CAN) += pch_can.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 2d8bd86bc5e2..7ef83d06f7ed 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1,8 +1,8 @@ /* * at91_can.c - CAN network driver for AT91 SoC CAN controller * - * (C) 2007 by Hans J. Koch <hjk@linutronix.de> - * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de> + * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> + * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de> * * This software may be distributed under the terms of the GNU General * Public License ("GPL") version 2 as distributed in the 'COPYING' @@ -40,7 +40,6 @@ #include <mach/board.h> -#define DRV_NAME "at91_can" #define AT91_NAPI_WEIGHT 12 /* @@ -172,6 +171,7 @@ struct at91_priv { }; static struct can_bittiming_const at91_bittiming_const = { + .name = KBUILD_MODNAME, .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, @@ -199,13 +199,13 @@ static inline int get_tx_echo_mb(const struct at91_priv *priv) static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg) { - return readl(priv->reg_base + reg); + return __raw_readl(priv->reg_base + reg); } static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg, u32 value) { - writel(value, priv->reg_base + reg); + __raw_writel(value, priv->reg_base + reg); } static inline void set_mb_mode_prio(const struct at91_priv *priv, @@ -243,6 +243,12 @@ static void at91_setup_mailboxes(struct net_device *dev) set_mb_mode(priv, i, AT91_MB_MODE_RX); set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); + /* reset acceptance mask and id register */ + for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) { + at91_write(priv, AT91_MAM(i), 0x0 ); + at91_write(priv, AT91_MID(i), AT91_MID_MIDE); + } + /* The last 4 mailboxes are used for transmitting. */ for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++) set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0); @@ -257,18 +263,30 @@ static int at91_set_bittiming(struct net_device *dev) const struct can_bittiming *bt = &priv->can.bittiming; u32 reg_br; - reg_br = ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) << 24) | - ((bt->brp - 1) << 16) | ((bt->sjw - 1) << 12) | + reg_br = ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 << 24 : 0) | + ((bt->brp - 1) << 16) | ((bt->sjw - 1) << 12) | ((bt->prop_seg - 1) << 8) | ((bt->phase_seg1 - 1) << 4) | ((bt->phase_seg2 - 1) << 0); - dev_info(dev->dev.parent, "writing AT91_BR: 0x%08x\n", reg_br); + netdev_info(dev, "writing AT91_BR: 0x%08x\n", reg_br); at91_write(priv, AT91_BR, reg_br); return 0; } +static int at91_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + const struct at91_priv *priv = netdev_priv(dev); + u32 reg_ecr = at91_read(priv, AT91_ECR); + + bec->rxerr = reg_ecr & 0xff; + bec->txerr = reg_ecr >> 16; + + return 0; +} + static void at91_chip_start(struct net_device *dev) { struct at91_priv *priv = netdev_priv(dev); @@ -281,6 +299,7 @@ static void at91_chip_start(struct net_device *dev) reg_mr = at91_read(priv, AT91_MR); at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN); + at91_set_bittiming(dev); at91_setup_mailboxes(dev); at91_transceiver_switch(priv, 1); @@ -350,8 +369,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(!(at91_read(priv, AT91_MSR(mb)) & AT91_MSR_MRDY))) { netif_stop_queue(dev); - dev_err(dev->dev.parent, - "BUG! TX buffer full when queue awake!\n"); + netdev_err(dev, "BUG! TX buffer full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -435,7 +453,7 @@ static void at91_rx_overflow_err(struct net_device *dev) struct sk_buff *skb; struct can_frame *cf; - dev_dbg(dev->dev.parent, "RX buffer overflow\n"); + netdev_dbg(dev, "RX buffer overflow\n"); stats->rx_over_errors++; stats->rx_errors++; @@ -480,6 +498,9 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb, *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb)); *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb)); + /* allow RX of extended frames */ + at91_write(priv, AT91_MID(mb), AT91_MID_MIDE); + if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI)) at91_rx_overflow_err(dev); } @@ -565,8 +586,8 @@ static int at91_poll_rx(struct net_device *dev, int quota) if (priv->rx_next > AT91_MB_RX_LOW_LAST && reg_sr & AT91_MB_RX_LOW_MASK) - dev_info(dev->dev.parent, - "order of incoming frames cannot be guaranteed\n"); + netdev_info(dev, + "order of incoming frames cannot be guaranteed\n"); again: for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next); @@ -604,7 +625,7 @@ static void at91_poll_err_frame(struct net_device *dev, /* CRC error */ if (reg_sr & AT91_IRQ_CERR) { - dev_dbg(dev->dev.parent, "CERR irq\n"); + netdev_dbg(dev, "CERR irq\n"); dev->stats.rx_errors++; priv->can.can_stats.bus_error++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; @@ -612,7 +633,7 @@ static void at91_poll_err_frame(struct net_device *dev, /* Stuffing Error */ if (reg_sr & AT91_IRQ_SERR) { - dev_dbg(dev->dev.parent, "SERR irq\n"); + netdev_dbg(dev, "SERR irq\n"); dev->stats.rx_errors++; priv->can.can_stats.bus_error++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; @@ -621,14 +642,14 @@ static void at91_poll_err_frame(struct net_device *dev, /* Acknowledgement Error */ if (reg_sr & AT91_IRQ_AERR) { - dev_dbg(dev->dev.parent, "AERR irq\n"); + netdev_dbg(dev, "AERR irq\n"); dev->stats.tx_errors++; cf->can_id |= CAN_ERR_ACK; } /* Form error */ if (reg_sr & AT91_IRQ_FERR) { - dev_dbg(dev->dev.parent, "FERR irq\n"); + netdev_dbg(dev, "FERR irq\n"); dev->stats.rx_errors++; priv->can.can_stats.bus_error++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; @@ -637,7 +658,7 @@ static void at91_poll_err_frame(struct net_device *dev, /* Bit Error */ if (reg_sr & AT91_IRQ_BERR) { - dev_dbg(dev->dev.parent, "BERR irq\n"); + netdev_dbg(dev, "BERR irq\n"); dev->stats.tx_errors++; priv->can.can_stats.bus_error++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; @@ -755,12 +776,10 @@ static void at91_irq_err_state(struct net_device *dev, struct can_frame *cf, enum can_state new_state) { struct at91_priv *priv = netdev_priv(dev); - u32 reg_idr, reg_ier, reg_ecr; - u8 tec, rec; + u32 reg_idr = 0, reg_ier = 0; + struct can_berr_counter bec; - reg_ecr = at91_read(priv, AT91_ECR); - rec = reg_ecr & 0xff; - tec = reg_ecr >> 16; + at91_get_berr_counter(dev, &bec); switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: @@ -771,11 +790,11 @@ static void at91_irq_err_state(struct net_device *dev, */ if (new_state >= CAN_STATE_ERROR_WARNING && new_state <= CAN_STATE_BUS_OFF) { - dev_dbg(dev->dev.parent, "Error Warning IRQ\n"); + netdev_dbg(dev, "Error Warning IRQ\n"); priv->can.can_stats.error_warning++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (tec > rec) ? + cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } @@ -787,11 +806,11 @@ static void at91_irq_err_state(struct net_device *dev, */ if (new_state >= CAN_STATE_ERROR_PASSIVE && new_state <= CAN_STATE_BUS_OFF) { - dev_dbg(dev->dev.parent, "Error Passive IRQ\n"); + netdev_dbg(dev, "Error Passive IRQ\n"); priv->can.can_stats.error_passive++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (tec > rec) ? + cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } @@ -804,7 +823,7 @@ static void at91_irq_err_state(struct net_device *dev, if (new_state <= CAN_STATE_ERROR_PASSIVE) { cf->can_id |= CAN_ERR_RESTARTED; - dev_dbg(dev->dev.parent, "restarted\n"); + netdev_dbg(dev, "restarted\n"); priv->can.can_stats.restarts++; netif_carrier_on(dev); @@ -825,7 +844,7 @@ static void at91_irq_err_state(struct net_device *dev, * circumstances. so just enable AT91_IRQ_ERRP, thus * the "fallthrough" */ - dev_dbg(dev->dev.parent, "Error Active\n"); + netdev_dbg(dev, "Error Active\n"); cf->can_id |= CAN_ERR_PROT; cf->data[2] = CAN_ERR_PROT_ACTIVE; case CAN_STATE_ERROR_WARNING: /* fallthrough */ @@ -843,7 +862,7 @@ static void at91_irq_err_state(struct net_device *dev, cf->can_id |= CAN_ERR_BUSOFF; - dev_dbg(dev->dev.parent, "bus-off\n"); + netdev_dbg(dev, "bus-off\n"); netif_carrier_off(dev); priv->can.can_stats.bus_off++; @@ -881,7 +900,7 @@ static void at91_irq_err(struct net_device *dev) else if (likely(reg_sr & AT91_IRQ_ERRA)) new_state = CAN_STATE_ERROR_ACTIVE; else { - dev_err(dev->dev.parent, "BUG! hardware in undefined state\n"); + netdev_err(dev, "BUG! hardware in undefined state\n"); return; } @@ -1018,7 +1037,7 @@ static const struct net_device_ops at91_netdev_ops = { .ndo_start_xmit = at91_start_xmit, }; -static int __init at91_can_probe(struct platform_device *pdev) +static int __devinit at91_can_probe(struct platform_device *pdev) { struct net_device *dev; struct at91_priv *priv; @@ -1067,8 +1086,8 @@ static int __init at91_can_probe(struct platform_device *pdev) priv = netdev_priv(dev); priv->can.clock.freq = clk_get_rate(clk); priv->can.bittiming_const = &at91_bittiming_const; - priv->can.do_set_bittiming = at91_set_bittiming; priv->can.do_set_mode = at91_set_mode; + priv->can.do_get_berr_counter = at91_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; priv->reg_base = addr; priv->dev = dev; @@ -1092,7 +1111,7 @@ static int __init at91_can_probe(struct platform_device *pdev) return 0; exit_free: - free_netdev(dev); + free_candev(dev); exit_iounmap: iounmap(addr); exit_release: @@ -1113,8 +1132,6 @@ static int __devexit at91_can_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - free_netdev(dev); - iounmap(priv->reg_base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1122,6 +1139,8 @@ static int __devexit at91_can_remove(struct platform_device *pdev) clk_put(priv->clk); + free_candev(dev); + return 0; } @@ -1129,21 +1148,19 @@ static struct platform_driver at91_can_driver = { .probe = at91_can_probe, .remove = __devexit_p(at91_can_remove), .driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .owner = THIS_MODULE, }, }; static int __init at91_can_module_init(void) { - printk(KERN_INFO "%s netdevice driver\n", DRV_NAME); return platform_driver_register(&at91_can_driver); } static void __exit at91_can_module_exit(void) { platform_driver_unregister(&at91_can_driver); - printk(KERN_INFO "%s: driver removed\n", DRV_NAME); } module_init(at91_can_module_init); @@ -1151,4 +1168,4 @@ module_exit(at91_can_module_exit); MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION(DRV_NAME " CAN netdevice driver"); +MODULE_DESCRIPTION(KBUILD_MODNAME " CAN netdevice driver"); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index ef443a090ba7..d4990568baee 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -992,7 +992,6 @@ static int __devexit flexcan_remove(struct platform_device *pdev) unregister_flexcandev(dev); platform_set_drvdata(pdev, NULL); - free_candev(dev); iounmap(priv->base); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1000,6 +999,8 @@ static int __devexit flexcan_remove(struct platform_device *pdev) clk_put(priv->clk); + free_candev(dev); + return 0; } diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 6aadc3e32bd5..7ab534aee452 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -169,6 +169,7 @@ # define RXBSIDH_SHIFT 3 #define RXBSIDL(n) (((n) * 0x10) + 0x60 + RXBSIDL_OFF) # define RXBSIDL_IDE 0x08 +# define RXBSIDL_SRR 0x10 # define RXBSIDL_EID 3 # define RXBSIDL_SHIFT 5 #define RXBEID8(n) (((n) * 0x10) + 0x60 + RXBEID8_OFF) @@ -475,6 +476,8 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) frame->can_id = (buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT); + if (buf[RXBSIDL_OFF] & RXBSIDL_SRR) + frame->can_id |= CAN_RTR_FLAG; } /* Data length */ frame->can_dlc = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c new file mode 100644 index 000000000000..672718261c68 --- /dev/null +++ b/drivers/net/can/pch_can.c @@ -0,0 +1,1463 @@ +/* + * Copyright (C) 1999 - 2010 Intel Corporation. + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> + +#define MAX_MSG_OBJ 32 +#define MSG_OBJ_RX 0 /* The receive message object flag. */ +#define MSG_OBJ_TX 1 /* The transmit message object flag. */ + +#define ENABLE 1 /* The enable flag */ +#define DISABLE 0 /* The disable flag */ +#define CAN_CTRL_INIT 0x0001 /* The INIT bit of CANCONT register. */ +#define CAN_CTRL_IE 0x0002 /* The IE bit of CAN control register */ +#define CAN_CTRL_IE_SIE_EIE 0x000e +#define CAN_CTRL_CCE 0x0040 +#define CAN_CTRL_OPT 0x0080 /* The OPT bit of CANCONT register. */ +#define CAN_OPT_SILENT 0x0008 /* The Silent bit of CANOPT reg. */ +#define CAN_OPT_LBACK 0x0010 /* The LoopBack bit of CANOPT reg. */ +#define CAN_CMASK_RX_TX_SET 0x00f3 +#define CAN_CMASK_RX_TX_GET 0x0073 +#define CAN_CMASK_ALL 0xff +#define CAN_CMASK_RDWR 0x80 +#define CAN_CMASK_ARB 0x20 +#define CAN_CMASK_CTRL 0x10 +#define CAN_CMASK_MASK 0x40 +#define CAN_CMASK_NEWDAT 0x04 +#define CAN_CMASK_CLRINTPND 0x08 + +#define CAN_IF_MCONT_NEWDAT 0x8000 +#define CAN_IF_MCONT_INTPND 0x2000 +#define CAN_IF_MCONT_UMASK 0x1000 +#define CAN_IF_MCONT_TXIE 0x0800 +#define CAN_IF_MCONT_RXIE 0x0400 +#define CAN_IF_MCONT_RMTEN 0x0200 +#define CAN_IF_MCONT_TXRQXT 0x0100 +#define CAN_IF_MCONT_EOB 0x0080 +#define CAN_IF_MCONT_DLC 0x000f +#define CAN_IF_MCONT_MSGLOST 0x4000 +#define CAN_MASK2_MDIR_MXTD 0xc000 +#define CAN_ID2_DIR 0x2000 +#define CAN_ID_MSGVAL 0x8000 + +#define CAN_STATUS_INT 0x8000 +#define CAN_IF_CREQ_BUSY 0x8000 +#define CAN_ID2_XTD 0x4000 + +#define CAN_REC 0x00007f00 +#define CAN_TEC 0x000000ff + +#define PCH_RX_OK 0x00000010 +#define PCH_TX_OK 0x00000008 +#define PCH_BUS_OFF 0x00000080 +#define PCH_EWARN 0x00000040 +#define PCH_EPASSIV 0x00000020 +#define PCH_LEC0 0x00000001 +#define PCH_LEC1 0x00000002 +#define PCH_LEC2 0x00000004 +#define PCH_LEC_ALL (PCH_LEC0 | PCH_LEC1 | PCH_LEC2) +#define PCH_STUF_ERR PCH_LEC0 +#define PCH_FORM_ERR PCH_LEC1 +#define PCH_ACK_ERR (PCH_LEC0 | PCH_LEC1) +#define PCH_BIT1_ERR PCH_LEC2 +#define PCH_BIT0_ERR (PCH_LEC0 | PCH_LEC2) +#define PCH_CRC_ERR (PCH_LEC1 | PCH_LEC2) + +/* bit position of certain controller bits. */ +#define BIT_BITT_BRP 0 +#define BIT_BITT_SJW 6 +#define BIT_BITT_TSEG1 8 +#define BIT_BITT_TSEG2 12 +#define BIT_IF1_MCONT_RXIE 10 +#define BIT_IF2_MCONT_TXIE 11 +#define BIT_BRPE_BRPE 6 +#define BIT_ES_TXERRCNT 0 +#define BIT_ES_RXERRCNT 8 +#define MSK_BITT_BRP 0x3f +#define MSK_BITT_SJW 0xc0 +#define MSK_BITT_TSEG1 0xf00 +#define MSK_BITT_TSEG2 0x7000 +#define MSK_BRPE_BRPE 0x3c0 +#define MSK_BRPE_GET 0x0f +#define MSK_CTRL_IE_SIE_EIE 0x07 +#define MSK_MCONT_TXIE 0x08 +#define MSK_MCONT_RXIE 0x10 +#define PCH_CAN_NO_TX_BUFF 1 +#define COUNTER_LIMIT 10 + +#define PCH_CAN_CLK 50000000 /* 50MHz */ + +/* Define the number of message object. + * PCH CAN communications are done via Message RAM. + * The Message RAM consists of 32 message objects. */ +#define PCH_RX_OBJ_NUM 26 /* 1~ PCH_RX_OBJ_NUM is Rx*/ +#define PCH_TX_OBJ_NUM 6 /* PCH_RX_OBJ_NUM is RX ~ Tx*/ +#define PCH_OBJ_NUM (PCH_TX_OBJ_NUM + PCH_RX_OBJ_NUM) + +#define PCH_FIFO_THRESH 16 + +enum pch_can_mode { + PCH_CAN_ENABLE, + PCH_CAN_DISABLE, + PCH_CAN_ALL, + PCH_CAN_NONE, + PCH_CAN_STOP, + PCH_CAN_RUN +}; + +struct pch_can_regs { + u32 cont; + u32 stat; + u32 errc; + u32 bitt; + u32 intr; + u32 opt; + u32 brpe; + u32 reserve1; + u32 if1_creq; + u32 if1_cmask; + u32 if1_mask1; + u32 if1_mask2; + u32 if1_id1; + u32 if1_id2; + u32 if1_mcont; + u32 if1_dataa1; + u32 if1_dataa2; + u32 if1_datab1; + u32 if1_datab2; + u32 reserve2; + u32 reserve3[12]; + u32 if2_creq; + u32 if2_cmask; + u32 if2_mask1; + u32 if2_mask2; + u32 if2_id1; + u32 if2_id2; + u32 if2_mcont; + u32 if2_dataa1; + u32 if2_dataa2; + u32 if2_datab1; + u32 if2_datab2; + u32 reserve4; + u32 reserve5[20]; + u32 treq1; + u32 treq2; + u32 reserve6[2]; + u32 reserve7[56]; + u32 reserve8[3]; + u32 srst; +}; + +struct pch_can_priv { + struct can_priv can; + unsigned int can_num; + struct pci_dev *dev; + unsigned int tx_enable[MAX_MSG_OBJ]; + unsigned int rx_enable[MAX_MSG_OBJ]; + unsigned int rx_link[MAX_MSG_OBJ]; + unsigned int int_enables; + unsigned int int_stat; + struct net_device *ndev; + spinlock_t msgif_reg_lock; /* Message Interface Registers Access Lock*/ + unsigned int msg_obj[MAX_MSG_OBJ]; + struct pch_can_regs __iomem *regs; + struct napi_struct napi; + unsigned int tx_obj; /* Point next Tx Obj index */ + unsigned int use_msi; +}; + +static struct can_bittiming_const pch_can_bittiming_const = { + .name = KBUILD_MODNAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 1024, /* 6bit + extended 4bit */ + .brp_inc = 1, +}; + +static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = { + {PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, pch_pci_tbl); + +static inline void pch_can_bit_set(void __iomem *addr, u32 mask) +{ + iowrite32(ioread32(addr) | mask, addr); +} + +static inline void pch_can_bit_clear(void __iomem *addr, u32 mask) +{ + iowrite32(ioread32(addr) & ~mask, addr); +} + +static void pch_can_set_run_mode(struct pch_can_priv *priv, + enum pch_can_mode mode) +{ + switch (mode) { + case PCH_CAN_RUN: + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_INIT); + break; + + case PCH_CAN_STOP: + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_INIT); + break; + + default: + dev_err(&priv->ndev->dev, "%s -> Invalid Mode.\n", __func__); + break; + } +} + +static void pch_can_set_optmode(struct pch_can_priv *priv) +{ + u32 reg_val = ioread32(&priv->regs->opt); + + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + reg_val |= CAN_OPT_SILENT; + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + reg_val |= CAN_OPT_LBACK; + + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_OPT); + iowrite32(reg_val, &priv->regs->opt); +} + +static void pch_can_set_int_custom(struct pch_can_priv *priv) +{ + /* Clearing the IE, SIE and EIE bits of Can control register. */ + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + + /* Appropriately setting them. */ + pch_can_bit_set(&priv->regs->cont, + ((priv->int_enables & MSK_CTRL_IE_SIE_EIE) << 1)); +} + +/* This function retrieves interrupt enabled for the CAN device. */ +static void pch_can_get_int_enables(struct pch_can_priv *priv, u32 *enables) +{ + /* Obtaining the status of IE, SIE and EIE interrupt bits. */ + *enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1); +} + +static void pch_can_set_int_enables(struct pch_can_priv *priv, + enum pch_can_mode interrupt_no) +{ + switch (interrupt_no) { + case PCH_CAN_ENABLE: + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE); + break; + + case PCH_CAN_DISABLE: + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE); + break; + + case PCH_CAN_ALL: + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + break; + + case PCH_CAN_NONE: + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE); + break; + + default: + dev_err(&priv->ndev->dev, "Invalid interrupt number.\n"); + break; + } +} + +static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num) +{ + u32 counter = COUNTER_LIMIT; + u32 ifx_creq; + + iowrite32(num, creq_addr); + while (counter) { + ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY; + if (!ifx_creq) + break; + counter--; + udelay(1); + } + if (!counter) + pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__); +} + +static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num, + u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + /* Reading the receive buffer data from RAM to Interface1 registers */ + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); + + /* Setting the IF1MASK1 register to access MsgVal and RxIE bits */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if1_cmask); + + if (set == ENABLE) { + /* Setting the MsgVal and RxIE bits */ + pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE); + pch_can_bit_set(&priv->regs->if1_id2, CAN_ID_MSGVAL); + + } else if (set == DISABLE) { + /* Resetting the MsgVal and RxIE bits */ + pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE); + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID_MSGVAL); + } + + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_rx_enable_all(struct pch_can_priv *priv) +{ + int i; + + /* Traversing to obtain the object configured as receivers. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_RX) + pch_can_set_rx_enable(priv, i + 1, ENABLE); + } +} + +static void pch_can_rx_disable_all(struct pch_can_priv *priv) +{ + int i; + + /* Traversing to obtain the object configured as receivers. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_RX) + pch_can_set_rx_enable(priv, i + 1, DISABLE); + } +} + +static void pch_can_set_tx_enable(struct pch_can_priv *priv, u32 buff_num, + u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + /* Reading the Msg buffer from Message RAM to Interface2 registers. */ + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); + + /* Setting the IF2CMASK register for accessing the + MsgVal and TxIE bits */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if2_cmask); + + if (set == ENABLE) { + /* Setting the MsgVal and TxIE bits */ + pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE); + pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL); + } else if (set == DISABLE) { + /* Resetting the MsgVal and TxIE bits. */ + pch_can_bit_clear(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE); + pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID_MSGVAL); + } + + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_tx_enable_all(struct pch_can_priv *priv) +{ + int i; + + /* Traversing to obtain the object configured as transmit object. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_TX) + pch_can_set_tx_enable(priv, i + 1, ENABLE); + } +} + +static void pch_can_tx_disable_all(struct pch_can_priv *priv) +{ + int i; + + /* Traversing to obtain the object configured as transmit object. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_TX) + pch_can_set_tx_enable(priv, i + 1, DISABLE); + } +} + +static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num, + u32 *enable) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num); + + if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) && + ((ioread32(&priv->regs->if1_mcont)) & + CAN_IF_MCONT_RXIE)) + *enable = ENABLE; + else + *enable = DISABLE; + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num, + u32 *enable) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num); + + if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) && + ((ioread32(&priv->regs->if2_mcont)) & + CAN_IF_MCONT_TXIE)) { + *enable = ENABLE; + } else { + *enable = DISABLE; + } + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static int pch_can_int_pending(struct pch_can_priv *priv) +{ + return ioread32(&priv->regs->intr) & 0xffff; +} + +static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv, + u32 buffer_num, u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask); + if (set == ENABLE) + pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB); + else + pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB); + + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv, + u32 buffer_num, u32 *link) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num); + + if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB) + *link = DISABLE; + else + *link = ENABLE; + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_clear_buffers(struct pch_can_priv *priv) +{ + int i; + + for (i = 0; i < PCH_RX_OBJ_NUM; i++) { + iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if1_cmask); + iowrite32(0xffff, &priv->regs->if1_mask1); + iowrite32(0xffff, &priv->regs->if1_mask2); + iowrite32(0x0, &priv->regs->if1_id1); + iowrite32(0x0, &priv->regs->if1_id2); + iowrite32(0x0, &priv->regs->if1_mcont); + iowrite32(0x0, &priv->regs->if1_dataa1); + iowrite32(0x0, &priv->regs->if1_dataa2); + iowrite32(0x0, &priv->regs->if1_datab1); + iowrite32(0x0, &priv->regs->if1_datab2); + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | + CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, i+1); + } + + for (i = i; i < PCH_OBJ_NUM; i++) { + iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask); + iowrite32(0xffff, &priv->regs->if2_mask1); + iowrite32(0xffff, &priv->regs->if2_mask2); + iowrite32(0x0, &priv->regs->if2_id1); + iowrite32(0x0, &priv->regs->if2_id2); + iowrite32(0x0, &priv->regs->if2_mcont); + iowrite32(0x0, &priv->regs->if2_dataa1); + iowrite32(0x0, &priv->regs->if2_dataa2); + iowrite32(0x0, &priv->regs->if2_datab1); + iowrite32(0x0, &priv->regs->if2_datab2); + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | + CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, i+1); + } +} + +static void pch_can_config_rx_tx_buffers(struct pch_can_priv *priv) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_RX) { + iowrite32(CAN_CMASK_RX_TX_GET, + &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, i+1); + + iowrite32(0x0, &priv->regs->if1_id1); + iowrite32(0x0, &priv->regs->if1_id2); + + pch_can_bit_set(&priv->regs->if1_mcont, + CAN_IF_MCONT_UMASK); + + /* Set FIFO mode set to 0 except last Rx Obj*/ + pch_can_bit_clear(&priv->regs->if1_mcont, + CAN_IF_MCONT_EOB); + /* In case FIFO mode, Last EoB of Rx Obj must be 1 */ + if (i == (PCH_RX_OBJ_NUM - 1)) + pch_can_bit_set(&priv->regs->if1_mcont, + CAN_IF_MCONT_EOB); + + iowrite32(0, &priv->regs->if1_mask1); + pch_can_bit_clear(&priv->regs->if1_mask2, + 0x1fff | CAN_MASK2_MDIR_MXTD); + + /* Setting CMASK for writing */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | + CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if1_cmask); + + pch_can_check_if_busy(&priv->regs->if1_creq, i+1); + } else if (priv->msg_obj[i] == MSG_OBJ_TX) { + iowrite32(CAN_CMASK_RX_TX_GET, + &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, i+1); + + /* Resetting DIR bit for reception */ + iowrite32(0x0, &priv->regs->if2_id1); + iowrite32(0x0, &priv->regs->if2_id2); + pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR); + + /* Setting EOB bit for transmitter */ + iowrite32(CAN_IF_MCONT_EOB, &priv->regs->if2_mcont); + + pch_can_bit_set(&priv->regs->if2_mcont, + CAN_IF_MCONT_UMASK); + + iowrite32(0, &priv->regs->if2_mask1); + pch_can_bit_clear(&priv->regs->if2_mask2, 0x1fff); + + /* Setting CMASK for writing */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK | + CAN_CMASK_ARB | CAN_CMASK_CTRL, + &priv->regs->if2_cmask); + + pch_can_check_if_busy(&priv->regs->if2_creq, i+1); + } + } + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); +} + +static void pch_can_init(struct pch_can_priv *priv) +{ + /* Stopping the Can device. */ + pch_can_set_run_mode(priv, PCH_CAN_STOP); + + /* Clearing all the message object buffers. */ + pch_can_clear_buffers(priv); + + /* Configuring the respective message object as either rx/tx object. */ + pch_can_config_rx_tx_buffers(priv); + + /* Enabling the interrupts. */ + pch_can_set_int_enables(priv, PCH_CAN_ALL); +} + +static void pch_can_release(struct pch_can_priv *priv) +{ + /* Stooping the CAN device. */ + pch_can_set_run_mode(priv, PCH_CAN_STOP); + + /* Disabling the interrupts. */ + pch_can_set_int_enables(priv, PCH_CAN_NONE); + + /* Disabling all the receive object. */ + pch_can_rx_disable_all(priv); + + /* Disabling all the transmit object. */ + pch_can_tx_disable_all(priv); +} + +/* This function clears interrupt(s) from the CAN device. */ +static void pch_can_int_clr(struct pch_can_priv *priv, u32 mask) +{ + if (mask == CAN_STATUS_INT) { + ioread32(&priv->regs->stat); + return; + } + + /* Clear interrupt for transmit object */ + if (priv->msg_obj[mask - 1] == MSG_OBJ_TX) { + /* Setting CMASK for clearing interrupts for + frame transmission. */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB, + &priv->regs->if2_cmask); + + /* Resetting the ID registers. */ + pch_can_bit_set(&priv->regs->if2_id2, + CAN_ID2_DIR | (0x7ff << 2)); + iowrite32(0x0, &priv->regs->if2_id1); + + /* Claring NewDat, TxRqst & IntPnd */ + pch_can_bit_clear(&priv->regs->if2_mcont, + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND | + CAN_IF_MCONT_TXRQXT); + pch_can_check_if_busy(&priv->regs->if2_creq, mask); + } else if (priv->msg_obj[mask - 1] == MSG_OBJ_RX) { + /* Setting CMASK for clearing the reception interrupts. */ + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB, + &priv->regs->if1_cmask); + + /* Clearing the Dir bit. */ + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR); + + /* Clearing NewDat & IntPnd */ + pch_can_bit_clear(&priv->regs->if1_mcont, + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND); + + pch_can_check_if_busy(&priv->regs->if1_creq, mask); + } +} + +static int pch_can_get_buffer_status(struct pch_can_priv *priv) +{ + return (ioread32(&priv->regs->treq1) & 0xffff) | + ((ioread32(&priv->regs->treq2) & 0xffff) << 16); +} + +static void pch_can_reset(struct pch_can_priv *priv) +{ + /* write to sw reset register */ + iowrite32(1, &priv->regs->srst); + iowrite32(0, &priv->regs->srst); +} + +static void pch_can_error(struct net_device *ndev, u32 status) +{ + struct sk_buff *skb; + struct pch_can_priv *priv = netdev_priv(ndev); + struct can_frame *cf; + u32 errc; + struct net_device_stats *stats = &(priv->ndev->stats); + enum can_state state = priv->can.state; + + skb = alloc_can_err_skb(ndev, &cf); + if (!skb) + return; + + if (status & PCH_BUS_OFF) { + pch_can_tx_disable_all(priv); + pch_can_rx_disable_all(priv); + state = CAN_STATE_BUS_OFF; + cf->can_id |= CAN_ERR_BUSOFF; + can_bus_off(ndev); + pch_can_set_run_mode(priv, PCH_CAN_RUN); + dev_err(&ndev->dev, "%s -> Bus Off occurres.\n", __func__); + } + + /* Warning interrupt. */ + if (status & PCH_EWARN) { + state = CAN_STATE_ERROR_WARNING; + priv->can.can_stats.error_warning++; + cf->can_id |= CAN_ERR_CRTL; + errc = ioread32(&priv->regs->errc); + if (((errc & CAN_REC) >> 8) > 96) + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; + if ((errc & CAN_TEC) > 96) + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; + dev_warn(&ndev->dev, + "%s -> Error Counter is more than 96.\n", __func__); + } + /* Error passive interrupt. */ + if (status & PCH_EPASSIV) { + priv->can.can_stats.error_passive++; + state = CAN_STATE_ERROR_PASSIVE; + cf->can_id |= CAN_ERR_CRTL; + errc = ioread32(&priv->regs->errc); + if (((errc & CAN_REC) >> 8) > 127) + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; + if ((errc & CAN_TEC) > 127) + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; + dev_err(&ndev->dev, + "%s -> CAN controller is ERROR PASSIVE .\n", __func__); + } + + if (status & PCH_LEC_ALL) { + priv->can.can_stats.bus_error++; + stats->rx_errors++; + switch (status & PCH_LEC_ALL) { + case PCH_STUF_ERR: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + case PCH_FORM_ERR: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case PCH_ACK_ERR: + cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + CAN_ERR_PROT_LOC_ACK_DEL; + break; + case PCH_BIT1_ERR: + case PCH_BIT0_ERR: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case PCH_CRC_ERR: + cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + CAN_ERR_PROT_LOC_CRC_DEL; + break; + default: + iowrite32(status | PCH_LEC_ALL, &priv->regs->stat); + break; + } + + } + + priv->can.state = state; + netif_rx(skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; +} + +static irqreturn_t pch_can_interrupt(int irq, void *dev_id) +{ + struct net_device *ndev = (struct net_device *)dev_id; + struct pch_can_priv *priv = netdev_priv(ndev); + + pch_can_set_int_enables(priv, PCH_CAN_NONE); + + napi_schedule(&priv->napi); + + return IRQ_HANDLED; +} + +static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat) +{ + u32 reg; + canid_t id; + u32 ide; + u32 rtr; + int i, j, k; + int rcv_pkts = 0; + struct sk_buff *skb; + struct can_frame *cf; + struct pch_can_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &(priv->ndev->stats); + + /* Reading the messsage object from the Message RAM */ + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, int_stat); + + /* Reading the MCONT register. */ + reg = ioread32(&priv->regs->if1_mcont); + reg &= 0xffff; + + for (k = int_stat; !(reg & CAN_IF_MCONT_EOB); k++) { + /* If MsgLost bit set. */ + if (reg & CAN_IF_MCONT_MSGLOST) { + dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n"); + pch_can_bit_clear(&priv->regs->if1_mcont, + CAN_IF_MCONT_MSGLOST); + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, + &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, k); + + skb = alloc_can_err_skb(ndev, &cf); + if (!skb) + return -ENOMEM; + + priv->can.can_stats.error_passive++; + priv->can.state = CAN_STATE_ERROR_PASSIVE; + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; + cf->data[2] |= CAN_ERR_PROT_OVERLOAD; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + netif_receive_skb(skb); + rcv_pkts++; + goto RX_NEXT; + } + if (!(reg & CAN_IF_MCONT_NEWDAT)) + goto RX_NEXT; + + skb = alloc_can_skb(priv->ndev, &cf); + if (!skb) + return -ENOMEM; + + /* Get Received data */ + ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD) >> 14; + if (ide) { + id = (ioread32(&priv->regs->if1_id1) & 0xffff); + id |= (((ioread32(&priv->regs->if1_id2)) & + 0x1fff) << 16); + cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; + } else { + id = (((ioread32(&priv->regs->if1_id2)) & + (CAN_SFF_MASK << 2)) >> 2); + cf->can_id = (id & CAN_SFF_MASK); + } + + rtr = (ioread32(&priv->regs->if1_id2) & CAN_ID2_DIR); + if (rtr) { + cf->can_dlc = 0; + cf->can_id |= CAN_RTR_FLAG; + } else { + cf->can_dlc = ((ioread32(&priv->regs->if1_mcont)) & + 0x0f); + } + + for (i = 0, j = 0; i < cf->can_dlc; j++) { + reg = ioread32(&priv->regs->if1_dataa1 + j*4); + cf->data[i++] = cpu_to_le32(reg & 0xff); + if (i == cf->can_dlc) + break; + cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff); + } + + netif_receive_skb(skb); + rcv_pkts++; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + if (k < PCH_FIFO_THRESH) { + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | + CAN_CMASK_ARB, &priv->regs->if1_cmask); + + /* Clearing the Dir bit. */ + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR); + + /* Clearing NewDat & IntPnd */ + pch_can_bit_clear(&priv->regs->if1_mcont, + CAN_IF_MCONT_INTPND); + pch_can_check_if_busy(&priv->regs->if1_creq, k); + } else if (k > PCH_FIFO_THRESH) { + pch_can_int_clr(priv, k); + } else if (k == PCH_FIFO_THRESH) { + int cnt; + for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++) + pch_can_int_clr(priv, cnt+1); + } +RX_NEXT: + /* Reading the messsage object from the Message RAM */ + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask); + pch_can_check_if_busy(&priv->regs->if1_creq, k + 1); + reg = ioread32(&priv->regs->if1_mcont); + } + + return rcv_pkts; +} +static int pch_can_rx_poll(struct napi_struct *napi, int quota) +{ + struct net_device *ndev = napi->dev; + struct pch_can_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &(priv->ndev->stats); + u32 dlc; + u32 int_stat; + int rcv_pkts = 0; + u32 reg_stat; + unsigned long flags; + + int_stat = pch_can_int_pending(priv); + if (!int_stat) + return 0; + +INT_STAT: + if (int_stat == CAN_STATUS_INT) { + reg_stat = ioread32(&priv->regs->stat); + if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) { + if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL) + pch_can_error(ndev, reg_stat); + } + + if (reg_stat & PCH_TX_OK) { + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, + ioread32(&priv->regs->intr)); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK); + } + + if (reg_stat & PCH_RX_OK) + pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK); + + int_stat = pch_can_int_pending(priv); + if (int_stat == CAN_STATUS_INT) + goto INT_STAT; + } + +MSG_OBJ: + if ((int_stat >= 1) && (int_stat <= PCH_RX_OBJ_NUM)) { + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + rcv_pkts = pch_can_rx_normal(ndev, int_stat); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + if (rcv_pkts < 0) + return 0; + } else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) { + if (priv->msg_obj[int_stat - 1] == MSG_OBJ_TX) { + /* Handle transmission interrupt */ + can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_NUM - 1); + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + iowrite32(CAN_CMASK_RX_TX_GET | CAN_CMASK_CLRINTPND, + &priv->regs->if2_cmask); + dlc = ioread32(&priv->regs->if2_mcont) & + CAN_IF_MCONT_DLC; + pch_can_check_if_busy(&priv->regs->if2_creq, int_stat); + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + if (dlc > 8) + dlc = 8; + stats->tx_bytes += dlc; + stats->tx_packets++; + } + } + + int_stat = pch_can_int_pending(priv); + if (int_stat == CAN_STATUS_INT) + goto INT_STAT; + else if (int_stat >= 1 && int_stat <= 32) + goto MSG_OBJ; + + napi_complete(napi); + pch_can_set_int_enables(priv, PCH_CAN_ALL); + + return rcv_pkts; +} + +static int pch_set_bittiming(struct net_device *ndev) +{ + struct pch_can_priv *priv = netdev_priv(ndev); + const struct can_bittiming *bt = &priv->can.bittiming; + u32 canbit; + u32 bepe; + u32 brp; + + /* Setting the CCE bit for accessing the Can Timing register. */ + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE); + + brp = (bt->tq) / (1000000000/PCH_CAN_CLK) - 1; + canbit = brp & MSK_BITT_BRP; + canbit |= (bt->sjw - 1) << BIT_BITT_SJW; + canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << BIT_BITT_TSEG1; + canbit |= (bt->phase_seg2 - 1) << BIT_BITT_TSEG2; + bepe = (brp & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE; + iowrite32(canbit, &priv->regs->bitt); + iowrite32(bepe, &priv->regs->brpe); + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_CCE); + + return 0; +} + +static void pch_can_start(struct net_device *ndev) +{ + struct pch_can_priv *priv = netdev_priv(ndev); + + if (priv->can.state != CAN_STATE_STOPPED) + pch_can_reset(priv); + + pch_set_bittiming(ndev); + pch_can_set_optmode(priv); + + pch_can_tx_enable_all(priv); + pch_can_rx_enable_all(priv); + + /* Setting the CAN to run mode. */ + pch_can_set_run_mode(priv, PCH_CAN_RUN); + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + + return; +} + +static int pch_can_do_set_mode(struct net_device *ndev, enum can_mode mode) +{ + int ret = 0; + + switch (mode) { + case CAN_MODE_START: + pch_can_start(ndev); + netif_wake_queue(ndev); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int pch_can_open(struct net_device *ndev) +{ + struct pch_can_priv *priv = netdev_priv(ndev); + int retval; + + retval = pci_enable_msi(priv->dev); + if (retval) { + dev_info(&ndev->dev, "PCH CAN opened without MSI\n"); + priv->use_msi = 0; + } else { + dev_info(&ndev->dev, "PCH CAN opened with MSI\n"); + priv->use_msi = 1; + } + + /* Regsitering the interrupt. */ + retval = request_irq(priv->dev->irq, pch_can_interrupt, IRQF_SHARED, + ndev->name, ndev); + if (retval) { + dev_err(&ndev->dev, "request_irq failed.\n"); + goto req_irq_err; + } + + /* Open common can device */ + retval = open_candev(ndev); + if (retval) { + dev_err(ndev->dev.parent, "open_candev() failed %d\n", retval); + goto err_open_candev; + } + + pch_can_init(priv); + pch_can_start(ndev); + napi_enable(&priv->napi); + netif_start_queue(ndev); + + return 0; + +err_open_candev: + free_irq(priv->dev->irq, ndev); +req_irq_err: + if (priv->use_msi) + pci_disable_msi(priv->dev); + + pch_can_release(priv); + + return retval; +} + +static int pch_close(struct net_device *ndev) +{ + struct pch_can_priv *priv = netdev_priv(ndev); + + netif_stop_queue(ndev); + napi_disable(&priv->napi); + pch_can_release(priv); + free_irq(priv->dev->irq, ndev); + if (priv->use_msi) + pci_disable_msi(priv->dev); + close_candev(ndev); + priv->can.state = CAN_STATE_STOPPED; + return 0; +} + +static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id) +{ + u32 buffer_status = 0; + struct pch_can_priv *priv = netdev_priv(ndev); + + /* Getting the message object status. */ + buffer_status = (u32) pch_can_get_buffer_status(priv); + + return buffer_status & obj_id; +} + + +static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + int i, j; + unsigned long flags; + struct pch_can_priv *priv = netdev_priv(ndev); + struct can_frame *cf = (struct can_frame *)skb->data; + int tx_buffer_avail = 0; + + if (can_dropped_invalid_skb(ndev, skb)) + return NETDEV_TX_OK; + + if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj */ + while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) << + PCH_RX_OBJ_NUM))) + udelay(500); + + priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */ + tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */ + } else { + tx_buffer_avail = priv->tx_obj; + } + priv->tx_obj++; + + /* Attaining the lock. */ + spin_lock_irqsave(&priv->msgif_reg_lock, flags); + + /* Reading the Msg Obj from the Msg RAM to the Interface register. */ + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask); + pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail); + + /* Setting the CMASK register. */ + pch_can_bit_set(&priv->regs->if2_cmask, CAN_CMASK_ALL); + + /* If ID extended is set. */ + pch_can_bit_clear(&priv->regs->if2_id1, 0xffff); + pch_can_bit_clear(&priv->regs->if2_id2, 0x1fff | CAN_ID2_XTD); + if (cf->can_id & CAN_EFF_FLAG) { + pch_can_bit_set(&priv->regs->if2_id1, cf->can_id & 0xffff); + pch_can_bit_set(&priv->regs->if2_id2, + ((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD); + } else { + pch_can_bit_set(&priv->regs->if2_id1, 0); + pch_can_bit_set(&priv->regs->if2_id2, + (cf->can_id & CAN_SFF_MASK) << 2); + } + + /* If remote frame has to be transmitted.. */ + if (cf->can_id & CAN_RTR_FLAG) + pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID2_DIR); + + for (i = 0, j = 0; i < cf->can_dlc; j++) { + iowrite32(le32_to_cpu(cf->data[i++]), + (&priv->regs->if2_dataa1) + j*4); + if (i == cf->can_dlc) + break; + iowrite32(le32_to_cpu(cf->data[i++] << 8), + (&priv->regs->if2_dataa1) + j*4); + } + + can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1); + + /* Updating the size of the data. */ + pch_can_bit_clear(&priv->regs->if2_mcont, 0x0f); + pch_can_bit_set(&priv->regs->if2_mcont, cf->can_dlc); + + /* Clearing IntPend, NewDat & TxRqst */ + pch_can_bit_clear(&priv->regs->if2_mcont, + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND | + CAN_IF_MCONT_TXRQXT); + + /* Setting NewDat, TxRqst bits */ + pch_can_bit_set(&priv->regs->if2_mcont, + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT); + + pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail); + + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags); + + return NETDEV_TX_OK; +} + +static const struct net_device_ops pch_can_netdev_ops = { + .ndo_open = pch_can_open, + .ndo_stop = pch_close, + .ndo_start_xmit = pch_xmit, +}; + +static void __devexit pch_can_remove(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct pch_can_priv *priv = netdev_priv(ndev); + + unregister_candev(priv->ndev); + free_candev(priv->ndev); + pci_iounmap(pdev, priv->regs); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + pch_can_reset(priv); +} + +#ifdef CONFIG_PM +static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; /* Counter variable. */ + int retval; /* Return value. */ + u32 buf_stat; /* Variable for reading the transmit buffer status. */ + u32 counter = 0xFFFFFF; + + struct net_device *dev = pci_get_drvdata(pdev); + struct pch_can_priv *priv = netdev_priv(dev); + + /* Stop the CAN controller */ + pch_can_set_run_mode(priv, PCH_CAN_STOP); + + /* Indicate that we are aboutto/in suspend */ + priv->can.state = CAN_STATE_SLEEPING; + + /* Waiting for all transmission to complete. */ + while (counter) { + buf_stat = pch_can_get_buffer_status(priv); + if (!buf_stat) + break; + counter--; + udelay(1); + } + if (!counter) + dev_err(&pdev->dev, "%s -> Transmission time out.\n", __func__); + + /* Save interrupt configuration and then disable them */ + pch_can_get_int_enables(priv, &(priv->int_enables)); + pch_can_set_int_enables(priv, PCH_CAN_DISABLE); + + /* Save Tx buffer enable state */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_TX) + pch_can_get_tx_enable(priv, i + 1, + &(priv->tx_enable[i])); + } + + /* Disable all Transmit buffers */ + pch_can_tx_disable_all(priv); + + /* Save Rx buffer enable state */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_RX) { + pch_can_get_rx_enable(priv, i + 1, + &(priv->rx_enable[i])); + pch_can_get_rx_buffer_link(priv, i + 1, + &(priv->rx_link[i])); + } + } + + /* Disable all Receive buffers */ + pch_can_rx_disable_all(priv); + retval = pci_save_state(pdev); + if (retval) { + dev_err(&pdev->dev, "pci_save_state failed.\n"); + } else { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + } + + return retval; +} + +static int pch_can_resume(struct pci_dev *pdev) +{ + int i; /* Counter variable. */ + int retval; /* Return variable. */ + struct net_device *dev = pci_get_drvdata(pdev); + struct pch_can_priv *priv = netdev_priv(dev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "pci_enable_device failed.\n"); + return retval; + } + + pci_enable_wake(pdev, PCI_D3hot, 0); + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + + /* Disabling all interrupts. */ + pch_can_set_int_enables(priv, PCH_CAN_DISABLE); + + /* Setting the CAN device in Stop Mode. */ + pch_can_set_run_mode(priv, PCH_CAN_STOP); + + /* Configuring the transmit and receive buffers. */ + pch_can_config_rx_tx_buffers(priv); + + /* Restore the CAN state */ + pch_set_bittiming(dev); + + /* Listen/Active */ + pch_can_set_optmode(priv); + + /* Enabling the transmit buffer. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_TX) { + pch_can_set_tx_enable(priv, i + 1, + priv->tx_enable[i]); + } + } + + /* Configuring the receive buffer and enabling them. */ + for (i = 0; i < PCH_OBJ_NUM; i++) { + if (priv->msg_obj[i] == MSG_OBJ_RX) { + /* Restore buffer link */ + pch_can_set_rx_buffer_link(priv, i + 1, + priv->rx_link[i]); + + /* Restore buffer enables */ + pch_can_set_rx_enable(priv, i + 1, priv->rx_enable[i]); + } + } + + /* Enable CAN Interrupts */ + pch_can_set_int_custom(priv); + + /* Restore Run Mode */ + pch_can_set_run_mode(priv, PCH_CAN_RUN); + + return retval; +} +#else +#define pch_can_suspend NULL +#define pch_can_resume NULL +#endif + +static int pch_can_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct pch_can_priv *priv = netdev_priv(dev); + + bec->txerr = ioread32(&priv->regs->errc) & CAN_TEC; + bec->rxerr = (ioread32(&priv->regs->errc) & CAN_REC) >> 8; + + return 0; +} + +static int __devinit pch_can_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct net_device *ndev; + struct pch_can_priv *priv; + int rc; + int index; + void __iomem *addr; + + rc = pci_enable_device(pdev); + if (rc) { + dev_err(&pdev->dev, "Failed pci_enable_device %d\n", rc); + goto probe_exit_endev; + } + + rc = pci_request_regions(pdev, KBUILD_MODNAME); + if (rc) { + dev_err(&pdev->dev, "Failed pci_request_regions %d\n", rc); + goto probe_exit_pcireq; + } + + addr = pci_iomap(pdev, 1, 0); + if (!addr) { + rc = -EIO; + dev_err(&pdev->dev, "Failed pci_iomap\n"); + goto probe_exit_ipmap; + } + + ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_NUM); + if (!ndev) { + rc = -ENOMEM; + dev_err(&pdev->dev, "Failed alloc_candev\n"); + goto probe_exit_alloc_candev; + } + + priv = netdev_priv(ndev); + priv->ndev = ndev; + priv->regs = addr; + priv->dev = pdev; + priv->can.bittiming_const = &pch_can_bittiming_const; + priv->can.do_set_mode = pch_can_do_set_mode; + priv->can.do_get_berr_counter = pch_can_get_berr_counter; + priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK; + priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj */ + + ndev->irq = pdev->irq; + ndev->flags |= IFF_ECHO; + + pci_set_drvdata(pdev, ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + ndev->netdev_ops = &pch_can_netdev_ops; + + priv->can.clock.freq = PCH_CAN_CLK; /* Hz */ + for (index = 0; index < PCH_RX_OBJ_NUM;) + priv->msg_obj[index++] = MSG_OBJ_RX; + + for (index = index; index < PCH_OBJ_NUM;) + priv->msg_obj[index++] = MSG_OBJ_TX; + + netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM); + + rc = register_candev(ndev); + if (rc) { + dev_err(&pdev->dev, "Failed register_candev %d\n", rc); + goto probe_exit_reg_candev; + } + + return 0; + +probe_exit_reg_candev: + free_candev(ndev); +probe_exit_alloc_candev: + pci_iounmap(pdev, addr); +probe_exit_ipmap: + pci_release_regions(pdev); +probe_exit_pcireq: + pci_disable_device(pdev); +probe_exit_endev: + return rc; +} + +static struct pci_driver pch_can_pci_driver = { + .name = "pch_can", + .id_table = pch_pci_tbl, + .probe = pch_can_probe, + .remove = __devexit_p(pch_can_remove), + .suspend = pch_can_suspend, + .resume = pch_can_resume, +}; + +static int __init pch_can_pci_init(void) +{ + return pci_register_driver(&pch_can_pci_driver); +} +module_init(pch_can_pci_init); + +static void __exit pch_can_pci_exit(void) +{ + pci_unregister_driver(&pch_can_pci_driver); +} +module_exit(pch_can_pci_exit); + +MODULE_DESCRIPTION("Controller Area Network Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("0.94"); diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index ae3505afd682..6fdc031daaae 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -58,4 +58,16 @@ config CAN_PLX_PCI - esd CAN-PCIe/2000 - Marathon CAN-bus-PCI card (http://www.marathon.ru/) - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/) + +config CAN_TSCAN1 + tristate "TS-CAN1 PC104 boards" + depends on ISA + help + This driver is for Technologic Systems' TSCAN-1 PC104 boards. + http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1 + The driver supports multiple boards and automatically configures them: + PLD IO base addresses are read from jumpers JP1 and JP2, + IRQ numbers are read from jumpers JP4 and JP5, + SJA1000 IO base addresses are chosen heuristically (first that works). + endif diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index ce924553995d..2c591eb321c7 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -9,5 +9,6 @@ obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o +obj-$(CONFIG_CAN_TSCAN1) += tscan1.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c new file mode 100644 index 000000000000..9756099a883a --- /dev/null +++ b/drivers/net/can/sja1000/tscan1.c @@ -0,0 +1,216 @@ +/* + * tscan1.c: driver for Technologic Systems TS-CAN1 PC104 boards + * + * Copyright 2010 Andre B. Oliveira + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * References: + * - Getting started with TS-CAN1, Technologic Systems, Jun 2009 + * http://www.embeddedarm.com/documentation/ts-can1-manual.pdf + */ + +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/isa.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include "sja1000.h" + +MODULE_DESCRIPTION("Driver for Technologic Systems TS-CAN1 PC104 boards"); +MODULE_AUTHOR("Andre B. Oliveira <anbadeol@gmail.com>"); +MODULE_LICENSE("GPL"); + +/* Maximum number of boards (one in each JP1:JP2 setting of IO address) */ +#define TSCAN1_MAXDEV 4 + +/* PLD registers address offsets */ +#define TSCAN1_ID1 0 +#define TSCAN1_ID2 1 +#define TSCAN1_VERSION 2 +#define TSCAN1_LED 3 +#define TSCAN1_PAGE 4 +#define TSCAN1_MODE 5 +#define TSCAN1_JUMPERS 6 + +/* PLD board identifier registers magic values */ +#define TSCAN1_ID1_VALUE 0xf6 +#define TSCAN1_ID2_VALUE 0xb9 + +/* PLD mode register SJA1000 IO enable bit */ +#define TSCAN1_MODE_ENABLE 0x40 + +/* PLD jumpers register bits */ +#define TSCAN1_JP4 0x10 +#define TSCAN1_JP5 0x20 + +/* PLD IO base addresses start */ +#define TSCAN1_PLD_ADDRESS 0x150 + +/* PLD register space size */ +#define TSCAN1_PLD_SIZE 8 + +/* SJA1000 register space size */ +#define TSCAN1_SJA1000_SIZE 32 + +/* SJA1000 crystal frequency (16MHz) */ +#define TSCAN1_SJA1000_XTAL 16000000 + +/* SJA1000 IO base addresses */ +static const unsigned short tscan1_sja1000_addresses[] __devinitconst = { + 0x100, 0x120, 0x180, 0x1a0, 0x200, 0x240, 0x280, 0x320 +}; + +/* Read SJA1000 register */ +static u8 tscan1_read(const struct sja1000_priv *priv, int reg) +{ + return inb((unsigned long)priv->reg_base + reg); +} + +/* Write SJA1000 register */ +static void tscan1_write(const struct sja1000_priv *priv, int reg, u8 val) +{ + outb(val, (unsigned long)priv->reg_base + reg); +} + +/* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */ +static int __devinit tscan1_probe(struct device *dev, unsigned id) +{ + struct net_device *netdev; + struct sja1000_priv *priv; + unsigned long pld_base, sja1000_base; + int irq, i; + + pld_base = TSCAN1_PLD_ADDRESS + id * TSCAN1_PLD_SIZE; + if (!request_region(pld_base, TSCAN1_PLD_SIZE, dev_name(dev))) + return -EBUSY; + + if (inb(pld_base + TSCAN1_ID1) != TSCAN1_ID1_VALUE || + inb(pld_base + TSCAN1_ID2) != TSCAN1_ID2_VALUE) { + release_region(pld_base, TSCAN1_PLD_SIZE); + return -ENODEV; + } + + switch (inb(pld_base + TSCAN1_JUMPERS) & (TSCAN1_JP4 | TSCAN1_JP5)) { + case TSCAN1_JP4: + irq = 6; + break; + case TSCAN1_JP5: + irq = 7; + break; + case TSCAN1_JP4 | TSCAN1_JP5: + irq = 5; + break; + default: + dev_err(dev, "invalid JP4:JP5 setting (no IRQ)\n"); + release_region(pld_base, TSCAN1_PLD_SIZE); + return -EINVAL; + } + + netdev = alloc_sja1000dev(0); + if (!netdev) { + release_region(pld_base, TSCAN1_PLD_SIZE); + return -ENOMEM; + } + + dev_set_drvdata(dev, netdev); + SET_NETDEV_DEV(netdev, dev); + + netdev->base_addr = pld_base; + netdev->irq = irq; + + priv = netdev_priv(netdev); + priv->read_reg = tscan1_read; + priv->write_reg = tscan1_write; + priv->can.clock.freq = TSCAN1_SJA1000_XTAL / 2; + priv->cdr = CDR_CBP | CDR_CLK_OFF; + priv->ocr = OCR_TX0_PUSHPULL; + + /* Select the first SJA1000 IO address that is free and that works */ + for (i = 0; i < ARRAY_SIZE(tscan1_sja1000_addresses); i++) { + sja1000_base = tscan1_sja1000_addresses[i]; + if (!request_region(sja1000_base, TSCAN1_SJA1000_SIZE, + dev_name(dev))) + continue; + + /* Set SJA1000 IO base address and enable it */ + outb(TSCAN1_MODE_ENABLE | i, pld_base + TSCAN1_MODE); + + priv->reg_base = (void __iomem *)sja1000_base; + if (!register_sja1000dev(netdev)) { + /* SJA1000 probe succeeded; turn LED off and return */ + outb(0, pld_base + TSCAN1_LED); + netdev_info(netdev, "TS-CAN1 at 0x%lx 0x%lx irq %d\n", + pld_base, sja1000_base, irq); + return 0; + } + + /* SJA1000 probe failed; release and try next address */ + outb(0, pld_base + TSCAN1_MODE); + release_region(sja1000_base, TSCAN1_SJA1000_SIZE); + } + + dev_err(dev, "failed to assign SJA1000 IO address\n"); + dev_set_drvdata(dev, NULL); + free_sja1000dev(netdev); + release_region(pld_base, TSCAN1_PLD_SIZE); + return -ENXIO; +} + +static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/) +{ + struct net_device *netdev; + struct sja1000_priv *priv; + unsigned long pld_base, sja1000_base; + + netdev = dev_get_drvdata(dev); + unregister_sja1000dev(netdev); + dev_set_drvdata(dev, NULL); + + priv = netdev_priv(netdev); + pld_base = netdev->base_addr; + sja1000_base = (unsigned long)priv->reg_base; + + outb(0, pld_base + TSCAN1_MODE); /* disable SJA1000 IO space */ + + release_region(sja1000_base, TSCAN1_SJA1000_SIZE); + release_region(pld_base, TSCAN1_PLD_SIZE); + + free_sja1000dev(netdev); + + return 0; +} + +static struct isa_driver tscan1_isa_driver = { + .probe = tscan1_probe, + .remove = __devexit_p(tscan1_remove), + .driver = { + .name = "tscan1", + }, +}; + +static int __init tscan1_init(void) +{ + return isa_register_driver(&tscan1_isa_driver, TSCAN1_MAXDEV); +} +module_init(tscan1_init); + +static void __exit tscan1_exit(void) +{ + isa_unregister_driver(&tscan1_isa_driver); +} +module_exit(tscan1_exit); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index a04ce6a5f637..407d4e272075 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1266,11 +1266,13 @@ static int cxgb_up(struct adapter *adap) } if (!(adap->flags & QUEUES_BOUND)) { - err = bind_qsets(adap); - if (err) { - CH_ERR(adap, "failed to bind qsets, err %d\n", err); + int ret = bind_qsets(adap); + + if (ret < 0) { + CH_ERR(adap, "failed to bind qsets, err %d\n", ret); t3_intr_disable(adap); free_irq_resources(adap); + err = ret; goto out; } adap->flags |= QUEUES_BOUND; @@ -3299,7 +3301,6 @@ static int __devinit init_one(struct pci_dev *pdev, pi->rx_offload = T3_RX_CSUM | T3_LRO; pi->port_id = i; netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); netdev->irq = pdev->irq; netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len - 1; @@ -3340,6 +3341,7 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->name = adapter->port[i]->name; __set_bit(i, &adapter->registered_device_map); + netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 5d72bda54389..f9f6645b2e61 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -296,8 +296,10 @@ static void free_tx_desc(struct adapter *adapter, struct sge_txq *q, if (d->skb) { /* an SGL is present */ if (need_unmap) unmap_skb(d->skb, q, cidx, pdev); - if (d->eop) + if (d->eop) { kfree_skb(d->skb); + d->skb = NULL; + } } ++d; if (++cidx == q->size) { diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h index eaa49e4119f1..3d4253d311eb 100644 --- a/drivers/net/cxgb4/cxgb4.h +++ b/drivers/net/cxgb4/cxgb4.h @@ -281,7 +281,6 @@ struct sge_rspq; struct port_info { struct adapter *adapter; - struct vlan_group *vlan_grp; u16 viid; s16 xact_addr_filt; /* index of exact MAC address filter */ u16 rss_size; /* size of VI's RSS table slice */ diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 87054e0a5746..f17703f410b3 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -403,7 +403,7 @@ static int link_start(struct net_device *dev) * that step explicitly. */ ret = t4_set_rxmode(pi->adapter, mb, pi->viid, dev->mtu, -1, -1, -1, - pi->vlan_grp != NULL, true); + !!(dev->features & NETIF_F_HW_VLAN_RX), true); if (ret == 0) { ret = t4_change_mac(pi->adapter, mb, pi->viid, pi->xact_addr_filt, dev->dev_addr, true, @@ -1881,7 +1881,24 @@ static int set_tso(struct net_device *dev, u32 value) static int set_flags(struct net_device *dev, u32 flags) { - return ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH); + int err; + unsigned long old_feat = dev->features; + + err = ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH | + ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); + if (err) + return err; + + if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX) { + const struct port_info *pi = netdev_priv(dev); + + err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1, + -1, -1, -1, !!(flags & ETH_FLAG_RXVLAN), + true); + if (err) + dev->features = old_feat; + } + return err; } static int get_rss_table(struct net_device *dev, struct ethtool_rxfh_indir *p) @@ -2842,15 +2859,6 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p) return 0; } -static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct port_info *pi = netdev_priv(dev); - - pi->vlan_grp = grp; - t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1, -1, -1, -1, - grp != NULL, true); -} - #ifdef CONFIG_NET_POLL_CONTROLLER static void cxgb_netpoll(struct net_device *dev) { @@ -2878,7 +2886,6 @@ static const struct net_device_ops cxgb4_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = cxgb_ioctl, .ndo_change_mtu = cxgb_change_mtu, - .ndo_vlan_rx_register = vlan_rx_register, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cxgb_netpoll, #endif @@ -3658,7 +3665,6 @@ static int __devinit init_one(struct pci_dev *pdev, pi->rx_offload = RX_CSO; pi->port_id = i; netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); netdev->irq = pdev->irq; netdev->features |= NETIF_F_SG | TSO_FLAGS; @@ -3730,6 +3736,7 @@ static int __devinit init_one(struct pci_dev *pdev, __set_bit(i, &adapter->registered_device_map); adapter->chan_map[adap2pinfo(adapter, i)->tx_chan] = i; + netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c index 9967f3debce7..17022258ed68 100644 --- a/drivers/net/cxgb4/sge.c +++ b/drivers/net/cxgb4/sge.c @@ -1530,18 +1530,11 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl, skb->rxhash = (__force u32)pkt->rsshdr.hash_val; if (unlikely(pkt->vlan_ex)) { - struct port_info *pi = netdev_priv(rxq->rspq.netdev); - struct vlan_group *grp = pi->vlan_grp; - + __vlan_hwaccel_put_tag(skb, ntohs(pkt->vlan)); rxq->stats.vlan_ex++; - if (likely(grp)) { - ret = vlan_gro_frags(&rxq->rspq.napi, grp, - ntohs(pkt->vlan)); - goto stats; - } } ret = napi_gro_frags(&rxq->rspq.napi); -stats: if (ret == GRO_HELD) + if (ret == GRO_HELD) rxq->stats.lro_pkts++; else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE) rxq->stats.lro_merged++; @@ -1608,16 +1601,10 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, skb_checksum_none_assert(skb); if (unlikely(pkt->vlan_ex)) { - struct vlan_group *grp = pi->vlan_grp; - + __vlan_hwaccel_put_tag(skb, ntohs(pkt->vlan)); rxq->stats.vlan_ex++; - if (likely(grp)) - vlan_hwaccel_receive_skb(skb, grp, ntohs(pkt->vlan)); - else - dev_kfree_skb_any(skb); - } else - netif_receive_skb(skb); - + } + netif_receive_skb(skb); return 0; } diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 000000000000..e92b2b6cd8c4 --- /dev/null +++ b/drivers/net/davinci_cpdma.c @@ -0,0 +1,965 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> + +#include "davinci_cpdma.h" + +/* DMA Registers */ +#define CPDMA_TXIDVER 0x00 +#define CPDMA_TXCONTROL 0x04 +#define CPDMA_TXTEARDOWN 0x08 +#define CPDMA_RXIDVER 0x10 +#define CPDMA_RXCONTROL 0x14 +#define CPDMA_SOFTRESET 0x1c +#define CPDMA_RXTEARDOWN 0x18 +#define CPDMA_TXINTSTATRAW 0x80 +#define CPDMA_TXINTSTATMASKED 0x84 +#define CPDMA_TXINTMASKSET 0x88 +#define CPDMA_TXINTMASKCLEAR 0x8c +#define CPDMA_MACINVECTOR 0x90 +#define CPDMA_MACEOIVECTOR 0x94 +#define CPDMA_RXINTSTATRAW 0xa0 +#define CPDMA_RXINTSTATMASKED 0xa4 +#define CPDMA_RXINTMASKSET 0xa8 +#define CPDMA_RXINTMASKCLEAR 0xac +#define CPDMA_DMAINTSTATRAW 0xb0 +#define CPDMA_DMAINTSTATMASKED 0xb4 +#define CPDMA_DMAINTMASKSET 0xb8 +#define CPDMA_DMAINTMASKCLEAR 0xbc +#define CPDMA_DMAINT_HOSTERR BIT(1) + +/* the following exist only if has_ext_regs is set */ +#define CPDMA_DMACONTROL 0x20 +#define CPDMA_DMASTATUS 0x24 +#define CPDMA_RXBUFFOFS 0x28 +#define CPDMA_EM_CONTROL 0x2c + +/* Descriptor mode bits */ +#define CPDMA_DESC_SOP BIT(31) +#define CPDMA_DESC_EOP BIT(30) +#define CPDMA_DESC_OWNER BIT(29) +#define CPDMA_DESC_EOQ BIT(28) +#define CPDMA_DESC_TD_COMPLETE BIT(27) +#define CPDMA_DESC_PASS_CRC BIT(26) + +#define CPDMA_TEARDOWN_VALUE 0xfffffffc + +struct cpdma_desc { + /* hardware fields */ + u32 hw_next; + u32 hw_buffer; + u32 hw_len; + u32 hw_mode; + /* software fields */ + void *sw_token; + u32 sw_buffer; + u32 sw_len; +}; + +struct cpdma_desc_pool { + u32 phys; + void __iomem *iomap; /* ioremap map */ + void *cpumap; /* dma_alloc map */ + int desc_size, mem_size; + int num_desc, used_desc; + unsigned long *bitmap; + struct device *dev; + spinlock_t lock; +}; + +enum cpdma_state { + CPDMA_STATE_IDLE, + CPDMA_STATE_ACTIVE, + CPDMA_STATE_TEARDOWN, +}; + +const char *cpdma_state_str[] = { "idle", "active", "teardown" }; + +struct cpdma_ctlr { + enum cpdma_state state; + struct cpdma_params params; + struct device *dev; + struct cpdma_desc_pool *pool; + spinlock_t lock; + struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; +}; + +struct cpdma_chan { + enum cpdma_state state; + struct cpdma_ctlr *ctlr; + int chan_num; + spinlock_t lock; + struct cpdma_desc __iomem *head, *tail; + int count; + void __iomem *hdp, *cp, *rxfree; + u32 mask; + cpdma_handler_fn handler; + enum dma_data_direction dir; + struct cpdma_chan_stats stats; + /* offsets into dmaregs */ + int int_set, int_clear, td; +}; + +/* The following make access to common cpdma_ctlr params more readable */ +#define dmaregs params.dmaregs +#define num_chan params.num_chan + +/* various accessors */ +#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) +#define chan_read(chan, fld) __raw_readl((chan)->fld) +#define desc_read(desc, fld) __raw_readl(&(desc)->fld) +#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) +#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) +#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) + +/* + * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci + * emac) have dedicated on-chip memory for these descriptors. Some other + * devices (e.g. cpsw switches) use plain old memory. Descriptor pools + * abstract out these details + */ +static struct cpdma_desc_pool * +cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) +{ + int bitmap_size; + struct cpdma_desc_pool *pool; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + pool->dev = dev; + pool->mem_size = size; + pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); + pool->num_desc = size / pool->desc_size; + + bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); + pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!pool->bitmap) + goto fail; + + if (phys) { + pool->phys = phys; + pool->iomap = ioremap(phys, size); + } else { + pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + GFP_KERNEL); + pool->iomap = (void __force __iomem *)pool->cpumap; + } + + if (pool->iomap) + return pool; + +fail: + kfree(pool->bitmap); + kfree(pool); + return NULL; +} + +static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) +{ + unsigned long flags; + + if (!pool) + return; + + spin_lock_irqsave(&pool->lock, flags); + WARN_ON(pool->used_desc); + kfree(pool->bitmap); + if (pool->cpumap) { + dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, + pool->phys); + } else { + iounmap(pool->iomap); + } + spin_unlock_irqrestore(&pool->lock, flags); + kfree(pool); +} + +static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc) +{ + if (!desc) + return 0; + return pool->phys + (__force dma_addr_t)desc - + (__force dma_addr_t)pool->iomap; +} + +static inline struct cpdma_desc __iomem * +desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) +{ + return dma ? pool->iomap + dma - pool->phys : NULL; +} + +static struct cpdma_desc __iomem * +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +{ + unsigned long flags; + int index; + struct cpdma_desc __iomem *desc = NULL; + + spin_lock_irqsave(&pool->lock, flags); + + index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, + num_desc, 0); + if (index < pool->num_desc) { + bitmap_set(pool->bitmap, index, num_desc); + desc = pool->iomap + pool->desc_size * index; + pool->used_desc++; + } + + spin_unlock_irqrestore(&pool->lock, flags); + return desc; +} + +static void cpdma_desc_free(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc, int num_desc) +{ + unsigned long flags, index; + + index = ((unsigned long)desc - (unsigned long)pool->iomap) / + pool->desc_size; + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, index, num_desc); + pool->used_desc--; + spin_unlock_irqrestore(&pool->lock, flags); +} + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) +{ + struct cpdma_ctlr *ctlr; + + ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) + return NULL; + + ctlr->state = CPDMA_STATE_IDLE; + ctlr->params = *params; + ctlr->dev = params->dev; + spin_lock_init(&ctlr->lock); + + ctlr->pool = cpdma_desc_pool_create(ctlr->dev, + ctlr->params.desc_mem_phys, + ctlr->params.desc_mem_size, + ctlr->params.desc_align); + if (!ctlr->pool) { + kfree(ctlr); + return NULL; + } + + if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) + ctlr->num_chan = CPDMA_MAX_CHANNELS; + return ctlr; +} + +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EBUSY; + } + + if (ctlr->params.has_soft_reset) { + unsigned long timeout = jiffies + HZ/10; + + dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); + while (time_before(jiffies, timeout)) { + if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) + break; + } + WARN_ON(!time_before(jiffies, timeout)); + } + + for (i = 0; i < ctlr->num_chan; i++) { + __raw_writel(0, ctlr->params.txhdp + 4 * i); + __raw_writel(0, ctlr->params.rxhdp + 4 * i); + __raw_writel(0, ctlr->params.txcp + 4 * i); + __raw_writel(0, ctlr->params.rxcp + 4 * i); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); + + ctlr->state = CPDMA_STATE_ACTIVE; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_start(ctlr->channels[i]); + } + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + ctlr->state = CPDMA_STATE_TEARDOWN; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_stop(ctlr->channels[i]); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); + + ctlr->state = CPDMA_STATE_IDLE; + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) +{ + struct device *dev = ctlr->dev; + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + + dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); + + dev_info(dev, "CPDMA: txidver: %x", + dma_reg_read(ctlr, CPDMA_TXIDVER)); + dev_info(dev, "CPDMA: txcontrol: %x", + dma_reg_read(ctlr, CPDMA_TXCONTROL)); + dev_info(dev, "CPDMA: txteardown: %x", + dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); + dev_info(dev, "CPDMA: rxidver: %x", + dma_reg_read(ctlr, CPDMA_RXIDVER)); + dev_info(dev, "CPDMA: rxcontrol: %x", + dma_reg_read(ctlr, CPDMA_RXCONTROL)); + dev_info(dev, "CPDMA: softreset: %x", + dma_reg_read(ctlr, CPDMA_SOFTRESET)); + dev_info(dev, "CPDMA: rxteardown: %x", + dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); + dev_info(dev, "CPDMA: txintstatraw: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); + dev_info(dev, "CPDMA: txintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); + dev_info(dev, "CPDMA: txintmaskset: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); + dev_info(dev, "CPDMA: txintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); + dev_info(dev, "CPDMA: macinvector: %x", + dma_reg_read(ctlr, CPDMA_MACINVECTOR)); + dev_info(dev, "CPDMA: maceoivector: %x", + dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); + dev_info(dev, "CPDMA: rxintstatraw: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); + dev_info(dev, "CPDMA: rxintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); + dev_info(dev, "CPDMA: rxintmaskset: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); + dev_info(dev, "CPDMA: rxintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); + dev_info(dev, "CPDMA: dmaintstatraw: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); + dev_info(dev, "CPDMA: dmaintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); + dev_info(dev, "CPDMA: dmaintmaskset: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); + dev_info(dev, "CPDMA: dmaintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); + + if (!ctlr->params.has_ext_regs) { + dev_info(dev, "CPDMA: dmacontrol: %x", + dma_reg_read(ctlr, CPDMA_DMACONTROL)); + dev_info(dev, "CPDMA: dmastatus: %x", + dma_reg_read(ctlr, CPDMA_DMASTATUS)); + dev_info(dev, "CPDMA: rxbuffofs: %x", + dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); + } + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) + if (ctlr->channels[i]) + cpdma_chan_dump(ctlr->channels[i]); + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int ret = 0, i; + + if (!ctlr) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) + cpdma_ctlr_stop(ctlr); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_destroy(ctlr->channels[i]); + } + + cpdma_desc_pool_destroy(ctlr->pool); + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(ctlr); + return ret; +} + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) +{ + unsigned long flags; + int i, reg; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; + dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_int_ctrl(ctlr->channels[i], enable); + } + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +{ + dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +} + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler) +{ + struct cpdma_chan *chan; + int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) + return NULL; + + ret = -ENOMEM; + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + goto err_chan_alloc; + + spin_lock_irqsave(&ctlr->lock, flags); + ret = -EBUSY; + if (ctlr->channels[chan_num]) + goto err_chan_busy; + + chan->ctlr = ctlr; + chan->state = CPDMA_STATE_IDLE; + chan->chan_num = chan_num; + chan->handler = handler; + + if (is_rx_chan(chan)) { + chan->hdp = ctlr->params.rxhdp + offset; + chan->cp = ctlr->params.rxcp + offset; + chan->rxfree = ctlr->params.rxfree + offset; + chan->int_set = CPDMA_RXINTMASKSET; + chan->int_clear = CPDMA_RXINTMASKCLEAR; + chan->td = CPDMA_RXTEARDOWN; + chan->dir = DMA_FROM_DEVICE; + } else { + chan->hdp = ctlr->params.txhdp + offset; + chan->cp = ctlr->params.txcp + offset; + chan->int_set = CPDMA_TXINTMASKSET; + chan->int_clear = CPDMA_TXINTMASKCLEAR; + chan->td = CPDMA_TXTEARDOWN; + chan->dir = DMA_TO_DEVICE; + } + chan->mask = BIT(chan_linear(chan)); + + spin_lock_init(&chan->lock); + + ctlr->channels[chan_num] = chan; + spin_unlock_irqrestore(&ctlr->lock, flags); + return chan; + +err_chan_busy: + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); +err_chan_alloc: + return ERR_PTR(ret); +} + +int cpdma_chan_destroy(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + unsigned long flags; + + if (!chan) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) + cpdma_chan_stop(chan); + ctlr->channels[chan->chan_num] = NULL; + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); + return 0; +} + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats) +{ + unsigned long flags; + if (!chan) + return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); + memcpy(stats, &chan->stats, sizeof(*stats)); + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_dump(struct cpdma_chan *chan) +{ + unsigned long flags; + struct device *dev = chan->ctlr->dev; + + spin_lock_irqsave(&chan->lock, flags); + + dev_info(dev, "channel %d (%s %d) state %s", + chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", + chan_linear(chan), cpdma_state_str[chan->state]); + dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); + dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); + if (chan->rxfree) { + dev_info(dev, "\trxfree: %x\n", + chan_read(chan, rxfree)); + } + + dev_info(dev, "\tstats head_enqueue: %d\n", + chan->stats.head_enqueue); + dev_info(dev, "\tstats tail_enqueue: %d\n", + chan->stats.tail_enqueue); + dev_info(dev, "\tstats pad_enqueue: %d\n", + chan->stats.pad_enqueue); + dev_info(dev, "\tstats misqueued: %d\n", + chan->stats.misqueued); + dev_info(dev, "\tstats desc_alloc_fail: %d\n", + chan->stats.desc_alloc_fail); + dev_info(dev, "\tstats pad_alloc_fail: %d\n", + chan->stats.pad_alloc_fail); + dev_info(dev, "\tstats runt_receive_buff: %d\n", + chan->stats.runt_receive_buff); + dev_info(dev, "\tstats runt_transmit_buff: %d\n", + chan->stats.runt_transmit_buff); + dev_info(dev, "\tstats empty_dequeue: %d\n", + chan->stats.empty_dequeue); + dev_info(dev, "\tstats busy_dequeue: %d\n", + chan->stats.busy_dequeue); + dev_info(dev, "\tstats good_dequeue: %d\n", + chan->stats.good_dequeue); + dev_info(dev, "\tstats requeue: %d\n", + chan->stats.requeue); + dev_info(dev, "\tstats teardown_dequeue: %d\n", + chan->stats.teardown_dequeue); + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +static void __cpdma_chan_submit(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *prev = chan->tail; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + u32 mode; + + desc_dma = desc_phys(pool, desc); + + /* simple case - idle channel */ + if (!chan->head) { + chan->stats.head_enqueue++; + chan->head = desc; + chan->tail = desc; + if (chan->state == CPDMA_STATE_ACTIVE) + chan_write(chan, hdp, desc_dma); + return; + } + + /* first chain the descriptor at the tail of the list */ + desc_write(prev, hw_next, desc_dma); + chan->tail = desc; + chan->stats.tail_enqueue++; + + /* next check if EOQ has been triggered already */ + mode = desc_read(prev, hw_mode); + if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && + (chan->state == CPDMA_STATE_ACTIVE)) { + desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); + chan_write(chan, hdp, desc_dma); + chan->stats.misqueued++; + } +} + +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + dma_addr_t buffer; + unsigned long flags; + u32 mode; + int ret = 0; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->state == CPDMA_STATE_TEARDOWN) { + ret = -EINVAL; + goto unlock_ret; + } + + desc = cpdma_desc_alloc(ctlr->pool, 1); + if (!desc) { + chan->stats.desc_alloc_fail++; + ret = -ENOMEM; + goto unlock_ret; + } + + if (len < ctlr->params.min_packet_size) { + len = ctlr->params.min_packet_size; + chan->stats.runt_transmit_buff++; + } + + buffer = dma_map_single(ctlr->dev, data, len, chan->dir); + mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; + + desc_write(desc, hw_next, 0); + desc_write(desc, hw_buffer, buffer); + desc_write(desc, hw_len, len); + desc_write(desc, hw_mode, mode | len); + desc_write(desc, sw_token, token); + desc_write(desc, sw_buffer, buffer); + desc_write(desc, sw_len, len); + + __cpdma_chan_submit(chan, desc); + + if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) + chan_write(chan, rxfree, 1); + + chan->count++; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return ret; +} + +static void __cpdma_chan_free(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc, + int outlen, int status) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t buff_dma; + int origlen; + void *token; + + token = (void *)desc_read(desc, sw_token); + buff_dma = desc_read(desc, sw_buffer); + origlen = desc_read(desc, sw_len); + + dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); + cpdma_desc_free(pool, desc, 1); + (*chan->handler)(token, outlen, status); +} + +static int __cpdma_chan_process(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + int status, outlen; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = chan->head; + if (!desc) { + chan->stats.empty_dequeue++; + status = -ENOENT; + goto unlock_ret; + } + desc_dma = desc_phys(pool, desc); + + status = __raw_readl(&desc->hw_mode); + outlen = status & 0x7ff; + if (status & CPDMA_DESC_OWNER) { + chan->stats.busy_dequeue++; + status = -EBUSY; + goto unlock_ret; + } + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); + + chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); + chan_write(chan, cp, desc_dma); + chan->count--; + chan->stats.good_dequeue++; + + if (status & CPDMA_DESC_EOQ) { + chan->stats.requeue++; + chan_write(chan, hdp, desc_phys(pool, chan->head)); + } + + spin_unlock_irqrestore(&chan->lock, flags); + + __cpdma_chan_free(chan, desc, outlen, status); + return status; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return status; +} + +int cpdma_chan_process(struct cpdma_chan *chan, int quota) +{ + int used = 0, ret = 0; + + if (chan->state != CPDMA_STATE_ACTIVE) + return -EINVAL; + + while (used < quota) { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + used++; + } + return used; +} + +int cpdma_chan_start(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + dma_reg_write(ctlr, chan->int_set, chan->mask); + chan->state = CPDMA_STATE_ACTIVE; + if (chan->head) { + chan_write(chan, hdp, desc_phys(pool, chan->head)); + if (chan->rxfree) + chan_write(chan, rxfree, chan->count); + } + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_stop(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + int ret; + unsigned long timeout; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + chan->state = CPDMA_STATE_TEARDOWN; + dma_reg_write(ctlr, chan->int_clear, chan->mask); + + /* trigger teardown */ + dma_reg_write(ctlr, chan->td, chan->chan_num); + + /* wait for teardown complete */ + timeout = jiffies + HZ/10; /* 100 msec */ + while (time_before(jiffies, timeout)) { + u32 cp = chan_read(chan, cp); + if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) + break; + cpu_relax(); + } + WARN_ON(!time_before(jiffies, timeout)); + chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); + + /* handle completed packets */ + do { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + + /* remaining packets haven't been tx/rx'ed, clean them up */ + while (chan->head) { + struct cpdma_desc __iomem *desc = chan->head; + dma_addr_t next_dma; + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ + spin_unlock_irqrestore(&chan->lock, flags); + __cpdma_chan_free(chan, desc, 0, -ENOSYS); + spin_lock_irqsave(&chan->lock, flags); + } + + chan->state = CPDMA_STATE_IDLE; + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, + chan->mask); + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +struct cpdma_control_info { + u32 reg; + u32 shift, mask; + int access; +#define ACCESS_RO BIT(0) +#define ACCESS_WO BIT(1) +#define ACCESS_RW (ACCESS_RO | ACCESS_WO) +}; + +struct cpdma_control_info controls[] = { + [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, + [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, + [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, + [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, + [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, + [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, + [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, + [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, + [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_RO) != ACCESS_RO) + goto unlock_ret; + + ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} + +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + u32 val; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_WO) != ACCESS_WO) + goto unlock_ret; + + val = dma_reg_read(ctlr, info->reg); + val &= ~(info->mask << info->shift); + val |= (value & info->mask) << info->shift; + dma_reg_write(ctlr, info->reg, val); + ret = 0; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 000000000000..868e50ebde45 --- /dev/null +++ b/drivers/net/davinci_cpdma.h @@ -0,0 +1,108 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __DAVINCI_CPDMA_H__ +#define __DAVINCI_CPDMA_H__ + +#define CPDMA_MAX_CHANNELS BITS_PER_LONG + +#define tx_chan_num(chan) (chan) +#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) +#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) +#define is_tx_chan(chan) (!is_rx_chan(chan)) +#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) +#define chan_linear(chan) __chan_linear((chan)->chan_num) + +struct cpdma_params { + struct device *dev; + void __iomem *dmaregs; + void __iomem *txhdp, *rxhdp, *txcp, *rxcp; + void __iomem *rxthresh, *rxfree; + int num_chan; + bool has_soft_reset; + int min_packet_size; + u32 desc_mem_phys; + int desc_mem_size; + int desc_align; + + /* + * Some instances of embedded cpdma controllers have extra control and + * status registers. The following flag enables access to these + * "extended" registers. + */ + bool has_ext_regs; +}; + +struct cpdma_chan_stats { + u32 head_enqueue; + u32 tail_enqueue; + u32 pad_enqueue; + u32 misqueued; + u32 desc_alloc_fail; + u32 pad_alloc_fail; + u32 runt_receive_buff; + u32 runt_transmit_buff; + u32 empty_dequeue; + u32 busy_dequeue; + u32 good_dequeue; + u32 requeue; + u32 teardown_dequeue; +}; + +struct cpdma_ctlr; +struct cpdma_chan; + +typedef void (*cpdma_handler_fn)(void *token, int len, int status); + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr); + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler); +int cpdma_chan_destroy(struct cpdma_chan *chan); +int cpdma_chan_start(struct cpdma_chan *chan); +int cpdma_chan_stop(struct cpdma_chan *chan); +int cpdma_chan_dump(struct cpdma_chan *chan); + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats); +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask); +int cpdma_chan_process(struct cpdma_chan *chan, int quota); + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); + +enum cpdma_control { + CPDMA_CMD_IDLE, /* write-only */ + CPDMA_COPY_ERROR_FRAMES, /* read-write */ + CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ + CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ + CPDMA_TX_PRIO_FIXED, /* read-write */ + CPDMA_STAT_IDLE, /* read-only */ + CPDMA_STAT_TX_ERR_CHAN, /* read-only */ + CPDMA_STAT_TX_ERR_CODE, /* read-only */ + CPDMA_STAT_RX_ERR_CHAN, /* read-only */ + CPDMA_STAT_RX_ERR_CODE, /* read-only */ + CPDMA_RX_BUFFER_OFFSET, /* read-write */ +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); + +#endif diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052ddb0a..2a628d17d178 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -63,6 +63,8 @@ #include <asm/irq.h> #include <asm/page.h> +#include "davinci_cpdma.h" + static int debug_level; module_param(debug_level, int, 0); MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); @@ -113,7 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ -#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ +#define EMAC_DEF_RX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -125,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC register related defines */ #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) #define EMAC_NUM_MULTICAST_BITS (64) -#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) @@ -212,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ /* EMAC Peripheral Device Register Memory Layout structure */ -#define EMAC_TXIDVER 0x0 -#define EMAC_TXCONTROL 0x4 -#define EMAC_TXTEARDOWN 0x8 -#define EMAC_RXIDVER 0x10 -#define EMAC_RXCONTROL 0x14 -#define EMAC_RXTEARDOWN 0x18 -#define EMAC_TXINTSTATRAW 0x80 -#define EMAC_TXINTSTATMASKED 0x84 -#define EMAC_TXINTMASKSET 0x88 -#define EMAC_TXINTMASKCLEAR 0x8C #define EMAC_MACINVECTOR 0x90 #define EMAC_DM646X_MACEOIVECTOR 0x94 -#define EMAC_RXINTSTATRAW 0xA0 -#define EMAC_RXINTSTATMASKED 0xA4 -#define EMAC_RXINTMASKSET 0xA8 -#define EMAC_RXINTMASKCLEAR 0xAC #define EMAC_MACINTSTATRAW 0xB0 #define EMAC_MACINTSTATMASKED 0xB4 #define EMAC_MACINTMASKSET 0xB8 @@ -256,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_MACADDRHI 0x504 #define EMAC_MACINDEX 0x508 -/* EMAC HDP and Completion registors */ -#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) -#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) -#define EMAC_TXCP(ch) (0x640 + (ch * 4)) -#define EMAC_RXCP(ch) (0x660 + (ch * 4)) - /* EMAC statistics registers */ #define EMAC_RXGOODFRAMES 0x200 #define EMAC_RXBCASTFRAMES 0x204 @@ -303,25 +284,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DM644X_INTMIN_INTVL 0x1 #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) -/* EMAC MDIO related */ -/* Mask & Control defines */ -#define MDIO_CONTROL_CLKDIV (0xFF) -#define MDIO_CONTROL_ENABLE BIT(30) -#define MDIO_USERACCESS_GO BIT(31) -#define MDIO_USERACCESS_WRITE BIT(30) -#define MDIO_USERACCESS_READ (0) -#define MDIO_USERACCESS_REGADR (0x1F << 21) -#define MDIO_USERACCESS_PHYADR (0x1F << 16) -#define MDIO_USERACCESS_DATA (0xFFFF) -#define MDIO_USERPHYSEL_LINKSEL BIT(7) -#define MDIO_VER_MODID (0xFFFF << 16) -#define MDIO_VER_REVMAJ (0xFF << 8) -#define MDIO_VER_REVMIN (0xFF) - -#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) -#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) -#define MDIO_CONTROL (0x04) - /* EMAC DM646X control module registers */ #define EMAC_DM646X_CMINTCTRL 0x0C #define EMAC_DM646X_CMRXINTEN 0x14 @@ -345,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC Stats Clear Mask */ #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) -/** net_buf_obj: EMAC network bufferdata structure - * - * EMAC network buffer data structure - */ -struct emac_netbufobj { - void *buf_token; - char *data_ptr; - int length; -}; - -/** net_pkt_obj: EMAC network packet data structure - * - * EMAC network packet data structure - supports buffer list (for future) - */ -struct emac_netpktobj { - void *pkt_token; /* data token may hold tx/rx chan id */ - struct emac_netbufobj *buf_list; /* array of network buffer objects */ - int num_bufs; - int pkt_length; -}; - -/** emac_tx_bd: EMAC TX Buffer descriptor data structure - * - * EMAC TX Buffer descriptor data structure - */ -struct emac_tx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ - struct emac_tx_bd __iomem *next; - void *buf_token; -}; - -/** emac_txch: EMAC TX Channel data structure - * - * EMAC TX Channel data structure - */ -struct emac_txch { - /* Config related */ - u32 num_bd; - u32 service_max; - - /* CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_tx_bd __iomem *bd_pool_head; - struct emac_tx_bd __iomem *active_queue_head; - struct emac_tx_bd __iomem *active_queue_tail; - struct emac_tx_bd __iomem *last_hw_bdprocessed; - u32 queue_active; - u32 teardown_pending; - u32 *tx_complete; - - /** statistics */ - u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ - u32 mis_queued_packets; - u32 queue_reinit; - u32 end_of_queue_add; - u32 out_of_tx_bd; - u32 no_active_pkts; /* IRQ when there were no packets to process */ - u32 active_queue_count; -}; - -/** emac_rx_bd: EMAC RX Buffer descriptor data structure - * - * EMAC RX Buffer descriptor data structure - */ -struct emac_rx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; - struct emac_rx_bd __iomem *next; - void *data_ptr; - void *buf_token; -}; - -/** emac_rxch: EMAC RX Channel data structure - * - * EMAC RX Channel data structure - */ -struct emac_rxch { - /* configuration info */ - u32 num_bd; - u32 service_max; - u32 buf_size; - char mac_addr[6]; - - /** CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_rx_bd __iomem *bd_pool_head; - struct emac_rx_bd __iomem *active_queue_head; - struct emac_rx_bd __iomem *active_queue_tail; - u32 queue_active; - u32 teardown_pending; - - /* packet and buffer objects */ - struct emac_netpktobj pkt_queue; - struct emac_netbufobj buf_queue; - - /** statistics */ - u32 proc_count; /* number of times emac_rx_bdproc is called */ - u32 processed_bd; - u32 recycled_bd; - u32 out_of_rx_bd; - u32 out_of_rx_buffers; - u32 queue_reinit; - u32 end_of_queue_add; - u32 end_of_queue; - u32 mis_queued_packets; -}; - /* emac_priv: EMAC private data structure * * EMAC adapter private data structure @@ -469,17 +317,13 @@ struct emac_priv { struct platform_device *pdev; struct napi_struct napi; char mac_addr[6]; - spinlock_t tx_lock; - spinlock_t rx_lock; void __iomem *remap_addr; u32 emac_base_phys; void __iomem *emac_base; void __iomem *ctrl_base; - void __iomem *emac_ctrl_ram; - u32 ctrl_ram_size; - u32 hw_ram_addr; - struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; - struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + struct cpdma_ctlr *dma; + struct cpdma_chan *txchan; + struct cpdma_chan *rxchan; u32 link; /* 1=link on, 0=link off */ u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ u32 duplex; /* Link duplex: 0=Half, 1=Full */ @@ -493,13 +337,7 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; u32 rx_addr_type; - /* periodic timer required for MDIO polling */ - struct timer_list periodic_timer; - u32 periodic_ticks; - u32 timer_active; - u32 phy_mask; - /* mii_bus,phy members */ - struct mii_bus *mii_bus; + const char *phy_id; struct phy_device *phydev; spinlock_t lock; /*platform specific members*/ @@ -510,19 +348,6 @@ struct emac_priv { /* clock frequency for EMAC */ static struct clk *emac_clk; static unsigned long emac_bus_frequency; -static unsigned long mdio_max_freq; - -#define emac_virt_to_phys(addr, priv) \ - (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ - + priv->hw_ram_addr) - -/* Cache macros - Packet buffers would be from skb pool which is cached */ -#define EMAC_VIRT_NOCACHE(addr) (addr) - -/* DM644x does not have BD's in cached memory - so no cache functions */ -#define BD_CACHE_INVALIDATE(addr, size) -#define BD_CACHE_WRITEBACK(addr, size) -#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) /* EMAC TX Host Error description strings */ static char *emac_txhost_errcodes[16] = { @@ -548,9 +373,6 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) -#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) -#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) - /** * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure @@ -569,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_ctrl_read(EMAC_CTRL_EWCTL), emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); } - dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", - emac_read(EMAC_TXIDVER), - ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), - emac_read(EMAC_RXIDVER), - ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); - dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ - "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), - emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); - dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ - "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), - emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); - dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ - "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), - emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ @@ -591,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); - dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", - emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); dev_info(emac_dev, "EMAC Statistics\n"); dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", emac_read(EMAC_RXGOODFRAMES)); @@ -654,11 +460,10 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXMOFOVERRUNS)); dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", emac_read(EMAC_RXDMAOVERRUNS)); + + cpdma_ctlr_dump(priv->dma); } -/************************************************************************* - * EMAC MDIO/Phy Functionality - *************************************************************************/ /** * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter @@ -686,7 +491,7 @@ static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_gset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -704,7 +509,7 @@ static int emac_get_settings(struct net_device *ndev, static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_sset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -841,7 +646,7 @@ static void emac_update_phystatus(struct emac_priv *priv) mac_control = emac_read(EMAC_MACCONTROL); cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? DUPLEX_FULL : DUPLEX_HALF; - if (priv->phy_mask) + if (priv->phydev) new_duplex = priv->phydev->duplex; else new_duplex = DUPLEX_FULL; @@ -1184,371 +989,68 @@ static irqreturn_t emac_irq(int irq, void *dev_id) return IRQ_HANDLED; } -/** EMAC on-chip buffer descriptor memory - * - * WARNING: Please note that the on chip memory is used for both TX and RX - * buffer descriptor queues and is equally divided between TX and RX desc's - * If the number of TX or RX descriptors change this memory pointers need - * to be adjusted. If external memory is allocated then these pointers can - * pointer to the memory - * - */ -#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) -#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ - (((priv)->ctrl_ram_size) >> 1)) - -/** - * emac_init_txch: TX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device init to setup a TX channel (allocate buffer desc - * create free pool and keep ready for transmission - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_txch(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = NULL; - - txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); - if (NULL == txch) { - dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); - return -ENOMEM; - } - priv->txch[ch] = txch; - txch->service_max = EMAC_DEF_TX_MAX_SERVICE; - txch->active_queue_head = NULL; - txch->active_queue_tail = NULL; - txch->queue_active = 0; - txch->teardown_pending = 0; - - /* allocate memory for TX CPPI channel on a 4 byte boundry */ - txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), - GFP_KERNEL); - if (NULL == txch->tx_complete) { - dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); - kfree(txch); - return -ENOMEM; - } - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; - txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); - - /* alloc TX BD memory */ - txch->bd_mem = EMAC_TX_BD_MEM(priv); - __memzero((void __force *)txch->bd_mem, txch->alloc_size); - - /* initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) txch->bd_mem + 0xF) & ~0xF); - txch->bd_pool_head = NULL; - for (cnt = 0; cnt < txch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - } - - /* reset statistics counters */ - txch->out_of_tx_bd = 0; - txch->no_active_pkts = 0; - txch->active_queue_count = 0; - - return 0; -} - -/** - * emac_cleanup_txch: Book-keep function to clean TX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to clean up TX channel resources - * - */ -static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) +static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) { - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - if (txch->bd_mem) - txch->bd_mem = NULL; - kfree(txch->tx_complete); - kfree(txch); - priv->txch[ch] = NULL; - } + struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + if (WARN_ON(!skb)) + return NULL; + skb->dev = priv->ndev; + skb_reserve(skb, NET_IP_ALIGN); + return skb; } -/** - * emac_net_tx_complete: TX packet completion function - * @priv: The DaVinci EMAC private adapter structure - * @net_data_tokens: packet token - skb pointer - * @num_tokens: number of skb's to free - * @ch: TX channel number - * - * Frees the skb once packet is transmitted - * - */ -static int emac_net_tx_complete(struct emac_priv *priv, - void **net_data_tokens, - int num_tokens, u32 ch) +static void emac_rx_handler(void *token, int len, int status) { - struct net_device *ndev = priv->ndev; - u32 cnt; - - if (unlikely(num_tokens && netif_queue_stopped(ndev))) - netif_start_queue(ndev); - for (cnt = 0; cnt < num_tokens; cnt++) { - struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; - if (skb == NULL) - continue; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; + int ret; + + /* free and bail if we are shutting down */ + if (unlikely(!netif_running(ndev))) { dev_kfree_skb_any(skb); + return; } - return 0; -} - -/** - * emac_txch_teardown: TX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to teardown TX channel - * - */ -static void emac_txch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - struct emac_txch *txch = priv->txch[ch]; - struct emac_tx_bd __iomem *curr_bd; - - while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: TX teardown aborted\n"); - break; - } - } - emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); - - /* process sent packets and return skb's to upper layer */ - if (1 == txch->queue_active) { - curr_bd = txch->active_queue_head; - while (curr_bd != NULL) { - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - emac_net_tx_complete(priv, (void __force *) - &curr_bd->buf_token, 1, ch); - if (curr_bd != txch->active_queue_tail) - curr_bd = curr_bd->next; - else - break; - } - txch->bd_pool_head = txch->active_queue_head; - txch->active_queue_head = - txch->active_queue_tail = NULL; - } -} -/** - * emac_stop_txch: Stop TX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to stop TX channel operation - * - */ -static void emac_stop_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - txch->teardown_pending = 1; - emac_write(EMAC_TXTEARDOWN, 0); - emac_txch_teardown(priv, ch); - txch->teardown_pending = 0; - emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); + /* recycle on recieve error */ + if (status < 0) { + ndev->stats.rx_errors++; + goto recycle; } -} -/** - * emac_tx_bdproc: TX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes TX buffer descriptors after packets are transmitted - checks - * ownership bit on the TX * descriptor and requeues it to free pool & frees - * the SKB buffer. Only "budget" number of packets are processed and - * indication of pending packets provided to the caller - * - * Returns number of packets processed - */ -static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - struct device *emac_dev = &priv->ndev->dev; - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - u32 tx_complete_cnt = 0; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = priv->txch[ch]; - u32 *tx_complete_ptr = txch->tx_complete; - - if (unlikely(1 == txch->teardown_pending)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) { - dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ - "teardown pending\n"); - } - return 0; /* dont handle any pkt completions */ - } + /* feed received packet up the stack */ + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; - ++txch->proc_count; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->active_queue_head; - if (NULL == curr_bd) { - emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); - txch->no_active_pkts++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; + /* alloc a new packet for receive */ + skb = emac_rx_alloc(priv); + if (!skb) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "failed rx buffer alloc\n"); + return; } - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); - txch->active_queue_head = curr_bd->next; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd->next) { /* misqueued packet */ - emac_write(EMAC_TXHDP(ch), curr_bd->h_next); - ++txch->mis_queued_packets; - } else { - txch->queue_active = 0; /* end of queue */ - } - } - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - *tx_complete_ptr = (u32) curr_bd->buf_token; - ++tx_complete_ptr; - ++tx_complete_cnt; - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - --txch->active_queue_count; - pkts_processed++; - txch->last_hw_bdprocessed = curr_bd; - curr_bd = txch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - } /* end of pkt processing loop */ - - emac_net_tx_complete(priv, - (void *)&txch->tx_complete[0], - tx_complete_cnt, ch); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return pkts_processed; +recycle: + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + dev_kfree_skb_any(skb); } -#define EMAC_ERR_TX_OUT_OF_BD -1 - -/** - * emac_send: EMAC Transmit function (internal) - * @priv: The DaVinci EMAC private adapter structure - * @pkt: packet pointer (contains skb ptr) - * @ch: TX channel number - * - * Called by the transmit function to queue the packet in EMAC hardware queue - * - * Returns success(0) or error code (typically out of desc's) - */ -static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) +static void emac_tx_handler(void *token, int len, int status) { - unsigned long flags; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch; - struct emac_netbufobj *buf_list; - - txch = priv->txch[ch]; - buf_list = pkt->buf_list; /* get handle to the buffer array */ - - /* check packet size and pad if short */ - if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { - buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); - pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; - } + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->bd_pool_head; - if (curr_bd == NULL) { - txch->out_of_tx_bd++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return EMAC_ERR_TX_OUT_OF_BD; - } - - txch->bd_pool_head = curr_bd->next; - curr_bd->buf_token = buf_list->buf_token; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, - buf_list->length, DMA_TO_DEVICE); - curr_bd->off_b_len = buf_list->length; - curr_bd->h_next = 0; - curr_bd->next = NULL; - curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | - EMAC_CPPI_EOP_BIT | pkt->pkt_length); - - /* flush the packet from cache if write back cache is present */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - - /* send the packet */ - if (txch->active_queue_head == NULL) { - txch->active_queue_head = curr_bd; - txch->active_queue_tail = curr_bd; - if (1 != txch->queue_active) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - txch->queue_active = 1; - } - ++txch->queue_reinit; - } else { - register struct emac_tx_bd __iomem *tail_bd; - register u32 frame_status; - - tail_bd = txch->active_queue_tail; - tail_bd->next = curr_bd; - txch->active_queue_tail = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++txch->end_of_queue_add; - } - } - txch->active_queue_count++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; + if (unlikely(netif_queue_stopped(ndev))) + netif_start_queue(ndev); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += len; + dev_kfree_skb_any(skb); } /** @@ -1565,42 +1067,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) { struct device *emac_dev = &ndev->dev; int ret_code; - struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ - struct emac_netpktobj tx_packet; /* packet object */ struct emac_priv *priv = netdev_priv(ndev); /* If no link, return */ if (unlikely(!priv->link)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); - return NETDEV_TX_BUSY; + goto fail_tx; + } + + ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); + if (unlikely(ret_code < 0)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); + goto fail_tx; } - /* Build the buffer and packet objects - Since only single fragment is - * supported, need not set length and token in both packet & object. - * Doing so for completeness sake & to show that this needs to be done - * in multifragment case - */ - tx_packet.buf_list = &tx_buf; - tx_packet.num_bufs = 1; /* only single fragment supported */ - tx_packet.pkt_length = skb->len; - tx_packet.pkt_token = (void *)skb; - tx_buf.length = skb->len; - tx_buf.buf_token = (void *)skb; - tx_buf.data_ptr = skb->data; - ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, + GFP_KERNEL); if (unlikely(ret_code != 0)) { - if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ - " err. Out of TX BD's"); - netif_stop_queue(priv->ndev); - } - ndev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); + goto fail_tx; } return NETDEV_TX_OK; + +fail_tx: + ndev->stats.tx_dropped++; + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; } /** @@ -1621,218 +1117,16 @@ static void emac_dev_tx_timeout(struct net_device *ndev) if (netif_msg_tx_err(priv)) dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); + emac_dump_regs(priv); + ndev->stats.tx_errors++; emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_init_txch(priv, EMAC_DEF_TX_CH); - emac_write(EMAC_TXHDP(0), 0); - emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + cpdma_chan_stop(priv->txchan); + cpdma_chan_start(priv->txchan); emac_int_enable(priv); } /** - * emac_net_alloc_rx_buf: Allocate a skb for RX - * @priv: The DaVinci EMAC private adapter structure - * @buf_size: size of SKB data buffer to allocate - * @data_token: data token returned (skb handle for storing in buffer desc) - * @ch: RX channel number - * - * Called during RX channel setup - allocates skb buffer of required size - * and provides the skb handle and allocated buffer data pointer to caller - * - * Returns skb data pointer or 0 on failure to alloc skb - */ -static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, - void **data_token, u32 ch) -{ - struct net_device *ndev = priv->ndev; - struct device *emac_dev = &ndev->dev; - struct sk_buff *p_skb; - - p_skb = dev_alloc_skb(buf_size); - if (unlikely(NULL == p_skb)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); - return NULL; - } - - /* set device pointer in skb and reserve space for extra bytes */ - p_skb->dev = ndev; - skb_reserve(p_skb, NET_IP_ALIGN); - *data_token = (void *) p_skb; - return p_skb->data; -} - -/** - * emac_init_rxch: RX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * @param: mac address for RX channel - * - * Called during device init to setup a RX channel (allocate buffers and - * buffer descriptors, create queue and keep ready for reception - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rxch *rxch = NULL; - - rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); - if (NULL == rxch) { - dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); - return -ENOMEM; - } - priv->rxch[ch] = rxch; - rxch->buf_size = priv->rx_buf_size; - rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; - rxch->queue_active = 0; - rxch->teardown_pending = 0; - - /* save mac address */ - for (cnt = 0; cnt < 6; cnt++) - rxch->mac_addr[cnt] = param[cnt]; - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; - rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); - rxch->bd_mem = EMAC_RX_BD_MEM(priv); - __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); - rxch->pkt_queue.buf_list = &rxch->buf_queue; - - /* allocate RX buffer and initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); - rxch->active_queue_head = NULL; - rxch->active_queue_tail = mem; - for (cnt = 0; cnt < rxch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - /* for future use the last parameter contains the BD ptr */ - curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, - rxch->buf_size, - (void __force **)&curr_bd->buf_token, - EMAC_DEF_RX_CH); - if (curr_bd->data_ptr == NULL) { - dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ - "failed for ch %d\n", ch); - kfree(rxch); - return -ENOMEM; - } - - /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, - priv); - curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - - /* write back to hardware memory */ - BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, - EMAC_BD_LENGTH_FOR_CACHE); - curr_bd->next = rxch->active_queue_head; - rxch->active_queue_head = curr_bd; - } - - /* At this point rxCppi->activeQueueHead points to the first - RX BD ready to be given to RX HDP and rxch->active_queue_tail - points to the last RX BD - */ - return 0; -} - -/** - * emac_rxch_teardown: RX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to teardown RX channel - * - */ -static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - - while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: RX teardown aborted\n"); - break; - } - } - emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); -} - -/** - * emac_stop_rxch: Stop RX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to stop RX channel operation - * - */ -static void emac_stop_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - if (rxch) { - rxch->teardown_pending = 1; - emac_write(EMAC_RXTEARDOWN, ch); - /* wait for teardown complete */ - emac_rxch_teardown(priv, ch); - rxch->teardown_pending = 0; - emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_cleanup_rxch: Book-keep function to clean RX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to clean up RX channel resources - * - */ -static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - struct emac_rx_bd __iomem *curr_bd; - - if (rxch) { - /* free the receive buffers previously allocated */ - curr_bd = rxch->active_queue_head; - while (curr_bd) { - if (curr_bd->buf_token) { - dma_unmap_single(&priv->ndev->dev, - curr_bd->buff_ptr, - curr_bd->off_b_len - & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - dev_kfree_skb_any((struct sk_buff *)\ - curr_bd->buf_token); - } - curr_bd = curr_bd->next; - } - if (rxch->bd_mem) - rxch->bd_mem = NULL; - kfree(rxch); - priv->rxch[ch] = NULL; - } -} - -/** * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number @@ -1948,7 +1242,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) { struct emac_priv *priv = netdev_priv(ndev); - struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; @@ -1959,11 +1252,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - /* If the interface is down - rxch is NULL. */ /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } if (netif_msg_drv(priv)) @@ -1974,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_addbd_to_rx_queue: Recycle RX buffer descriptor - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @curr_bd: current buffer descriptor - * @buffer: buffer pointer for descriptor - * @buf_token: buffer token (stores skb information) - * - * Prepares the recycled buffer descriptor and addes it to hardware - * receive queue - if queue empty this descriptor becomes the head - * else addes the descriptor to end of queue - * - */ -static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, - struct emac_rx_bd __iomem *curr_bd, - char *buffer, void *buf_token) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - /* populate the hardware descriptor */ - curr_bd->h_next = 0; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - curr_bd->next = NULL; - curr_bd->data_ptr = buffer; - curr_bd->buf_token = buf_token; - - /* write back */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - if (rxch->active_queue_head == NULL) { - rxch->active_queue_head = curr_bd; - rxch->active_queue_tail = curr_bd; - if (0 != rxch->queue_active) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - rxch->queue_active = 1; - } - } else { - struct emac_rx_bd __iomem *tail_bd; - u32 frame_status; - - tail_bd = rxch->active_queue_tail; - rxch->active_queue_tail = curr_bd; - tail_bd->next = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++rxch->end_of_queue_add; - } - } - ++rxch->recycled_bd; -} - -/** - * emac_net_rx_cb: Prepares packet and sends to upper layer - * @priv: The DaVinci EMAC private adapter structure - * @net_pkt_list: Network packet list (received packets) - * - * Invalidates packet buffer memory and sends the received packet to upper - * layer - * - * Returns success or appropriate error code (none as of now) - */ -static int emac_net_rx_cb(struct emac_priv *priv, - struct emac_netpktobj *net_pkt_list) -{ - struct net_device *ndev = priv->ndev; - struct sk_buff *p_skb = net_pkt_list->pkt_token; - /* set length of packet */ - skb_put(p_skb, net_pkt_list->pkt_length); - p_skb->protocol = eth_type_trans(p_skb, priv->ndev); - netif_receive_skb(p_skb); - ndev->stats.rx_bytes += net_pkt_list->pkt_length; - ndev->stats.rx_packets++; - return 0; -} - -/** - * emac_rx_bdproc: RX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes RX buffer descriptors - checks ownership bit on the RX buffer - * descriptor, sends the receive packet to upper layer, allocates a new SKB - * and recycles the buffer descriptor (requeues it in hardware RX queue). - * Only "budget" number of packets are processed and indication of pending - * packets provided to the caller. - * - * Returns number of packets processed (and indication of pending packets) - */ -static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - char *new_buffer; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rx_bd __iomem *last_bd; - struct emac_netpktobj *curr_pkt, pkt_obj; - struct emac_netbufobj buf_obj; - struct emac_netbufobj *rx_buf_obj; - void *new_buf_token; - struct emac_rxch *rxch = priv->rxch[ch]; - - if (unlikely(1 == rxch->teardown_pending)) - return 0; - ++rxch->proc_count; - spin_lock_irqsave(&priv->rx_lock, flags); - pkt_obj.buf_list = &buf_obj; - curr_pkt = &pkt_obj; - curr_bd = rxch->active_queue_head; - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - - new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, - &new_buf_token, EMAC_DEF_RX_CH); - if (unlikely(NULL == new_buffer)) { - ++rxch->out_of_rx_buffers; - goto end_emac_rx_bdproc; - } - - /* populate received packet data structure */ - rx_buf_obj = &curr_pkt->buf_list[0]; - rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; - rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; - rx_buf_obj->buf_token = curr_bd->buf_token; - - dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; - curr_pkt->num_bufs = 1; - curr_pkt->pkt_length = - (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); - ++rxch->processed_bd; - last_bd = curr_bd; - curr_bd = last_bd->next; - rxch->active_queue_head = curr_bd; - - /* check if end of RX queue ? */ - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd) { - ++rxch->mis_queued_packets; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - } else { - ++rxch->end_of_queue; - rxch->queue_active = 0; - } - } - - /* recycle BD */ - emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, - new_buf_token); - - /* return the packet to the user - BD ptr passed in - * last parameter for potential *future* use */ - spin_unlock_irqrestore(&priv->rx_lock, flags); - emac_net_rx_cb(priv, curr_pkt); - spin_lock_irqsave(&priv->rx_lock, flags); - curr_bd = rxch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - ++pkts_processed; - } - -end_emac_rx_bdproc: - spin_unlock_irqrestore(&priv->rx_lock, flags); - return pkts_processed; -} - -/** * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * @@ -2172,7 +1276,7 @@ end_emac_rx_bdproc: */ static int emac_hw_enable(struct emac_priv *priv) { - u32 ch, val, mbp_enable, mac_control; + u32 val, mbp_enable, mac_control; /* Soft reset */ emac_write(EMAC_SOFTRESET, 1); @@ -2215,26 +1319,9 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; - val = emac_read(EMAC_TXCONTROL); - val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; - emac_write(EMAC_TXCONTROL, val); - val = emac_read(EMAC_RXCONTROL); - val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; - emac_write(EMAC_RXCONTROL, val); emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); - for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_TXINTMASKSET, BIT(ch)); - } - for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { - struct emac_rxch *rxch = priv->rxch[ch]; - emac_setmac(priv, ch, rxch->mac_addr); - emac_write(EMAC_RXINTMASKSET, BIT(ch)); - rxch->queue_active = 1; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - } + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); /* Enable MII */ val = emac_read(EMAC_MACCONTROL); @@ -2279,8 +1366,8 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, - EMAC_DEF_TX_MAX_SERVICE); + num_tx_pkts = cpdma_chan_process(priv->txchan, + EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; @@ -2289,7 +1376,7 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); } /* RX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; @@ -2348,79 +1435,6 @@ void emac_poll_controller(struct net_device *ndev) } #endif -/* PHY/MII bus related */ - -/* Wait until mdio is ready for next command */ -#define MDIO_WAIT_FOR_USER_ACCESS\ - while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ - MDIO_USERACCESS_GO) != 0) - -static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) -{ - unsigned int phy_data = 0; - unsigned int phy_control; - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - phy_control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_READ | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), phy_control); - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; - -} - -static int emac_mii_write(struct mii_bus *bus, int phy_id, - int phy_reg, u16 phy_data) -{ - - unsigned int control; - - /* until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_WRITE | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), control); - - return 0; -} - -static int emac_mii_reset(struct mii_bus *bus) -{ - unsigned int clk_div; - int mdio_bus_freq = emac_bus_frequency; - - if (mdio_max_freq && mdio_bus_freq) - clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); - else - clk_div = 0xFF; - - clk_div &= MDIO_CONTROL_CLKDIV; - - /* Set enable and clock divider in MDIOControl */ - emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); - - return 0; - -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; - -/* emac_driver: EMAC MII bus structure */ - -static struct mii_bus *emac_mii; - static void emac_adjust_link(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); @@ -2485,6 +1499,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) return -EOPNOTSUPP; } +static int match_first_device(struct device *dev, void *data) +{ + return 1; +} + /** * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter @@ -2498,10 +1517,9 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; - u32 rc, cnt, ch; - int phy_addr; + u32 cnt; struct resource *res; - int q, m; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -2513,29 +1531,21 @@ static int emac_dev_open(struct net_device *ndev) /* Configuration items */ priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; - /* Clear basic hardware */ - for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - } priv->mac_hash1 = 0; priv->mac_hash2 = 0; emac_write(EMAC_MACHASH1, 0); emac_write(EMAC_MACHASH2, 0); - /* multi ch not supported - open 1 TX, 1RX ch by default */ - rc = emac_init_txch(priv, EMAC_DEF_TX_CH); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); - return rc; - } - rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); - return rc; + for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { + struct sk_buff *skb = emac_rx_alloc(priv); + + if (!skb) + break; + + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + break; } /* Request IRQ */ @@ -2560,28 +1570,28 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } - /* find the first phy */ + cpdma_ctlr_start(priv->dma); + priv->phydev = NULL; - if (priv->phy_mask) { - emac_mii_reset(priv->mii_bus); - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (priv->mii_bus->phy_map[phy_addr]) { - priv->phydev = priv->mii_bus->phy_map[phy_addr]; - break; - } - } + /* use the first phy on the bus if pdata did not give us a phy id */ + if (!priv->phy_id) { + struct device *phy; - if (!priv->phydev) { - printk(KERN_ERR "%s: no PHY found\n", ndev->name); - return -1; - } + phy = bus_find_device(&mdio_bus_type, NULL, NULL, + match_first_device); + if (phy) + priv->phy_id = dev_name(phy); + } - priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), - &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (priv->phy_id && *priv->phy_id) { + priv->phydev = phy_connect(ndev, priv->phy_id, + &emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", - ndev->name); + dev_err(emac_dev, "could not connect to phy %s\n", + priv->phy_id); + priv->phydev = NULL; return PTR_ERR(priv->phydev); } @@ -2589,12 +1599,13 @@ static int emac_dev_open(struct net_device *ndev) priv->speed = 0; priv->duplex = ~0; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + dev_info(emac_dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", priv->phydev->drv->name, dev_name(&priv->phydev->dev), priv->phydev->phy_id); - } else{ + } else { /* No PHY , fix the link, speed and duplex settings */ + dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); priv->link = 1; priv->speed = SPEED_100; priv->duplex = DUPLEX_FULL; @@ -2607,7 +1618,7 @@ static int emac_dev_open(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); - if (priv->phy_mask) + if (priv->phydev) phy_start(priv->phydev); return 0; @@ -2648,10 +1659,7 @@ static int emac_dev_stop(struct net_device *ndev) netif_carrier_off(ndev); emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_stop_rxch(priv, EMAC_DEF_RX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + cpdma_ctlr_stop(priv->dma); emac_write(EMAC_SOFTRESET, 1); if (priv->phydev) @@ -2756,9 +1764,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size; + unsigned long size, hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; + struct cpdma_params dma_params; /* obtain emac clock from kernel */ emac_clk = clk_get(&pdev->dev, NULL); @@ -2782,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); pdata = pdev->dev.platform_data; @@ -2794,7 +1801,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) /* MAC addr and PHY mask , RMII enable info from platform_data */ memcpy(priv->mac_addr, pdata->mac_addr, 6); - priv->phy_mask = pdata->phy_mask; + priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; @@ -2831,14 +1838,41 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev->base_addr = (unsigned long)priv->remap_addr; priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; - priv->ctrl_ram_size = pdata->ctrl_ram_size; - priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; - if (pdata->hw_ram_addr) - priv->hw_ram_addr = pdata->hw_ram_addr; - else - priv->hw_ram_addr = (u32 __force)res->start + - pdata->ctrl_ram_offset; + hw_ram_addr = pdata->hw_ram_addr; + if (!hw_ram_addr) + hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; + + memset(&dma_params, 0, sizeof(dma_params)); + dma_params.dev = emac_dev; + dma_params.dmaregs = priv->emac_base; + dma_params.rxthresh = priv->emac_base + 0x120; + dma_params.rxfree = priv->emac_base + 0x140; + dma_params.txhdp = priv->emac_base + 0x600; + dma_params.rxhdp = priv->emac_base + 0x620; + dma_params.txcp = priv->emac_base + 0x640; + dma_params.rxcp = priv->emac_base + 0x660; + dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; + dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; + dma_params.desc_mem_phys = hw_ram_addr; + dma_params.desc_mem_size = pdata->ctrl_ram_size; + dma_params.desc_align = 16; + + priv->dma = cpdma_ctlr_create(&dma_params); + if (!priv->dma) { + dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); + rc = -ENOMEM; + goto no_dma; + } + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); + if (WARN_ON(!priv->txchan || !priv->rxchan)) { + rc = -ENOMEM; + goto no_irq_res; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -2871,32 +1905,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } - /* MII/Phy intialisation, mdio bus registration */ - emac_mii = mdiobus_alloc(); - if (emac_mii == NULL) { - dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); - rc = -ENOMEM; - goto mdio_alloc_err; - } - - priv->mii_bus = emac_mii; - emac_mii->name = "emac-mii", - emac_mii->read = emac_mii_read, - emac_mii->write = emac_mii_write, - emac_mii->reset = emac_mii_reset, - emac_mii->irq = mii_irqs, - emac_mii->phy_mask = ~(priv->phy_mask); - emac_mii->parent = &pdev->dev; - emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); - mdio_max_freq = pdata->mdio_max_freq; - emac_mii->reset(emac_mii); - - /* Register the MII bus */ - rc = mdiobus_register(emac_mii); - if (rc) - goto mdiobus_quit; - if (netif_msg_probe(priv)) { dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ "(regs: %p, irq: %d)\n", @@ -2904,13 +1912,15 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } return 0; -mdiobus_quit: - mdiobus_free(emac_mii); - netdev_reg_err: -mdio_alloc_err: clk_disable(emac_clk); no_irq_res: + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); +no_dma: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); iounmap(priv->remap_addr); @@ -2938,8 +1948,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); + + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); release_mem_region(res->start, res->end - res->start + 1); diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 000000000000..7615040df756 --- /dev/null +++ b/drivers/net/davinci_mdio.c @@ -0,0 +1,475 @@ +/* + * DaVinci MDIO Module driver + * + * Copyright (C) 2010 Texas Instruments. + * + * Shamelessly ripped out of davinci_emac.c, original copyrights follow: + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --------------------------------------------------------------------------- + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/phy.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/davinci_emac.h> + +/* + * This timeout definition is a worst-case ultra defensive measure against + * unexpected controller lock ups. Ideally, we should never ever hit this + * scenario in practice. + */ +#define MDIO_TIMEOUT 100 /* msecs */ + +#define PHY_REG_MASK 0x1f +#define PHY_ID_MASK 0x1f + +#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ + +struct davinci_mdio_regs { + u32 version; + u32 control; +#define CONTROL_IDLE BIT(31) +#define CONTROL_ENABLE BIT(30) +#define CONTROL_MAX_DIV (0xff) + + u32 alive; + u32 link; + u32 linkintraw; + u32 linkintmasked; + u32 __reserved_0[2]; + u32 userintraw; + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; + u32 __reserved_1[20]; + + struct { + u32 access; +#define USERACCESS_GO BIT(31) +#define USERACCESS_WRITE BIT(30) +#define USERACCESS_ACK BIT(29) +#define USERACCESS_READ (0) +#define USERACCESS_DATA (0xffff) + + u32 physel; + } user[0]; +}; + +struct mdio_platform_data default_pdata = { + .bus_freq = DEF_OUT_FREQ, +}; + +struct davinci_mdio_data { + struct mdio_platform_data pdata; + struct davinci_mdio_regs __iomem *regs; + spinlock_t lock; + struct clk *clk; + struct device *dev; + struct mii_bus *bus; + bool suspended; + unsigned long access_time; /* jiffies */ +}; + +static void __davinci_mdio_reset(struct davinci_mdio_data *data) +{ + u32 mdio_in, div, mdio_out_khz, access_time; + + mdio_in = clk_get_rate(data->clk); + div = (mdio_in / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * One mdio transaction consists of: + * 32 bits of preamble + * 32 bits of transferred data + * 24 bits of bus yield (not needed unless shared?) + */ + mdio_out_khz = mdio_in / (1000 * (div + 1)); + access_time = (88 * 1000) / mdio_out_khz; + + /* + * In the worst case, we could be kicking off a user-access immediately + * after the mdio bus scan state-machine triggered its own read. If + * so, our request could get deferred by one access cycle. We + * defensively allow for 4 access cycles. + */ + data->access_time = usecs_to_jiffies(access_time * 4); + if (!data->access_time) + data->access_time = 1; +} + +static int davinci_mdio_reset(struct mii_bus *bus) +{ + struct davinci_mdio_data *data = bus->priv; + u32 phy_mask, ver; + + __davinci_mdio_reset(data); + + /* wait for scan logic to settle */ + msleep(PHY_MAX_ADDR * data->access_time); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(data->dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(data->dev, "no live phy, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + return 0; +} + +/* wait until hardware is ready for another user access */ +static inline int wait_for_user_access(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + u32 reg; + + while (time_after(timeout, jiffies)) { + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + + reg = __raw_readl(®s->control); + if ((reg & CONTROL_IDLE) == 0) + continue; + + /* + * An emac soft_reset may have clobbered the mdio controller's + * state machine. We need to reset and retry the current + * operation + */ + dev_warn(data->dev, "resetting idled controller\n"); + __davinci_mdio_reset(data); + return -EAGAIN; + } + dev_err(data->dev, "timed out waiting for user access\n"); + return -ETIMEDOUT; +} + +/* wait until hardware state machine is idle */ +static inline int wait_for_idle(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + + while (time_after(timeout, jiffies)) { + if (__raw_readl(®s->control) & CONTROL_IDLE) + return 0; + } + dev_err(data->dev, "timed out waiting for idle\n"); + return -ETIMEDOUT; +} + +static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | + (phy_id << 16)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + reg = __raw_readl(&data->regs->user[0].access); + ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; + break; + } + + spin_unlock(&data->lock); + + return ret; +} + +static int davinci_mdio_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | + (phy_id << 16) | (phy_data & USERACCESS_DATA)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + break; + } + + spin_unlock(&data->lock); + + return 0; +} + +static int __devinit davinci_mdio_probe(struct platform_device *pdev) +{ + struct mdio_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data; + struct resource *res; + struct phy_device *phy; + int ret, addr; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(dev, "failed to alloc device data\n"); + return -ENOMEM; + } + + data->pdata = pdata ? (*pdata) : default_pdata; + + data->bus = mdiobus_alloc(); + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + ret = -ENOMEM; + goto bail_out; + } + + data->bus->name = dev_name(dev); + data->bus->read = davinci_mdio_read, + data->bus->write = davinci_mdio_write, + data->bus->reset = davinci_mdio_reset, + data->bus->parent = dev; + data->bus->priv = data; + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + + data->clk = clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + data->clk = NULL; + dev_err(dev, "failed to get device clock\n"); + ret = PTR_ERR(data->clk); + goto bail_out; + } + + clk_enable(data->clk); + + dev_set_drvdata(dev, data); + data->dev = dev; + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "could not find register map resource\n"); + ret = -ENOENT; + goto bail_out; + } + + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); + if (!res) { + dev_err(dev, "could not allocate register map resource\n"); + ret = -ENXIO; + goto bail_out; + } + + data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!data->regs) { + dev_err(dev, "could not map mdio registers\n"); + ret = -ENOMEM; + goto bail_out; + } + + /* register the mii bus */ + ret = mdiobus_register(data->bus); + if (ret) + goto bail_out; + + /* scan and dump the bus */ + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + phy = data->bus->phy_map[addr]; + if (phy) { + dev_info(dev, "phy[%d]: device %s, driver %s\n", + phy->addr, dev_name(&phy->dev), + phy->drv ? phy->drv->name : "unknown"); + } + } + + return 0; + +bail_out: + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + kfree(data); + + return ret; +} + +static int __devexit davinci_mdio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data = dev_get_drvdata(dev); + + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + dev_set_drvdata(dev, NULL); + + kfree(data); + + return 0; +} + +static int davinci_mdio_suspend(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + + /* shutdown the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + wait_for_idle(data); + + if (data->clk) + clk_disable(data->clk); + + data->suspended = true; + spin_unlock(&data->lock); + + return 0; +} + +static int davinci_mdio_resume(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + if (data->clk) + clk_enable(data->clk); + + /* restart the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl |= CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + + data->suspended = false; + spin_unlock(&data->lock); + + return 0; +} + +static const struct dev_pm_ops davinci_mdio_pm_ops = { + .suspend = davinci_mdio_suspend, + .resume = davinci_mdio_resume, +}; + +static struct platform_driver davinci_mdio_driver = { + .driver = { + .name = "davinci_mdio", + .owner = THIS_MODULE, + .pm = &davinci_mdio_pm_ops, + }, + .probe = davinci_mdio_probe, + .remove = __devexit_p(davinci_mdio_remove), +}; + +static int __init davinci_mdio_init(void) +{ + return platform_driver_register(&davinci_mdio_driver); +} +device_initcall(davinci_mdio_init); + +static void __exit davinci_mdio_exit(void) +{ + platform_driver_unregister(&davinci_mdio_driver); +} +module_exit(davinci_mdio_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DaVinci MDIO driver"); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a117f2a0252e..4686c3983fc3 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -521,7 +521,7 @@ void e1000_down(struct e1000_adapter *adapter) e1000_clean_all_rx_rings(adapter); } -void e1000_reinit_safe(struct e1000_adapter *adapter) +static void e1000_reinit_safe(struct e1000_adapter *adapter) { while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) msleep(1); diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index ca663f19d7df..7236f1a53ba0 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -52,6 +52,10 @@ (ID_LED_DEF1_DEF2)) #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 +#define E1000_BASE1000T_STATUS 10 +#define E1000_IDLE_ERROR_COUNT_MASK 0xFF +#define E1000_RECEIVE_ERROR_COUNTER 21 +#define E1000_RECEIVE_ERROR_MAX 0xFFFF #define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ @@ -1243,6 +1247,39 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) } /** + * e1000_check_phy_82574 - check 82574 phy hung state + * @hw: pointer to the HW structure + * + * Returns whether phy is hung or not + **/ +bool e1000_check_phy_82574(struct e1000_hw *hw) +{ + u16 status_1kbt = 0; + u16 receive_errors = 0; + bool phy_hung = false; + s32 ret_val = 0; + + /* + * Read PHY Receive Error counter first, if its is max - all F's then + * read the Base1000T status register If both are max then PHY is hung. + */ + ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); + + if (ret_val) + goto out; + if (receive_errors == E1000_RECEIVE_ERROR_MAX) { + ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); + if (ret_val) + goto out; + if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == + E1000_IDLE_ERROR_COUNT_MASK) + phy_hung = true; + } +out: + return phy_hung; +} + +/** * e1000_setup_link_82571 - Setup flow control and link settings * @hw: pointer to the HW structure * @@ -1859,6 +1896,7 @@ struct e1000_info e1000_82574_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, + .flags2 = FLAG2_CHECK_PHY_HANG, .pba = 36, .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cee882dd67bf..fdc67fead4ea 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -397,6 +397,7 @@ struct e1000_adapter { struct work_struct print_hang_task; bool idle_check; + int phy_hang_count; }; struct e1000_info { @@ -454,6 +455,7 @@ struct e1000_info { #define FLAG2_HAS_EEE (1 << 5) #define FLAG2_DMA_BURST (1 << 6) #define FLAG2_DISABLE_AIM (1 << 8) +#define FLAG2_CHECK_PHY_HANG (1 << 9) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) @@ -631,6 +633,7 @@ extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw); extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); +extern bool e1000_check_phy_82574(struct e1000_hw *hw); static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ec8cf3f51423..c4ca1629f532 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4098,6 +4098,25 @@ static void e1000e_enable_receives(struct e1000_adapter *adapter) } } +static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + + /* + * With 82574 controllers, PHY needs to be checked periodically + * for hung state and reset, if two calls return true + */ + if (e1000_check_phy_82574(hw)) + adapter->phy_hang_count++; + else + adapter->phy_hang_count = 0; + + if (adapter->phy_hang_count > 1) { + adapter->phy_hang_count = 0; + schedule_work(&adapter->reset_task); + } +} + /** * e1000_watchdog - Timer Call-back * @data: pointer to adapter cast into an unsigned long @@ -4333,6 +4352,9 @@ link_up: if (e1000e_get_laa_state_82571(hw)) e1000e_rar_set(hw, adapter->hw.mac.addr, 0); + if (adapter->flags2 & FLAG2_CHECK_PHY_HANG) + e1000e_check_82574_phy_workaround(adapter); + /* Reset the timer */ if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, @@ -4860,8 +4882,11 @@ static void e1000_reset_task(struct work_struct *work) struct e1000_adapter *adapter; adapter = container_of(work, struct e1000_adapter, reset_task); - e1000e_dump(adapter); - e_err("Reset adapter\n"); + if (!((adapter->flags & FLAG_RX_NEEDS_RESTART) && + (adapter->flags & FLAG_RX_RESTART_NOW))) { + e1000e_dump(adapter); + e_err("Reset adapter\n"); + } e1000e_reinit_locked(adapter); } diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 1321cb6401cf..8e745e74828d 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -396,7 +396,9 @@ struct ehea_port_res { int swqe_ll_count; u32 swqe_id_counter; u64 tx_packets; + u64 tx_bytes; u64 rx_packets; + u64 rx_bytes; u32 poll_counter; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS]; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index bb7d306fb446..182b2a7be8dc 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -330,7 +330,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) struct ehea_port *port = netdev_priv(dev); struct net_device_stats *stats = &port->stats; struct hcp_ehea_port_cb2 *cb2; - u64 hret, rx_packets, tx_packets; + u64 hret, rx_packets, tx_packets, rx_bytes = 0, tx_bytes = 0; int i; memset(stats, 0, sizeof(*stats)); @@ -353,18 +353,22 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) ehea_dump(cb2, sizeof(*cb2), "net_device_stats"); rx_packets = 0; - for (i = 0; i < port->num_def_qps; i++) + for (i = 0; i < port->num_def_qps; i++) { rx_packets += port->port_res[i].rx_packets; + rx_bytes += port->port_res[i].rx_bytes; + } tx_packets = 0; - for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { tx_packets += port->port_res[i].tx_packets; + tx_bytes += port->port_res[i].tx_bytes; + } stats->tx_packets = tx_packets; stats->multicast = cb2->rxmcp; stats->rx_errors = cb2->rxuerr; - stats->rx_bytes = cb2->rxo; - stats->tx_bytes = cb2->txo; + stats->rx_bytes = rx_bytes; + stats->tx_bytes = tx_bytes; stats->rx_packets = rx_packets; out_herr: @@ -703,6 +707,7 @@ static int ehea_proc_rwqes(struct net_device *dev, int skb_arr_rq2_len = pr->rq2_skba.len; int skb_arr_rq3_len = pr->rq3_skba.len; int processed, processed_rq1, processed_rq2, processed_rq3; + u64 processed_bytes = 0; int wqe_index, last_wqe_index, rq, port_reset; processed = processed_rq1 = processed_rq2 = processed_rq3 = 0; @@ -760,6 +765,7 @@ static int ehea_proc_rwqes(struct net_device *dev, processed_rq3++; } + processed_bytes += skb->len; ehea_proc_skb(pr, cqe, skb); } else { pr->p_stats.poll_receive_errors++; @@ -775,6 +781,7 @@ static int ehea_proc_rwqes(struct net_device *dev, lro_flush_all(&pr->lro_mgr); pr->rx_packets += processed; + pr->rx_bytes += processed_bytes; ehea_refill_rq1(pr, last_wqe_index, processed_rq1); ehea_refill_rq2(pr, processed_rq2); @@ -1509,9 +1516,20 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, enum ehea_eq_type eq_type = EHEA_EQ; struct ehea_qp_init_attr *init_attr = NULL; int ret = -EIO; + u64 tx_bytes, rx_bytes, tx_packets, rx_packets; + + tx_bytes = pr->tx_bytes; + tx_packets = pr->tx_packets; + rx_bytes = pr->rx_bytes; + rx_packets = pr->rx_packets; memset(pr, 0, sizeof(struct ehea_port_res)); + pr->tx_bytes = rx_bytes; + pr->tx_packets = tx_packets; + pr->rx_bytes = rx_bytes; + pr->rx_packets = rx_packets; + pr->port = port; spin_lock_init(&pr->xmit_lock); spin_lock_init(&pr->netif_queue); @@ -2249,6 +2267,14 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) memset(swqe, 0, SWQE_HEADER_SIZE); atomic_dec(&pr->swqe_avail); + if (vlan_tx_tag_present(skb)) { + swqe->tx_control |= EHEA_SWQE_VLAN_INSERT; + swqe->vlan_tag = vlan_tx_tag_get(skb); + } + + pr->tx_packets++; + pr->tx_bytes += skb->len; + if (skb->len <= SWQE3_MAX_IMM) { u32 sig_iv = port->sig_comp_iv; u32 swqe_num = pr->swqe_id_counter; @@ -2279,11 +2305,6 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } pr->swqe_id_counter += 1; - if (vlan_tx_tag_present(skb)) { - swqe->tx_control |= EHEA_SWQE_VLAN_INSERT; - swqe->vlan_tag = vlan_tx_tag_get(skb); - } - if (netif_msg_tx_queued(port)) { ehea_info("post swqe on QP %d", pr->qp->init_attr.qp_nr); ehea_dump(swqe, 512, "swqe"); @@ -2295,7 +2316,6 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } ehea_post_swqe(pr->qp, swqe); - pr->tx_packets++; if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) { spin_lock_irqsave(&pr->netif_queue, flags); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4c4cc80ec0a1..49e4ce1246a7 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2511,7 +2511,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) skb_recycle_check(skb, priv->rx_buffer_size + RXBUF_ALIGNMENT)) { gfar_align_skb(skb); - __skb_queue_head(&priv->rx_recycle, skb); + skb_queue_head(&priv->rx_recycle, skb); } else dev_kfree_skb_any(skb); @@ -2594,7 +2594,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev) struct gfar_private *priv = netdev_priv(dev); struct sk_buff *skb = NULL; - skb = __skb_dequeue(&priv->rx_recycle); + skb = skb_dequeue(&priv->rx_recycle); if (!skb) skb = gfar_alloc_skb(dev); @@ -2750,7 +2750,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) if (unlikely(!newskb)) newskb = skb; else if (skb) - __skb_queue_head(&priv->rx_recycle, skb); + skb_queue_head(&priv->rx_recycle, skb); } else { /* Increment the number of packets */ rx_queue->stats.rx_packets++; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 14db09e2fa8b..892d196f17ac 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4107,7 +4107,6 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, struct igb_ring *tx_ring) { - struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); int tso = 0, count; u32 tx_flags = 0; u16 first; diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index ebfaa68ee630..28af019c97bb 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2783,15 +2783,15 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ igbvf_reset(adapter); - /* tell the stack to leave us alone until igbvf_open() is called */ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_hw_init; + /* tell the stack to leave us alone until igbvf_open() is called */ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + igbvf_print_device_info(adapter); igbvf_initialize_last_counter_stats(adapter); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 666207a9c039..caa8192fff2a 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -533,6 +533,7 @@ ixgb_remove(struct pci_dev *pdev) pci_release_regions(pdev); free_netdev(netdev); + pci_disable_device(pdev); } /** diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index 8bb9ddb6dffe..0d44c6470ca3 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -43,9 +43,12 @@ * ixgbe_dcb_check_config(). */ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, - u8 direction) + int max_frame, u8 direction) { struct tc_bw_alloc *p; + int min_credit; + int min_multiplier; + int min_percent = 100; s32 ret_val = 0; /* Initialization values default for Tx settings */ u32 credit_refill = 0; @@ -59,6 +62,31 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, goto out; } + min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) / + DCB_CREDIT_QUANTUM; + + /* Find smallest link percentage */ + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { + p = &dcb_config->tc_config[i].path[direction]; + bw_percent = dcb_config->bw_percentage[direction][p->bwg_id]; + link_percentage = p->bwg_percent; + + link_percentage = (link_percentage * bw_percent) / 100; + + if (link_percentage && link_percentage < min_percent) + min_percent = link_percentage; + } + + /* + * The ratio between traffic classes will control the bandwidth + * percentages seen on the wire. To calculate this ratio we use + * a multiplier. It is required that the refill credits must be + * larger than the max frame size so here we find the smallest + * multiplier that will allow all bandwidth percentages to be + * greater than the max frame size. + */ + min_multiplier = (min_credit / min_percent) + 1; + /* Find out the link percentage for each TC first */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { p = &dcb_config->tc_config[i].path[direction]; @@ -73,8 +101,9 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, /* Save link_percentage for reference */ p->link_percent = (u8)link_percentage; - /* Calculate credit refill and save it */ - credit_refill = link_percentage * MINIMUM_CREDIT_REFILL; + /* Calculate credit refill ratio using multiplier */ + credit_refill = min(link_percentage * min_multiplier, + MAX_CREDIT_REFILL); p->data_credits_refill = (u16)credit_refill; /* Calculate maximum credit for the TC */ @@ -85,8 +114,8 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, * of a TC is too small, the maximum credit may not be * enough to send out a jumbo frame in data plane arbitration. */ - if (credit_max && (credit_max < MINIMUM_CREDIT_FOR_JUMBO)) - credit_max = MINIMUM_CREDIT_FOR_JUMBO; + if (credit_max && (credit_max < min_credit)) + credit_max = min_credit; if (direction == DCB_TX_CONFIG) { /* diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index eb1059f09da0..0208a87b129e 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h @@ -150,15 +150,14 @@ struct ixgbe_dcb_config { /* DCB driver APIs */ /* DCB credits calculation */ -s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8); +s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, int, u8); /* DCB hw initialization */ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); /* DCB definitions for credit calculation */ +#define DCB_CREDIT_QUANTUM 64 /* DCB Quantum */ #define MAX_CREDIT_REFILL 511 /* 0x1FF * 64B = 32704B */ -#define MINIMUM_CREDIT_REFILL 5 /* 5*64B = 320B */ -#define MINIMUM_CREDIT_FOR_JUMBO 145 /* 145= UpperBound((9*1024+54)/64B) for 9KB jumbo frame */ #define DCB_MAX_TSO_SIZE (32*1024) /* MAX TSO packet size supported in DCB mode */ #define MINIMUM_CREDIT_FOR_TSO (DCB_MAX_TSO_SIZE/64 + 1) /* 513 for 32KB TSO packet */ #define MAX_CREDIT 4095 /* Maximum credit supported: 256KB * 1204 / 64B */ diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index 67c219f86c3a..05f224715073 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -397,6 +397,11 @@ static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw) reg &= ~IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); + /* Enable Security TX Buffer IFG for DCB */ + reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG); + reg |= IXGBE_SECTX_DCB; + IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg); + return 0; } diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h index 18d7fbf6c292..3841649fb954 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h @@ -95,6 +95,9 @@ #define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */ +/* SECTXMINIFG DCB */ +#define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer IFG */ + /* DCB hardware-specific driver APIs */ diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f85631263af8..2bd3eb4ee5a1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3347,6 +3347,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; + int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; u32 txdctl; int i, j; @@ -3359,8 +3360,15 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82598EB) netif_set_gso_max_size(adapter->netdev, 32768); - ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG); - ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG); +#ifdef CONFIG_FCOE + if (adapter->netdev->features & NETIF_F_FCOE_MTU) + max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); +#endif + + ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame, + DCB_TX_CONFIG); + ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame, + DCB_RX_CONFIG); /* reconfigure the hardware */ ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg); diff --git a/drivers/net/jme.c b/drivers/net/jme.c index d7a975ee2add..d85edf3119c2 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -1623,12 +1623,12 @@ err_out: return rc; } -#ifdef CONFIG_PM static void jme_set_100m_half(struct jme_adapter *jme) { u32 bmcr, tmp; + jme_phy_on(jme); bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_FULLDPLX); @@ -1656,7 +1656,6 @@ jme_wait_link(struct jme_adapter *jme) phylink = jme_linkstat_from_phy(jme); } } -#endif static inline void jme_phy_off(struct jme_adapter *jme) @@ -1664,6 +1663,21 @@ jme_phy_off(struct jme_adapter *jme) jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN); } +static void +jme_powersave_phy(struct jme_adapter *jme) +{ + if (jme->reg_pmcs) { + jme_set_100m_half(jme); + + if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) + jme_wait_link(jme); + + jwrite32(jme, JME_PMCS, jme->reg_pmcs); + } else { + jme_phy_off(jme); + } +} + static int jme_close(struct net_device *netdev) { @@ -2991,6 +3005,16 @@ jme_remove_one(struct pci_dev *pdev) } +static void +jme_shutdown(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); + + jme_powersave_phy(jme); + pci_pme_active(pdev, true); +} + #ifdef CONFIG_PM static int jme_suspend(struct pci_dev *pdev, pm_message_t state) @@ -3028,19 +3052,9 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) tasklet_hi_enable(&jme->rxempty_task); pci_save_state(pdev); - if (jme->reg_pmcs) { - jme_set_100m_half(jme); - - if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) - jme_wait_link(jme); - - jwrite32(jme, JME_PMCS, jme->reg_pmcs); - - pci_enable_wake(pdev, PCI_D3cold, true); - } else { - jme_phy_off(jme); - } - pci_set_power_state(pdev, PCI_D3cold); + jme_powersave_phy(jme); + pci_enable_wake(jme->pdev, PCI_D3hot, true); + pci_set_power_state(pdev, PCI_D3hot); return 0; } @@ -3087,6 +3101,7 @@ static struct pci_driver jme_driver = { .suspend = jme_suspend, .resume = jme_resume, #endif /* CONFIG_PM */ + .shutdown = jme_shutdown, }; static int __init diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 316bb70775b1..e7030ceb178b 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -1077,7 +1077,6 @@ static void __NS8390_init(struct net_device *dev, int startp) ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - netif_start_queue(dev); ei_local->tx1 = ei_local->tx2 = 0; ei_local->txing = 0; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 4297f6e8c4bc..f69e73e2191e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -515,14 +515,15 @@ static int macb_poll(struct napi_struct *napi, int budget) (unsigned long)status, budget); work_done = macb_rx(bp, budget); - if (work_done < budget) + if (work_done < budget) { napi_complete(napi); - /* - * We've done what we can to clean the buffers. Make sure we - * get notified when new packets arrive. - */ - macb_writel(bp, IER, MACB_RX_INT_FLAGS); + /* + * We've done what we can to clean the buffers. Make sure we + * get notified when new packets arrive. + */ + macb_writel(bp, IER, MACB_RX_INT_FLAGS); + } /* TODO: Handle errors */ @@ -550,12 +551,16 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) } if (status & MACB_RX_INT_FLAGS) { + /* + * There's no point taking any more interrupts + * until we have processed the buffers. The + * scheduling call may fail if the poll routine + * is already scheduled, so disable interrupts + * now. + */ + macb_writel(bp, IDR, MACB_RX_INT_FLAGS); + if (napi_schedule_prep(&bp->napi)) { - /* - * There's no point taking any more interrupts - * until we have processed the buffers - */ - macb_writel(bp, IDR, MACB_RX_INT_FLAGS); dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n"); __napi_schedule(&bp->napi); diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 143906417048..f6e0d40cd876 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -124,6 +124,13 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) return 0; } +static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port) +{ + struct mlx4_en_dev *endev = ctx; + + return endev->pndev[port]; +} + static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, enum mlx4_dev_event event, int port) { @@ -282,9 +289,11 @@ err_free_res: } static struct mlx4_interface mlx4_en_interface = { - .add = mlx4_en_add, - .remove = mlx4_en_remove, - .event = mlx4_en_event, + .add = mlx4_en_add, + .remove = mlx4_en_remove, + .event = mlx4_en_event, + .get_dev = mlx4_en_get_netdev, + .protocol = MLX4_PROTOCOL_EN, }; static int __init mlx4_en_init(void) diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 79478bd4211a..6d6806b361e3 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -69,6 +69,7 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; int err; + int idx; if (!priv->vlgrp) return; @@ -83,7 +84,10 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) if (err) en_err(priv, "Failed configuring VLAN filter\n"); } + if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx)) + en_err(priv, "failed adding vlan %d\n", vid); mutex_unlock(&mdev->state_lock); + } static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) @@ -91,6 +95,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; int err; + int idx; if (!priv->vlgrp) return; @@ -101,6 +106,11 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) /* Remove VID from port VLAN filter */ mutex_lock(&mdev->state_lock); + if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx)) + mlx4_unregister_vlan(mdev->dev, priv->port, idx); + else + en_err(priv, "could not find vid %d in cache\n", vid); + if (mdev->device_up && priv->port_up) { err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); if (err) diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c index aa3ef2aee5bf..7f5a3221e0c1 100644 --- a/drivers/net/mlx4/en_port.c +++ b/drivers/net/mlx4/en_port.c @@ -127,8 +127,8 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, memset(context, 0, sizeof *context); context->base_qpn = cpu_to_be32(base_qpn); - context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn); - context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn); + context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn); + context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn); context->intra_no_vlan = 0; context->no_vlan = MLX4_NO_VLAN_IDX; context->intra_vlan_miss = 0; diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h index f6511aa2b7df..092e814b1981 100644 --- a/drivers/net/mlx4/en_port.h +++ b/drivers/net/mlx4/en_port.h @@ -36,7 +36,8 @@ #define SET_PORT_GEN_ALL_VALID 0x7 -#define SET_PORT_PROMISC_SHIFT 31 +#define SET_PORT_PROMISC_EN_SHIFT 31 +#define SET_PORT_PROMISC_MODE_SHIFT 30 enum { MLX4_CMD_SET_VLAN_FLTR = 0x47, diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index b716e1a1b298..b68eee2414c2 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -98,7 +98,8 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags) [20] = "Address vector port checking support", [21] = "UD multicast support", [24] = "Demand paging support", - [25] = "Router support" + [25] = "Router support", + [30] = "IBoE support" }; int i; diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index b07e4dee80aa..02393fdf44c1 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c @@ -210,38 +210,12 @@ static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt) return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM, icm, virt); } -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count) +static int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count) { return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM, MLX4_CMD_TIME_CLASS_B); } -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt) -{ - struct mlx4_cmd_mailbox *mailbox; - __be64 *inbox; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - inbox[0] = cpu_to_be64(virt); - inbox[1] = cpu_to_be64(dma_addr); - - err = mlx4_cmd(dev, mailbox->dma, 1, 0, MLX4_CMD_MAP_ICM, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - - if (!err) - mlx4_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", - (unsigned long long) dma_addr, (unsigned long long) virt); - - return err; -} - int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm) { return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM_AUX, icm, -1); diff --git a/drivers/net/mlx4/icm.h b/drivers/net/mlx4/icm.h index ab56a2f89b65..b10c07a1dc1a 100644 --- a/drivers/net/mlx4/icm.h +++ b/drivers/net/mlx4/icm.h @@ -128,8 +128,6 @@ static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) return sg_dma_len(&iter->chunk->mem[iter->page_idx]); } -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count); -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt); int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c index 555067802751..73c94fcdfddf 100644 --- a/drivers/net/mlx4/intf.c +++ b/drivers/net/mlx4/intf.c @@ -161,3 +161,24 @@ void mlx4_unregister_device(struct mlx4_dev *dev) mutex_unlock(&intf_mutex); } + +void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_device_context *dev_ctx; + unsigned long flags; + void *result = NULL; + + spin_lock_irqsave(&priv->ctx_lock, flags); + + list_for_each_entry(dev_ctx, &priv->ctx_list, list) + if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) { + result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port); + break; + } + + spin_unlock_irqrestore(&priv->ctx_lock, flags); + + return result; +} +EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev); diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 569fa3df381f..782f11d8fa71 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -103,7 +103,7 @@ MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " static int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG); module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444); -MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)"); +MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-7)"); int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type) @@ -1310,7 +1310,7 @@ static int __init mlx4_verify_params(void) return -1; } - if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) { + if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 7)) { pr_warning("mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg); return -1; } diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 1fc16ab7ad2f..dfed6a07c2d7 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -475,6 +475,7 @@ struct mlx4_en_priv { char *mc_addrs; int mc_addrs_cnt; struct mlx4_en_stat_out_mbox hw_stats; + int vids[128]; }; diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index 606aa58afdea..451339559bdc 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -111,6 +111,12 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index) goto out; } } + + if (free < 0) { + err = -ENOMEM; + goto out; + } + mlx4_dbg(dev, "Free MAC index is %d\n", free); if (table->total == table->max) { @@ -182,6 +188,25 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, return err; } +int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) +{ + struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; + int i; + + for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { + if (table->refs[i] && + (vid == (MLX4_VLAN_MASK & + be32_to_cpu(table->entries[i])))) { + /* VLAN already registered, increase reference count */ + *idx = i; + return 0; + } + } + + return -ENOENT; +} +EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); + int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) { struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; @@ -205,6 +230,11 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) } } + if (free < 0) { + err = -ENOMEM; + goto out; + } + if (table->total == table->max) { /* No free vlan entries */ err = -ENOSPC; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 12612127a087..f7d06cbc70ae 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -255,19 +255,6 @@ out_free_rq: } static void -nx_fw_cmd_reset_ctx(struct netxen_adapter *adapter) -{ - - netxen_issue_cmd(adapter, adapter->ahw.pci_func, NXHAL_VERSION, - adapter->ahw.pci_func, NX_DESTROY_CTX_RESET, 0, - NX_CDRP_CMD_DESTROY_RX_CTX); - - netxen_issue_cmd(adapter, adapter->ahw.pci_func, NXHAL_VERSION, - adapter->ahw.pci_func, NX_DESTROY_CTX_RESET, 0, - NX_CDRP_CMD_DESTROY_TX_CTX); -} - -static void nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; @@ -698,8 +685,6 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state)) goto done; - if (reset_devices) - nx_fw_cmd_reset_ctx(adapter); err = nx_fw_cmd_create_rx_ctx(adapter); if (err) goto err_out_free; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 50820beac3aa..a75ba9517404 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1240,7 +1240,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter, dev_warn(&pdev->dev, "failed to read mac addr\n"); netif_carrier_off(netdev); - netif_stop_queue(netdev); err = register_netdev(netdev); if (err) { @@ -1356,6 +1355,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } + if (reset_devices) { + if (adapter->portnum == 0) { + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, 0); + adapter->need_fw_reset = 1; + } + } + err = netxen_start_firmware(adapter); if (err) goto err_out_decr_ref; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 03096c80103d..d05c44692f08 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1536,6 +1536,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), + PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index e2afdce0a437..f0bd1a1aba3a 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -74,8 +74,8 @@ #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) -#define MII_88EC048_PHY_MSCR1_REG 16 -#define MII_88EC048_PHY_MSCR1_PAD_ODD BIT(6) +#define MII_88E1318S_PHY_MSCR1_REG 16 +#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6) #define MII_88E1121_PHY_LED_CTRL 16 #define MII_88E1121_PHY_LED_PAGE 3 @@ -240,7 +240,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev) return err; } -static int m88ec048_config_aneg(struct phy_device *phydev) +static int m88e1318_config_aneg(struct phy_device *phydev) { int err, oldpage, mscr; @@ -251,10 +251,10 @@ static int m88ec048_config_aneg(struct phy_device *phydev) if (err < 0) return err; - mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG); - mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD; + mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG); + mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD; - err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); + err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr); if (err < 0) return err; @@ -659,12 +659,12 @@ static struct phy_driver marvell_drivers[] = { .driver = { .owner = THIS_MODULE }, }, { - .phy_id = MARVELL_PHY_ID_88EC048, + .phy_id = MARVELL_PHY_ID_88E1318S, .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88EC048", + .name = "Marvell 88E1318S", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, - .config_aneg = &m88ec048_config_aneg, + .config_aneg = &m88e1318_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1bb16cb79433..7670aac0e93f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -65,7 +65,7 @@ EXPORT_SYMBOL(phy_print_status); * * Returns 0 on success on < 0 on error. */ -int phy_clear_interrupt(struct phy_device *phydev) +static int phy_clear_interrupt(struct phy_device *phydev) { int err = 0; @@ -82,7 +82,7 @@ int phy_clear_interrupt(struct phy_device *phydev) * * Returns 0 on success on < 0 on error. */ -int phy_config_interrupt(struct phy_device *phydev, u32 interrupts) +static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts) { int err = 0; @@ -208,7 +208,7 @@ static inline int phy_find_valid(int idx, u32 features) * duplexes. Drop down by one in this order: 1000/FULL, * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF. */ -void phy_sanitize_settings(struct phy_device *phydev) +static void phy_sanitize_settings(struct phy_device *phydev) { u32 features = phydev->supported; int idx; @@ -223,7 +223,6 @@ void phy_sanitize_settings(struct phy_device *phydev) phydev->speed = settings[idx].speed; phydev->duplex = settings[idx].duplex; } -EXPORT_SYMBOL(phy_sanitize_settings); /** * phy_ethtool_sset - generic ethtool sset function, handles all the details @@ -532,7 +531,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) * phy_enable_interrupts - Enable the interrupts from the PHY side * @phydev: target phy_device struct */ -int phy_enable_interrupts(struct phy_device *phydev) +static int phy_enable_interrupts(struct phy_device *phydev) { int err; @@ -545,13 +544,12 @@ int phy_enable_interrupts(struct phy_device *phydev) return err; } -EXPORT_SYMBOL(phy_enable_interrupts); /** * phy_disable_interrupts - Disable the PHY interrupts from the PHY side * @phydev: target phy_device struct */ -int phy_disable_interrupts(struct phy_device *phydev) +static int phy_disable_interrupts(struct phy_device *phydev) { int err; @@ -574,7 +572,6 @@ phy_err: return err; } -EXPORT_SYMBOL(phy_disable_interrupts); /** * phy_start_interrupts - request and enable interrupts for a PHY device diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 16ddc77313cb..993c52c82aeb 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -57,6 +57,9 @@ extern void mdio_bus_exit(void); static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); +static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface); + /* * Creates a new phy_fixup and adds it to the list * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID) @@ -146,7 +149,8 @@ int phy_scan_fixups(struct phy_device *phydev) } EXPORT_SYMBOL(phy_scan_fixups); -struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) +static struct phy_device* phy_device_create(struct mii_bus *bus, + int addr, int phy_id) { struct phy_device *dev; @@ -193,7 +197,6 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) return dev; } -EXPORT_SYMBOL(phy_device_create); /** * get_phy_id - reads the specified addr for its ID. @@ -316,7 +319,7 @@ EXPORT_SYMBOL(phy_find_first); * If you want to monitor your own link state, don't call * this function. */ -void phy_prepare_link(struct phy_device *phydev, +static void phy_prepare_link(struct phy_device *phydev, void (*handler)(struct net_device *)) { phydev->adjust_link = handler; @@ -435,8 +438,8 @@ int phy_init_hw(struct phy_device *phydev) * the attaching device, and given a callback for link status * change. The phy_device is returned to the attaching driver. */ -int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, - u32 flags, phy_interface_t interface) +static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface) { struct device *d = &phydev->dev; @@ -473,7 +476,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, * (dev_flags and interface) */ return phy_init_hw(phydev); } -EXPORT_SYMBOL(phy_attach_direct); /** * phy_attach - attach a network device to a particular PHY device @@ -540,7 +542,7 @@ EXPORT_SYMBOL(phy_detach); * what is supported. Returns < 0 on error, 0 if the PHY's advertisement * hasn't changed, and > 0 if it has changed. */ -int genphy_config_advert(struct phy_device *phydev) +static int genphy_config_advert(struct phy_device *phydev) { u32 advertise; int oldadv, adv; @@ -605,7 +607,6 @@ int genphy_config_advert(struct phy_device *phydev) return changed; } -EXPORT_SYMBOL(genphy_config_advert); /** * genphy_setup_forced - configures/forces speed/duplex from @phydev @@ -615,7 +616,7 @@ EXPORT_SYMBOL(genphy_config_advert); * to the values in phydev. Assumes that the values are valid. * Please see phy_sanitize_settings(). */ -int genphy_setup_forced(struct phy_device *phydev) +static int genphy_setup_forced(struct phy_device *phydev) { int err; int ctl = 0; diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 26c37d3a5868..8ecc170c9b74 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -146,11 +146,13 @@ #define MAX_CMD_DESCRIPTORS 1024 #define MAX_RCV_DESCRIPTORS_1G 4096 #define MAX_RCV_DESCRIPTORS_10G 8192 +#define MAX_RCV_DESCRIPTORS_VF 2048 #define MAX_JUMBO_RCV_DESCRIPTORS_1G 512 #define MAX_JUMBO_RCV_DESCRIPTORS_10G 1024 #define DEFAULT_RCV_DESCRIPTORS_1G 2048 #define DEFAULT_RCV_DESCRIPTORS_10G 4096 +#define DEFAULT_RCV_DESCRIPTORS_VF 1024 #define MAX_RDS_RINGS 2 #define get_next_index(index, length) \ @@ -942,6 +944,7 @@ struct qlcnic_ipaddr { #define QLCNIC_LOOPBACK_TEST 2 #define QLCNIC_FILTER_AGE 80 +#define QLCNIC_READD_AGE 20 #define QLCNIC_LB_MAX_FILTERS 64 struct qlcnic_filter { @@ -970,6 +973,8 @@ struct qlcnic_adapter { u16 num_txd; u16 num_rxd; u16 num_jumbo_rxd; + u16 max_rxd; + u16 max_jumbo_rxd; u8 max_rds_rings; u8 max_sds_rings; @@ -1129,7 +1134,7 @@ struct qlcnic_eswitch { #define MAX_RX_QUEUES 4 #define DEFAULT_MAC_LEARN 1 -#define IS_VALID_VLAN(vlan) (vlan >= MIN_VLAN_ID && vlan <= MAX_VLAN_ID) +#define IS_VALID_VLAN(vlan) (vlan >= MIN_VLAN_ID && vlan < MAX_VLAN_ID) #define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 25e93a53fca0..ec21d24015c4 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -437,14 +437,8 @@ qlcnic_get_ringparam(struct net_device *dev, ring->rx_jumbo_pending = adapter->num_jumbo_rxd; ring->tx_pending = adapter->num_txd; - if (adapter->ahw.port_type == QLCNIC_GBE) { - ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; - ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G; - } else { - ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; - ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G; - } - + ring->rx_max_pending = adapter->max_rxd; + ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd; ring->tx_max_pending = MAX_CMD_DESCRIPTORS; ring->rx_mini_max_pending = 0; @@ -472,24 +466,17 @@ qlcnic_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { struct qlcnic_adapter *adapter = netdev_priv(dev); - u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G; - u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; u16 num_rxd, num_jumbo_rxd, num_txd; - if (ring->rx_mini_pending) return -EOPNOTSUPP; - if (adapter->ahw.port_type == QLCNIC_GBE) { - max_rcv_desc = MAX_RCV_DESCRIPTORS_1G; - max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; - } - num_rxd = qlcnic_validate_ringparam(ring->rx_pending, - MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx"); + MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx"); num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending, - MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo"); + MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd, + "rx jumbo"); num_txd = qlcnic_validate_ringparam(ring->tx_pending, MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx"); diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index f047c7c48314..7a298cdf9ab3 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -656,13 +656,23 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) dev_info(&pdev->dev, "firmware v%d.%d.%d\n", fw_major, fw_minor, fw_build); - if (adapter->ahw.port_type == QLCNIC_XGBE) { - adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; + if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF; + adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF; + } else { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; + adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G; + } + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; + adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } else if (adapter->ahw.port_type == QLCNIC_GBE) { adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; + adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; + adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G; } adapter->msix_supported = !!use_msi_x; @@ -1860,6 +1870,11 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter, hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && tmp_fil->vlan_id == vlan_id) { + + if (jiffies > + (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) + qlcnic_change_filter(adapter, src_addr, vlan_id, + tx_ring); tmp_fil->ftime = jiffies; return; } diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index a478786840a6..22821398fc63 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2226,7 +2226,6 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump); int ql_mb_about_fw(struct ql_adapter *qdev); -int ql_wol(struct ql_adapter *qdev); int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol); int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol); int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config); @@ -2243,16 +2242,13 @@ netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev); void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *); int ql_own_firmware(struct ql_adapter *qdev); int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget); -void qlge_set_multicast_list(struct net_device *ndev); -#if 1 -#define QL_ALL_DUMP -#define QL_REG_DUMP -#define QL_DEV_DUMP -#define QL_CB_DUMP +/* #define QL_ALL_DUMP */ +/* #define QL_REG_DUMP */ +/* #define QL_DEV_DUMP */ +/* #define QL_CB_DUMP */ /* #define QL_IB_DUMP */ /* #define QL_OB_DUMP */ -#endif #ifdef QL_REG_DUMP extern void ql_dump_xgmac_control_regs(struct ql_adapter *qdev); diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ba0053d8515e..c30e0fe55a31 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -94,6 +94,9 @@ static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { MODULE_DEVICE_TABLE(pci, qlge_pci_tbl); +static int ql_wol(struct ql_adapter *qdev); +static void qlge_set_multicast_list(struct net_device *ndev); + /* This hardware semaphore causes exclusive access to * resources shared between the NIC driver, MPI firmware, * FCOE firmware and the FC driver. @@ -2382,6 +2385,20 @@ static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) } +static void qlge_restore_vlan(struct ql_adapter *qdev) +{ + qlge_vlan_rx_register(qdev->ndev, qdev->vlgrp); + + if (qdev->vlgrp) { + u16 vid; + for (vid = 0; vid < VLAN_N_VID; vid++) { + if (!vlan_group_get_device(qdev->vlgrp, vid)) + continue; + qlge_vlan_rx_add_vid(qdev->ndev, vid); + } + } +} + /* MSI-X Multiple Vector Interrupt Handler for inbound completions. */ static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id) { @@ -3842,7 +3859,7 @@ static void ql_display_dev_info(struct net_device *ndev) "MAC address %pM\n", ndev->dev_addr); } -int ql_wol(struct ql_adapter *qdev) +static int ql_wol(struct ql_adapter *qdev) { int status = 0; u32 wol = MB_WOL_DISABLE; @@ -3957,6 +3974,9 @@ static int ql_adapter_up(struct ql_adapter *qdev) clear_bit(QL_PROMISCUOUS, &qdev->flags); qlge_set_multicast_list(qdev->ndev); + /* Restore vlan setting. */ + qlge_restore_vlan(qdev); + ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); netif_tx_start_all_queues(qdev->ndev); @@ -4242,7 +4262,7 @@ static struct net_device_stats *qlge_get_stats(struct net_device return &ndev->stats; } -void qlge_set_multicast_list(struct net_device *ndev) +static void qlge_set_multicast_list(struct net_device *ndev) { struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); struct netdev_hw_addr *ha; diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index f84e8570c7cb..0e7c7c7ee164 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -87,7 +87,7 @@ exit: return status; } -int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) +static int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) { int status; status = ql_write_mpi_reg(qdev, 0x00001010, 1); @@ -681,7 +681,7 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev) /* Send and ACK mailbox command to the firmware to * let it continue with the change. */ -int ql_mb_idc_ack(struct ql_adapter *qdev) +static int ql_mb_idc_ack(struct ql_adapter *qdev) { struct mbox_params mbc; struct mbox_params *mbcp = &mbc; @@ -744,7 +744,7 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev) return status; } -int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, +static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, u32 size) { int status = 0; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index a9ae505e1baf..66c2f1a01963 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -961,9 +961,9 @@ sb1000_open(struct net_device *dev) lp->rx_error_count = 0; lp->rx_error_dpc_count = 0; lp->rx_session_id[0] = 0x50; - lp->rx_session_id[0] = 0x48; - lp->rx_session_id[0] = 0x44; - lp->rx_session_id[0] = 0x42; + lp->rx_session_id[1] = 0x48; + lp->rx_session_id[2] = 0x44; + lp->rx_session_id[3] = 0x42; lp->rx_frame_id[0] = 0; lp->rx_frame_id[1] = 0; lp->rx_frame_id[2] = 0; diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 9265315baa0b..3a0cc63428ee 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -531,7 +531,7 @@ static int sgiseeq_open(struct net_device *dev) if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); - err = -EAGAIN; + return -EAGAIN; } err = init_seeq(dev, sp, sregs); diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index ac279fad9d45..ab9e3b785b5b 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -688,18 +688,8 @@ slhc_toss(struct slcompress *comp) return 0; } - -/* VJ header compression */ -EXPORT_SYMBOL(slhc_init); -EXPORT_SYMBOL(slhc_free); -EXPORT_SYMBOL(slhc_remember); -EXPORT_SYMBOL(slhc_compress); -EXPORT_SYMBOL(slhc_uncompress); -EXPORT_SYMBOL(slhc_toss); - #else /* CONFIG_INET */ - int slhc_toss(struct slcompress *comp) { @@ -738,6 +728,10 @@ slhc_init(int rslots, int tslots) printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init"); return NULL; } + +#endif /* CONFIG_INET */ + +/* VJ header compression */ EXPORT_SYMBOL(slhc_init); EXPORT_SYMBOL(slhc_free); EXPORT_SYMBOL(slhc_remember); @@ -745,5 +739,4 @@ EXPORT_SYMBOL(slhc_compress); EXPORT_SYMBOL(slhc_uncompress); EXPORT_SYMBOL(slhc_toss); -#endif /* CONFIG_INET */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index a8e5856ce882..64bfdae5956f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -2075,7 +2075,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) } else { /* Try reading mac address from device. if EEPROM is present * it will already have been set */ - smsc911x_read_mac_address(dev); + smsc_get_mac(dev); if (is_valid_ether_addr(dev->dev_addr)) { /* eeprom values are valid so use them */ @@ -2176,6 +2176,7 @@ static struct platform_driver smsc911x_driver = { /* Entry point for loading the module */ static int __init smsc911x_init_module(void) { + SMSC_INITIALIZE(); return platform_driver_register(&smsc911x_driver); } diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h index 016360c65ce2..52f38e12a879 100644 --- a/drivers/net/smsc911x.h +++ b/drivers/net/smsc911x.h @@ -394,4 +394,15 @@ #define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \ LPA_PAUSE_ASYM) +/* + * Provide hooks to let the arch add to the initialisation procedure + * and to override the source of the MAC address. + */ +#define SMSC_INITIALIZE() do {} while (0) +#define smsc_get_mac(dev) smsc911x_read_mac_address((dev)) + +#ifdef CONFIG_SMSC911X_ARCH_HOOKS +#include <asm/smsc911x.h> +#endif + #endif /* __SMSC911X_H__ */ diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 823b9e6431d5..06bc6034ce81 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -337,33 +337,19 @@ static int stmmac_init_phy(struct net_device *dev) return 0; } -static inline void stmmac_mac_enable_rx(void __iomem *ioaddr) +static inline void stmmac_enable_mac(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); - value |= MAC_RNABLE_RX; - /* Set the RE (receive enable bit into the MAC CTRL register). */ - writel(value, ioaddr + MAC_CTRL_REG); -} -static inline void stmmac_mac_enable_tx(void __iomem *ioaddr) -{ - u32 value = readl(ioaddr + MAC_CTRL_REG); - value |= MAC_ENABLE_TX; - /* Set the TE (transmit enable bit into the MAC CTRL register). */ + value |= MAC_RNABLE_RX | MAC_ENABLE_TX; writel(value, ioaddr + MAC_CTRL_REG); } -static inline void stmmac_mac_disable_rx(void __iomem *ioaddr) +static inline void stmmac_disable_mac(void __iomem *ioaddr) { u32 value = readl(ioaddr + MAC_CTRL_REG); - value &= ~MAC_RNABLE_RX; - writel(value, ioaddr + MAC_CTRL_REG); -} -static inline void stmmac_mac_disable_tx(void __iomem *ioaddr) -{ - u32 value = readl(ioaddr + MAC_CTRL_REG); - value &= ~MAC_ENABLE_TX; + value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX); writel(value, ioaddr + MAC_CTRL_REG); } @@ -857,8 +843,7 @@ static int stmmac_open(struct net_device *dev) writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK); /* Enable the MAC Rx/Tx */ - stmmac_mac_enable_rx(priv->ioaddr); - stmmac_mac_enable_tx(priv->ioaddr); + stmmac_enable_mac(priv->ioaddr); /* Set the HW DMA mode and the COE */ stmmac_dma_operation_mode(priv); @@ -928,9 +913,8 @@ static int stmmac_release(struct net_device *dev) /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv); - /* Disable the MAC core */ - stmmac_mac_disable_tx(priv->ioaddr); - stmmac_mac_disable_rx(priv->ioaddr); + /* Disable the MAC Rx/Tx */ + stmmac_disable_mac(priv->ioaddr); netif_carrier_off(dev); @@ -1787,8 +1771,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev) priv->hw->dma->stop_rx(priv->ioaddr); priv->hw->dma->stop_tx(priv->ioaddr); - stmmac_mac_disable_rx(priv->ioaddr); - stmmac_mac_disable_tx(priv->ioaddr); + stmmac_disable_mac(priv->ioaddr); netif_carrier_off(ndev); @@ -1839,13 +1822,11 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) dis_ic); priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); - stmmac_mac_disable_tx(priv->ioaddr); - /* Enable Power down mode by programming the PMT regs */ if (device_can_wakeup(priv->device)) priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); else - stmmac_mac_disable_rx(priv->ioaddr); + stmmac_disable_mac(priv->ioaddr); } else { priv->shutdown = 1; /* Although this can appear slightly redundant it actually @@ -1886,8 +1867,7 @@ static int stmmac_resume(struct platform_device *pdev) netif_device_attach(dev); /* Enable the MAC and DMA */ - stmmac_mac_enable_rx(priv->ioaddr); - stmmac_mac_enable_tx(priv->ioaddr); + stmmac_enable_mac(priv->ioaddr); priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 852e917778f8..30ccbb6d097a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9948,16 +9948,16 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) !((tp->tg3_flags & TG3_FLAG_WOL_CAP) && device_can_wakeup(dp))) return -EINVAL; + device_set_wakeup_enable(dp, wol->wolopts & WAKE_MAGIC); + spin_lock_bh(&tp->lock); - if (wol->wolopts & WAKE_MAGIC) { + if (device_may_wakeup(dp)) tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; - device_set_wakeup_enable(dp, true); - } else { + else tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - device_set_wakeup_enable(dp, false); - } spin_unlock_bh(&tp->lock); + return 0; } diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 663b8860a531..793020347e54 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -1220,7 +1220,7 @@ void tms380tr_wait(unsigned long time) tmp = schedule_timeout_interruptible(tmp); } while(time_after(tmp, jiffies)); #else - udelay(time); + mdelay(time / 1000); #endif } diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 1cc67138adbf..5b83c3f35f47 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -24,10 +24,6 @@ 3XP Processor. It has been tested on x86 and sparc64. KNOWN ISSUES: - *) The current firmware always strips the VLAN tag off, even if - we tell it not to. You should filter VLANs at the switch - as a workaround (good practice in any event) until we can - get this fixed. *) Cannot DMA Rx packets to a 2 byte aligned address. Also firmware issue. Hopefully 3Com will fix it. *) Waiting for a command response takes 8ms due to non-preemptable @@ -280,8 +276,6 @@ struct typhoon { struct pci_dev * pdev; struct net_device * dev; struct napi_struct napi; - spinlock_t state_lock; - struct vlan_group * vlgrp; struct basic_ring rxHiRing; struct basic_ring rxBuffRing; struct rxbuff_ent rxbuffers[RXENT_ENTRIES]; @@ -695,44 +689,6 @@ out: return err; } -static void -typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct typhoon *tp = netdev_priv(dev); - struct cmd_desc xp_cmd; - int err; - - spin_lock_bh(&tp->state_lock); - if(!tp->vlgrp != !grp) { - /* We've either been turned on for the first time, or we've - * been turned off. Update the 3XP. - */ - if(grp) - tp->offload |= TYPHOON_OFFLOAD_VLAN; - else - tp->offload &= ~TYPHOON_OFFLOAD_VLAN; - - /* If the interface is up, the runtime is running -- and we - * must be up for the vlan core to call us. - * - * Do the command outside of the spin lock, as it is slow. - */ - INIT_COMMAND_WITH_RESPONSE(&xp_cmd, - TYPHOON_CMD_SET_OFFLOAD_TASKS); - xp_cmd.parm2 = tp->offload; - xp_cmd.parm3 = tp->offload; - spin_unlock_bh(&tp->state_lock); - err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); - if(err < 0) - netdev_err(tp->dev, "vlan offload error %d\n", -err); - spin_lock_bh(&tp->state_lock); - } - - /* now make the change visible */ - tp->vlgrp = grp; - spin_unlock_bh(&tp->state_lock); -} - static inline void typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing, u32 ring_dma) @@ -818,7 +774,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) first_txd->processFlags |= TYPHOON_TX_PF_INSERT_VLAN | TYPHOON_TX_PF_VLAN_PRIORITY; first_txd->processFlags |= - cpu_to_le32(ntohs(vlan_tx_tag_get(skb)) << + cpu_to_le32(htons(vlan_tx_tag_get(skb)) << TYPHOON_TX_PF_VLAN_TAG_SHIFT); } @@ -936,7 +892,7 @@ typhoon_set_rx_mode(struct net_device *dev) filter |= TYPHOON_RX_FILTER_MCAST_HASH; } - INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_RX_FILTER); + INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_RX_FILTER); xp_cmd.parm1 = filter; typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); } @@ -1198,6 +1154,20 @@ typhoon_get_rx_csum(struct net_device *dev) return 1; } +static int +typhoon_set_flags(struct net_device *dev, u32 data) +{ + /* There's no way to turn off the RX VLAN offloading and stripping + * on the current 3XP firmware -- it does not respect the offload + * settings -- so we only allow the user to toggle the TX processing. + */ + if (!(data & ETH_FLAG_RXVLAN)) + return -EINVAL; + + return ethtool_op_set_flags(dev, data, + ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); +} + static void typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { @@ -1224,6 +1194,8 @@ static const struct ethtool_ops typhoon_ethtool_ops = { .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, .get_ringparam = typhoon_get_ringparam, + .set_flags = typhoon_set_flags, + .get_flags = ethtool_op_get_flags, }; static int @@ -1309,9 +1281,9 @@ typhoon_init_interface(struct typhoon *tp) tp->offload = TYPHOON_OFFLOAD_IP_CHKSUM | TYPHOON_OFFLOAD_TCP_CHKSUM; tp->offload |= TYPHOON_OFFLOAD_UDP_CHKSUM | TSO_OFFLOAD_ON; + tp->offload |= TYPHOON_OFFLOAD_VLAN; spin_lock_init(&tp->command_lock); - spin_lock_init(&tp->state_lock); /* Force the writes to the shared memory area out before continuing. */ wmb(); @@ -1328,7 +1300,7 @@ typhoon_init_rings(struct typhoon *tp) tp->rxHiRing.lastWrite = 0; tp->rxBuffRing.lastWrite = 0; tp->cmdRing.lastWrite = 0; - tp->cmdRing.lastWrite = 0; + tp->respRing.lastWrite = 0; tp->txLoRing.lastRead = 0; tp->txHiRing.lastRead = 0; @@ -1762,13 +1734,10 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * read } else skb_checksum_none_assert(new_skb); - spin_lock(&tp->state_lock); - if(tp->vlgrp != NULL && rx->rxStatus & TYPHOON_RX_VLAN) - vlan_hwaccel_receive_skb(new_skb, tp->vlgrp, - ntohl(rx->vlanTag) & 0xffff); - else - netif_receive_skb(new_skb); - spin_unlock(&tp->state_lock); + if (rx->rxStatus & TYPHOON_RX_VLAN) + __vlan_hwaccel_put_tag(new_skb, + ntohl(rx->vlanTag) & 0xffff); + netif_receive_skb(new_skb); received++; budget--; @@ -1989,11 +1958,9 @@ typhoon_start_runtime(struct typhoon *tp) goto error_out; INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_OFFLOAD_TASKS); - spin_lock_bh(&tp->state_lock); xp_cmd.parm2 = tp->offload; xp_cmd.parm3 = tp->offload; err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); - spin_unlock_bh(&tp->state_lock); if(err < 0) goto error_out; @@ -2231,13 +2198,9 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) if(!netif_running(dev)) return 0; - spin_lock_bh(&tp->state_lock); - if(tp->vlgrp && tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) { - spin_unlock_bh(&tp->state_lock); - netdev_err(dev, "cannot do WAKE_MAGIC with VLANS\n"); - return -EBUSY; - } - spin_unlock_bh(&tp->state_lock); + /* TYPHOON_OFFLOAD_VLAN is always on now, so this doesn't work */ + if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) + netdev_warn(dev, "cannot do WAKE_MAGIC with VLAN offloading\n"); netif_device_detach(dev); @@ -2338,7 +2301,6 @@ static const struct net_device_ops typhoon_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = typhoon_set_mac_address, .ndo_change_mtu = eth_change_mtu, - .ndo_vlan_rx_register = typhoon_vlan_rx_register, }; static int __devinit diff --git a/drivers/net/vmxnet3/upt1_defs.h b/drivers/net/vmxnet3/upt1_defs.h index 37108fb226d3..969c751ee404 100644 --- a/drivers/net/vmxnet3/upt1_defs.h +++ b/drivers/net/vmxnet3/upt1_defs.h @@ -88,9 +88,9 @@ struct UPT1_RSSConf { /* features */ enum { - UPT1_F_RXCSUM = 0x0001, /* rx csum verification */ - UPT1_F_RSS = 0x0002, - UPT1_F_RXVLAN = 0x0004, /* VLAN tag stripping */ - UPT1_F_LRO = 0x0008, + UPT1_F_RXCSUM = cpu_to_le64(0x0001), /* rx csum verification */ + UPT1_F_RSS = cpu_to_le64(0x0002), + UPT1_F_RXVLAN = cpu_to_le64(0x0004), /* VLAN tag stripping */ + UPT1_F_LRO = cpu_to_le64(0x0008), }; #endif diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h index ca7727b940ad..4d84912c99ba 100644 --- a/drivers/net/vmxnet3/vmxnet3_defs.h +++ b/drivers/net/vmxnet3/vmxnet3_defs.h @@ -523,9 +523,9 @@ struct Vmxnet3_RxFilterConf { #define VMXNET3_PM_MAX_PATTERN_SIZE 128 #define VMXNET3_PM_MAX_MASK_SIZE (VMXNET3_PM_MAX_PATTERN_SIZE / 8) -#define VMXNET3_PM_WAKEUP_MAGIC 0x01 /* wake up on magic pkts */ -#define VMXNET3_PM_WAKEUP_FILTER 0x02 /* wake up on pkts matching - * filters */ +#define VMXNET3_PM_WAKEUP_MAGIC cpu_to_le16(0x01) /* wake up on magic pkts */ +#define VMXNET3_PM_WAKEUP_FILTER cpu_to_le16(0x02) /* wake up on pkts matching + * filters */ struct Vmxnet3_PM_PktFilter { diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 3f60e0e3097b..21314e06e6d7 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -873,7 +873,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + skb_shinfo(skb)->nr_frags + 1; - ctx.ipv4 = (skb->protocol == __constant_ntohs(ETH_P_IP)); + ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP)); ctx.mss = skb_shinfo(skb)->gso_size; if (ctx.mss) { @@ -1563,8 +1563,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) adapter->vlan_grp = grp; /* update FEATURES to device */ - set_flag_le64(&devRead->misc.uptFeatures, - UPT1_F_RXVLAN); + devRead->misc.uptFeatures |= UPT1_F_RXVLAN; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); /* @@ -1587,7 +1586,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) struct Vmxnet3_DSDevRead *devRead = &shared->devRead; adapter->vlan_grp = NULL; - if (le64_to_cpu(devRead->misc.uptFeatures) & UPT1_F_RXVLAN) { + if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) { int i; for (i = 0; i < VMXNET3_VFT_SIZE; i++) { @@ -1600,8 +1599,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) VMXNET3_CMD_UPDATE_VLAN_FILTERS); /* update FEATURES to device */ - reset_flag_le64(&devRead->misc.uptFeatures, - UPT1_F_RXVLAN); + devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); } @@ -1762,15 +1760,15 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) /* set up feature flags */ if (adapter->rxcsum) - set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_RXCSUM); + devRead->misc.uptFeatures |= UPT1_F_RXCSUM; if (adapter->lro) { - set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_LRO); + devRead->misc.uptFeatures |= UPT1_F_LRO; devRead->misc.maxNumRxSG = cpu_to_le16(1 + MAX_SKB_FRAGS); } if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX) && adapter->vlan_grp) { - set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_RXVLAN); + devRead->misc.uptFeatures |= UPT1_F_RXVLAN; } devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu); @@ -2577,7 +2575,7 @@ vmxnet3_suspend(struct device *device) memcpy(pmConf->filters[i].pattern, netdev->dev_addr, ETH_ALEN); pmConf->filters[i].mask[0] = 0x3F; /* LSB ETH_ALEN bits */ - set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_FILTER); + pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER; i++; } @@ -2619,13 +2617,13 @@ vmxnet3_suspend(struct device *device) pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */ in_dev_put(in_dev); - set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_FILTER); + pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER; i++; } skip_arp: if (adapter->wol & WAKE_MAGIC) - set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_MAGIC); + pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_MAGIC; pmConf->numFilters = i; @@ -2667,7 +2665,7 @@ vmxnet3_resume(struct device *device) adapter->shared->devRead.pmConfDesc.confVer = cpu_to_le32(1); adapter->shared->devRead.pmConfDesc.confLen = cpu_to_le32(sizeof( *pmConf)); - adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le32(virt_to_phys( + adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le64(virt_to_phys( pmConf)); netif_device_attach(netdev); diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 7e4b5a89165a..b79070bcc92e 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -50,13 +50,11 @@ vmxnet3_set_rx_csum(struct net_device *netdev, u32 val) adapter->rxcsum = val; if (netif_running(netdev)) { if (val) - set_flag_le64( - &adapter->shared->devRead.misc.uptFeatures, - UPT1_F_RXCSUM); + adapter->shared->devRead.misc.uptFeatures |= + UPT1_F_RXCSUM; else - reset_flag_le64( - &adapter->shared->devRead.misc.uptFeatures, - UPT1_F_RXCSUM); + adapter->shared->devRead.misc.uptFeatures &= + ~UPT1_F_RXCSUM; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); @@ -292,10 +290,10 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) /* update harware LRO capability accordingly */ if (lro_requested) adapter->shared->devRead.misc.uptFeatures |= - cpu_to_le64(UPT1_F_LRO); + UPT1_F_LRO; else adapter->shared->devRead.misc.uptFeatures &= - cpu_to_le64(~UPT1_F_LRO); + ~UPT1_F_LRO; VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); } diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index c88ea5cbba0d..edf228843afc 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -301,8 +301,8 @@ struct vmxnet3_adapter { struct net_device *netdev; struct pci_dev *pdev; - u8 *hw_addr0; /* for BAR 0 */ - u8 *hw_addr1; /* for BAR 1 */ + u8 __iomem *hw_addr0; /* for BAR 0 */ + u8 __iomem *hw_addr1; /* for BAR 1 */ /* feature control */ bool rxcsum; @@ -330,14 +330,14 @@ struct vmxnet3_adapter { }; #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ - writel(cpu_to_le32(val), (adapter)->hw_addr0 + (reg)) + writel((val), (adapter)->hw_addr0 + (reg)) #define VMXNET3_READ_BAR0_REG(adapter, reg) \ - le32_to_cpu(readl((adapter)->hw_addr0 + (reg))) + readl((adapter)->hw_addr0 + (reg)) #define VMXNET3_WRITE_BAR1_REG(adapter, reg, val) \ - writel(cpu_to_le32(val), (adapter)->hw_addr1 + (reg)) + writel((val), (adapter)->hw_addr1 + (reg)) #define VMXNET3_READ_BAR1_REG(adapter, reg) \ - le32_to_cpu(readl((adapter)->hw_addr1 + (reg))) + readl((adapter)->hw_addr1 + (reg)) #define VMXNET3_WAKE_QUEUE_THRESHOLD(tq) (5) #define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \ @@ -353,21 +353,6 @@ struct vmxnet3_adapter { #define VMXNET3_MAX_ETH_HDR_SIZE 22 #define VMXNET3_MAX_SKB_BUF_SIZE (3*1024) -static inline void set_flag_le16(__le16 *data, u16 flag) -{ - *data = cpu_to_le16(le16_to_cpu(*data) | flag); -} - -static inline void set_flag_le64(__le64 *data, u64 flag) -{ - *data = cpu_to_le64(le64_to_cpu(*data) | flag); -} - -static inline void reset_flag_le64(__le64 *data, u64 flag) -{ - *data = cpu_to_le64(le64_to_cpu(*data) & ~flag); -} - int vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter); diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 0e6db5935609..906a3ca3676b 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c @@ -20,6 +20,179 @@ #include "vxge-traffic.h" #include "vxge-config.h" +static enum vxge_hw_status +__vxge_hw_fifo_create( + struct __vxge_hw_vpath_handle *vpath_handle, + struct vxge_hw_fifo_attr *attr); + +static enum vxge_hw_status +__vxge_hw_fifo_abort( + struct __vxge_hw_fifo *fifoh); + +static enum vxge_hw_status +__vxge_hw_fifo_reset( + struct __vxge_hw_fifo *ringh); + +static enum vxge_hw_status +__vxge_hw_fifo_delete( + struct __vxge_hw_vpath_handle *vpath_handle); + +static struct __vxge_hw_blockpool_entry * +__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *hldev, + u32 size); + +static void +__vxge_hw_blockpool_block_free(struct __vxge_hw_device *hldev, + struct __vxge_hw_blockpool_entry *entry); + +static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh, + void *block_addr, + u32 length, + struct pci_dev *dma_h, + struct pci_dev *acc_handle); + +static enum vxge_hw_status +__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev, + struct __vxge_hw_blockpool *blockpool, + u32 pool_size, + u32 pool_max); + +static void +__vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool); + +static void * +__vxge_hw_blockpool_malloc(struct __vxge_hw_device *hldev, + u32 size, + struct vxge_hw_mempool_dma *dma_object); + +static void +__vxge_hw_blockpool_free(struct __vxge_hw_device *hldev, + void *memblock, + u32 size, + struct vxge_hw_mempool_dma *dma_object); + + +static struct __vxge_hw_channel* +__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph, + enum __vxge_hw_channel_type type, u32 length, + u32 per_dtr_space, void *userdata); + +static void +__vxge_hw_channel_free( + struct __vxge_hw_channel *channel); + +static enum vxge_hw_status +__vxge_hw_channel_initialize( + struct __vxge_hw_channel *channel); + +static enum vxge_hw_status +__vxge_hw_channel_reset( + struct __vxge_hw_channel *channel); + +static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp); + +static enum vxge_hw_status +__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config); + +static enum vxge_hw_status +__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config); + +static void +__vxge_hw_device_id_get(struct __vxge_hw_device *hldev); + +static void +__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev); + +static enum vxge_hw_status +__vxge_hw_vpath_card_info_get( + u32 vp_id, + struct vxge_hw_vpath_reg __iomem *vpath_reg, + struct vxge_hw_device_hw_info *hw_info); + +static enum vxge_hw_status +__vxge_hw_device_initialize(struct __vxge_hw_device *hldev); + +static void +__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev); + +static enum vxge_hw_status +__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev); + +static enum vxge_hw_status +__vxge_hw_device_register_poll( + void __iomem *reg, + u64 mask, u32 max_millis); + +static inline enum vxge_hw_status +__vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr, + u64 mask, u32 max_millis) +{ + __vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr); + wmb(); + + __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr); + wmb(); + + return __vxge_hw_device_register_poll(addr, mask, max_millis); +} + +static struct vxge_hw_mempool* +__vxge_hw_mempool_create(struct __vxge_hw_device *devh, u32 memblock_size, + u32 item_size, u32 private_size, u32 items_initial, + u32 items_max, struct vxge_hw_mempool_cbs *mp_callback, + void *userdata); +static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool); + +static enum vxge_hw_status +__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_vpath_stats_hw_info *hw_stats); + +static enum vxge_hw_status +vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vpath_handle); + +static enum vxge_hw_status +__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg); + +static u64 +__vxge_hw_vpath_pci_func_mode_get(u32 vp_id, + struct vxge_hw_vpath_reg __iomem *vpath_reg); + +static u32 +__vxge_hw_vpath_func_id_get(u32 vp_id, struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg); + +static enum vxge_hw_status +__vxge_hw_vpath_addr_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, + u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN]); + +static enum vxge_hw_status +__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath); + + +static enum vxge_hw_status +__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *devh, u32 vp_id); + +static enum vxge_hw_status +__vxge_hw_vpath_fw_ver_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, + struct vxge_hw_device_hw_info *hw_info); + +static enum vxge_hw_status +__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh, u32 vp_id); + +static void +__vxge_hw_vp_terminate(struct __vxge_hw_device *devh, u32 vp_id); + +static enum vxge_hw_status +__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath, + u32 operation, u32 offset, u64 *stat); + +static enum vxge_hw_status +__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats); + +static enum vxge_hw_status +__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); + /* * __vxge_hw_channel_allocate - Allocate memory for channel * This function allocates required memory for the channel and various arrays @@ -190,7 +363,7 @@ __vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev) * Will poll certain register for specified amount of time. * Will poll until masked bit is not cleared. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis) { u64 val64; @@ -221,7 +394,7 @@ __vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis) * in progress * This routine checks the vpath reset in progress register is turned zero */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog) { enum vxge_hw_status status; @@ -236,7 +409,7 @@ __vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog) * This routine sets the swapper and reads the toc pointer and returns the * memory mapped address of the toc */ -struct vxge_hw_toc_reg __iomem * +static struct vxge_hw_toc_reg __iomem * __vxge_hw_device_toc_get(void __iomem *bar0) { u64 val64; @@ -779,7 +952,7 @@ exit: * vxge_hw_device_xmac_aggr_stats_get - Get the Statistics on aggregate port * Get the Statistics on aggregate port */ -enum vxge_hw_status +static enum vxge_hw_status vxge_hw_device_xmac_aggr_stats_get(struct __vxge_hw_device *hldev, u32 port, struct vxge_hw_xmac_aggr_stats *aggr_stats) { @@ -814,7 +987,7 @@ exit: * vxge_hw_device_xmac_port_stats_get - Get the Statistics on a port * Get the Statistics on port */ -enum vxge_hw_status +static enum vxge_hw_status vxge_hw_device_xmac_port_stats_get(struct __vxge_hw_device *hldev, u32 port, struct vxge_hw_xmac_port_stats *port_stats) { @@ -952,20 +1125,6 @@ u32 vxge_hw_device_trace_level_get(struct __vxge_hw_device *hldev) return 0; #endif } -/* - * vxge_hw_device_debug_mask_get - Get the debug mask - * This routine returns the current debug mask set - */ -u32 vxge_hw_device_debug_mask_get(struct __vxge_hw_device *hldev) -{ -#if defined(VXGE_DEBUG_TRACE_MASK) || defined(VXGE_DEBUG_ERR_MASK) - if (hldev == NULL) - return 0; - return hldev->debug_module_mask; -#else - return 0; -#endif -} /* * vxge_hw_getpause_data -Pause frame frame generation and reception. @@ -1090,7 +1249,7 @@ __vxge_hw_ring_block_next_pointer_set(u8 *block, dma_addr_t dma_next) * first block * Returns the dma address of the first RxD block */ -u64 __vxge_hw_ring_first_block_address_get(struct __vxge_hw_ring *ring) +static u64 __vxge_hw_ring_first_block_address_get(struct __vxge_hw_ring *ring) { struct vxge_hw_mempool_dma *dma_object; @@ -1252,7 +1411,7 @@ exit: * This function creates Ring and initializes it. * */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp, struct vxge_hw_ring_attr *attr) { @@ -1363,7 +1522,7 @@ exit: * __vxge_hw_ring_abort - Returns the RxD * This function terminates the RxDs of ring */ -enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring) +static enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring) { void *rxdh; struct __vxge_hw_channel *channel; @@ -1392,7 +1551,7 @@ enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring) * __vxge_hw_ring_reset - Resets the ring * This function resets the ring during vpath reset operation */ -enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring) +static enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring) { enum vxge_hw_status status = VXGE_HW_OK; struct __vxge_hw_channel *channel; @@ -1419,7 +1578,7 @@ exit: * __vxge_hw_ring_delete - Removes the ring * This function freeup the memory pool and removes the ring */ -enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp) +static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp) { struct __vxge_hw_ring *ring = vp->vpath->ringh; @@ -1438,7 +1597,7 @@ enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp) * __vxge_hw_mempool_grow * Will resize mempool up to %num_allocate value. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate, u32 *num_allocated) { @@ -1527,7 +1686,7 @@ exit: * with size enough to hold %items_initial number of items. Memory is * DMA-able but client must map/unmap before interoperating with the device. */ -struct vxge_hw_mempool* +static struct vxge_hw_mempool* __vxge_hw_mempool_create( struct __vxge_hw_device *devh, u32 memblock_size, @@ -1644,7 +1803,7 @@ exit: /* * vxge_hw_mempool_destroy */ -void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool) +static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool) { u32 i, j; struct __vxge_hw_device *devh = mempool->devh; @@ -1700,7 +1859,7 @@ __vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config) * __vxge_hw_device_vpath_config_check - Check vpath configuration. * Check the vpath configuration */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config) { enum vxge_hw_status status; @@ -1922,7 +2081,7 @@ vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config) * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion. * Set the swapper bits appropriately for the lagacy section. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg) { u64 val64; @@ -1977,7 +2136,7 @@ __vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg) * __vxge_hw_vpath_swapper_set - Set the swapper bits for the vpath. * Set the swapper bits appropriately for the vpath. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg) { #ifndef __BIG_ENDIAN @@ -1996,7 +2155,7 @@ __vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg) * __vxge_hw_kdfc_swapper_set - Set the swapper bits for the kdfc. * Set the swapper bits appropriately for the vpath. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_kdfc_swapper_set( struct vxge_hw_legacy_reg __iomem *legacy_reg, struct vxge_hw_vpath_reg __iomem *vpath_reg) @@ -2021,28 +2180,6 @@ __vxge_hw_kdfc_swapper_set( } /* - * vxge_hw_mgmt_device_config - Retrieve device configuration. - * Get device configuration. Permits to retrieve at run-time configuration - * values that were used to initialize and configure the device. - */ -enum vxge_hw_status -vxge_hw_mgmt_device_config(struct __vxge_hw_device *hldev, - struct vxge_hw_device_config *dev_config, int size) -{ - - if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) - return VXGE_HW_ERR_INVALID_DEVICE; - - if (size != sizeof(struct vxge_hw_device_config)) - return VXGE_HW_ERR_VERSION_CONFLICT; - - memcpy(dev_config, &hldev->config, - sizeof(struct vxge_hw_device_config)); - - return VXGE_HW_OK; -} - -/* * vxge_hw_mgmt_reg_read - Read Titan register. */ enum vxge_hw_status @@ -2438,7 +2575,7 @@ exit: * __vxge_hw_fifo_abort - Returns the TxD * This function terminates the TxDs of fifo */ -enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo) +static enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo) { void *txdlh; @@ -2466,7 +2603,7 @@ enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo) * __vxge_hw_fifo_reset - Resets the fifo * This function resets the fifo during vpath reset operation */ -enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo) +static enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo) { enum vxge_hw_status status = VXGE_HW_OK; @@ -2501,7 +2638,7 @@ enum vxge_hw_status __vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp) * in pci config space. * Read from the vpath pci config space. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_pci_read(struct __vxge_hw_virtualpath *vpath, u32 phy_func_0, u32 offset, u32 *val) { @@ -2542,7 +2679,7 @@ exit: * __vxge_hw_vpath_func_id_get - Get the function id of the vpath. * Returns the function number of the vpath. */ -u32 +static u32 __vxge_hw_vpath_func_id_get(u32 vp_id, struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg) { @@ -2573,7 +2710,7 @@ __vxge_hw_read_rts_ds(struct vxge_hw_vpath_reg __iomem *vpath_reg, * __vxge_hw_vpath_card_info_get - Get the serial numbers, * part number and product description. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_card_info_get( u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, @@ -2695,7 +2832,7 @@ __vxge_hw_vpath_card_info_get( * __vxge_hw_vpath_fw_ver_get - Get the fw version * Returns FW Version */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_fw_ver_get( u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, @@ -2789,7 +2926,7 @@ exit: * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode * Returns pci function mode */ -u64 +static u64 __vxge_hw_vpath_pci_func_mode_get( u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg) @@ -2995,7 +3132,7 @@ exit: * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath * from MAC address table. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_addr_get( u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg, u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN]) @@ -3347,7 +3484,7 @@ __vxge_hw_vpath_mgmt_read( * This routine checks the vpath_rst_in_prog register to see if * adapter completed the reset process for the vpath */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath) { enum vxge_hw_status status; @@ -3365,7 +3502,7 @@ __vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath) * __vxge_hw_vpath_reset * This routine resets the vpath on the device */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_reset(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3383,7 +3520,7 @@ __vxge_hw_vpath_reset(struct __vxge_hw_device *hldev, u32 vp_id) * __vxge_hw_vpath_sw_reset * This routine resets the vpath structures */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_sw_reset(struct __vxge_hw_device *hldev, u32 vp_id) { enum vxge_hw_status status = VXGE_HW_OK; @@ -3408,7 +3545,7 @@ exit: * This routine configures the prc registers of virtual path using the config * passed */ -void +static void __vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3480,7 +3617,7 @@ __vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev, u32 vp_id) * This routine configures the kdfc registers of virtual path using the * config passed */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_kdfc_configure(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3553,7 +3690,7 @@ exit: * __vxge_hw_vpath_mac_configure * This routine configures the mac of virtual path using the config passed */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_mac_configure(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3621,7 +3758,7 @@ __vxge_hw_vpath_mac_configure(struct __vxge_hw_device *hldev, u32 vp_id) * This routine configures the tim registers of virtual path using the config * passed */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3897,7 +4034,7 @@ vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id) * This routine is the final phase of init which initializes the * registers of the vpath using the configuration passed. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_initialize(struct __vxge_hw_device *hldev, u32 vp_id) { u64 val64; @@ -3966,7 +4103,7 @@ exit: * This routine is the initial phase of init which resets the vpath and * initializes the software support structures. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id, struct vxge_hw_vp_config *config) { @@ -4022,7 +4159,7 @@ exit: * __vxge_hw_vp_terminate - Terminate Virtual Path structure * This routine closes all channels it opened and freeup memory */ -void +static void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id) { struct __vxge_hw_virtualpath *vpath; @@ -4384,7 +4521,7 @@ vxge_hw_vpath_enable(struct __vxge_hw_vpath_handle *vp) * Enable the DMA vpath statistics. The function is to be called to re-enable * the adapter to update stats into the host memory */ -enum vxge_hw_status +static enum vxge_hw_status vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vp) { enum vxge_hw_status status = VXGE_HW_OK; @@ -4409,7 +4546,7 @@ exit: * __vxge_hw_vpath_stats_access - Get the statistics from the given location * and offset and perform an operation */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath, u32 operation, u32 offset, u64 *stat) { @@ -4445,7 +4582,7 @@ vpath_stats_access_exit: /* * __vxge_hw_vpath_xmac_tx_stats_get - Get the TX Statistics of a vpath */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_xmac_tx_stats_get( struct __vxge_hw_virtualpath *vpath, struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats) @@ -4478,9 +4615,9 @@ exit: /* * __vxge_hw_vpath_xmac_rx_stats_get - Get the RX Statistics of a vpath */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats) + struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats) { u64 *val64; enum vxge_hw_status status = VXGE_HW_OK; @@ -4509,9 +4646,9 @@ exit: /* * __vxge_hw_vpath_stats_get - Get the vpath hw statistics. */ -enum vxge_hw_status __vxge_hw_vpath_stats_get( - struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_vpath_stats_hw_info *hw_stats) +static enum vxge_hw_status +__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath, + struct vxge_hw_vpath_stats_hw_info *hw_stats) { u64 val64; enum vxge_hw_status status = VXGE_HW_OK; @@ -4643,6 +4780,32 @@ exit: return status; } + +static void vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh, + unsigned long size) +{ + gfp_t flags; + void *vaddr; + + if (in_interrupt()) + flags = GFP_ATOMIC | GFP_DMA; + else + flags = GFP_KERNEL | GFP_DMA; + + vaddr = kmalloc((size), flags); + + vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev); +} + +static void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr, + struct pci_dev **p_dma_acch) +{ + unsigned long misaligned = *(unsigned long *)p_dma_acch; + u8 *tmp = (u8 *)vaddr; + tmp -= misaligned; + kfree((void *)tmp); +} + /* * __vxge_hw_blockpool_create - Create block pool */ @@ -4845,12 +5008,11 @@ void __vxge_hw_blockpool_blocks_remove(struct __vxge_hw_blockpool *blockpool) * vxge_hw_blockpool_block_add - callback for vxge_os_dma_malloc_async * Adds a block to block pool */ -void vxge_hw_blockpool_block_add( - struct __vxge_hw_device *devh, - void *block_addr, - u32 length, - struct pci_dev *dma_h, - struct pci_dev *acc_handle) +static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh, + void *block_addr, + u32 length, + struct pci_dev *dma_h, + struct pci_dev *acc_handle) { struct __vxge_hw_blockpool *blockpool; struct __vxge_hw_blockpool_entry *entry = NULL; diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h index 1a94343023cb..5c00861b6c2c 100644 --- a/drivers/net/vxge/vxge-config.h +++ b/drivers/net/vxge/vxge-config.h @@ -183,11 +183,6 @@ struct vxge_hw_device_version { char version[VXGE_HW_FW_STRLEN]; }; -u64 -__vxge_hw_vpath_pci_func_mode_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg); - /** * struct vxge_hw_fifo_config - Configuration of fifo. * @enable: Is this fifo to be commissioned @@ -1426,9 +1421,6 @@ struct vxge_hw_rth_hash_types { u8 hash_type_ipv6ex_en; }; -u32 -vxge_hw_device_debug_mask_get(struct __vxge_hw_device *devh); - void vxge_hw_device_debug_set( struct __vxge_hw_device *devh, enum vxge_debug_level level, @@ -1440,9 +1432,6 @@ vxge_hw_device_error_level_get(struct __vxge_hw_device *devh); u32 vxge_hw_device_trace_level_get(struct __vxge_hw_device *devh); -u32 -vxge_hw_device_debug_mask_get(struct __vxge_hw_device *devh); - /** * vxge_hw_ring_rxd_size_get - Get the size of ring descriptor. * @buf_mode: Buffer mode (1, 3 or 5) @@ -1817,60 +1806,10 @@ struct vxge_hw_vpath_attr { struct vxge_hw_fifo_attr fifo_attr; }; -enum vxge_hw_status -__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev, - struct __vxge_hw_blockpool *blockpool, - u32 pool_size, - u32 pool_max); - -void -__vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool); - -struct __vxge_hw_blockpool_entry * -__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *hldev, - u32 size); - -void -__vxge_hw_blockpool_block_free(struct __vxge_hw_device *hldev, - struct __vxge_hw_blockpool_entry *entry); - -void * -__vxge_hw_blockpool_malloc(struct __vxge_hw_device *hldev, - u32 size, - struct vxge_hw_mempool_dma *dma_object); - -void -__vxge_hw_blockpool_free(struct __vxge_hw_device *hldev, - void *memblock, - u32 size, - struct vxge_hw_mempool_dma *dma_object); - -enum vxge_hw_status -__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config); - -enum vxge_hw_status -__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config); - -enum vxge_hw_status -vxge_hw_mgmt_device_config(struct __vxge_hw_device *devh, - struct vxge_hw_device_config *dev_config, int size); - enum vxge_hw_status __devinit vxge_hw_device_hw_info_get( void __iomem *bar0, struct vxge_hw_device_hw_info *hw_info); -enum vxge_hw_status -__vxge_hw_vpath_fw_ver_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info); - -enum vxge_hw_status -__vxge_hw_vpath_card_info_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - struct vxge_hw_device_hw_info *hw_info); - enum vxge_hw_status __devinit vxge_hw_device_config_default_get( struct vxge_hw_device_config *device_config); @@ -1954,38 +1893,6 @@ out: return vaddr; } -extern void vxge_hw_blockpool_block_add( - struct __vxge_hw_device *devh, - void *block_addr, - u32 length, - struct pci_dev *dma_h, - struct pci_dev *acc_handle); - -static inline void vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh, - unsigned long size) -{ - gfp_t flags; - void *vaddr; - - if (in_interrupt()) - flags = GFP_ATOMIC | GFP_DMA; - else - flags = GFP_KERNEL | GFP_DMA; - - vaddr = kmalloc((size), flags); - - vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev); -} - -static inline void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr, - struct pci_dev **p_dma_acch) -{ - unsigned long misaligned = *(unsigned long *)p_dma_acch; - u8 *tmp = (u8 *)vaddr; - tmp -= misaligned; - kfree((void *)tmp); -} - /* * __vxge_hw_mempool_item_priv - will return pointer on per item private space */ @@ -2010,40 +1917,6 @@ __vxge_hw_mempool_item_priv( (*memblock_item_idx) * mempool->items_priv_size; } -enum vxge_hw_status -__vxge_hw_mempool_grow( - struct vxge_hw_mempool *mempool, - u32 num_allocate, - u32 *num_allocated); - -struct vxge_hw_mempool* -__vxge_hw_mempool_create( - struct __vxge_hw_device *devh, - u32 memblock_size, - u32 item_size, - u32 private_size, - u32 items_initial, - u32 items_max, - struct vxge_hw_mempool_cbs *mp_callback, - void *userdata); - -struct __vxge_hw_channel* -__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph, - enum __vxge_hw_channel_type type, u32 length, - u32 per_dtr_space, void *userdata); - -void -__vxge_hw_channel_free( - struct __vxge_hw_channel *channel); - -enum vxge_hw_status -__vxge_hw_channel_initialize( - struct __vxge_hw_channel *channel); - -enum vxge_hw_status -__vxge_hw_channel_reset( - struct __vxge_hw_channel *channel); - /* * __vxge_hw_fifo_txdl_priv - Return the max fragments allocated * for the fifo. @@ -2065,9 +1938,6 @@ enum vxge_hw_status vxge_hw_vpath_open( struct vxge_hw_vpath_attr *attr, struct __vxge_hw_vpath_handle **vpath_handle); -enum vxge_hw_status -__vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog); - enum vxge_hw_status vxge_hw_vpath_close( struct __vxge_hw_vpath_handle *vpath_handle); @@ -2089,54 +1959,9 @@ enum vxge_hw_status vxge_hw_vpath_mtu_set( struct __vxge_hw_vpath_handle *vpath_handle, u32 new_mtu); -enum vxge_hw_status vxge_hw_vpath_stats_enable( - struct __vxge_hw_vpath_handle *vpath_handle); - -enum vxge_hw_status -__vxge_hw_vpath_stats_access( - struct __vxge_hw_virtualpath *vpath, - u32 operation, - u32 offset, - u64 *stat); - -enum vxge_hw_status -__vxge_hw_vpath_xmac_tx_stats_get( - struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats); - -enum vxge_hw_status -__vxge_hw_vpath_xmac_rx_stats_get( - struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); - -enum vxge_hw_status -__vxge_hw_vpath_stats_get( - struct __vxge_hw_virtualpath *vpath, - struct vxge_hw_vpath_stats_hw_info *hw_stats); - void vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp); -enum vxge_hw_status -__vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config); - -void -__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev); - -enum vxge_hw_status -__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg); - -enum vxge_hw_status -__vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg); - -enum vxge_hw_status -__vxge_hw_kdfc_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg, - struct vxge_hw_vpath_reg __iomem *vpath_reg); - -enum vxge_hw_status -__vxge_hw_device_register_poll( - void __iomem *reg, - u64 mask, u32 max_millis); #ifndef readq static inline u64 readq(void __iomem *addr) @@ -2168,62 +1993,12 @@ static inline void __vxge_hw_pio_mem_write32_lower(u32 val, void __iomem *addr) writel(val, addr); } -static inline enum vxge_hw_status -__vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr, - u64 mask, u32 max_millis) -{ - enum vxge_hw_status status = VXGE_HW_OK; - - __vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr); - wmb(); - __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr); - wmb(); - - status = __vxge_hw_device_register_poll(addr, mask, max_millis); - return status; -} - -struct vxge_hw_toc_reg __iomem * -__vxge_hw_device_toc_get(void __iomem *bar0); - -enum vxge_hw_status -__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev); - -void -__vxge_hw_device_id_get(struct __vxge_hw_device *hldev); - -void -__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev); - enum vxge_hw_status vxge_hw_device_flick_link_led(struct __vxge_hw_device *devh, u64 on_off); enum vxge_hw_status -__vxge_hw_device_initialize(struct __vxge_hw_device *hldev); - -enum vxge_hw_status -__vxge_hw_vpath_pci_read( - struct __vxge_hw_virtualpath *vpath, - u32 phy_func_0, - u32 offset, - u32 *val); - -enum vxge_hw_status -__vxge_hw_vpath_addr_get( - u32 vp_id, - struct vxge_hw_vpath_reg __iomem *vpath_reg, - u8 (macaddr)[ETH_ALEN], - u8 (macaddr_mask)[ETH_ALEN]); - -u32 -__vxge_hw_vpath_func_id_get( - u32 vp_id, struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg); - -enum vxge_hw_status -__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath); - -enum vxge_hw_status vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask); + /** * vxge_debug * @level: level of debug verbosity. diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index 05679e306fdd..b67746eef923 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -1142,7 +1142,7 @@ static const struct ethtool_ops vxge_ethtool_ops = { .get_ethtool_stats = vxge_get_ethtool_stats, }; -void initialize_ethtool_ops(struct net_device *ndev) +void vxge_initialize_ethtool_ops(struct net_device *ndev) { SET_ETHTOOL_OPS(ndev, &vxge_ethtool_ops); } diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index a69542ecb68d..813829f3d024 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -82,6 +82,16 @@ module_param_array(bw_percentage, uint, NULL, 0); static struct vxge_drv_config *driver_config; +static enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, + struct macInfo *mac); +static enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev, + struct macInfo *mac); +static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac); +static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac); +static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath); +static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath); +static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev); + static inline int is_vxge_card_up(struct vxgedev *vdev) { return test_bit(__VXGE_STATE_CARD_UP, &vdev->state); @@ -138,7 +148,7 @@ static inline void VXGE_COMPLETE_ALL_RX(struct vxgedev *vdev) * This function is called during interrupt context to notify link up state * change. */ -void +static void vxge_callback_link_up(struct __vxge_hw_device *hldev) { struct net_device *dev = hldev->ndev; @@ -162,7 +172,7 @@ vxge_callback_link_up(struct __vxge_hw_device *hldev) * This function is called during interrupt context to notify link down state * change. */ -void +static void vxge_callback_link_down(struct __vxge_hw_device *hldev) { struct net_device *dev = hldev->ndev; @@ -354,7 +364,7 @@ static inline void vxge_post(int *dtr_cnt, void **first_dtr, * If the interrupt is because of a received frame or if the receive ring * contains fresh as yet un-processed frames, this function is called. */ -enum vxge_hw_status +static enum vxge_hw_status vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, u8 t_code, void *userdata) { @@ -531,7 +541,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, * freed and frees all skbs whose data have already DMA'ed into the NICs * internal memory. */ -enum vxge_hw_status +static enum vxge_hw_status vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr, enum vxge_hw_fifo_tcode t_code, void *userdata, struct sk_buff ***skb_ptr, int nr_skb, int *more) @@ -1246,7 +1256,7 @@ static int vxge_set_mac_addr(struct net_device *dev, void *p) * * Enables the interrupts for the vpath */ -void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id) +static void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id) { struct vxge_vpath *vpath = &vdev->vpaths[vp_id]; int msix_id = 0; @@ -1279,7 +1289,7 @@ void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id) * * Disables the interrupts for the vpath */ -void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id) +static void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id) { struct vxge_vpath *vpath = &vdev->vpaths[vp_id]; int msix_id; @@ -1553,7 +1563,7 @@ out: * * driver may reset the chip on events of serr, eccerr, etc */ -int vxge_reset(struct vxgedev *vdev) +static int vxge_reset(struct vxgedev *vdev) { return do_vxge_reset(vdev, VXGE_LL_FULL_RESET); } @@ -1724,7 +1734,7 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev) return status; } -int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac) +static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac) { struct vxge_mac_addrs *new_mac_entry; u8 *mac_address = NULL; @@ -1757,7 +1767,8 @@ int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac) } /* Add a mac address to DA table */ -enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, struct macInfo *mac) +static enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, + struct macInfo *mac) { enum vxge_hw_status status = VXGE_HW_OK; struct vxge_vpath *vpath; @@ -1782,7 +1793,7 @@ enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, struct macInfo *mac) return status; } -int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac) +static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac) { struct list_head *entry, *next; u64 del_mac = 0; @@ -1807,7 +1818,8 @@ int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac) return FALSE; } /* delete a mac address from DA table */ -enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev, struct macInfo *mac) +static enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev, + struct macInfo *mac) { enum vxge_hw_status status = VXGE_HW_OK; struct vxge_vpath *vpath; @@ -1854,7 +1866,7 @@ static vxge_search_mac_addr_in_da_table(struct vxge_vpath *vpath, } /* Store all vlan ids from the list to the vid table */ -enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath) +static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath) { enum vxge_hw_status status = VXGE_HW_OK; struct vxgedev *vdev = vpath->vdev; @@ -1874,7 +1886,7 @@ enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath) } /* Store all mac addresses from the list to the DA table */ -enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath) +static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath) { enum vxge_hw_status status = VXGE_HW_OK; struct macInfo mac_info; @@ -1916,7 +1928,7 @@ enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath) } /* reset vpaths */ -enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev) +static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev) { enum vxge_hw_status status = VXGE_HW_OK; struct vxge_vpath *vpath; @@ -1948,7 +1960,7 @@ enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev) } /* close vpaths */ -void vxge_close_vpaths(struct vxgedev *vdev, int index) +static void vxge_close_vpaths(struct vxgedev *vdev, int index) { struct vxge_vpath *vpath; int i; @@ -1966,7 +1978,7 @@ void vxge_close_vpaths(struct vxgedev *vdev, int index) } /* open vpaths */ -int vxge_open_vpaths(struct vxgedev *vdev) +static int vxge_open_vpaths(struct vxgedev *vdev) { struct vxge_hw_vpath_attr attr; enum vxge_hw_status status; @@ -2517,7 +2529,7 @@ static void vxge_poll_vp_lockup(unsigned long data) * Return value: '0' on success and an appropriate (-)ve integer as * defined in errno.h file on failure. */ -int +static int vxge_open(struct net_device *dev) { enum vxge_hw_status status; @@ -2721,7 +2733,7 @@ out0: } /* Loop throught the mac address list and delete all the entries */ -void vxge_free_mac_add_list(struct vxge_vpath *vpath) +static void vxge_free_mac_add_list(struct vxge_vpath *vpath) { struct list_head *entry, *next; @@ -2745,7 +2757,7 @@ static void vxge_napi_del_all(struct vxgedev *vdev) } } -int do_vxge_close(struct net_device *dev, int do_io) +static int do_vxge_close(struct net_device *dev, int do_io) { enum vxge_hw_status status; struct vxgedev *vdev; @@ -2856,7 +2868,7 @@ int do_vxge_close(struct net_device *dev, int do_io) * Return value: '0' on success and an appropriate (-)ve integer as * defined in errno.h file on failure. */ -int +static int vxge_close(struct net_device *dev) { do_vxge_close(dev, 1); @@ -3113,10 +3125,10 @@ static const struct net_device_ops vxge_netdev_ops = { #endif }; -int __devinit vxge_device_register(struct __vxge_hw_device *hldev, - struct vxge_config *config, - int high_dma, int no_of_vpath, - struct vxgedev **vdev_out) +static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, + struct vxge_config *config, + int high_dma, int no_of_vpath, + struct vxgedev **vdev_out) { struct net_device *ndev; enum vxge_hw_status status = VXGE_HW_OK; @@ -3164,7 +3176,7 @@ int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ndev->watchdog_timeo = VXGE_LL_WATCH_DOG_TIMEOUT; - initialize_ethtool_ops(ndev); + vxge_initialize_ethtool_ops(ndev); /* Allocate memory for vpath */ vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * @@ -3249,7 +3261,7 @@ _out0: * * This function will unregister and free network device */ -void +static void vxge_device_unregister(struct __vxge_hw_device *hldev) { struct vxgedev *vdev; diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h index d4be07eaacd7..de64536cb7d0 100644 --- a/drivers/net/vxge/vxge-main.h +++ b/drivers/net/vxge/vxge-main.h @@ -396,64 +396,7 @@ struct vxge_tx_priv { mod_timer(&timer, (jiffies + exp)); \ } while (0); -int __devinit vxge_device_register(struct __vxge_hw_device *devh, - struct vxge_config *config, - int high_dma, int no_of_vpath, - struct vxgedev **vdev); - -void vxge_device_unregister(struct __vxge_hw_device *devh); - -void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id); - -void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id); - -void vxge_callback_link_up(struct __vxge_hw_device *devh); - -void vxge_callback_link_down(struct __vxge_hw_device *devh); - -enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, - struct macInfo *mac); - -int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac); - -int vxge_reset(struct vxgedev *vdev); - -enum vxge_hw_status -vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, - u8 t_code, void *userdata); - -enum vxge_hw_status -vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr, - enum vxge_hw_fifo_tcode t_code, void *userdata, - struct sk_buff ***skb_ptr, int nr_skbs, int *more); - -int vxge_close(struct net_device *dev); - -int vxge_open(struct net_device *dev); - -void vxge_close_vpaths(struct vxgedev *vdev, int index); - -int vxge_open_vpaths(struct vxgedev *vdev); - -enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev); - -enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev, - struct macInfo *mac); - -enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev, - struct macInfo *mac); - -int vxge_mac_list_add(struct vxge_vpath *vpath, - struct macInfo *mac); - -void vxge_free_mac_add_list(struct vxge_vpath *vpath); - -enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath); - -enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath); - -int do_vxge_close(struct net_device *dev, int do_io); -extern void initialize_ethtool_ops(struct net_device *ndev); +extern void vxge_initialize_ethtool_ops(struct net_device *ndev); /** * #define VXGE_DEBUG_INIT: debug for initialization functions * #define VXGE_DEBUG_TX : debug transmit related functions diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index cedf08f99cb3..4bdb611a6842 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -17,6 +17,13 @@ #include "vxge-config.h" #include "vxge-main.h" +static enum vxge_hw_status +__vxge_hw_device_handle_error(struct __vxge_hw_device *hldev, + u32 vp_id, enum vxge_hw_event type); +static enum vxge_hw_status +__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath, + u32 skip_alarms); + /* * vxge_hw_vpath_intr_enable - Enable vpath interrupts. * @vp: Virtual Path handle. @@ -513,7 +520,7 @@ exit: * Link up indication handler. The function is invoked by HW when * Titan indicates that the link is up for programmable amount of time. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev) { /* @@ -538,7 +545,7 @@ exit: * Link down indication handler. The function is invoked by HW when * Titan indicates that the link is down. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev) { /* @@ -564,7 +571,7 @@ exit: * * Handle error. */ -enum vxge_hw_status +static enum vxge_hw_status __vxge_hw_device_handle_error( struct __vxge_hw_device *hldev, u32 vp_id, @@ -646,7 +653,7 @@ void vxge_hw_device_clear_tx_rx(struct __vxge_hw_device *hldev) * it swaps the reserve and free arrays. * */ -enum vxge_hw_status +static enum vxge_hw_status vxge_hw_channel_dtr_alloc(struct __vxge_hw_channel *channel, void **dtrh) { void **tmp_arr; @@ -692,7 +699,8 @@ _alloc_after_swap: * Posts a dtr to work array. * */ -void vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, void *dtrh) +static void vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, + void *dtrh) { vxge_assert(channel->work_arr[channel->post_index] == NULL); @@ -1658,37 +1666,6 @@ exit: } /** - * vxge_hw_vpath_vid_get_next - Get the next vid entry for this vpath - * from vlan id table. - * @vp: Vpath handle. - * @vid: Buffer to return vlan id - * - * Returns the next vlan id in the list for this vpath. - * see also: vxge_hw_vpath_vid_get - * - */ -enum vxge_hw_status -vxge_hw_vpath_vid_get_next(struct __vxge_hw_vpath_handle *vp, u64 *vid) -{ - u64 data; - enum vxge_hw_status status = VXGE_HW_OK; - - if (vp == NULL) { - status = VXGE_HW_ERR_INVALID_HANDLE; - goto exit; - } - - status = __vxge_hw_vpath_rts_table_get(vp, - VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY, - VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID, - 0, vid, &data); - - *vid = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID(*vid); -exit: - return status; -} - -/** * vxge_hw_vpath_vid_delete - Delete the vlan id entry for this vpath * to vlan id table. * @vp: Vpath handle. @@ -1898,9 +1875,9 @@ exit: * Process vpath alarms. * */ -enum vxge_hw_status __vxge_hw_vpath_alarm_process( - struct __vxge_hw_virtualpath *vpath, - u32 skip_alarms) +static enum vxge_hw_status +__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath, + u32 skip_alarms) { u64 val64; u64 alarm_status; @@ -2265,36 +2242,6 @@ vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vp, int msix_id) } /** - * vxge_hw_vpath_msix_clear - Clear MSIX Vector. - * @vp: Virtual Path handle. - * @msix_id: MSI ID - * - * The function clears the msix interrupt for the given msix_id - * - * Returns: 0, - * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range - * status. - * See also: - */ -void -vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id) -{ - struct __vxge_hw_device *hldev = vp->vpath->hldev; - if (hldev->config.intr_mode == - VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) { - __vxge_hw_pio_mem_write32_upper( - (u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32), - &hldev->common_reg-> - clr_msix_one_shot_vec[msix_id%4]); - } else { - __vxge_hw_pio_mem_write32_upper( - (u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32), - &hldev->common_reg-> - clear_msix_mask_vect[msix_id%4]); - } -} - -/** * vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector. * @vp: Virtual Path handle. * @msix_id: MSI ID @@ -2316,22 +2263,6 @@ vxge_hw_vpath_msix_unmask(struct __vxge_hw_vpath_handle *vp, int msix_id) } /** - * vxge_hw_vpath_msix_mask_all - Mask all MSIX vectors for the vpath. - * @vp: Virtual Path handle. - * - * The function masks all msix interrupt for the given vpath - * - */ -void -vxge_hw_vpath_msix_mask_all(struct __vxge_hw_vpath_handle *vp) -{ - - __vxge_hw_pio_mem_write32_upper( - (u32)vxge_bVALn(vxge_mBIT(vp->vpath->vp_id), 0, 32), - &vp->vpath->hldev->common_reg->set_msix_mask_all_vect); -} - -/** * vxge_hw_vpath_inta_mask_tx_rx - Mask Tx and Rx interrupts. * @vp: Virtual Path handle. * diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 6fa07d13798e..9890d4d596d0 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -1749,14 +1749,6 @@ vxge_hw_mrpcim_stats_access( u64 *stat); enum vxge_hw_status -vxge_hw_device_xmac_aggr_stats_get(struct __vxge_hw_device *devh, u32 port, - struct vxge_hw_xmac_aggr_stats *aggr_stats); - -enum vxge_hw_status -vxge_hw_device_xmac_port_stats_get(struct __vxge_hw_device *devh, u32 port, - struct vxge_hw_xmac_port_stats *port_stats); - -enum vxge_hw_status vxge_hw_device_xmac_stats_get(struct __vxge_hw_device *devh, struct vxge_hw_xmac_stats *xmac_stats); @@ -2117,49 +2109,10 @@ struct __vxge_hw_ring_rxd_priv { #endif }; -/* ========================= RING PRIVATE API ============================= */ -u64 -__vxge_hw_ring_first_block_address_get( - struct __vxge_hw_ring *ringh); - -enum vxge_hw_status -__vxge_hw_ring_create( - struct __vxge_hw_vpath_handle *vpath_handle, - struct vxge_hw_ring_attr *attr); - -enum vxge_hw_status -__vxge_hw_ring_abort( - struct __vxge_hw_ring *ringh); - -enum vxge_hw_status -__vxge_hw_ring_reset( - struct __vxge_hw_ring *ringh); - -enum vxge_hw_status -__vxge_hw_ring_delete( - struct __vxge_hw_vpath_handle *vpath_handle); - /* ========================= FIFO PRIVATE API ============================= */ struct vxge_hw_fifo_attr; -enum vxge_hw_status -__vxge_hw_fifo_create( - struct __vxge_hw_vpath_handle *vpath_handle, - struct vxge_hw_fifo_attr *attr); - -enum vxge_hw_status -__vxge_hw_fifo_abort( - struct __vxge_hw_fifo *fifoh); - -enum vxge_hw_status -__vxge_hw_fifo_reset( - struct __vxge_hw_fifo *ringh); - -enum vxge_hw_status -__vxge_hw_fifo_delete( - struct __vxge_hw_vpath_handle *vpath_handle); - struct vxge_hw_mempool_cbs { void (*item_func_alloc)( struct vxge_hw_mempool *mempoolh, @@ -2169,10 +2122,6 @@ struct vxge_hw_mempool_cbs { u32 is_last); }; -void -__vxge_hw_mempool_destroy( - struct vxge_hw_mempool *mempool); - #define VXGE_HW_VIRTUAL_PATH_HANDLE(vpath) \ ((struct __vxge_hw_vpath_handle *)(vpath)->vpath_handles.next) @@ -2195,61 +2144,10 @@ __vxge_hw_vpath_rts_table_set( u64 data2); enum vxge_hw_status -__vxge_hw_vpath_reset( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_sw_reset( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status __vxge_hw_vpath_enable( struct __vxge_hw_device *devh, u32 vp_id); -void -__vxge_hw_vpath_prc_configure( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_kdfc_configure( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_mac_configure( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_tim_configure( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_initialize( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vp_initialize( - struct __vxge_hw_device *devh, - u32 vp_id, - struct vxge_hw_vp_config *config); - -void -__vxge_hw_vp_terminate( - struct __vxge_hw_device *devh, - u32 vp_id); - -enum vxge_hw_status -__vxge_hw_vpath_alarm_process( - struct __vxge_hw_virtualpath *vpath, - u32 skip_alarms); - void vxge_hw_device_intr_enable( struct __vxge_hw_device *devh); @@ -2321,11 +2219,6 @@ vxge_hw_vpath_vid_get( u64 *vid); enum vxge_hw_status -vxge_hw_vpath_vid_get_next( - struct __vxge_hw_vpath_handle *vpath_handle, - u64 *vid); - -enum vxge_hw_status vxge_hw_vpath_vid_delete( struct __vxge_hw_vpath_handle *vpath_handle, u64 vid); @@ -2387,16 +2280,9 @@ vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vpath_handle, void vxge_hw_device_flush_io(struct __vxge_hw_device *devh); void -vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vpath_handle, - int msix_id); - -void vxge_hw_vpath_msix_unmask(struct __vxge_hw_vpath_handle *vpath_handle, int msix_id); -void -vxge_hw_vpath_msix_mask_all(struct __vxge_hw_vpath_handle *vpath_handle); - enum vxge_hw_status vxge_hw_vpath_intr_enable( struct __vxge_hw_vpath_handle *vpath_handle); @@ -2415,12 +2301,6 @@ vxge_hw_channel_msix_mask(struct __vxge_hw_channel *channelh, int msix_id); void vxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channelh, int msix_id); -enum vxge_hw_status -vxge_hw_channel_dtr_alloc(struct __vxge_hw_channel *channel, void **dtrh); - -void -vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, void *dtrh); - void vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel, void **dtrh); @@ -2436,18 +2316,4 @@ vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel); void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id); -/* ========================== PRIVATE API ================================= */ - -enum vxge_hw_status -__vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev); - -enum vxge_hw_status -__vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev); - -enum vxge_hw_status -__vxge_hw_device_handle_error( - struct __vxge_hw_device *hldev, - u32 vp_id, - enum vxge_hw_event type); - #endif diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index 4604de09a8b2..6452c5055a63 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c @@ -54,7 +54,7 @@ int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) { - __le32 buf[2] = { + const __le32 buf[2] = { cpu_to_le32(reg), cpu_to_le32(val), }; diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 5dbb5361fd51..d3be6f9816b5 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -161,8 +161,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); if (unlikely(!aru)) { dev_kfree_skb_irq(skb); @@ -219,8 +218,7 @@ free: static void ar9170_usb_rx_completed(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int err; if (!aru) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 501050c0296f..26bdbeee424f 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -104,6 +104,11 @@ enum ath_cipher { ATH_CIPHER_MIC = 127 }; +enum ath_drv_info { + AR7010_DEVICE = BIT(0), + AR9287_DEVICE = BIT(1), +}; + /** * struct ath_ops - Register read/write operations * @@ -147,6 +152,7 @@ struct ath_common { u8 rx_chainmask; u32 rx_bufsize; + u32 driver_info; u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); @@ -162,6 +168,8 @@ struct ath_common { struct ath_regulatory regulatory; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; + + bool btcoex_enabled; }; struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index eb83b7b4d0e3..e0793319389d 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,9 +1,12 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 + depends on (PCI || ATHEROS_AR231X) && MAC80211 select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS + select AVERAGE + select ATH5K_AHB if (ATHEROS_AR231X && !PCI) + select ATH5K_PCI if (!ATHEROS_AR231X && PCI) ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. @@ -37,3 +40,16 @@ config ATH5K_DEBUG modprobe ath5k debug=0x00000400 +config ATH5K_AHB + bool "Atheros 5xxx AHB bus support" + depends on (ATHEROS_AR231X && !PCI) + ---help--- + This adds support for WiSoC type chipsets of the 5xxx Atheros + family. + +config ATH5K_PCI + bool "Atheros 5xxx PCI bus support" + depends on (!ATHEROS_AR231X && PCI) + ---help--- + This adds support for PCI type chipsets of the 5xxx Atheros + family. diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 2242a140e4fe..67dd9fd0650e 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -15,4 +15,6 @@ ath5k-y += rfkill.o ath5k-y += ani.o ath5k-y += sysfs.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o +ath5k-$(CONFIG_ATH5K_AHB) += ahb.o +ath5k-$(CONFIG_ATH5K_PCI) += pci.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c new file mode 100644 index 000000000000..707cde149248 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> + * + * 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/nl80211.h> +#include <linux/platform_device.h> +#include <ar231x_platform.h> +#include "ath5k.h" +#include "debug.h" +#include "base.h" +#include "reg.h" +#include "debug.h" + +/* return bus cachesize in 4B word units */ +static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz) +{ + *csz = L1_CACHE_BYTES >> 2; +} + +bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) +{ + struct ath5k_softc *sc = common->priv; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + u16 *eeprom, *eeprom_end; + + + + bcfg = pdev->dev.platform_data; + eeprom = (u16 *) bcfg->radio; + eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ; + + eeprom += off; + if (eeprom > eeprom_end) + return -EINVAL; + + *data = *eeprom; + return 0; +} + +int ath5k_hw_read_srev(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + ah->ah_mac_srev = bcfg->devid; + return 0; +} + +static const struct ath_bus_ops ath_ahb_bus_ops = { + .ath_bus_type = ATH_AHB, + .read_cachesize = ath5k_ahb_read_cachesize, + .eeprom_read = ath5k_ahb_eeprom_read, +}; + +/*Initialization*/ +static int ath_ahb_probe(struct platform_device *pdev) +{ + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + struct ath5k_softc *sc; + struct ieee80211_hw *hw; + struct resource *res; + void __iomem *mem; + int irq; + int ret = 0; + u32 reg; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "no platform data specified\n"); + ret = -EINVAL; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource found\n"); + ret = -ENXIO; + goto err_out; + } + + mem = ioremap_nocache(res->start, res->end - res->start + 1); + if (mem == NULL) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + ret = -ENXIO; + goto err_out; + } + + irq = res->start; + + hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); + ret = -ENOMEM; + goto err_out; + } + + sc = hw->priv; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->iobase = mem; + sc->irq = irq; + sc->devid = bcfg->devid; + + if (bcfg->devid >= AR5K_SREV_AR2315_R6) { + /* Enable WMAC AHB arbitration */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + + /* Enable global WMAC swapping */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP); + reg |= AR5K_AR2315_BYTESWAP_WMAC; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP); + } else { + /* Enable WMAC DMA access (assuming 5312 or 231x*/ + /* TODO: check other platforms */ + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); + if (to_platform_device(sc->dev)->id == 0) + reg |= AR5K_AR5312_ENABLE_WLAN0; + else + reg |= AR5K_AR5312_ENABLE_WLAN1; + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + } + + ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); + if (ret != 0) { + dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); + ret = -ENODEV; + goto err_free_hw; + } + + platform_set_drvdata(pdev, hw); + + return 0; + + err_free_hw: + ieee80211_free_hw(hw); + platform_set_drvdata(pdev, NULL); + err_out: + return ret; +} + +static int ath_ahb_remove(struct platform_device *pdev) +{ + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + struct ieee80211_hw *hw = platform_get_drvdata(pdev); + struct ath5k_softc *sc; + u32 reg; + + if (!hw) + return 0; + + sc = hw->priv; + + if (bcfg->devid >= AR5K_SREV_AR2315_R6) { + /* Disable WMAC AHB arbitration */ + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN; + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + } else { + /*Stop DMA access */ + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); + if (to_platform_device(sc->dev)->id == 0) + reg &= ~AR5K_AR5312_ENABLE_WLAN0; + else + reg &= ~AR5K_AR5312_ENABLE_WLAN1; + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + } + + ath5k_deinit_softc(sc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ath_ahb_driver = { + .probe = ath_ahb_probe, + .remove = ath_ahb_remove, + .driver = { + .name = "ar231x-wmac", + .owner = THIS_MODULE, + }, +}; + +static int __init +ath5k_ahb_init(void) +{ + return platform_driver_register(&ath_ahb_driver); +} + +static void __exit +ath5k_ahb_exit(void) +{ + platform_driver_unregister(&ath_ahb_driver); +} + +module_init(ath5k_ahb_init); +module_exit(ath5k_ahb_exit); diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index f1419198a479..f915f404302d 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -58,20 +58,20 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) { /* TODO: * ANI documents suggest the following five levels to use, but the HAL - * and ath9k use only use the last two levels, making this + * and ath9k use only the last two levels, making this * essentially an on/off option. There *may* be a reason for this (???), * so i stick with the HAL version for now... */ #if 0 - const s8 hi[] = { -18, -18, -16, -14, -12 }; - const s8 lo[] = { -52, -56, -60, -64, -70 }; - const s8 sz[] = { -34, -41, -48, -55, -62 }; - const s8 fr[] = { -70, -72, -75, -78, -80 }; + static const s8 lo[] = { -52, -56, -60, -64, -70 }; + static const s8 hi[] = { -18, -18, -16, -14, -12 }; + static const s8 sz[] = { -34, -41, -48, -55, -62 }; + static const s8 fr[] = { -70, -72, -75, -78, -80 }; #else - const s8 sz[] = { -55, -62 }; - const s8 lo[] = { -64, -70 }; - const s8 hi[] = { -14, -12 }; - const s8 fr[] = { -78, -80 }; + static const s8 lo[] = { -64, -70 }; + static const s8 hi[] = { -14, -12 }; + static const s8 sz[] = { -55, -62 }; + static const s8 fr[] = { -78, -80 }; #endif if (level < 0 || level >= ARRAY_SIZE(sz)) { ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", @@ -102,7 +102,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) { - const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; if (level < 0 || level >= ARRAY_SIZE(val) || level > ah->ah_sc->ani_state.max_spur_level) { @@ -127,7 +127,7 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) { - const int val[] = { 0, 4, 8 }; + static const int val[] = { 0, 4, 8 }; if (level < 0 || level >= ARRAY_SIZE(val)) { ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); @@ -151,12 +151,12 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) { - const int m1l[] = { 127, 50 }; - const int m2l[] = { 127, 40 }; - const int m1[] = { 127, 0x4d }; - const int m2[] = { 127, 0x40 }; - const int m2cnt[] = { 31, 16 }; - const int m2lcnt[] = { 63, 48 }; + static const int m1l[] = { 127, 50 }; + static const int m2l[] = { 127, 40 }; + static const int m1[] = { 127, 0x4d }; + static const int m2[] = { 127, 0x40 }; + static const int m2cnt[] = { 31, 16 }; + static const int m2lcnt[] = { 63, 48 }; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); @@ -192,7 +192,7 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) { - const int val[] = { 8, 6 }; + static const int val[] = { 8, 6 }; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); ah->ah_sc->ani_state.cck_weak_sig = on; @@ -216,7 +216,7 @@ static void ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, bool ofdm_trigger) { - int rssi = ah->ah_beacon_rssi_avg.avg; + int rssi = ewma_read(&ah->ah_beacon_rssi_avg); ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", ofdm_trigger ? "ODFM" : "CCK"); @@ -301,7 +301,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, static void ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) { - int rssi = ah->ah_beacon_rssi_avg.avg; + int rssi = ewma_read(&ah->ah_beacon_rssi_avg); ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 308b79e1ff08..d6e744088bc6 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -25,6 +25,7 @@ #include <linux/io.h> #include <linux/types.h> +#include <linux/average.h> #include <net/mac80211.h> /* RX/TX descriptor hw structs @@ -157,15 +158,6 @@ #define AR5K_INI_RFGAIN_5GHZ 0 #define AR5K_INI_RFGAIN_2GHZ 1 -/* TODO: Clean this up */ -#define AR5K_INI_VAL_11A 0 -#define AR5K_INI_VAL_11A_TURBO 1 -#define AR5K_INI_VAL_11B 2 -#define AR5K_INI_VAL_11G 3 -#define AR5K_INI_VAL_11G_TURBO 4 -#define AR5K_INI_VAL_XR 0 -#define AR5K_INI_VAL_MAX 5 - /* * Some tuneable values (these should be changeable by the user) * TODO: Make use of them and add more options OR use debug/configfs @@ -221,42 +213,66 @@ /* Initial values */ #define AR5K_INIT_CYCRSSI_THR1 2 -#define AR5K_INIT_TX_LATENCY 502 -#define AR5K_INIT_USEC 39 -#define AR5K_INIT_USEC_TURBO 79 -#define AR5K_INIT_USEC_32 31 -#define AR5K_INIT_SLOT_TIME 396 -#define AR5K_INIT_SLOT_TIME_TURBO 480 -#define AR5K_INIT_ACK_CTS_TIMEOUT 1024 -#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 -#define AR5K_INIT_PROG_IFS 920 -#define AR5K_INIT_PROG_IFS_TURBO 960 -#define AR5K_INIT_EIFS 3440 -#define AR5K_INIT_EIFS_TURBO 6880 -#define AR5K_INIT_SIFS 560 -#define AR5K_INIT_SIFS_TURBO 480 + +/* Tx retry limits */ #define AR5K_INIT_SH_RETRY 10 #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY +/* For station mode */ #define AR5K_INIT_SSH_RETRY 32 #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY #define AR5K_INIT_TX_RETRY 10 -#define AR5K_INIT_TRANSMIT_LATENCY ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC) \ -) -#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC_TURBO) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ - (AR5K_INIT_PROG_IFS) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ - (AR5K_INIT_PROG_IFS_TURBO) \ -) + +/* Slot time */ +#define AR5K_INIT_SLOT_TIME_TURBO 6 +#define AR5K_INIT_SLOT_TIME_DEFAULT 9 +#define AR5K_INIT_SLOT_TIME_HALF_RATE 13 +#define AR5K_INIT_SLOT_TIME_QUARTER_RATE 21 +#define AR5K_INIT_SLOT_TIME_B 20 +#define AR5K_SLOT_TIME_MAX 0xffff + +/* SIFS */ +#define AR5K_INIT_SIFS_TURBO 6 +/* XXX: 8 from initvals 10 from standard */ +#define AR5K_INIT_SIFS_DEFAULT_BG 8 +#define AR5K_INIT_SIFS_DEFAULT_A 16 +#define AR5K_INIT_SIFS_HALF_RATE 32 +#define AR5K_INIT_SIFS_QUARTER_RATE 64 + +/* Used to calculate tx time for non 5/10/40MHz + * operation */ +/* It's preamble time + signal time (16 + 4) */ +#define AR5K_INIT_OFDM_PREAMPLE_TIME 20 +/* Preamble time for 40MHz (turbo) operation (min ?) */ +#define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14 +#define AR5K_INIT_OFDM_SYMBOL_TIME 4 +#define AR5K_INIT_OFDM_PLCP_BITS 22 + +/* Rx latency for 5 and 10MHz operation (max ?) */ +#define AR5K_INIT_RX_LAT_MAX 63 +/* Tx latencies from initvals (5212 only but no problem + * because we only tweak them on 5212) */ +#define AR5K_INIT_TX_LAT_A 54 +#define AR5K_INIT_TX_LAT_BG 384 +/* Tx latency for 40MHz (turbo) operation (min ?) */ +#define AR5K_INIT_TX_LAT_MIN 32 +/* Default Tx/Rx latencies (same for 5211)*/ +#define AR5K_INIT_TX_LATENCY_5210 54 +#define AR5K_INIT_RX_LATENCY_5210 29 + +/* Tx frame to Tx data start delay */ +#define AR5K_INIT_TXF2TXD_START_DEFAULT 14 +#define AR5K_INIT_TXF2TXD_START_DELAY_10MHZ 12 +#define AR5K_INIT_TXF2TXD_START_DELAY_5MHZ 13 + +/* We need to increase PHY switch and agc settling time + * on turbo mode */ +#define AR5K_SWITCH_SETTLING 5760 +#define AR5K_SWITCH_SETTLING_TURBO 7168 + +#define AR5K_AGC_SETTLING 28 +/* 38 on 5210 but shouldn't matter */ +#define AR5K_AGC_SETTLING_TURBO 37 /* GENERIC CHIPSET DEFINITIONS */ @@ -303,12 +319,19 @@ struct ath5k_srev_name { #define AR5K_SREV_AR5311B 0x30 /* Spirit */ #define AR5K_SREV_AR5211 0x40 /* Oahu */ #define AR5K_SREV_AR5212 0x50 /* Venice */ +#define AR5K_SREV_AR5312_R2 0x52 /* AP31 */ #define AR5K_SREV_AR5212_V4 0x54 /* ??? */ #define AR5K_SREV_AR5213 0x55 /* ??? */ +#define AR5K_SREV_AR5312_R7 0x57 /* AP30 */ +#define AR5K_SREV_AR2313_R8 0x58 /* AP43 */ #define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ #define AR5K_SREV_AR2414 0x70 /* Griffin */ +#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ +#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ #define AR5K_SREV_AR5424 0x90 /* Condor */ +#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ +#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ #define AR5K_SREV_AR5414 0xa0 /* Eagle */ #define AR5K_SREV_AR2415 0xb0 /* Talon */ @@ -404,12 +427,10 @@ struct ath5k_srev_name { enum ath5k_driver_mode { AR5K_MODE_11A = 0, - AR5K_MODE_11A_TURBO = 1, - AR5K_MODE_11B = 2, - AR5K_MODE_11G = 3, - AR5K_MODE_11G_TURBO = 4, + AR5K_MODE_11B = 1, + AR5K_MODE_11G = 2, AR5K_MODE_XR = 0, - AR5K_MODE_MAX = 5 + AR5K_MODE_MAX = 3 }; enum ath5k_ant_mode { @@ -423,6 +444,12 @@ enum ath5k_ant_mode { AR5K_ANTMODE_MAX, }; +enum ath5k_bw_mode { + AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ + AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ + AR5K_BWMODE_10MHZ = 2, /* Half rate */ + AR5K_BWMODE_40MHZ = 3 /* Turbo */ +}; /****************\ TX DEFINITIONS @@ -655,7 +682,6 @@ struct ath5k_gain { /* channel_flags */ #define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ -#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ #define CHANNEL_CCK 0x0020 /* CCK channel */ #define CHANNEL_OFDM 0x0040 /* OFDM channel */ #define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ @@ -667,16 +693,10 @@ struct ath5k_gain { #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_108A CHANNEL_T -#define CHANNEL_108G CHANNEL_TG #define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) -#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ - CHANNEL_TURBO) +#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ) -#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) #define CHANNEL_MODES CHANNEL_ALL /* @@ -1025,7 +1045,6 @@ struct ath5k_hw { enum ath5k_int ah_imr; struct ieee80211_channel *ah_current_channel; - bool ah_turbo; bool ah_calibration; bool ah_single_chip; @@ -1034,6 +1053,7 @@ struct ath5k_hw { u32 ah_phy; u32 ah_mac_srev; u16 ah_mac_version; + u16 ah_mac_revision; u16 ah_phy_revision; u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision; @@ -1043,6 +1063,8 @@ struct ath5k_hw { u32 ah_limit_tx_retries; u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; /* Antenna Control */ u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; @@ -1102,7 +1124,7 @@ struct ath5k_hw { struct ath5k_nfcal_hist ah_nfcal_hist; /* average beacon RSSI in our BSS (used by ANI) */ - struct ath5k_avg_val ah_beacon_rssi_avg; + struct ewma ah_beacon_rssi_avg; /* noise floor from last periodic calibration */ s32 ah_noise_floor; @@ -1131,36 +1153,50 @@ struct ath5k_hw { /* * Prototypes */ +extern const struct ieee80211_ops ath5k_hw_ops; -/* Attach/Detach Functions */ -int ath5k_hw_attach(struct ath5k_softc *sc); -void ath5k_hw_detach(struct ath5k_hw *ah); +/* Initialization and detach functions */ +int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); +void ath5k_deinit_softc(struct ath5k_softc *sc); +int ath5k_hw_init(struct ath5k_softc *sc); +void ath5k_hw_deinit(struct ath5k_hw *ah); int ath5k_sysfs_register(struct ath5k_softc *sc); void ath5k_sysfs_unregister(struct ath5k_softc *sc); +/*Chip id helper functions */ +const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); +int ath5k_hw_read_srev(struct ath5k_hw *ah); + /* LED functions */ int ath5k_init_leds(struct ath5k_softc *sc); void ath5k_led_enable(struct ath5k_softc *sc); void ath5k_led_off(struct ath5k_softc *sc); void ath5k_unregister_leds(struct ath5k_softc *sc); + /* Reset Functions */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); int ath5k_hw_on_hold(struct ath5k_hw *ah); int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel); + struct ieee80211_channel *channel, bool fast, bool skip_pcu); int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set); /* Power management functions */ + +/* Clock rate related functions */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); +void ath5k_hw_set_clockrate(struct ath5k_hw *ah); + + /* DMA Related Functions */ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); +int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); +int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue); u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr); @@ -1170,38 +1206,43 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); +/* Init/Stop functions */ +void ath5k_hw_dma_init(struct ath5k_hw *ah); +int ath5k_hw_dma_stop(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); void ath5k_eeprom_detach(struct ath5k_hw *ah); int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); + /* Protocol Control Unit Functions */ +/* Helpers */ +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, + int len, struct ieee80211_rate *rate); +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); -/* BSSID Functions */ +/* RX filter control*/ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); void ath5k_hw_set_bssid(struct ath5k_hw *ah); void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); -/* Receive start/stop functions */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); -/* RX Filter functions */ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); +/* Receive (DRU) start/stop functions */ +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); /* Beacon control functions */ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); -/* ACK bit rate */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); -/* Clock rate related functions */ -unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); -unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); -void ath5k_hw_set_clockrate(struct ath5k_hw *ah); +/* Init function */ +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode); /* Queue Control Unit, DFS Control Unit Functions */ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, @@ -1214,7 +1255,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time); +/* Init function */ +int ath5k_hw_init_queues(struct ath5k_hw *ah); /* Hardware Descriptor Functions */ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); @@ -1224,6 +1267,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); + /* GPIO Functions */ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); @@ -1233,11 +1277,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); -/* rfkill Functions */ + +/* RFkill Functions */ void ath5k_rfkill_hw_start(struct ath5k_hw *ah); void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); -/* Misc functions */ + +/* Misc functions TODO: Cleanup */ int ath5k_hw_set_capabilities(struct ath5k_hw *ah); int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, @@ -1245,19 +1291,20 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); + /* Initial register settings functions */ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); -/* Initialize RF */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode); -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); + +/* PHY functions */ +/* Misc PHY functions */ +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); +int ath5k_hw_phy_disable(struct ath5k_hw *ah); +/* Gain_F optimization */ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); /* PHY/RF channel functions */ bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); /* PHY calibration */ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, @@ -1266,18 +1313,14 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, struct ieee80211_channel *channel); -void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, - struct ieee80211_channel *channel); -/* Misc PHY functions */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* Antenna control */ void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); /* TX power setup */ -int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower); int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); +/* Init function */ +int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 mode, u8 ee_mode, u8 freq, bool fast); /* * Functions used internaly @@ -1293,6 +1336,32 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) return &(ath5k_hw_common(ah)->regulatory); } +#ifdef CONFIG_ATHEROS_AR231X +#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000) + +static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg) +{ + /* On AR2315 and AR2317 the PCI clock domain registers + * are outside of the WMAC register space */ + if (unlikely((reg >= 0x4000) && (reg < 0x5000) && + (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6))) + return AR5K_AR2315_PCI_BASE + reg; + + return ah->ah_iobase + reg; +} + +static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) +{ + return __raw_readl(ath5k_ahb_reg(ah, reg)); +} + +static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) +{ + __raw_writel(val, ath5k_ahb_reg(ah, reg)); +} + +#else + static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) { return ioread32(ah->ah_iobase + reg); @@ -1303,6 +1372,24 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) iowrite32(val, ah->ah_iobase + reg); } +#endif + +static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah) +{ + return ath5k_hw_common(ah)->bus_ops->ath_bus_type; +} + +static inline void ath5k_read_cachesize(struct ath_common *common, int *csz) +{ + common->bus_ops->read_cachesize(common, csz); +} + +static inline bool ath5k_hw_nvram_read(struct ath5k_hw *ah, u32 off, u16 *data) +{ + struct ath_common *common = ath5k_hw_common(ah); + return common->bus_ops->eeprom_read(common, off, data); +} + static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) { u32 retval = 0, bit, i; @@ -1315,27 +1402,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) return retval; } -#define AVG_SAMPLES 8 -#define AVG_FACTOR 1000 - -/** - * ath5k_moving_average - Exponentially weighted moving average - * @avg: average structure - * @val: current value - * - * This implementation make use of a struct ath5k_avg_val to prevent rounding - * errors. - */ -static inline struct ath5k_avg_val -ath5k_moving_average(const struct ath5k_avg_val avg, const int val) -{ - struct ath5k_avg_val new; - new.avg_weight = avg.avg_weight ? - (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + - (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : - (val * (AVG_FACTOR)); - new.avg = new.avg_weight / (AVG_FACTOR); - return new; -} - #endif diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index fbe8aca975d8..9dbc1fa81795 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -93,16 +93,16 @@ static int ath5k_hw_post(struct ath5k_hw *ah) } /** - * ath5k_hw_attach - Check if hw is supported and init the needed structs + * ath5k_hw_init - Check if hw is supported and init the needed structs * - * @sc: The &struct ath5k_softc we got from the driver's attach function + * @sc: The &struct ath5k_softc we got from the driver's init_softc function * * Check if the device is supported, perform a POST and initialize the needed * structs. Returns -ENOMEM if we don't have memory for the needed structs, * -ENODEV if the device is not supported or prints an error msg if something * else went wrong. */ -int ath5k_hw_attach(struct ath5k_softc *sc) +int ath5k_hw_init(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -115,7 +115,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) * HW information */ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; - ah->ah_turbo = false; + ah->ah_bwmode = AR5K_BWMODE_DEFAULT; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; ah->ah_imr = 0; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; @@ -128,7 +128,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * Find the mac version */ - srev = ath5k_hw_reg_read(ah, AR5K_SREV); + ath5k_hw_read_srev(ah); + srev = ah->ah_mac_srev; if (srev < AR5K_SREV_AR5311) ah->ah_version = AR5K_AR5210; else if (srev < AR5K_SREV_AR5212) @@ -136,6 +137,10 @@ int ath5k_hw_attach(struct ath5k_softc *sc) else ah->ah_version = AR5K_AR5212; + /* Get the MAC revision */ + ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); + ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); + /* Fill the ath5k_hw struct with the needed functions */ ret = ath5k_hw_init_desc_functions(ah); if (ret) @@ -146,9 +151,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) if (ret) goto err; - /* Get MAC, PHY and RADIO revisions */ - ah->ah_mac_srev = srev; - ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); + /* Get PHY and RADIO revisions */ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 0xffffffff; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, @@ -273,7 +276,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* * Write PCI-E power save settings */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { + if ((ah->ah_version == AR5K_AR5212) && pdev && (pdev->is_pcie)) { ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); @@ -305,8 +308,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) /* Get misc capabilities */ ret = ath5k_hw_set_capabilities(ah); if (ret) { - ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", - sc->pdev->device); + ATH5K_ERR(sc, "unable to get device capabilities\n"); goto err; } @@ -346,11 +348,11 @@ err: } /** - * ath5k_hw_detach - Free the ath5k_hw struct + * ath5k_hw_deinit - Free the ath5k_hw struct * * @ah: The &struct ath5k_hw */ -void ath5k_hw_detach(struct ath5k_hw *ah) +void ath5k_hw_deinit(struct ath5k_hw *ah) { __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8251946842e6..0a7071a6dd7a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -47,8 +47,6 @@ #include <linux/io.h> #include <linux/netdevice.h> #include <linux/cache.h> -#include <linux/pci.h> -#include <linux/pci-aspm.h> #include <linux/ethtool.h> #include <linux/uaccess.h> #include <linux/slab.h> @@ -80,37 +78,24 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); +static int ath5k_init(struct ieee80211_hw *hw); +static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu); static int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); -/* Known PCI ids */ -static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { - { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); - /* Known SREVs */ static const struct ath5k_srev_name srev_names[] = { +#ifdef CONFIG_ATHEROS_AR231X + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 }, + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 }, + { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 }, +#else { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, @@ -129,6 +114,7 @@ static const struct ath5k_srev_name srev_names[] = { { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, +#endif { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, @@ -142,10 +128,12 @@ static const struct ath5k_srev_name srev_names[] = { { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, - { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, - { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, +#ifdef CONFIG_ATHEROS_AR231X + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, +#endif { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, }; @@ -197,8 +185,8 @@ static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, BUG_ON(!bf); if (!bf->skb) return; - pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, - PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; bf->skbaddr = 0; @@ -214,8 +202,8 @@ static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, BUG_ON(!bf); if (!bf->skb) return; - pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, + DMA_FROM_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; bf->skbaddr = 0; @@ -233,7 +221,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) return (tsf & ~0x7fff) | rstamp; } -static const char * +const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) { const char *name = "xxxxx"; @@ -327,14 +315,12 @@ ath5k_copy_channels(struct ath5k_hw *ah, switch (mode) { case AR5K_MODE_11A: - case AR5K_MODE_11A_TURBO: /* 1..220, but 2GHz frequencies are filtered by check_channel */ size = 220 ; chfreq = CHANNEL_5GHZ; break; case AR5K_MODE_11B: case AR5K_MODE_11G: - case AR5K_MODE_11G_TURBO: size = 26; chfreq = CHANNEL_2GHZ; break; @@ -363,11 +349,6 @@ ath5k_copy_channels(struct ath5k_hw *ah, case AR5K_MODE_11G: channels[count].hw_value = chfreq | CHANNEL_OFDM; break; - case AR5K_MODE_11A_TURBO: - case AR5K_MODE_11G_TURBO: - channels[count].hw_value = chfreq | - CHANNEL_OFDM | CHANNEL_TURBO; - break; case AR5K_MODE_11B: channels[count].hw_value = CHANNEL_B; } @@ -496,7 +477,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - return ath5k_reset(sc, chan); + return ath5k_reset(sc, chan, true); } static void @@ -549,7 +530,7 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) /* Calculate combined mode - when APs are active, operate in AP mode. * Otherwise use the mode of the new interface. This can currently * only deal with combinations of APs and STAs. Only one ad-hoc - * interfaces is allowed above. + * interfaces is allowed. */ if (avf->opmode == NL80211_IFTYPE_AP) iter_data->opmode = NL80211_IFTYPE_AP; @@ -558,16 +539,8 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) iter_data->opmode = avf->opmode; } -static void ath_do_set_opmode(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - ath5k_hw_set_opmode(ah, sc->opmode); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", - sc->opmode, ath_opmode_to_string(sc->opmode)); -} - -void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, - struct ieee80211_vif *vif) +static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, + struct ieee80211_vif *vif) { struct ath_common *common = ath5k_hw_common(sc->ah); struct ath_vif_iter_data iter_data; @@ -595,7 +568,9 @@ void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, /* Nothing active, default to station mode */ sc->opmode = NL80211_IFTYPE_STATION; - ath_do_set_opmode(sc); + ath5k_hw_set_opmode(sc->ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", + sc->opmode, ath_opmode_to_string(sc->opmode)); if (iter_data.need_set_hw_addr && iter_data.found_active) ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); @@ -659,10 +634,11 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) return NULL; } - *skb_addr = pci_map_single(sc->pdev, + *skb_addr = dma_map_single(sc->dev, skb->data, common->rx_bufsize, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { + DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) { ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); dev_kfree_skb(skb); return NULL; @@ -758,8 +734,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; /* XXX endianness */ - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); if (!rate) { @@ -839,7 +815,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -848,7 +824,7 @@ err_unmap: \*******************/ static int -ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_alloc(struct ath5k_softc *sc) { struct ath5k_desc *ds; struct ath5k_buf *bf; @@ -859,7 +835,9 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) /* allocate descriptors */ sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); + + sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len, + &sc->desc_daddr, GFP_KERNEL); if (sc->desc == NULL) { ATH5K_ERR(sc, "can't allocate descriptors\n"); ret = -ENOMEM; @@ -905,14 +883,14 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) return 0; err_free: - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); err: sc->desc = NULL; return ret; } static void -ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_free(struct ath5k_softc *sc) { struct ath5k_buf *bf; @@ -924,7 +902,7 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) ath5k_txbuf_free_skb(sc, bf); /* Free memory associated with all descriptors */ - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); sc->desc = NULL; sc->desc_daddr = 0; @@ -1069,62 +1047,44 @@ err: return ret; } +/** + * ath5k_drain_tx_buffs - Empty tx buffers + * + * @sc The &struct ath5k_softc + * + * Empty tx buffers from all queues in preparation + * of a reset or during shutdown. + * + * NB: this assumes output has been stopped and + * we do not need to block ath5k_tx_tasklet + */ static void -ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) +ath5k_drain_tx_buffs(struct ath5k_softc *sc) { + struct ath5k_txq *txq; struct ath5k_buf *bf, *bf0; + int i; - /* - * NB: this assumes output has been stopped and - * we do not need to block ath5k_tx_tasklet - */ - spin_lock_bh(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); - - ath5k_txbuf_free_skb(sc, bf); + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { + if (sc->txqs[i].setup) { + txq = &sc->txqs[i]; + spin_lock_bh(&txq->lock); + list_for_each_entry_safe(bf, bf0, &txq->q, list) { + ath5k_debug_printtxbuf(sc, bf); - spin_lock_bh(&sc->txbuflock); - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - txq->txq_len--; - spin_unlock_bh(&sc->txbuflock); - } - txq->link = NULL; - txq->txq_poll_mark = false; - spin_unlock_bh(&txq->lock); -} + ath5k_txbuf_free_skb(sc, bf); -/* - * Drain the transmit queues and reclaim resources. - */ -static void -ath5k_txq_cleanup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned int i; - - /* XXX return value */ - if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { - /* don't touch the hardware if marked invalid */ - ath5k_hw_stop_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", - ath5k_hw_get_txdp(ah, sc->bhalq)); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) { - ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " - "link %p\n", - sc->txqs[i].qnum, - ath5k_hw_get_txdp(ah, - sc->txqs[i].qnum), - sc->txqs[i].link); + spin_lock_bh(&sc->txbuflock); + list_move_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + txq->txq_len--; + spin_unlock_bh(&sc->txbuflock); } + txq->link = NULL; + txq->txq_poll_mark = false; + spin_unlock_bh(&txq->lock); + } } - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) - ath5k_txq_drainq(sc, &sc->txqs[i]); } static void @@ -1184,16 +1144,19 @@ err: } /* - * Disable the receive h/w in preparation for a reset. + * Disable the receive logic on PCU (DRU) + * In preparation for a shutdown. + * + * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop + * does. */ static void ath5k_rx_stop(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; - ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ - ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ + ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_debug_printrxbuffs(sc, ah); } @@ -1307,8 +1270,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) return; - ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, - rssi); + ewma_add(&ah->ah_beacon_rssi_avg, rssi); /* in IBSS mode we should keep RSSI statistics per neighbour */ /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ @@ -1551,9 +1513,9 @@ ath5k_tasklet_rx(unsigned long data) if (!next_skb) goto next; - pci_unmap_single(sc->pdev, bf->skbaddr, + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); skb_put(skb, rs.rs_datalen); @@ -1716,8 +1678,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) skb = bf->skb; bf->skb = NULL; - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); + + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, + DMA_TO_DEVICE); ath5k_tx_frame_completed(sc, skb, &ts); } @@ -1771,12 +1734,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) u32 flags; const int padsize = 0; - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " "skbaddr %llx\n", skb, skb->data, skb->len, (unsigned long long)bf->skbaddr); - if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { + + if (dma_mapping_error(sc->dev, bf->skbaddr)) { ATH5K_ERR(sc, "beacon DMA mapping failed\n"); return -EIO; } @@ -1828,7 +1792,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -1944,7 +1908,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) * This should never fail since we check above that no frames * are still pending on the queue. */ - if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { + if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) { ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } @@ -2113,7 +2077,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) } else ath5k_beacon_update_timers(sc, -1); } else { - ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); + ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq); } ath5k_hw_set_imr(ah, sc->imask); @@ -2175,7 +2139,7 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } -static irqreturn_t +irqreturn_t ath5k_intr(int irq, void *dev_id) { struct ath5k_softc *sc = dev_id; @@ -2184,7 +2148,8 @@ ath5k_intr(int irq, void *dev_id) unsigned int counter = 1000; if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || - !ath5k_hw_is_intr_pending(ah))) + ((ath5k_get_bus_type(ah) != ATH_AHB) && + !ath5k_hw_is_intr_pending(ah)))) return IRQ_NONE; do { @@ -2250,6 +2215,10 @@ ath5k_intr(int irq, void *dev_id) tasklet_schedule(&sc->rf_kill.toggleq); } + + if (ath5k_get_bus_type(ah) == ATH_AHB) + break; + } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); if (unlikely(!counter)) @@ -2349,7 +2318,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work) if (needreset) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "TX queues stuck, resetting\n"); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@ -2361,6 +2330,158 @@ ath5k_tx_complete_poll_work(struct work_struct *work) * Initialization routines * \*************************/ +int +ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_common *common; + int ret; + int csz; + + /* Initialize driver private data */ + SET_IEEE80211_DEV(hw, sc->dev); + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->extra_tx_headroom = 2; + hw->channel_change_time = 5000; + + /* + * Mark the device as detached to avoid processing + * interrupts until setup is complete. + */ + __set_bit(ATH_STAT_INVALID, sc->status); + + sc->opmode = NL80211_IFTYPE_STATION; + sc->bintval = 1000; + mutex_init(&sc->lock); + spin_lock_init(&sc->rxbuflock); + spin_lock_init(&sc->txbuflock); + spin_lock_init(&sc->block); + + + /* Setup interrupt handler */ + ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + if (ret) { + ATH5K_ERR(sc, "request_irq failed\n"); + goto err; + } + + /* If we passed the test, malloc an ath5k_hw struct */ + sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); + if (!sc->ah) { + ret = -ENOMEM; + ATH5K_ERR(sc, "out of memory\n"); + goto err_irq; + } + + sc->ah->ah_sc = sc; + sc->ah->ah_iobase = sc->iobase; + common = ath5k_hw_common(sc->ah); + common->ops = &ath5k_common_ops; + common->bus_ops = bus_ops; + common->ah = sc->ah; + common->hw = hw; + common->priv = sc; + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath5k_read_cachesize(common, &csz); + common->cachelsz = csz << 2; /* convert to bytes */ + + spin_lock_init(&common->cc_lock); + + /* Initialize device */ + ret = ath5k_hw_init(sc); + if (ret) + goto err_free_ah; + + /* set up multi-rate retry capabilities */ + if (sc->ah->ah_version == AR5K_AR5212) { + hw->max_rates = 4; + hw->max_rate_tries = 11; + } + + hw->vif_data_size = sizeof(struct ath5k_vif); + + /* Finish private driver data initialization */ + ret = ath5k_init(hw); + if (ret) + goto err_ah; + + ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", + ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), + sc->ah->ah_mac_srev, + sc->ah->ah_phy_revision); + + if (!sc->ah->ah_single_chip) { + /* Single chip radio (!RF5111) */ + if (sc->ah->ah_radio_5ghz_revision && + !sc->ah->ah_radio_2ghz_revision) { + /* No 5GHz support -> report 2GHz radio */ + if (!test_bit(AR5K_MODE_11A, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* No 2GHz support (5110 and some + * 5Ghz only cards) -> report 5Ghz radio */ + } else if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* Multiband radio */ + } else { + ATH5K_INFO(sc, "RF%s multiband radio found" + " (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + } + } + /* Multi chip radio (RF5111 - RF2111) -> + * report both 2GHz/5GHz radios */ + else if (sc->ah->ah_radio_5ghz_revision && + sc->ah->ah_radio_2ghz_revision){ + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_2ghz_revision), + sc->ah->ah_radio_2ghz_revision); + } + } + + ath5k_debug_init_device(sc); + + /* ready to process interrupts */ + __clear_bit(ATH_STAT_INVALID, sc->status); + + return 0; +err_ah: + ath5k_hw_deinit(sc->ah); +err_free_ah: + kfree(sc->ah); +err_irq: + free_irq(sc->irq, sc); +err: + return ret; +} + static int ath5k_stop_locked(struct ath5k_softc *sc) { @@ -2389,11 +2510,10 @@ ath5k_stop_locked(struct ath5k_softc *sc) if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_led_off(sc); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); - } - ath5k_txq_cleanup(sc); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { + synchronize_irq(sc->irq); ath5k_rx_stop(sc); + ath5k_hw_dma_stop(ah); + ath5k_drain_tx_buffs(sc); ath5k_hw_phy_disable(ah); } @@ -2401,7 +2521,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) } static int -ath5k_init(struct ath5k_softc *sc) +ath5k_init_hw(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -2430,7 +2550,7 @@ ath5k_init(struct ath5k_softc *sc) AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; - ret = ath5k_reset(sc, NULL); + ret = ath5k_reset(sc, NULL, false); if (ret) goto done; @@ -2443,7 +2563,9 @@ ath5k_init(struct ath5k_softc *sc) for (i = 0; i < common->keymax; i++) ath_hw_keyreset(common, (u16) i); - ath5k_hw_set_ack_bitrate_high(ah, true); + /* Use higher rates for acks instead of base + * rate */ + ah->ah_ack_bitrate_high = true; for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) sc->bslot[i] = NULL; @@ -2527,7 +2649,8 @@ ath5k_stop_hw(struct ath5k_softc *sc) * This should be called with sc->lock. */ static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) +ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu) { struct ath5k_hw *ah = sc->ah; int ret; @@ -2535,17 +2658,17 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); + synchronize_irq(sc->irq); stop_tasklets(sc); if (chan) { - ath5k_txq_cleanup(sc); - ath5k_rx_stop(sc); + ath5k_drain_tx_buffs(sc); sc->curchan = chan; sc->curband = &sc->sbands[chan->band]; } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; @@ -2562,6 +2685,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ah->ah_cal_next_full = jiffies; ah->ah_cal_next_ani = jiffies; ah->ah_cal_next_nf = jiffies; + ewma_init(&ah->ah_beacon_rssi_avg, 1000, 8); /* * Change channels and update the h/w rate map if we're switching; @@ -2590,13 +2714,14 @@ static void ath5k_reset_work(struct work_struct *work) reset_work); mutex_lock(&sc->lock); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); mutex_unlock(&sc->lock); } static int -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) +ath5k_init(struct ieee80211_hw *hw) { + struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); @@ -2604,7 +2729,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) u8 mac[ETH_ALEN] = {}; int ret; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); /* * Check if the MAC has multi-rate retry support. @@ -2641,7 +2765,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) /* * Allocate tx+rx descriptors and populate the lists. */ - ret = ath5k_desc_alloc(sc, pdev); + ret = ath5k_desc_alloc(sc); if (ret) { ATH5K_ERR(sc, "can't allocate descriptors\n"); goto err; @@ -2705,8 +2829,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", - sc->pdev->device); + ATH5K_ERR(sc, "unable to read address from EEPROM\n"); goto err_queues; } @@ -2741,15 +2864,15 @@ err_queues: err_bhal: ath5k_hw_release_tx_queue(ah, sc->bhalq); err_desc: - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); err: return ret; } -static void -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) +void +ath5k_deinit_softc(struct ath5k_softc *sc) { - struct ath5k_softc *sc = hw->priv; + struct ieee80211_hw *hw = sc->hw; /* * NB: the order of these is important: @@ -2764,8 +2887,9 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) * XXX: ??? detach ath5k_hw ??? * Other than that, it's straightforward... */ + ath5k_debug_finish_device(sc); ieee80211_unregister_hw(hw); - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); ath5k_txq_release(sc); ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); ath5k_unregister_leds(sc); @@ -2776,6 +2900,8 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) * returns because we'll get called back to reclaim node * state and potentially want to use them. */ + ath5k_hw_deinit(sc->ah); + free_irq(sc->irq, sc); } /********************\ @@ -2798,7 +2924,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int ath5k_start(struct ieee80211_hw *hw) { - return ath5k_init(hw->priv); + return ath5k_init_hw(hw->priv); } static void ath5k_stop(struct ieee80211_hw *hw) @@ -3206,14 +3332,32 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, { struct ath5k_softc *sc = hw->priv; struct ieee80211_conf *conf = &hw->conf; + struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_cycle_counters *cc = &common->cc_survey; + unsigned int div = common->clockrate * 1000; - if (idx != 0) + if (idx != 0) return -ENOENT; survey->channel = conf->channel; survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = sc->ah->ah_noise_floor; + spin_lock_bh(&common->cc_lock); + ath_hw_cycle_counters_update(common); + if (cc->cycles > 0) { + survey->filled |= SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | + SURVEY_INFO_CHANNEL_TIME_TX; + survey->channel_time += cc->cycles / div; + survey->channel_time_busy += cc->rx_busy / div; + survey->channel_time_rx += cc->rx_frame / div; + survey->channel_time_tx += cc->tx_frame / div; + } + memset(cc, 0, sizeof(*cc)); + spin_unlock_bh(&common->cc_lock); + return 0; } @@ -3395,7 +3539,37 @@ static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, return ret; } -static const struct ieee80211_ops ath5k_hw_ops = { +static int ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + if (tx_ant == 1 && rx_ant == 1) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + else if (tx_ant == 2 && rx_ant == 2) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + else + return -EINVAL; + return 0; +} + +static int ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + switch (sc->ah->ah_ant_mode) { + case AR5K_ANTMODE_FIXED_A: + *tx_ant = 1; *rx_ant = 1; break; + case AR5K_ANTMODE_FIXED_B: + *tx_ant = 2; *rx_ant = 2; break; + case AR5K_ANTMODE_DEFAULT: + *tx_ant = 3; *rx_ant = 3; break; + } + return 0; +} + +const struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, .start = ath5k_start, .stop = ath5k_stop, @@ -3415,341 +3589,6 @@ static const struct ieee80211_ops ath5k_hw_ops = { .sw_scan_start = ath5k_sw_scan_start, .sw_scan_complete = ath5k_sw_scan_complete, .set_coverage_class = ath5k_set_coverage_class, + .set_antenna = ath5k_set_antenna, + .get_antenna = ath5k_get_antenna, }; - -/********************\ -* PCI Initialization * -\********************/ - -static int __devinit -ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath5k_softc *sc; - struct ath_common *common; - struct ieee80211_hw *hw; - int ret; - u8 csz; - - /* - * L0s needs to be disabled on all ath5k cards. - * - * For distributions shipping with CONFIG_PCIEASPM (this will be enabled - * by default in the future in 2.6.36) this will also mean both L1 and - * L0s will be disabled when a pre 1.1 PCIe device is detected. We do - * know L1 works correctly even for all ath5k pre 1.1 PCIe devices - * though but cannot currently undue the effect of a blacklist, for - * details you can read pcie_aspm_sanity_check() and see how it adjusts - * the device link capability. - * - * It may be possible in the future to implement some PCI API to allow - * drivers to override blacklists for pre 1.1 PCIe but for now it is - * best to accept that both L0s and L1 will be disabled completely for - * distributions shipping with CONFIG_PCIEASPM rather than having this - * issue present. Motivation for adding this new API will be to help - * with power consumption for some of these devices. - */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device\n"); - goto err; - } - - /* XXX 32-bit addressing only */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "32-bit DMA not available\n"); - goto err_dis; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES >> 2; - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_write_config_byte(pdev, 0x41, 0); - - ret = pci_request_region(pdev, 0, "ath5k"); - if (ret) { - dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); - goto err_dis; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; - ret = -EIO; - goto err_reg; - } - - /* - * Allocate hw (mac80211 main struct) - * and hw->priv (driver private data) - */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); - ret = -ENOMEM; - goto err_map; - } - - dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - - /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, &pdev->dev); - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->extra_tx_headroom = 2; - hw->channel_change_time = 5000; - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - - /* - * Mark the device as detached to avoid processing - * interrupts until setup is complete. - */ - __set_bit(ATH_STAT_INVALID, sc->status); - - sc->iobase = mem; /* So we can unmap it on detach */ - sc->opmode = NL80211_IFTYPE_STATION; - sc->bintval = 1000; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - - /* Set private data */ - pci_set_drvdata(pdev, sc); - - /* Setup interrupt handler */ - ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_free; - } - - /* If we passed the test, malloc an ath5k_hw struct */ - sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (!sc->ah) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err_irq; - } - - sc->ah->ah_sc = sc; - sc->ah->ah_iobase = sc->iobase; - common = ath5k_hw_common(sc->ah); - common->ops = &ath5k_common_ops; - common->ah = sc->ah; - common->hw = hw; - common->cachelsz = csz << 2; /* convert to bytes */ - spin_lock_init(&common->cc_lock); - - /* Initialize device */ - ret = ath5k_hw_attach(sc); - if (ret) { - goto err_free_ah; - } - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_rates = 4; - hw->max_rate_tries = 11; - } - - hw->vif_data_size = sizeof(struct ath5k_vif); - - /* Finish private driver data initialization */ - ret = ath5k_attach(pdev, hw); - if (ret) - goto err_ah; - - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); - - if (!sc->ah->ah_single_chip) { - /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { - /* No 5GHz support -> report 2GHz radio */ - if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ - } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* Multiband radio */ - } else { - ATH5K_INFO(sc, "RF%s multiband radio found" - " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - } - } - /* Multi chip radio (RF5111 - RF2111) -> - * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); - } - } - - ath5k_debug_init_device(sc); - - /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); - - return 0; -err_ah: - ath5k_hw_detach(sc->ah); -err_free_ah: - kfree(sc->ah); -err_irq: - free_irq(pdev->irq, sc); -err_free: - ieee80211_free_hw(hw); -err_map: - pci_iounmap(pdev, mem); -err_reg: - pci_release_region(pdev, 0); -err_dis: - pci_disable_device(pdev); -err: - return ret; -} - -static void __devexit -ath5k_pci_remove(struct pci_dev *pdev) -{ - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - ath5k_debug_finish_device(sc); - ath5k_detach(pdev, sc->hw); - ath5k_hw_detach(sc->ah); - kfree(sc->ah); - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->iobase); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(sc->hw); -} - -#ifdef CONFIG_PM_SLEEP -static int ath5k_pci_suspend(struct device *dev) -{ - struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); - - ath5k_led_off(sc); - return 0; -} - -static int ath5k_pci_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_write_config_byte(pdev, 0x41, 0); - - ath5k_led_enable(sc); - return 0; -} - -static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); -#define ATH5K_PM_OPS (&ath5k_pm_ops) -#else -#define ATH5K_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - -static struct pci_driver ath5k_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = ath5k_pci_id_table, - .probe = ath5k_pci_probe, - .remove = __devexit_p(ath5k_pci_remove), - .driver.pm = ATH5K_PM_OPS, -}; - -/* - * Module init/exit functions - */ -static int __init -init_ath5k_pci(void) -{ - int ret; - - ret = pci_register_driver(&ath5k_pci_driver); - if (ret) { - printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); - return ret; - } - - return 0; -} - -static void __exit -exit_ath5k_pci(void) -{ - pci_unregister_driver(&ath5k_pci_driver); -} - -module_init(init_ath5k_pci); -module_exit(exit_ath5k_pci); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 9a79773cdc2a..aa6c32aafb59 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -169,7 +169,10 @@ struct ath5k_vif { /* Software Carrier, keeps track of the driver state * associated with an instance of a device */ struct ath5k_softc { - struct pci_dev *pdev; /* for dma mapping */ + struct pci_dev *pdev; + struct device *dev; /* for dma mapping */ + int irq; + u16 devid; void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ struct ieee80211_hw *hw; /* IEEE 802.11 common */ diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index beae519aa735..31cad80e9b01 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -49,7 +49,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) /* Set supported modes */ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); } else { /* * XXX The tranceiver supports frequencies from 4920 to 6100GHz @@ -74,11 +73,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) /* Set supported modes */ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, - ah->ah_capabilities.cap_mode); - if (ah->ah_version == AR5K_AR5212) - __set_bit(AR5K_MODE_11G_TURBO, - ah->ah_capabilities.cap_mode); } /* Enable 802.11b if a 2GHz capable radio (2111/5112) is diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index acda56ee521b..5341dd2860d3 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -312,6 +312,7 @@ static const struct { { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, + { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, { ATH5K_DEBUG_DESC, "desc", "descriptor chains" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, @@ -554,63 +555,63 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, "RX\n---------------------\n"); - len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n", st->rxerr_crc, st->rx_all_count > 0 ? st->rxerr_crc*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n", st->rxerr_phy, st->rx_all_count > 0 ? st->rxerr_phy*100/st->rx_all_count : 0); for (i = 0; i < 32; i++) { if (st->rxerr_phy_code[i]) len += snprintf(buf+len, sizeof(buf)-len, - " phy_err[%d]\t%d\n", + " phy_err[%u]\t%u\n", i, st->rxerr_phy_code[i]); } - len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", st->rxerr_fifo, st->rx_all_count > 0 ? st->rxerr_fifo*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n", st->rxerr_decrypt, st->rx_all_count > 0 ? st->rxerr_decrypt*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n", st->rxerr_mic, st->rx_all_count > 0 ? st->rxerr_mic*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n", st->rxerr_proc, st->rx_all_count > 0 ? st->rxerr_proc*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n", st->rxerr_jumbo, st->rx_all_count > 0 ? st->rxerr_jumbo*100/st->rx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", + len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n", st->rx_all_count); - len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n", + len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n", st->rx_bytes_count); len += snprintf(buf+len, sizeof(buf)-len, "\nTX\n---------------------\n"); - len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n", st->txerr_retry, st->tx_all_count > 0 ? st->txerr_retry*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", st->txerr_fifo, st->tx_all_count > 0 ? st->txerr_fifo*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", + len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n", st->txerr_filt, st->tx_all_count > 0 ? st->txerr_filt*100/st->tx_all_count : 0); - len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", + len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n", st->tx_all_count); - len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n", + len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n", st->tx_bytes_count); if (len > sizeof(buf)) @@ -719,7 +720,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, st->mib_intr); len += snprintf(buf+len, sizeof(buf)-len, "beacon RSSI average:\t%d\n", - sc->ah->ah_beacon_rssi_avg.avg); + (int)ewma_read(&sc->ah->ah_beacon_rssi_avg)); #define CC_PRINT(_struct, _field) \ _struct._field, \ diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 236edbd2507d..3e34428d5126 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -95,6 +95,7 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_DUMP_RX: print received skb content * @ATH5K_DEBUG_DUMP_TX: print transmit skb content * @ATH5K_DEBUG_DUMPBANDS: dump bands + * @ATH5K_DEBUG_DMA: debug dma start/stop * @ATH5K_DEBUG_TRACE: trace function calls * @ATH5K_DEBUG_DESC: descriptor setup * @ATH5K_DEBUG_ANY: show at any debug level @@ -118,6 +119,7 @@ enum ath5k_debug_level { ATH5K_DEBUG_DUMP_RX = 0x00000100, ATH5K_DEBUG_DUMP_TX = 0x00000200, ATH5K_DEBUG_DUMPBANDS = 0x00000400, + ATH5K_DEBUG_DMA = 0x00000800, ATH5K_DEBUG_ANI = 0x00002000, ATH5K_DEBUG_DESC = 0x00004000, ATH5K_DEBUG_ANY = 0xffffffff diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 43244382f213..16b44ff7dd3e 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -26,9 +26,10 @@ #include "debug.h" #include "base.h" -/* - * TX Descriptors - */ + +/************************\ +* TX Control descriptors * +\************************/ /* * Initialize the 2-word tx control descriptor on 5210/5211 @@ -335,6 +336,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, return 0; } + +/***********************\ +* TX Status descriptors * +\***********************/ + /* * Proccess the tx status descriptor on 5210/5211 */ @@ -476,9 +482,10 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, return 0; } -/* - * RX Descriptors - */ + +/****************\ +* RX Descriptors * +\****************/ /* * Initialize an rx control descriptor @@ -666,6 +673,11 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, return 0; } + +/********\ +* Attach * +\********/ + /* * Init function pointers inside ath5k_hw struct */ diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index b2adb2a281c2..2509d0bf037d 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -26,7 +26,7 @@ struct ath5k_hw_rx_ctl { u32 rx_control_0; /* RX control word 0 */ u32 rx_control_1; /* RX control word 1 */ -} __packed; +} __packed __aligned(4); /* RX control word 1 fields/flags */ #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ @@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl { struct ath5k_hw_rx_status { u32 rx_status_0; /* RX status word 0 */ u32 rx_status_1; /* RX status word 1 */ -} __packed; +} __packed __aligned(4); /* 5210/5211 */ /* RX status word 0 fields/flags */ @@ -129,7 +129,7 @@ enum ath5k_phy_error_code { struct ath5k_hw_2w_tx_ctl { u32 tx_control_0; /* TX control word 0 */ u32 tx_control_1; /* TX control word 1 */ -} __packed; +} __packed __aligned(4); /* TX control word 0 fields/flags */ #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ @@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl { u32 tx_control_1; /* TX control word 1 */ u32 tx_control_2; /* TX control word 2 */ u32 tx_control_3; /* TX control word 3 */ -} __packed; +} __packed __aligned(4); /* TX control word 0 fields/flags */ #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ @@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl { struct ath5k_hw_tx_status { u32 tx_status_0; /* TX status word 0 */ u32 tx_status_1; /* TX status word 1 */ -} __packed; +} __packed __aligned(4); /* TX status word 0 fields/flags */ #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ @@ -282,7 +282,7 @@ struct ath5k_hw_tx_status { struct ath5k_hw_5210_tx_desc { struct ath5k_hw_2w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; -} __packed; +} __packed __aligned(4); /* * 5212 hardware TX descriptor @@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc { struct ath5k_hw_5212_tx_desc { struct ath5k_hw_4w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; -} __packed; +} __packed __aligned(4); /* * Common hardware RX descriptor @@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc { struct ath5k_hw_all_rx_desc { struct ath5k_hw_rx_ctl rx_ctl; struct ath5k_hw_rx_status rx_stat; -} __packed; +} __packed __aligned(4); /* * Atheros hardware DMA descriptor @@ -313,7 +313,7 @@ struct ath5k_desc { struct ath5k_hw_5212_tx_desc ds_tx5212; struct ath5k_hw_all_rx_desc ds_rx; } ud; -} __packed; +} __packed __aligned(4); #define AR5K_RXDESC_INTREQ 0x0020 diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 923c9ca5c4f0..82541fec9f0e 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -37,6 +37,7 @@ #include "debug.h" #include "base.h" + /*********\ * Receive * \*********/ @@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) * * @ah: The &struct ath5k_hw */ -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) +static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) { unsigned int i; @@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) for (i = 1000; i > 0 && (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; i--) - udelay(10); + udelay(100); + + if (i) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "failed to stop RX DMA !\n"); return i ? 0 : -EBUSY; } @@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) * @ah: The &struct ath5k_hw * @phys_addr: RX descriptor address * - * XXX: Should we check if rx is enabled before setting rxdp ? + * Returns -EIO if rx is active */ -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) +int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) { + if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "tried to set RXDP while rx was active !\n"); + return -EIO; + } + ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); + return 0; } @@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Return if queue is declared inactive */ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; + return -EINVAL; if (ah->ah_version == AR5K_AR5210) { tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); @@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) * * Stop DMA transmit on a specific hw queue and drain queue so we don't * have any pending frames. Returns -EBUSY if we still have pending frames, - * -EINVAL if queue number is out of range. + * -EINVAL if queue number is out of range or inactive. * */ -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) +static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) { unsigned int i = 40; u32 tx_queue, pending; @@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Return if queue is declared inactive */ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; + return -EINVAL; if (ah->ah_version == AR5K_AR5210) { tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); @@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } else { + + /* + * Enable DCU early termination to quickly + * flush any pending frames from QCU + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + /* * Schedule TX disable and wait until queue is empty */ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); - /*Check for pending frames*/ + /* Wait for queue to stop */ + for (i = 1000; i > 0 && + (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0); + i--) + udelay(100); + + if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "queue %i didn't stop !\n", queue); + + /* Check for pending frames */ + i = 1000; do { pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)) & @@ -247,12 +278,12 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); /* Wait a while and disable mechanism */ - udelay(200); + udelay(400); AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, AR5K_QUIET_CTL1_QT_EN); /* Re-check for pending frames */ - i = 40; + i = 100; do { pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)) & @@ -262,12 +293,27 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); + + if (pending) + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "quiet mechanism didn't work q:%i !\n", + queue); } + /* + * Disable DCU early termination + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); - if (pending) + if (pending) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "tx dma didn't stop (q:%i, frm:%i) !\n", + queue, pending); return -EBUSY; + } } /* TODO: Check for success on 5210 else return error */ @@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) } /** + * ath5k_hw_stop_beacon_queue - Stop beacon queue + * + * @ah The &struct ath5k_hw + * @queue The queue number + * + * Returns -EIO if queue didn't stop + */ +int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) +{ + int ret; + ret = ath5k_hw_stop_tx_dma(ah, queue); + if (ret) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + "beacon queue didn't stop !\n"); + return -EIO; + } + return 0; +} + +/** * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue * * @ah: The &struct ath5k_hw @@ -427,6 +493,7 @@ done: return ret; } + /*******************\ * Interrupt masking * \*******************/ @@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) return old_mask; } + +/********************\ + Init/Stop functions +\********************/ + +/** + * ath5k_hw_dma_init - Initialize DMA unit + * + * @ah: The &struct ath5k_hw + * + * Set DMA size and pre-enable interrupts + * (driver handles tx/rx buffer setup and + * dma start/stop) + * + * XXX: Save/restore RXDP/TXDP registers ? + */ +void ath5k_hw_dma_init(struct ath5k_hw *ah) +{ + /* + * Set Rx/Tx DMA Configuration + * + * Set standard DMA size (128). Note that + * a DMA size of 512 causes rx overruns and tx errors + * on pci-e cards (tested on 5424 but since rx overruns + * also occur on 5416/5418 with madwifi we set 128 + * for all PCI-E cards to be safe). + * + * XXX: need to check 5210 for this + * TODO: Check out tx triger level, it's always 64 on dumps but I + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); + } + + /* Pre-enable interrupts on 5211/5212*/ + if (ah->ah_version != AR5K_AR5210) + ath5k_hw_set_imr(ah, ah->ah_imr); + +} + +/** + * ath5k_hw_dma_stop - stop DMA unit + * + * @ah: The &struct ath5k_hw + * + * Stop tx/rx DMA and interrupts. Returns + * -EBUSY if tx or rx dma failed to stop. + * + * XXX: Sometimes DMA unit hangs and we have + * stuck frames on tx queues, only a reset + * can fix that. + */ +int ath5k_hw_dma_stop(struct ath5k_hw *ah) +{ + int i, qmax, err; + err = 0; + + /* Disable interrupts */ + ath5k_hw_set_imr(ah, 0); + + /* Stop rx dma */ + err = ath5k_hw_stop_rx_dma(ah); + if (err) + return err; + + /* Clear any pending interrupts + * and disable tx dma */ + if (ah->ah_version != AR5K_AR5210) { + ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); + qmax = AR5K_NUM_TX_QUEUES; + } else { + /* PISR/SISR Not available on 5210 */ + ath5k_hw_reg_read(ah, AR5K_ISR); + qmax = AR5K_NUM_TX_QUEUES_NOQCU; + } + + for (i = 0; i < qmax; i++) { + err = ath5k_hw_stop_tx_dma(ah, i); + /* -EINVAL -> queue inactive */ + if (err != -EINVAL) + return err; + } + + return err; +} diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 39722dd73e43..97eaa9a4415e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -28,45 +28,16 @@ #include "debug.h" #include "base.h" -/* - * Read from eeprom - */ -static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) -{ - u32 status, timeout; - - /* - * Initialize EEPROM access - */ - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); - (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); - } else { - ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); - AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, - AR5K_EEPROM_CMD_READ); - } - for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { - status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); - if (status & AR5K_EEPROM_STAT_RDDONE) { - if (status & AR5K_EEPROM_STAT_RDERR) - return -EIO; - *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & - 0xffff); - return 0; - } - udelay(15); - } - - return -ETIMEDOUT; -} +/******************\ +* Helper functions * +\******************/ /* * Translate binary channel representation in EEPROM to frequency */ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, - unsigned int mode) + unsigned int mode) { u16 val; @@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, return val; } + +/*********\ +* Parsers * +\*********/ + /* * Initialize eeprom & capabilities structs */ @@ -198,7 +174,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) * * XXX: Serdes values seem to be fixed so * no need to read them here, we write them - * during ath5k_hw_attach */ + * during ath5k_hw_init */ AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? true : false; @@ -647,6 +623,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) return 0; } + /* * Read power calibration for RF5111 chips * @@ -1514,6 +1491,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) return 0; } + /* * Read per channel calibration info from EEPROM * @@ -1607,15 +1585,6 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) return 0; } -void -ath5k_eeprom_detach(struct ath5k_hw *ah) -{ - u8 mode; - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) - ath5k_eeprom_free_pcal_info(ah, mode); -} - /* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) @@ -1757,6 +1726,44 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) } /* + * Read the MAC address from eeprom + */ +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + u8 mac_d[ETH_ALEN] = {}; + u32 total, offset; + u16 data; + int octet, ret; + + ret = ath5k_hw_nvram_read(ah, 0x20, &data); + if (ret) + return ret; + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { + ret = ath5k_hw_nvram_read(ah, offset, &data); + if (ret) + return ret; + + total += data; + mac_d[octet + 1] = data & 0xff; + mac_d[octet] = data >> 8; + octet += 2; + } + + if (!total || total == 3 * 0xffff) + return -EINVAL; + + memcpy(mac, mac_d, ETH_ALEN); + + return 0; +} + + +/***********************\ +* Init/Detach functions * +\***********************/ + +/* * Initialize eeprom data structure */ int @@ -1787,35 +1794,11 @@ ath5k_eeprom_init(struct ath5k_hw *ah) return 0; } -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +void +ath5k_eeprom_detach(struct ath5k_hw *ah) { - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet, ret; - - ret = ath5k_hw_eeprom_read(ah, 0x20, &data); - if (ret) - return ret; - - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - ret = ath5k_hw_eeprom_read(ah, offset, &data); - if (ret) - return ret; - - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; - } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); + u8 mode; - return 0; + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) + ath5k_eeprom_free_pcal_info(ah, mode); } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index c4a6d5f26af4..0017006be841 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -241,7 +241,7 @@ enum ath5k_eeprom_freq_bands{ #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 #define AR5K_EEPROM_READ(_o, _v) do { \ - ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ + ret = ath5k_hw_nvram_read(ah, (_o), &(_v)); \ if (ret) \ return ret; \ } while (0) diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 8fa439308828..e49340d18df4 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -44,7 +44,7 @@ struct ath5k_ini { struct ath5k_ini_mode { u16 mode_register; - u32 mode_value[5]; + u32 mode_value[3]; }; /* Initial register settings for AR5210 */ @@ -391,76 +391,74 @@ static const struct ath5k_ini ar5211_ini[] = { */ static const struct ath5k_ini_mode ar5211_ini_mode[] = { { AR5K_TXCFG, - /* a aTurbo b g (OFDM) */ - { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x0000001d, 0x00000015 } }, { AR5K_QUEUE_DFS_LOCAL_IFS(0), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, + { 0x00000168, 0x000001b8, 0x00000168 } }, { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, + { 0x00000230, 0x000000b0, 0x00000230 } }, { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, + { 0x00000d98, 0x00001f48, 0x00000d98 } }, { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, + { 0x0000a0e0, 0x00005880, 0x0000a0e0 } }, { AR5K_TIME_OUT, - { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, + { 0x04000400, 0x20003000, 0x04000400 } }, { AR5K_USEC_5211, - { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, + { 0x0e8d8fa7, 0x01608f95, 0x0e8d8fa7 } }, { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, - { AR5K_PHY(9), - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, - { AR5K_PHY(10), - { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, - { AR5K_PHY(13), - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY(14), - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, - { AR5K_PHY(17), - { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, - { AR5K_PHY(18), - { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, - { AR5K_PHY(20), - { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, + { 0x02020200, 0x02010200, 0x02020200 } }, + { AR5K_PHY_RF_CTL2, + { 0x00000e0e, 0x00000707, 0x00000e0e } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x05010000, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000007, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_SETTLING, + { 0x1372169c, 0x137216a8, 0x1372169c } }, + { AR5K_PHY_GAIN, + { 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, + { 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, { AR5K_PHY_AGCCTL, - { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, + { 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, + { 0x00002710, 0x0000157c, 0x00002710 } }, { AR5K_PHY(70), - { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, + { 0x00000190, 0x00000084, 0x00000190 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, + { 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, { AR5K_PHY_PCDAC_TXPOWER_BASE, - { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, + { 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, { AR5K_RF_BUFFER_CONTROL_4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, + { 0x00000010, 0x00000010, 0x00000010 } }, }; /* Initial register settings for AR5212 */ @@ -677,89 +675,87 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { { AR5K_QUEUE_DFS_LOCAL_IFS(0), - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + /* A/XR B G */ + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, + { 0x00000230, 0x000000b0, 0x00000160 } }, { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, + { 0x00000168, 0x000001b8, 0x0000018c } }, { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, + { 0x00000e60, 0x00001f1c, 0x00003e38 } }, { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, + { 0x0000a0e0, 0x00005880, 0x0000b0e0 } }, { AR5K_TIME_OUT, - { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, + { 0x03e803e8, 0x04200420, 0x08400840 } }, { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, + { 0x02020200, 0x02010200, 0x02020200 } }, { AR5K_PHY_RF_CTL2, - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000707, 0x00000e0e } }, { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, + { 0x1372161c, 0x13721722, 0x137216a2 } }, { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, + { 0x00009d10, 0x00009d18, 0x00009d18 } }, { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_WEAK_OFDM_HIGH_THR, - { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, + { 0x409a4190, 0x409a4190, 0x409a4190 } }, { AR5K_PHY(70), - { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, + { 0x000001b8, 0x00000084, 0x00000108 } }, { AR5K_PHY_OFDM_SELFCORR, - { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, + { 0x10058a05, 0x10058a05, 0x10058a05 } }, { 0xa230, - { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000108 } }, }; /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + /* A/XR B G */ + { 0x00008015, 0x00008015, 0x00008015 } }, { AR5K_USEC_5211, - { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, + { 0x128d8fa7, 0x04e00f95, 0x12e00fab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05010100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, + { 0x0018da5a, 0x0018ca69, 0x0018ca69 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, + { 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, + { 0x050cb081, 0x050cb081, 0x050cb080 } }, { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, + { 0x00002710, 0x0000157c, 0x00002af8 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, + { 0xf7b81020, 0xf7b80d20, 0xf7b81020 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, + { 0x642c416a, 0x6440416a, 0x6440416a } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1873800a, 0x1883800a } }, }; static const struct ath5k_ini rf5111_ini_common_end[] = { @@ -782,38 +778,38 @@ static const struct ath5k_ini rf5111_ini_common_end[] = { /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + /* A/XR B G */ + { 0x00008015, 0x00008015, 0x00008015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, + { 0x0018da6d, 0x0018ca75, 0x0018ca75 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, + { 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, + { 0xf7b81020, 0xf7b80d10, 0xf7b81010 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, + { 0x00000000, 0x00000008, 0x00000008 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, + { 0x642c0140, 0x6442c160, 0x6442c160 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1873800a, 0x1883800a } }, }; static const struct ath5k_ini rf5112_ini_common_end[] = { @@ -833,66 +829,66 @@ static const struct ath5k_ini rf5112_ini_common_end[] = { /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000007, 0x0000000b, 0x0000000b } }, { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, + { 0x0018fa61, 0x001a1a63, 0x001a1a63 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { 0x3139605e, 0x3139605e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, + { 0x002ec1e0, 0x002ac120, 0x002ac120 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, { 0xa300, - { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, + { 0x18010000, 0x18010000, 0x18010000 } }, { 0xa304, - { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, + { 0x30032602, 0x30032602, 0x30032602 } }, { 0xa308, - { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, + { 0x48073e06, 0x48073e06, 0x48073e06 } }, { 0xa30c, - { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, + { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, { 0xa310, - { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, + { 0x641a600f, 0x641a600f, 0x641a600f } }, { 0xa314, - { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, + { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, { 0xa318, - { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, + { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, { 0xa31c, - { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, + { 0x90cf865b, 0x8ecf865b, 0x8ecf865b } }, { 0xa320, - { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, + { 0x9d4f970f, 0x9b4f970f, 0x9b4f970f } }, { 0xa324, - { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, + { 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f } }, { 0xa328, - { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, + { 0xb55faf1f, 0xb35faf1f, 0xb35faf1f } }, { 0xa32c, - { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, + { 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f } }, { 0xa330, - { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, + { 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f } }, { 0xa334, - { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, + { 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, }; static const struct ath5k_ini rf5413_ini_common_end[] = { @@ -972,38 +968,38 @@ static const struct ath5k_ini rf5413_ini_common_end[] = { /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020000, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, + { 0x00000e00, 0x00000e00, 0x00000e00 } }, { AR5K_PHY_PA_CTL, - { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, + { 0x00000002, 0x0000000a, 0x0000000a } }, { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, + { 0x0018da6d, 0x001a6a64, 0x001a6a64 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, + { 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, + { 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, + { 0x3137665e, 0x3137665e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, + { 0x002c0140, 0x0042c140, 0x0042c140 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, }; static const struct ath5k_ini rf2413_ini_common_end[] = { @@ -1094,52 +1090,50 @@ static const struct ath5k_ini rf2413_ini_common_end[] = { /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + /* A/XR B G */ + { 0x00000015, 0x00000015, 0x00000015 } }, { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, + { 0x128d93a7, 0x04e01395, 0x12e013ab } }, { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { 0x0a020001, 0x05020100, 0x0a020001 } }, { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, { AR5K_PHY_PA_CTL, - { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, + { 0x00000003, 0x0000000b, 0x0000000b } }, { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, + { 0x1372161c, 0x13721722, 0x13721422 } }, { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, + { 0x0018fa61, 0x00199a65, 0x00199a65 } }, { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { 0x3139605e, 0x3139605e, 0x3139605e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { 0x050cb081, 0x050cb081, 0x050cb081 } }, { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { 0x000007d0, 0x0000044c, 0x00000898 } }, { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, { AR5K_PHY_GAIN_2GHZ, - { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, + { 0x00000140, 0x0052c140, 0x0052c140 } }, { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0x1883800a, 0x1863800a, 0x1883800a } }, { 0xa324, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa328, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa32c, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa330, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, { 0xa334, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, }; static const struct ath5k_ini rf2425_ini_common_end[] = { @@ -1368,15 +1362,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = { * Write initial register dump */ static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, - const struct ath5k_ini *ini_regs, bool change_channel) + const struct ath5k_ini *ini_regs, bool skip_pcu) { unsigned int i; /* Write initial registers */ for (i = 0; i < size; i++) { - /* On channel change there is - * no need to mess with PCU */ - if (change_channel && + /* Skip PCU registers if + * requested */ + if (skip_pcu && ini_regs[i].ini_register >= AR5K_PCU_MIN && ini_regs[i].ini_register <= AR5K_PCU_MAX) continue; @@ -1409,7 +1403,7 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, } -int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) +int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) { /* * Write initial register settings @@ -1427,7 +1421,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) * Write initial settings common for all modes */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), - ar5212_ini_common_start, change_channel); + ar5212_ini_common_start, skip_pcu); /* Second set of mode-specific settings */ switch (ah->ah_radio) { @@ -1439,12 +1433,12 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_common_end), - rf5111_ini_common_end, change_channel); + rf5111_ini_common_end, skip_pcu); /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); + rf5111_ini_bbgain, skip_pcu); break; case AR5K_RF5112: @@ -1455,11 +1449,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_common_end), - rf5112_ini_common_end, change_channel); + rf5112_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF5413: @@ -1470,11 +1464,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5413_ini_common_end), - rf5413_ini_common_end, change_channel); + rf5413_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF2316: @@ -1486,7 +1480,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf2413_ini_common_end), - rf2413_ini_common_end, change_channel); + rf2413_ini_common_end, skip_pcu); /* Override settings from rf2413_ini_common_end */ if (ah->ah_radio == AR5K_RF2316) { @@ -1498,9 +1492,32 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; case AR5K_RF2317: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2413_ini_mode_end), + rf2413_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf2425_ini_common_end), + rf2425_ini_common_end, skip_pcu); + + /* Override settings from rf2413_ini_mode_end */ + ath5k_hw_reg_write(ah, 0x00180a65, AR5K_PHY_GAIN); + + /* Override settings from rf2413_ini_common_end */ + ath5k_hw_reg_write(ah, 0x00004000, AR5K_PHY_AGC); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TPC_RG5, + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, 0xa); + ath5k_hw_reg_write(ah, 0x800000a8, 0x8140); + ath5k_hw_reg_write(ah, 0x000000ff, 0x9958); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, skip_pcu); + break; case AR5K_RF2425: ath5k_hw_ini_mode_registers(ah, @@ -1509,11 +1526,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf2425_ini_common_end), - rf2425_ini_common_end, change_channel); + rf2425_ini_common_end, skip_pcu); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); + rf5112_ini_bbgain, skip_pcu); break; default: return -EINVAL; @@ -1538,17 +1555,17 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) * Write initial settings common for all modes */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), - ar5211_ini, change_channel); + ar5211_ini, skip_pcu); /* AR5211 only comes with 5111 */ /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); + rf5111_ini_bbgain, skip_pcu); /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ } else if (ah->ah_version == AR5K_AR5210) { ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), - ar5210_ini, change_channel); + ar5210_ini, skip_pcu); } return 0; diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 67aa52e9bf94..576edf2965dc 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -133,7 +133,7 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, led->led_dev.default_trigger = trigger; led->led_dev.brightness_set = ath5k_led_brightness_set; - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); + err = led_classdev_register(sc->dev, &led->led_dev); if (err) { ATH5K_WARN(sc, "could not register LED %s\n", name); led->sc = NULL; @@ -161,11 +161,20 @@ int ath5k_init_leds(struct ath5k_softc *sc) { int ret = 0; struct ieee80211_hw *hw = sc->hw; +#ifndef CONFIG_ATHEROS_AR231X struct pci_dev *pdev = sc->pdev; +#endif char name[ATH5K_LED_MAX_NAME_LEN + 1]; const struct pci_device_id *match; + if (!sc->pdev) + return 0; + +#ifdef CONFIG_ATHEROS_AR231X + match = NULL; +#else match = pci_match_id(&ath5k_led_devices[0], pdev); +#endif if (match) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = ATH_PIN(match->driver_data); diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c new file mode 100644 index 000000000000..39f033128c5a --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * 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/nl80211.h> +#include <linux/pci.h> +#include <linux/pci-aspm.h> +#include "../ath.h" +#include "ath5k.h" +#include "debug.h" +#include "base.h" +#include "reg.h" + +/* Known PCI ids */ +static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { + { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ + { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ + { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ + { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ + { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ + { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ + { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ + { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ + { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ + { 0 } +}; + +/* return bus cachesize in 4B word units */ +static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) +{ + struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; + u8 u8tmp; + + pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); + *csz = (int)u8tmp; + + /* + * This check was put in to avoid "unplesant" consequences if + * the bootrom has not fully initialized all PCI devices. + * Sometimes the cache line size register is not set + */ + + if (*csz == 0) + *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ +} + +/* + * Read from eeprom + */ +bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) +{ + struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; + u32 status, timeout; + + /* + * Initialize EEPROM access + */ + if (ah->ah_version == AR5K_AR5210) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); + (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); + } else { + ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); + AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, + AR5K_EEPROM_CMD_READ); + } + + for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { + status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); + if (status & AR5K_EEPROM_STAT_RDDONE) { + if (status & AR5K_EEPROM_STAT_RDERR) + return -EIO; + *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & + 0xffff); + return 0; + } + udelay(15); + } + + return -ETIMEDOUT; +} + +int ath5k_hw_read_srev(struct ath5k_hw *ah) +{ + ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV); + return 0; +} + +/* Common ath_bus_opts structure */ +static const struct ath_bus_ops ath_pci_bus_ops = { + .ath_bus_type = ATH_PCI, + .read_cachesize = ath5k_pci_read_cachesize, + .eeprom_read = ath5k_pci_eeprom_read, +}; + +/********************\ +* PCI Initialization * +\********************/ + +static int __devinit +ath5k_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem *mem; + struct ath5k_softc *sc; + struct ieee80211_hw *hw; + int ret; + u8 csz; + + /* + * L0s needs to be disabled on all ath5k cards. + * + * For distributions shipping with CONFIG_PCIEASPM (this will be enabled + * by default in the future in 2.6.36) this will also mean both L1 and + * L0s will be disabled when a pre 1.1 PCIe device is detected. We do + * know L1 works correctly even for all ath5k pre 1.1 PCIe devices + * though but cannot currently undue the effect of a blacklist, for + * details you can read pcie_aspm_sanity_check() and see how it adjusts + * the device link capability. + * + * It may be possible in the future to implement some PCI API to allow + * drivers to override blacklists for pre 1.1 PCIe but for now it is + * best to accept that both L0s and L1 will be disabled completely for + * distributions shipping with CONFIG_PCIEASPM rather than having this + * issue present. Motivation for adding this new API will be to help + * with power consumption for some of these devices. + */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "can't enable device\n"); + goto err; + } + + /* XXX 32-bit addressing only */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "32-bit DMA not available\n"); + goto err_dis; + } + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); + if (csz == 0) { + /* + * Linux 2.4.18 (at least) writes the cache line size + * register as a 16-bit wide register which is wrong. + * We must have this setup properly for rx buffer + * DMA to work so force a reasonable value here if it + * comes up zero. + */ + csz = L1_CACHE_BYTES >> 2; + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); + } + /* + * The default setting of latency timer yields poor results, + * set it to the value used by other systems. It may be worth + * tweaking this setting more. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* + * Disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state. + */ + pci_write_config_byte(pdev, 0x41, 0); + + ret = pci_request_region(pdev, 0, "ath5k"); + if (ret) { + dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); + goto err_dis; + } + + mem = pci_iomap(pdev, 0, 0); + if (!mem) { + dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; + ret = -EIO; + goto err_reg; + } + + /* + * Allocate hw (mac80211 main struct) + * and hw->priv (driver private data) + */ + hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); + ret = -ENOMEM; + goto err_map; + } + + dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); + + sc = hw->priv; + sc->hw = hw; + sc->pdev = pdev; + sc->dev = &pdev->dev; + sc->irq = pdev->irq; + sc->devid = id->device; + sc->iobase = mem; /* So we can unmap it on detach */ + + /* Initialize */ + ret = ath5k_init_softc(sc, &ath_pci_bus_ops); + if (ret) + goto err_free; + + /* Set private data */ + pci_set_drvdata(pdev, hw); + + return 0; +err_free: + ieee80211_free_hw(hw); +err_map: + pci_iounmap(pdev, mem); +err_reg: + pci_release_region(pdev, 0); +err_dis: + pci_disable_device(pdev); +err: + return ret; +} + +static void __devexit +ath5k_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath5k_softc *sc = hw->priv; + + ath5k_deinit_softc(sc); + pci_iounmap(pdev, sc->iobase); + pci_release_region(pdev, 0); + pci_disable_device(pdev); + ieee80211_free_hw(hw); +} + +#ifdef CONFIG_PM_SLEEP +static int ath5k_pci_suspend(struct device *dev) +{ + struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); + + ath5k_led_off(sc); + return 0; +} + +static int ath5k_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ath5k_softc *sc = pci_get_drvdata(pdev); + + /* + * Suspend/Resume resets the PCI configuration space, so we have to + * re-disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state + */ + pci_write_config_byte(pdev, 0x41, 0); + + ath5k_led_enable(sc); + return 0; +} + +static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); +#define ATH5K_PM_OPS (&ath5k_pm_ops) +#else +#define ATH5K_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + +static struct pci_driver ath5k_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = ath5k_pci_id_table, + .probe = ath5k_pci_probe, + .remove = __devexit_p(ath5k_pci_remove), + .driver.pm = ATH5K_PM_OPS, +}; + +/* + * Module init/exit functions + */ +static int __init +init_ath5k_pci(void) +{ + int ret; + + ret = pci_register_driver(&ath5k_pci_driver); + if (ret) { + printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); + return ret; + } + + return 0; +} + +static void __exit +exit_ath5k_pci(void) +{ + pci_unregister_driver(&ath5k_pci_driver); +} + +module_init(init_ath5k_pci); +module_exit(exit_ath5k_pci); diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 074b4c644399..e5f2b96a4c63 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -31,87 +31,163 @@ #include "debug.h" #include "base.h" +/* + * AR5212+ can use higher rates for ack transmition + * based on current tx rate instead of the base rate. + * It does this to better utilize channel usage. + * This is a mapping between G rates (that cover both + * CCK and OFDM) and ack rates that we use when setting + * rate -> duration table. This mapping is hw-based so + * don't change anything. + * + * To enable this functionality we must set + * ah->ah_ack_bitrate_high to true else base rate is + * used (1Mb for CCK, 6Mb for OFDM). + */ +static const unsigned int ack_rates_high[] = +/* Tx -> ACK */ +/* 1Mb -> 1Mb */ { 0, +/* 2MB -> 2Mb */ 1, +/* 5.5Mb -> 2Mb */ 1, +/* 11Mb -> 2Mb */ 1, +/* 6Mb -> 6Mb */ 4, +/* 9Mb -> 6Mb */ 4, +/* 12Mb -> 12Mb */ 6, +/* 18Mb -> 12Mb */ 6, +/* 24Mb -> 24Mb */ 8, +/* 36Mb -> 24Mb */ 8, +/* 48Mb -> 24Mb */ 8, +/* 54Mb -> 24Mb */ 8 }; + /*******************\ -* Generic functions * +* Helper functions * \*******************/ /** - * ath5k_hw_set_opmode - Set PCU operating mode + * ath5k_hw_get_frame_duration - Get tx time of a frame * * @ah: The &struct ath5k_hw - * @op_mode: &enum nl80211_iftype operating mode + * @len: Frame's length in bytes + * @rate: The @struct ieee80211_rate * - * Initialize PCU for the various operating modes (AP/STA etc) + * Calculate tx duration of a frame given it's rate and length + * It extends ieee80211_generic_frame_duration for non standard + * bwmodes. */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, + int len, struct ieee80211_rate *rate) { - struct ath_common *common = ath5k_hw_common(ah); - u32 pcu_reg, beacon_reg, low_id, high_id; + struct ath5k_softc *sc = ah->ah_sc; + int sifs, preamble, plcp_bits, sym_time; + int bitrate, bits, symbols, symbol_bits; + int dur; + + /* Fallback */ + if (!ah->ah_bwmode) { + dur = ieee80211_generic_frame_duration(sc->hw, + NULL, len, rate); + return dur; + } - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); + bitrate = rate->bitrate; + preamble = AR5K_INIT_OFDM_PREAMPLE_TIME; + plcp_bits = AR5K_INIT_OFDM_PLCP_BITS; + sym_time = AR5K_INIT_OFDM_SYMBOL_TIME; - /* Preserve rest settings */ - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP - | AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + sifs = AR5K_INIT_SIFS_TURBO; + preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN; + break; + case AR5K_BWMODE_10MHZ: + sifs = AR5K_INIT_SIFS_HALF_RATE; + preamble *= 2; + sym_time *= 2; + break; + case AR5K_BWMODE_5MHZ: + sifs = AR5K_INIT_SIFS_QUARTER_RATE; + preamble *= 4; + sym_time *= 4; + break; + default: + sifs = AR5K_INIT_SIFS_DEFAULT_BG; + break; + } - beacon_reg = 0; + bits = plcp_bits + (len << 3); + /* Bit rate is in 100Kbits */ + symbol_bits = bitrate * sym_time; + symbols = DIV_ROUND_UP(bits * 10, symbol_bits); - switch (op_mode) { - case NL80211_IFTYPE_ADHOC: - pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_ADHOC; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; + dur = sifs + preamble + (sym_time * symbols); - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_AP; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; + return dur; +} - case NL80211_IFTYPE_STATION: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_PWR_SV : 0); - case NL80211_IFTYPE_MONITOR: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_NO_PSPOLL : 0); - break; +/** + * ath5k_hw_get_default_slottime - Get the default slot time for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + unsigned int slot_time; + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + slot_time = AR5K_INIT_SLOT_TIME_TURBO; + break; + case AR5K_BWMODE_10MHZ: + slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE; + break; + case AR5K_BWMODE_5MHZ: + slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; + break; + case AR5K_BWMODE_DEFAULT: + slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; default: - return -EINVAL; + if (channel->hw_value & CHANNEL_CCK) + slot_time = AR5K_INIT_SLOT_TIME_B; + break; } - /* - * Set PCU registers - */ - low_id = get_unaligned_le32(common->macaddr); - high_id = get_unaligned_le16(common->macaddr + 4); - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + return slot_time; +} - /* - * Set Beacon Control Register on 5210 - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); +/** + * ath5k_hw_get_default_sifs - Get the default SIFS for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + unsigned int sifs; - return 0; + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + sifs = AR5K_INIT_SIFS_TURBO; + break; + case AR5K_BWMODE_10MHZ: + sifs = AR5K_INIT_SIFS_HALF_RATE; + break; + case AR5K_BWMODE_5MHZ: + sifs = AR5K_INIT_SIFS_QUARTER_RATE; + break; + case AR5K_BWMODE_DEFAULT: + sifs = AR5K_INIT_SIFS_DEFAULT_BG; + default: + if (channel->hw_value & CHANNEL_5GHZ) + sifs = AR5K_INIT_SIFS_DEFAULT_A; + break; + } + + return sifs; } /** - * ath5k_hw_update - Update MIB counters (mac layer statistics) + * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) * * @ah: The &struct ath5k_hw * @@ -133,36 +209,88 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); } + +/******************\ +* ACK/CTS Timeouts * +\******************/ + /** - * ath5k_hw_set_ack_bitrate - set bitrate for ACKs + * ath5k_hw_write_rate_duration - fill rate code to duration table * - * @ah: The &struct ath5k_hw - * @high: Flag to determine if we want to use high transmission rate - * for ACKs or not + * @ah: the &struct ath5k_hw + * @mode: one of enum ath5k_driver_mode + * + * Write the rate code to duration table upon hw reset. This is a helper for + * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on + * the hardware, based on current mode, for each rate. The rates which are + * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have + * different rate code so we write their value twice (one for long preamble + * and one for short). + * + * Note: Band doesn't matter here, if we set the values for OFDM it works + * on both a and g modes. So all we have to do is set values for all g rates + * that include all OFDM and CCK rates. * - * If high flag is set, we tell hw to use a set of control rates based on - * the current transmission rate (check out control_rates array inside reset.c). - * If not hw just uses the lowest rate available for the current modulation - * scheme being used (1Mbit for CCK and 6Mbits for OFDM). */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) +static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) { - if (ah->ah_version != AR5K_AR5212) - return; - else { - u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; - if (high) - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + struct ath5k_softc *sc = ah->ah_sc; + struct ieee80211_rate *rate; + unsigned int i; + /* 802.11g covers both OFDM and CCK */ + u8 band = IEEE80211_BAND_2GHZ; + + /* Write rate duration table */ + for (i = 0; i < sc->sbands[band].n_bitrates; i++) { + u32 reg; + u16 tx_time; + + if (ah->ah_ack_bitrate_high) + rate = &sc->sbands[band].bitrates[ack_rates_high[i]]; + /* CCK -> 1Mb */ + else if (i < 4) + rate = &sc->sbands[band].bitrates[0]; + /* OFDM -> 6Mb */ else - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); + rate = &sc->sbands[band].bitrates[4]; + + /* Set ACK timeout */ + reg = AR5K_RATE_DUR(rate->hw_value); + + /* An ACK frame consists of 10 bytes. If you add the FCS, + * which ieee80211_generic_frame_duration() adds, + * its 14 bytes. Note we use the control rate and not the + * actual rate for this rate. See mac80211 tx.c + * ieee80211_duration() for a brief description of + * what rate we should choose to TX ACKs. */ + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + + tx_time = le16_to_cpu(tx_time); + + ath5k_hw_reg_write(ah, tx_time, reg); + + if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) + continue; + + /* + * We're not distinguishing short preamble here, + * This is true, all we'll get is a longer value here + * which is not necessarilly bad. We could use + * export ieee80211_frame_duration() but that needs to be + * fixed first to be properly used by mac802111 drivers: + * + * - remove erp stuff and let the routine figure ofdm + * erp rates + * - remove passing argument ieee80211_local as + * drivers don't have access to it + * - move drivers using ieee80211_generic_frame_duration() + * to this + */ + ath5k_hw_reg_write(ah, tx_time, + reg + (AR5K_SET_SHORT_PREAMBLE << 2)); } } - -/******************\ -* ACK/CTS Timeouts * -\******************/ - /** * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU * @@ -199,88 +327,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) return 0; } -/** - * ath5k_hw_htoclock - Translate usec to hw clock units - * - * @ah: The &struct ath5k_hw - * @usec: value in microseconds - */ -unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) -{ - struct ath_common *common = ath5k_hw_common(ah); - return usec * common->clockrate; -} - -/** - * ath5k_hw_clocktoh - Translate hw clock units to usec - * @clock: value in hw clock units - */ -unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) -{ - struct ath_common *common = ath5k_hw_common(ah); - return clock / common->clockrate; -} - -/** - * ath5k_hw_set_clockrate - Set common->clockrate for the current channel - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_set_clockrate(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - struct ath_common *common = ath5k_hw_common(ah); - int clock; - - if (channel->hw_value & CHANNEL_5GHZ) - clock = 40; /* 802.11a */ - else if (channel->hw_value & CHANNEL_CCK) - clock = 22; /* 802.11b */ - else - clock = 44; /* 802.11g */ - - /* Clock rate in turbo modes is twice the normal rate */ - if (channel->hw_value & CHANNEL_TURBO) - clock *= 2; - - common->clockrate = clock; -} - -/** - * ath5k_hw_get_default_slottime - Get the default slot time for current mode - * - * @ah: The &struct ath5k_hw - */ -static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - - if (channel->hw_value & CHANNEL_TURBO) - return 6; /* both turbo modes */ - - if (channel->hw_value & CHANNEL_CCK) - return 20; /* 802.11b */ - - return 9; /* 802.11 a/g */ -} - -/** - * ath5k_hw_get_default_sifs - Get the default SIFS for current mode - * - * @ah: The &struct ath5k_hw - */ -static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - - if (channel->hw_value & CHANNEL_TURBO) - return 8; /* both turbo modes */ - if (channel->hw_value & CHANNEL_5GHZ) - return 16; /* 802.11a */ - - return 10; /* 802.11 b/g */ -} +/*******************\ +* RX filter Control * +\*******************/ /** * ath5k_hw_set_lladdr - Set station id @@ -362,39 +412,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) ath_hw_setbssidmask(common); } -/************\ -* RX Control * -\************/ - -/** - * ath5k_hw_start_rx_pcu - Start RX engine - * - * @ah: The &struct ath5k_hw - * - * Starts RX engine on PCU so that hw can process RXed frames - * (ACK etc). - * - * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma - */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) -{ - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/** - * at5k_hw_stop_rx_pcu - Stop RX engine - * - * @ah: The &struct ath5k_hw - * - * Stops RX engine on PCU - * - * TODO: Detach ANI here - */ -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) -{ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - /* * Set multicast filter */ @@ -746,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) * @ah: The &struct ath5k_hw * @coverage_class: IEEE 802.11 coverage class number * - * Sets slot time, ACK timeout and CTS timeout for given coverage class. + * Sets IFS intervals and ACK/CTS timeouts for given coverage class. */ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) { @@ -755,9 +772,175 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; int cts_timeout = ack_timeout; - ath5k_hw_set_slot_time(ah, slot_time); + ath5k_hw_set_ifs_intervals(ah, slot_time); ath5k_hw_set_ack_timeout(ah, ack_timeout); ath5k_hw_set_cts_timeout(ah, cts_timeout); ah->ah_coverage_class = coverage_class; } + +/***************************\ +* Init/Start/Stop functions * +\***************************/ + +/** + * ath5k_hw_start_rx_pcu - Start RX engine + * + * @ah: The &struct ath5k_hw + * + * Starts RX engine on PCU so that hw can process RXed frames + * (ACK etc). + * + * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma + */ +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) +{ + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/** + * at5k_hw_stop_rx_pcu - Stop RX engine + * + * @ah: The &struct ath5k_hw + * + * Stops RX engine on PCU + */ +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) +{ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/** + * ath5k_hw_set_opmode - Set PCU operating mode + * + * @ah: The &struct ath5k_hw + * @op_mode: &enum nl80211_iftype operating mode + * + * Configure PCU for the various operating modes (AP/STA etc) + */ +int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +{ + struct ath_common *common = ath5k_hw_common(ah); + u32 pcu_reg, beacon_reg, low_id, high_id; + + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); + + /* Preserve rest settings */ + pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; + pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP + | AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); + + beacon_reg = 0; + + switch (op_mode) { + case NL80211_IFTYPE_ADHOC: + pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_ADHOC; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_AP; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_STATION: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_PWR_SV : 0); + case NL80211_IFTYPE_MONITOR: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_NO_PSPOLL : 0); + break; + + default: + return -EINVAL; + } + + /* + * Set PCU registers + */ + low_id = get_unaligned_le32(common->macaddr); + high_id = get_unaligned_le16(common->macaddr + 4); + ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); + ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + + /* + * Set Beacon Control Register on 5210 + */ + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); + + return 0; +} + +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode) +{ + /* Set bssid and bssid mask */ + ath5k_hw_set_bssid(ah); + + /* Set PCU config */ + ath5k_hw_set_opmode(ah, op_mode); + + /* Write rate duration table only on AR5212 and if + * virtual interface has already been brought up + * XXX: rethink this after new mode changes to + * mac80211 are integrated */ + if (ah->ah_version == AR5K_AR5212 && + ah->ah_sc->nvifs) + ath5k_hw_write_rate_duration(ah); + + /* Set RSSI/BRSSI thresholds + * + * Note: If we decide to set this value + * dynamicaly, have in mind that when AR5K_RSSI_THR + * register is read it might return 0x40 if we haven't + * wrote anything to it plus BMISS RSSI threshold is zeroed. + * So doing a save/restore procedure here isn't the right + * choice. Instead store it on ath5k_hw */ + ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | + AR5K_TUNE_BMISS_THRES << + AR5K_RSSI_THR_BMISS_S), + AR5K_RSSI_THR); + + /* MIC QoS support */ + if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { + ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); + ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); + } + + /* QoS NOACK Policy */ + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, + AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | + AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | + AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), + AR5K_QOS_NOACK); + } + + /* Restore slot time and ACK timeouts */ + if (ah->ah_coverage_class > 0) + ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); + + /* Set ACK bitrate mode (see ack_rates_high) */ + if (ah->ah_version == AR5K_AR5212) { + u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; + if (ah->ah_ack_bitrate_high) + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); + } + return; +} diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 219367884e64..df5cd0fd69d6 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -29,6 +29,95 @@ #include "rfbuffer.h" #include "rfgain.h" + +/******************\ +* Helper functions * +\******************/ + +/* + * Get the PHY Chip revision + */ +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) +{ + unsigned int i; + u32 srev; + u16 ret; + + /* + * Set the radio chip access register + */ + switch (chan) { + case CHANNEL_2GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); + break; + case CHANNEL_5GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + break; + default: + return 0; + } + + mdelay(2); + + /* ...wait until PHY is ready and read the selected radio revision */ + ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); + + for (i = 0; i < 8; i++) + ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); + + if (ah->ah_version == AR5K_AR5210) { + srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; + ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; + } else { + srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; + ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | + ((srev & 0x0f) << 4), 8); + } + + /* Reset to the 5GHz mode */ + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + + return ret; +} + +/* + * Check if a channel is supported + */ +bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) +{ + /* Check if the channel is in our supported range */ + if (flags & CHANNEL_2GHZ) { + if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) + return true; + } else if (flags & CHANNEL_5GHZ) + if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) + return true; + + return false; +} + +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u8 refclk_freq; + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + refclk_freq = 40; + else + refclk_freq = 32; + + if ((channel->center_freq % refclk_freq != 0) && + ((channel->center_freq % refclk_freq < 10) || + (channel->center_freq % refclk_freq > 22))) + return true; + else + return false; +} + /* * Used to modify RF Banks before writing them to AR5K_RF_BUFFER */ @@ -110,6 +199,90 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, return data; } +/** + * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * + * @ah: the &struct ath5k_hw + * @channel: the currently set channel upon reset + * + * Write the delta slope coefficient (used on pilot tracking ?) for OFDM + * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. + * + * Since delta slope is floating point we split it on its exponent and + * mantissa and provide these values on hw. + * + * For more infos i think this patent is related + * http://www.freepatentsonline.com/7184495.html + */ +static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + /* Get exponent and mantissa and set it */ + u32 coef_scaled, coef_exp, coef_man, + ds_coef_exp, ds_coef_man, clock; + + BUG_ON(!(ah->ah_version == AR5K_AR5212) || + !(channel->hw_value & CHANNEL_OFDM)); + + /* Get coefficient + * ALGO: coef = (5 * clock / carrier_freq) / 2 + * we scale coef by shifting clock value by 24 for + * better precision since we use integers */ + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + clock = 40 * 2; + break; + case AR5K_BWMODE_10MHZ: + clock = 40 / 2; + break; + case AR5K_BWMODE_5MHZ: + clock = 40 / 4; + break; + default: + clock = 40; + break; + } + coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; + + /* Get exponent + * ALGO: coef_exp = 14 - highest set bit position */ + coef_exp = ilog2(coef_scaled); + + /* Doesn't make sense if it's zero*/ + if (!coef_scaled || !coef_exp) + return -EINVAL; + + /* Note: we've shifted coef_scaled by 24 */ + coef_exp = 14 - (coef_exp - 24); + + + /* Get mantissa (significant digits) + * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ + coef_man = coef_scaled + + (1 << (24 - coef_exp - 1)); + + /* Calculate delta slope coefficient exponent + * and mantissa (remove scaling) and set them on hw */ + ds_coef_man = coef_man >> (24 - coef_exp); + ds_coef_exp = coef_exp - 16; + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + + return 0; +} + +int ath5k_hw_phy_disable(struct ath5k_hw *ah) +{ + /*Just a try M.F.*/ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + + return 0; +} + + /**********************\ * RF Gain optimization * \**********************/ @@ -436,7 +609,7 @@ done: /* Write initial RF gain table to set the RF sensitivity * this one works on all RF chips and has nothing to do * with gain_F calibration */ -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) +static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) { const struct ath5k_ini_rfgain *ath5k_rfg; unsigned int i, size; @@ -494,12 +667,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) * RF Registers setup * \********************/ - /* * Setup RF registers by writing RF buffer on hw */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - unsigned int mode) +static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, + struct ieee80211_channel *channel, unsigned int mode) { const struct ath5k_rf_reg *rf_regs; const struct ath5k_ini_rfbuffer *ini_rfb; @@ -652,6 +824,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, g_step = &go->go_step[ah->ah_gain.g_step_idx]; + /* Set turbo mode (N/A on RF5413) */ + if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && + (ah->ah_radio != AR5K_RF5413)) + ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false); + /* Bank Modifications (chip-specific) */ if (ah->ah_radio == AR5K_RF5111) { @@ -691,7 +868,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], AR5K_RF_PLO_SEL, true); - /* TODO: Half/quarter channel support */ + /* Tweak power detectors for half/quarter rate support */ + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || + ah->ah_bwmode == AR5K_BWMODE_10MHZ) { + u8 wait_i; + + ath5k_hw_rfb_op(ah, rf_regs, 0x1f, + AR5K_RF_WAIT_S, true); + + wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? + 0x1f : 0x10; + + ath5k_hw_rfb_op(ah, rf_regs, wait_i, + AR5K_RF_WAIT_I, true); + ath5k_hw_rfb_op(ah, rf_regs, 3, + AR5K_RF_MAX_TIME, true); + + } } if (ah->ah_radio == AR5K_RF5112) { @@ -789,8 +982,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], AR5K_RF_GAIN_I, true); - /* TODO: Half/quarter channel support */ + /* Tweak power detector for half/quarter rates */ + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || + ah->ah_bwmode == AR5K_BWMODE_10MHZ) { + u8 pd_delay; + + pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? + 0xf : 0x8; + + ath5k_hw_rfb_op(ah, rf_regs, pd_delay, + AR5K_RF_PD_PERIOD_A, true); + ath5k_hw_rfb_op(ah, rf_regs, 0xf, + AR5K_RF_PD_DELAY_A, true); + } } if (ah->ah_radio == AR5K_RF5413 && @@ -822,24 +1027,6 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, \**************************/ /* - * Check if a channel is supported - */ -bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) -{ - /* Check if the channel is in our supported range */ - if (flags & CHANNEL_2GHZ) { - if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) - return true; - } else if (flags & CHANNEL_5GHZ) - if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) - return true; - - return false; -} - -/* * Convertion needed for RF5110 */ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) @@ -1045,7 +1232,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, /* * Set a channel on the radio chip */ -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) +static int ath5k_hw_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) { int ret; /* @@ -1092,8 +1280,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) } ah->ah_current_channel = channel; - ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; - ath5k_hw_set_clockrate(ah); return 0; } @@ -1102,18 +1288,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) PHY calibration \*****************/ -static int sign_extend(int val, const int nbits) -{ - int order = BIT(nbits-1); - return (val ^ order) - order; -} - static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) { s32 val; val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); - return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); + return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); } void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) @@ -1183,12 +1363,10 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - case CHANNEL_T: case CHANNEL_XR: ee_mode = AR5K_EEPROM_MODE_11A; break; case CHANNEL_G: - case CHANNEL_TG: ee_mode = AR5K_EEPROM_MODE_11G; break; default: @@ -1425,31 +1603,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, return ret; } + /***************************\ * Spur mitigation functions * \***************************/ -bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - -void +static void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, struct ieee80211_channel *channel) { @@ -1478,7 +1637,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, spur_chan_fbin = AR5K_EEPROM_NO_SPUR; spur_detection_window = AR5K_SPUR_CHAN_WIDTH; /* XXX: Half/Quarter channels ?*/ - if (channel->hw_value & CHANNEL_TURBO) + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) spur_detection_window *= 2; for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { @@ -1507,32 +1666,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, * Calculate deltas: * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 * spur_delta_phase -> spur_offset / chip_freq << 11 - * Note: Both values have 100KHz resolution + * Note: Both values have 100Hz resolution */ - /* XXX: Half/Quarter rate channels ? */ - switch (channel->hw_value) { - case CHANNEL_A: - /* Both sample_freq and chip_freq are 40MHz */ - spur_delta_phase = (spur_offset << 17) / 25; - spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_G: - /* sample_freq -> 40MHz chip_freq -> 44MHz - * (for b compatibility) */ - spur_freq_sigma_delta = (spur_offset << 8) / 55; - spur_delta_phase = (spur_offset << 17) / 25; - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_T: - case CHANNEL_TG: + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: /* Both sample_freq and chip_freq are 80MHz */ spur_delta_phase = (spur_offset << 16) / 25; spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2; break; + case AR5K_BWMODE_10MHZ: + /* Both sample_freq and chip_freq are 20MHz (?) */ + spur_delta_phase = (spur_offset << 18) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; + case AR5K_BWMODE_5MHZ: + /* Both sample_freq and chip_freq are 10MHz (?) */ + spur_delta_phase = (spur_offset << 19) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; default: - return; + if (channel->hw_value == CHANNEL_A) { + /* Both sample_freq and chip_freq are 40MHz */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = + (spur_delta_phase >> 10); + symbol_width = + AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + } else { + /* sample_freq -> 40MHz chip_freq -> 44MHz + * (for b compatibility) */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = + (spur_offset << 8) / 55; + symbol_width = + AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + } + break; } /* Calculate pilot and magnitude masks */ @@ -1672,63 +1842,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, } } -/********************\ - Misc PHY functions -\********************/ - -int ath5k_hw_phy_disable(struct ath5k_hw *ah) -{ - /*Just a try M.F.*/ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - - return 0; -} - -/* - * Get the PHY Chip revision - */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) -{ - unsigned int i; - u32 srev; - u16 ret; - - /* - * Set the radio chip access register - */ - switch (chan) { - case CHANNEL_2GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); - break; - case CHANNEL_5GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - break; - default: - return 0; - } - - mdelay(2); - - /* ...wait until PHY is ready and read the selected radio revision */ - ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); - - for (i = 0; i < 8; i++) - ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); - - if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; - ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; - } else { - srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; - ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | - ((srev & 0x0f) << 4), 8); - } - - /* Reset to the 5GHz mode */ - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - - return ret; -} /*****************\ * Antenna control * @@ -1836,12 +1949,10 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - case CHANNEL_T: case CHANNEL_XR: ee_mode = AR5K_EEPROM_MODE_11A; break; case CHANNEL_G: - case CHANNEL_TG: ee_mode = AR5K_EEPROM_MODE_11G; break; case CHANNEL_B: @@ -2275,20 +2386,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - ctl_mode |= AR5K_CTL_11A; + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + ctl_mode |= AR5K_CTL_TURBO; + else + ctl_mode |= AR5K_CTL_11A; break; case CHANNEL_G: - ctl_mode |= AR5K_CTL_11G; + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + ctl_mode |= AR5K_CTL_TURBOG; + else + ctl_mode |= AR5K_CTL_11G; break; case CHANNEL_B: ctl_mode |= AR5K_CTL_11B; break; - case CHANNEL_T: - ctl_mode |= AR5K_CTL_TURBO; - break; - case CHANNEL_TG: - ctl_mode |= AR5K_CTL_TURBOG; - break; case CHANNEL_XR: /* Fall through */ default: @@ -2990,9 +3101,9 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, /* * Set transmission power */ -int +static int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower) + u8 ee_mode, u8 txpower, bool fast) { struct ath5k_rate_pcal_info rate_info; u8 type; @@ -3011,6 +3122,9 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, /* Initialize TX power table */ switch (ah->ah_radio) { + case AR5K_RF5110: + /* TODO */ + return 0; case AR5K_RF5111: type = AR5K_PWRTABLE_PWR_TO_PCDAC; break; @@ -3028,10 +3142,15 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - /* FIXME: Only on channel/mode change */ - ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); - if (ret) - return ret; + /* If fast is set it means we are on the same channel/mode + * so there is no need to recalculate the powertable, we 'll + * just use the cached one */ + if (!fast) { + ret = ath5k_setup_channel_powertable(ah, channel, + ee_mode, type); + if (ret) + return ret; + } /* Limit max power if we have a CTL available */ ath5k_get_max_ctl_power(ah, channel); @@ -3092,12 +3211,10 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - case CHANNEL_T: case CHANNEL_XR: ee_mode = AR5K_EEPROM_MODE_11A; break; case CHANNEL_G: - case CHANNEL_TG: ee_mode = AR5K_EEPROM_MODE_11G; break; case CHANNEL_B: @@ -3112,5 +3229,229 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, "changing txpower to %d\n", txpower); - return ath5k_hw_txpower(ah, channel, ee_mode, txpower); + return ath5k_hw_txpower(ah, channel, ee_mode, txpower, true); +} + +/*************\ + Init function +\*************/ + +int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 mode, u8 ee_mode, u8 freq, bool fast) +{ + struct ieee80211_channel *curr_channel; + int ret, i; + u32 phy_tst1; + bool fast_txp; + ret = 0; + + /* + * Sanity check for fast flag + * Don't try fast channel change when changing modulation + * mode/band. We check for chip compatibility on + * ath5k_hw_reset. + */ + curr_channel = ah->ah_current_channel; + if (fast && (channel->hw_value != curr_channel->hw_value)) + return -EINVAL; + + /* + * On fast channel change we only set the synth parameters + * while PHY is running, enable calibration and skip the rest. + */ + if (fast) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + for (i = 0; i < 100; i++) { + if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) + break; + udelay(5); + } + /* Failed */ + if (i >= 100) + return -EIO; + } + + /* + * If we don't change channel/mode skip + * tx powertable calculation and use the + * cached one. + */ + if ((channel->hw_value == curr_channel->hw_value) && + (channel->center_freq == curr_channel->center_freq)) + fast_txp = true; + else + fast_txp = false; + + /* + * Set TX power + * + * Note: We need to do that before we set + * RF buffer settings on 5211/5212+ so that we + * properly set curve indices. + */ + ret = ath5k_hw_txpower(ah, channel, ee_mode, + ah->ah_txpower.txp_max_pwr / 2, + fast_txp); + if (ret) + return ret; + + /* + * For 5210 we do all initialization using + * initvals, so we don't have to modify + * any settings (5210 also only supports + * a/aturbo modes) + */ + if ((ah->ah_version != AR5K_AR5210) && !fast) { + + /* + * Write initial RF gain settings + * This should work for both 5111/5112 + */ + ret = ath5k_hw_rfgain_init(ah, freq); + if (ret) + return ret; + + mdelay(1); + + /* + * Write RF buffer + */ + ret = ath5k_hw_rfregs_init(ah, channel, mode); + if (ret) + return ret; + + /* Write OFDM timings on 5212*/ + if (ah->ah_version == AR5K_AR5212 && + channel->hw_value & CHANNEL_OFDM) { + + ret = ath5k_hw_write_ofdm_timings(ah, channel); + if (ret) + return ret; + + /* Spur info is available only from EEPROM versions + * greater than 5.3, but the EEPROM routines will use + * static values for older versions */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424) + ath5k_hw_set_spur_mitigation_filter(ah, + channel); + } + + /*Enable/disable 802.11b mode on 5111 + (enable 2111 frequency converter + CCK)*/ + if (ah->ah_radio == AR5K_RF5111) { + if (mode == AR5K_MODE_11B) + AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + } + + } else if (ah->ah_version == AR5K_AR5210) { + mdelay(1); + /* Disable phy and wait */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + mdelay(1); + } + + /* Set channel on PHY */ + ret = ath5k_hw_channel(ah, channel); + if (ret) + return ret; + + /* + * Enable the PHY and wait until completion + * This includes BaseBand and Synthesizer + * activation. + */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); + + /* + * On 5211+ read activation -> rx delay + * and use it. + */ + if (ah->ah_version != AR5K_AR5210) { + u32 delay; + delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & + AR5K_PHY_RX_DELAY_M; + delay = (channel->hw_value & CHANNEL_CCK) ? + ((delay << 2) / 22) : (delay / 10); + if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) + delay = delay << 1; + if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) + delay = delay << 2; + /* XXX: /2 on turbo ? Let's be safe + * for now */ + udelay(100 + delay); + } else { + mdelay(1); + } + + if (fast) + /* + * Release RF Bus grant + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + else { + /* + * Perform ADC test to see if baseband is ready + * Set tx hold and check adc test register + */ + phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); + } + + /* + * Start automatic gain control calibration + * + * During AGC calibration RX path is re-routed to + * a power detector so we don't receive anything. + * + * This method is used to calibrate some static offsets + * used together with on-the fly I/Q calibration (the + * one performed via ath5k_hw_phy_calibrate), which doesn't + * interrupt rx path. + * + * While rx path is re-routed to the power detector we also + * start a noise floor calibration to measure the + * card's noise floor (the noise we measure when we are not + * transmitting or receiving anything). + * + * If we are in a noisy environment, AGC calibration may time + * out and/or noise floor calibration might timeout. + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); + + /* At the same time start I/Q calibration for QAM constellation + * -no need for CCK- */ + ah->ah_calibration = false; + if (!(mode == AR5K_MODE_11B)) { + ah->ah_calibration = true; + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_RUN); + } + + /* Wait for gain calibration to finish (we check for I/Q calibration + * during ath5k_phy_calibrate) */ + if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL, 0, false)) { + ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", + channel->center_freq); + } + + /* Restore antenna mode */ + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); + + return ret; } diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 84c717ded1c5..1849eee8235c 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -25,14 +25,52 @@ Queue Control Unit, DFS Control Unit Functions #include "debug.h" #include "base.h" + +/******************\ +* Helper functions * +\******************/ + /* - * Get properties for a transmit queue + * Get number of pending frames + * for a specific queue [5211+] */ -int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, - struct ath5k_txq_info *queue_info) +u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { - memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); - return 0; + u32 pending; + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is declared inactive */ + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return false; + + /* XXX: How about AR5K_CFG_TXCNT ? */ + if (ah->ah_version == AR5K_AR5210) + return false; + + pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); + pending &= AR5K_QCU_STS_FRMPENDCNT; + + /* It's possible to have no frames pending even if TXE + * is set. To indicate that q has not stopped return + * true */ + if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + return true; + + return pending; +} + +/* + * Set a transmit queue inactive + */ +void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) + return; + + /* This queue will be skipped in further operations */ + ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; + /*For SIMR setup*/ + AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); } /* @@ -50,6 +88,16 @@ static u16 ath5k_cw_validate(u16 cw_req) } /* + * Get properties for a transmit queue + */ +int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, + struct ath5k_txq_info *queue_info) +{ + memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); + return 0; +} + +/* * Set properties for a transmit queue */ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, @@ -172,113 +220,18 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, return queue; } -/* - * Get number of pending frames - * for a specific queue [5211+] - */ -u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) -{ - u32 pending; - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return false; - - /* XXX: How about AR5K_CFG_TXCNT ? */ - if (ah->ah_version == AR5K_AR5210) - return false; - - pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); - pending &= AR5K_QCU_STS_FRMPENDCNT; - - /* It's possible to have no frames pending even if TXE - * is set. To indicate that q has not stopped return - * true */ - if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return true; - - return pending; -} - -/* - * Set a transmit queue inactive - */ -void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) - return; - /* This queue will be skipped in further operations */ - ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; - /*For SIMR setup*/ - AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); -} +/*******************************\ +* Single QCU/DCU initialization * +\*******************************/ /* - * Set DFS properties for a transmit queue on DCU + * Set tx retry limits on DCU */ -int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, + unsigned int queue) { u32 retry_lg, retry_sh; - struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - tq = &ah->ah_txq[queue]; - - if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) - return 0; - - if (ah->ah_version == AR5K_AR5210) { - /* Only handle data queues, others will be ignored */ - if (tq->tqi_type != AR5K_TX_QUEUE_DATA) - return 0; - - /* Set Slot time */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, - AR5K_SLOT_TIME); - /* Set ACK_CTS timeout */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : - AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); - /* Set Transmit Latency */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_TRANSMIT_LATENCY_TURBO : - AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); - - /* Set IFS0 */ - if (ah->ah_turbo) { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + - tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) << - AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, - AR5K_IFS0); - } else { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + - tq->tqi_aifs * AR5K_INIT_SLOT_TIME) << - AR5K_IFS0_DIFS_S) | - AR5K_INIT_SIFS, AR5K_IFS0); - } - - /* Set IFS1 */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_PROTO_TIME_CNTRL_TURBO : - AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set AR5K_PHY_SETTLING */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x1C, - AR5K_PHY_SETTLING); - /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | - AR5K_PHY_TURBO_SHORT | 0x2020) : - (AR5K_PHY_FRAME_CTL_INI | 0x1020), - AR5K_PHY_FRAME_CTL_5210); - } /* * Calculate and set retry limits @@ -293,8 +246,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) retry_sh = AR5K_INIT_SH_RETRY; } - /*No QCU/DCU [5210]*/ + /* Single data queue on AR5210 */ if (ah->ah_version == AR5K_AR5210) { + struct ath5k_txq_info *tq = &ah->ah_txq[queue]; + + if (queue > 0) + return; + ath5k_hw_reg_write(ah, (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, @@ -304,8 +262,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), AR5K_NODCU_RETRY_LMT); + /* DCU on AR5211+ */ } else { - /*QCU/DCU [5211+]*/ ath5k_hw_reg_write(ah, AR5K_REG_SM(AR5K_INIT_SLG_RETRY, AR5K_DCU_RETRY_LMT_SLG_RETRY) | @@ -314,219 +272,393 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); + } + return; +} + +/** + * ath5k_hw_reset_tx_queue - Initialize a single hw queue + * + * @ah The &struct ath5k_hw + * @queue The hw queue number + * + * Set DFS properties for the given transmit queue on DCU + * and configures all queue-specific parameters. + */ +int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - /*===Rest is also for QCU/DCU only [5211+]===*/ + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - /* - * Set contention window (cw_min/cw_max) - * and arbitrated interframe space (aifs)... - */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | - AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | - AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), - AR5K_QUEUE_DFS_LOCAL_IFS(queue)); - - /* - * Set misc registers - */ - /* Enable DCU early termination for this queue */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_DCU_EARLY); + tq = &ah->ah_txq[queue]; + + /* Skip if queue inactive or if we are on AR5210 + * that doesn't have QCU/DCU */ + if ((ah->ah_version == AR5K_AR5210) || + (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)) + return 0; + + /* + * Set contention window (cw_min/cw_max) + * and arbitrated interframe space (aifs)... + */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | + AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | + AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), + AR5K_QUEUE_DFS_LOCAL_IFS(queue)); + + /* + * Set tx retry limits for this queue + */ + ath5k_hw_set_tx_retry_limits(ah, queue); + + + /* + * Set misc registers + */ + + /* Enable DCU to wait for next fragment from QCU */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_FRAG_WAIT); - /* Enable DCU to wait for next fragment from QCU */ + /* On Maui and Spirit use the global seqnum on DCU */ + if (ah->ah_mac_version < AR5K_SREV_AR5211) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_FRAG_WAIT); - - /* On Maui and Spirit use the global seqnum on DCU */ - if (ah->ah_mac_version < AR5K_SREV_AR5211) - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_SEQNUM_CTL); - - if (tq->tqi_cbr_period) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, - AR5K_QCU_CBRCFG_INTVAL) | - AR5K_REG_SM(tq->tqi_cbr_overflow_limit, - AR5K_QCU_CBRCFG_ORN_THRES), - AR5K_QUEUE_CBRCFG(queue)); + AR5K_DCU_MISC_SEQNUM_CTL); + + /* Constant bit rate period */ + if (tq->tqi_cbr_period) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, + AR5K_QCU_CBRCFG_INTVAL) | + AR5K_REG_SM(tq->tqi_cbr_overflow_limit, + AR5K_QCU_CBRCFG_ORN_THRES), + AR5K_QUEUE_CBRCFG(queue)); + + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_CBR); + + if (tq->tqi_cbr_overflow_limit) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_CBR); - if (tq->tqi_cbr_overflow_limit) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_CBR_THRES_ENABLE); - } + } - if (tq->tqi_ready_time && - (tq->tqi_type != AR5K_TX_QUEUE_CAB)) - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, - AR5K_QCU_RDYTIMECFG_INTVAL) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - if (tq->tqi_burst_time) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, - AR5K_DCU_CHAN_TIME_DUR) | - AR5K_DCU_CHAN_TIME_ENABLE, - AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); - - if (tq->tqi_flags - & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), + /* Ready time interval */ + if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB)) + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, + AR5K_QCU_RDYTIMECFG_INTVAL) | + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); + + if (tq->tqi_burst_time) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, + AR5K_DCU_CHAN_TIME_DUR) | + AR5K_DCU_CHAN_TIME_ENABLE, + AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_RDY_VEOL_POLICY); - } + } - if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, - AR5K_QUEUE_DFS_MISC(queue)); + /* Enable/disable Post frame backoff */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, + AR5K_QUEUE_DFS_MISC(queue)); - if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, - AR5K_QUEUE_DFS_MISC(queue)); + /* Enable/disable fragmentation burst backoff */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, + AR5K_QUEUE_DFS_MISC(queue)); - /* - * Set registers by queue type - */ - switch (tq->tqi_type) { - case AR5K_TX_QUEUE_BEACON: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + /* + * Set registers by queue type + */ + switch (tq->tqi_type) { + case AR5K_TX_QUEUE_BEACON: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_FRSHED_DBA_GT | AR5K_QCU_MISC_CBREXP_BCN_DIS | AR5K_QCU_MISC_BCN_ENABLE); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_DCU_MISC_ARBLOCK_CTL_S) | AR5K_DCU_MISC_ARBLOCK_IGNORE | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_DCU_MISC_BCN_ENABLE); - break; + break; - case AR5K_TX_QUEUE_CAB: - /* XXX: use BCN_SENT_GT, if we can figure out how */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_DIS | - AR5K_QCU_MISC_CBREXP_BCN_DIS); + case AR5K_TX_QUEUE_CAB: + /* XXX: use BCN_SENT_GT, if we can figure out how */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_DBA_GT | + AR5K_QCU_MISC_CBREXP_DIS | + AR5K_QCU_MISC_CBREXP_BCN_DIS); - ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - - (AR5K_TUNE_SW_BEACON_RESP - - AR5K_TUNE_DMA_BEACON_RESP) - + ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - + (AR5K_TUNE_SW_BEACON_RESP - + AR5K_TUNE_DMA_BEACON_RESP) - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S)); - break; + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_DCU_MISC_ARBLOCK_CTL_S)); + break; - case AR5K_TX_QUEUE_UAPSD: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBREXP_DIS); - break; + case AR5K_TX_QUEUE_UAPSD: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_CBREXP_DIS); + break; - case AR5K_TX_QUEUE_DATA: - default: + case AR5K_TX_QUEUE_DATA: + default: break; - } - - /* TODO: Handle frame compression */ - - /* - * Enable interrupts for this tx queue - * in the secondary interrupt mask registers - */ - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); - - /* Update secondary interrupt mask registers */ - - /* Filter out inactive queues */ - ah->ah_txq_imr_txok &= ah->ah_txq_status; - ah->ah_txq_imr_txerr &= ah->ah_txq_status; - ah->ah_txq_imr_txurn &= ah->ah_txq_status; - ah->ah_txq_imr_txdesc &= ah->ah_txq_status; - ah->ah_txq_imr_txeol &= ah->ah_txq_status; - ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; - ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; - ah->ah_txq_imr_qtrig &= ah->ah_txq_status; - ah->ah_txq_imr_nofrm &= ah->ah_txq_status; - - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, - AR5K_SIMR0_QCU_TXOK) | - AR5K_REG_SM(ah->ah_txq_imr_txdesc, - AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, - AR5K_SIMR1_QCU_TXERR) | - AR5K_REG_SM(ah->ah_txq_imr_txeol, - AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); - /* Update simr2 but don't overwrite rest simr2 settings */ - AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); - AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, - AR5K_REG_SM(ah->ah_txq_imr_txurn, - AR5K_SIMR2_QCU_TXURN)); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, - AR5K_SIMR3_QCBRORN) | - AR5K_REG_SM(ah->ah_txq_imr_cbrurn, - AR5K_SIMR3_QCBRURN), AR5K_SIMR3); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, - AR5K_SIMR4_QTRIG), AR5K_SIMR4); - /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, - AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); - /* No queue has TXNOFRM enabled, disable the interrupt - * by setting AR5K_TXNOFRM to zero */ - if (ah->ah_txq_imr_nofrm == 0) - ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); - - /* Set QCU mask for this DCU to save power */ - AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); } + /* TODO: Handle frame compression */ + + /* + * Enable interrupts for this tx queue + * in the secondary interrupt mask registers + */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); + + /* Update secondary interrupt mask registers */ + + /* Filter out inactive queues */ + ah->ah_txq_imr_txok &= ah->ah_txq_status; + ah->ah_txq_imr_txerr &= ah->ah_txq_status; + ah->ah_txq_imr_txurn &= ah->ah_txq_status; + ah->ah_txq_imr_txdesc &= ah->ah_txq_status; + ah->ah_txq_imr_txeol &= ah->ah_txq_status; + ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; + ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; + ah->ah_txq_imr_qtrig &= ah->ah_txq_status; + ah->ah_txq_imr_nofrm &= ah->ah_txq_status; + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, + AR5K_SIMR0_QCU_TXOK) | + AR5K_REG_SM(ah->ah_txq_imr_txdesc, + AR5K_SIMR0_QCU_TXDESC), + AR5K_SIMR0); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, + AR5K_SIMR1_QCU_TXERR) | + AR5K_REG_SM(ah->ah_txq_imr_txeol, + AR5K_SIMR1_QCU_TXEOL), + AR5K_SIMR1); + + /* Update SIMR2 but don't overwrite rest simr2 settings */ + AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); + AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, + AR5K_REG_SM(ah->ah_txq_imr_txurn, + AR5K_SIMR2_QCU_TXURN)); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, + AR5K_SIMR3_QCBRORN) | + AR5K_REG_SM(ah->ah_txq_imr_cbrurn, + AR5K_SIMR3_QCBRURN), + AR5K_SIMR3); + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, + AR5K_SIMR4_QTRIG), AR5K_SIMR4); + + /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, + AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); + + /* No queue has TXNOFRM enabled, disable the interrupt + * by setting AR5K_TXNOFRM to zero */ + if (ah->ah_txq_imr_nofrm == 0) + ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); + + /* Set QCU mask for this DCU to save power */ + AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); + return 0; } -/* - * Set slot time on DCU + +/**************************\ +* Global QCU/DCU functions * +\**************************/ + +/** + * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU + * + * @ah The &struct ath5k_hw + * @slot_time Slot time in us + * + * Sets the global IFS intervals on DCU (also works on AR5210) for + * the given slot time and the current bwmode. */ -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) +int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) { + struct ieee80211_channel *channel = ah->ah_current_channel; + struct ath5k_softc *sc = ah->ah_sc; + struct ieee80211_rate *rate; + u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) return -EINVAL; - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); + sifs = ath5k_hw_get_default_sifs(ah); + sifs_clock = ath5k_hw_htoclock(ah, sifs); + + /* EIFS + * Txtime of ack at lowest rate + SIFS + DIFS + * (DIFS = SIFS + 2 * Slot time) + * + * Note: HAL has some predefined values for EIFS + * Turbo: (37 + 2 * 6) + * Default: (74 + 2 * 9) + * Half: (149 + 2 * 13) + * Quarter: (298 + 2 * 21) + * + * (74 + 2 * 6) for AR5210 default and turbo ! + * + * According to the formula we have + * ack_tx_time = 25 for turbo and + * ack_tx_time = 42.5 * clock multiplier + * for default/half/quarter. + * + * This can't be right, 42 is what we would get + * from ath5k_hw_get_frame_dur_for_bwmode or + * ieee80211_generic_frame_duration for zero frame + * length and without SIFS ! + * + * Also we have different lowest rate for 802.11a + */ + if (channel->hw_value & CHANNEL_5GHZ) + rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; else - ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); + rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; + + ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + + /* ack_tx_time includes an SIFS already */ + eifs = ack_tx_time + sifs + 2 * slot_time; + eifs_clock = ath5k_hw_htoclock(ah, eifs); + + /* Set IFS settings on AR5210 */ + if (ah->ah_version == AR5K_AR5210) { + u32 pifs, pifs_clock, difs, difs_clock; + + /* Set slot time */ + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); + + /* Set EIFS */ + eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS); + + /* PIFS = Slot time + SIFS */ + pifs = slot_time + sifs; + pifs_clock = ath5k_hw_htoclock(ah, pifs); + pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS); + + /* DIFS = SIFS + 2 * Slot time */ + difs = sifs + 2 * slot_time; + difs_clock = ath5k_hw_htoclock(ah, difs); + + /* Set SIFS/DIFS */ + ath5k_hw_reg_write(ah, (difs_clock << + AR5K_IFS0_DIFS_S) | sifs_clock, + AR5K_IFS0); + + /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */ + ath5k_hw_reg_write(ah, pifs_clock | eifs_clock | + (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S), + AR5K_IFS1); + + return 0; + } + + /* Set IFS slot time */ + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); + + /* Set EIFS interval */ + ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS); + + /* Set SIFS interval in usecs */ + AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC, + sifs); + + /* Set SIFS interval in clock cycles */ + ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS); return 0; } + +int ath5k_hw_init_queues(struct ath5k_hw *ah) +{ + int i, ret; + + /* TODO: HW Compression support for data queues */ + /* TODO: Burst prefetch for data queues */ + + /* + * Reset queues and start beacon timers at the end of the reset routine + * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping + * Note: If we want we can assign multiple qcus on one dcu. + */ + if (ah->ah_version != AR5K_AR5210) + for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { + ret = ath5k_hw_reset_tx_queue(ah, i); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "failed to reset TX queue #%d\n", i); + return ret; + } + } + else + /* No QCU/DCU on AR5210, just set tx + * retry limits. We set IFS parameters + * on ath5k_hw_set_ifs_intervals */ + ath5k_hw_set_tx_retry_limits(ah, 0); + + /* Set the turbo flag when operating on 40MHz */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) + AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_TURBO_MODE); + + /* If we didn't set IFS timings through + * ath5k_hw_set_coverage_class make sure + * we set them here */ + if (!ah->ah_coverage_class) { + unsigned int slot_time = ath5k_hw_get_default_slottime(ah); + ath5k_hw_set_ifs_intervals(ah, slot_time); + } + + return 0; +} diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index ca79ecd832fd..7ad05d401ab5 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -787,6 +787,7 @@ #define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S 4 #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ @@ -1311,7 +1312,7 @@ #define AR5K_IFS1_EIFS 0x03fff000 #define AR5K_IFS1_EIFS_S 12 #define AR5K_IFS1_CS_EN 0x04000000 - +#define AR5K_IFS1_CS_EN_S 26 /* * CFP duration register @@ -2058,6 +2059,7 @@ #define AR5K_PHY_SCAL 0x9878 #define AR5K_PHY_SCAL_32MHZ 0x0000000e +#define AR5K_PHY_SCAL_32MHZ_5311 0x00000008 #define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a #define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 @@ -2244,6 +2246,8 @@ #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) /*---[5111+]---*/ +#define AR5K_PHY_FRAME_CTL_WIN_LEN 0x00000003 /* Force window length (?) */ +#define AR5K_PHY_FRAME_CTL_WIN_LEN_S 0 #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 #define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ @@ -2558,3 +2562,28 @@ */ #define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 #define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) + +/* + * Platform registers for WiSoC + */ +#define AR5K_AR5312_RESET 0xbc003020 +#define AR5K_AR5312_RESET_BB0_COLD 0x00000004 +#define AR5K_AR5312_RESET_BB1_COLD 0x00000200 +#define AR5K_AR5312_RESET_WMAC0 0x00002000 +#define AR5K_AR5312_RESET_BB0_WARM 0x00004000 +#define AR5K_AR5312_RESET_WMAC1 0x00020000 +#define AR5K_AR5312_RESET_BB1_WARM 0x00040000 + +#define AR5K_AR5312_ENABLE 0xbc003080 +#define AR5K_AR5312_ENABLE_WLAN0 0x00000001 +#define AR5K_AR5312_ENABLE_WLAN1 0x00000008 + +#define AR5K_AR2315_RESET 0xb1000004 +#define AR5K_AR2315_RESET_WMAC 0x00000001 +#define AR5K_AR2315_RESET_BB_WARM 0x00000002 + +#define AR5K_AR2315_AHB_ARB_CTL 0xb1000008 +#define AR5K_AR2315_AHB_ARB_CTL_WLAN 0x00000002 + +#define AR5K_AR2315_BYTESWAP 0xb100000c +#define AR5K_AR2315_BYTESWAP_WMAC 0x00000002 diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 5b179d01f97d..bc84aaa31446 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -27,11 +27,17 @@ #include <linux/pci.h> /* To determine if a card is pci-e */ #include <linux/log2.h> +#include <linux/platform_device.h> #include "ath5k.h" #include "reg.h" #include "base.h" #include "debug.h" + +/******************\ +* Helper functions * +\******************/ + /* * Check if a register write has been completed */ @@ -53,146 +59,267 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, return (i <= 0) ? -EAGAIN : 0; } + +/*************************\ +* Clock related functions * +\*************************/ + /** - * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * ath5k_hw_htoclock - Translate usec to hw clock units * - * @ah: the &struct ath5k_hw - * @channel: the currently set channel upon reset - * - * Write the delta slope coefficient (used on pilot tracking ?) for OFDM - * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). + * @ah: The &struct ath5k_hw + * @usec: value in microseconds + */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) +{ + struct ath_common *common = ath5k_hw_common(ah); + return usec * common->clockrate; +} + +/** + * ath5k_hw_clocktoh - Translate hw clock units to usec + * @clock: value in hw clock units + */ +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) +{ + struct ath_common *common = ath5k_hw_common(ah); + return clock / common->clockrate; +} + +/** + * ath5k_hw_init_core_clock - Initialize core clock * - * Since delta slope is floating point we split it on its exponent and - * mantissa and provide these values on hw. + * @ah The &struct ath5k_hw * - * For more infos i think this patent is related - * http://www.freepatentsonline.com/7184495.html + * Initialize core clock parameters (usec, usec32, latencies etc). */ -static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) { - /* Get exponent and mantissa and set it */ - u32 coef_scaled, coef_exp, coef_man, - ds_coef_exp, ds_coef_man, clock; - - BUG_ON(!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)); - - /* Get coefficient - * ALGO: coef = (5 * clock / carrier_freq) / 2 - * we scale coef by shifting clock value by 24 for - * better precision since we use integers */ - /* TODO: Half/quarter rate */ - clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; - coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; - - /* Get exponent - * ALGO: coef_exp = 14 - highest set bit position */ - coef_exp = ilog2(coef_scaled); - - /* Doesn't make sense if it's zero*/ - if (!coef_scaled || !coef_exp) - return -EINVAL; + struct ieee80211_channel *channel = ah->ah_current_channel; + struct ath_common *common = ath5k_hw_common(ah); + u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs; + + /* + * Set core clock frequency + */ + if (channel->hw_value & CHANNEL_5GHZ) + clock = 40; /* 802.11a */ + else if (channel->hw_value & CHANNEL_CCK) + clock = 22; /* 802.11b */ + else + clock = 44; /* 802.11g */ + + /* Use clock multiplier for non-default + * bwmode */ + switch (ah->ah_bwmode) { + case AR5K_BWMODE_40MHZ: + clock *= 2; + break; + case AR5K_BWMODE_10MHZ: + clock /= 2; + break; + case AR5K_BWMODE_5MHZ: + clock /= 4; + break; + default: + break; + } - /* Note: we've shifted coef_scaled by 24 */ - coef_exp = 14 - (coef_exp - 24); + common->clockrate = clock; + /* + * Set USEC parameters + */ + /* Set USEC counter on PCU*/ + usec = clock - 1; + usec = AR5K_REG_SM(usec, AR5K_USEC_1); - /* Get mantissa (significant digits) - * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ - coef_man = coef_scaled + - (1 << (24 - coef_exp - 1)); + /* Set usec duration on DCU */ + if (ah->ah_version != AR5K_AR5210) + AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, + AR5K_DCU_GBL_IFS_MISC_USEC_DUR, + clock); - /* Calculate delta slope coefficient exponent - * and mantissa (remove scaling) and set them on hw */ - ds_coef_man = coef_man >> (24 - coef_exp); - ds_coef_exp = coef_exp - 16; + /* Set 32MHz USEC counter */ + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_radio == AR5K_RF2317)) + /* Remain on 40MHz clock ? */ + sclock = 40 - 1; + else + sclock = 32 - 1; + sclock = AR5K_REG_SM(sclock, AR5K_USEC_32); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + /* + * Set tx/rx latencies + */ + usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); + txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); - return 0; -} + /* + * 5210 initvals don't include usec settings + * so we need to use magic values here for + * tx/rx latencies + */ + if (ah->ah_version == AR5K_AR5210) { + /* same for turbo */ + txlat = AR5K_INIT_TX_LATENCY_5210; + rxlat = AR5K_INIT_RX_LATENCY_5210; + } + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + /* 5311 has different tx/rx latency masks + * from 5211, since we deal 5311 the same + * as 5211 when setting initvals, shift + * values here to their proper locations + * + * Note: Initvals indicate tx/rx/ latencies + * are the same for turbo mode */ + txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210); + rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210); + } else + switch (ah->ah_bwmode) { + case AR5K_BWMODE_10MHZ: + txlat = AR5K_REG_SM(txlat * 2, + AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ; + break; + case AR5K_BWMODE_5MHZ: + txlat = AR5K_REG_SM(txlat * 4, + AR5K_USEC_TX_LATENCY_5211); + rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ; + break; + case AR5K_BWMODE_40MHZ: + txlat = AR5K_INIT_TX_LAT_MIN; + rxlat = AR5K_REG_SM(rxlat / 2, + AR5K_USEC_RX_LATENCY_5211); + txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; + break; + default: + break; + } -/* - * index into rates for control rates, we can set it up like this because - * this is only used for AR5212 and we know it supports G mode - */ -static const unsigned int control_rates[] = - { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; + usec_reg = (usec | sclock | txlat | rxlat); + ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC); -/** - * ath5k_hw_write_rate_duration - fill rate code to duration table - * - * @ah: the &struct ath5k_hw - * @mode: one of enum ath5k_driver_mode - * - * Write the rate code to duration table upon hw reset. This is a helper for - * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on - * the hardware, based on current mode, for each rate. The rates which are - * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have - * different rate code so we write their value twice (one for long preample - * and one for short). + /* On 5112 set tx frane to tx data start delay */ + if (ah->ah_radio == AR5K_RF5112) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2, + AR5K_PHY_RF_CTL2_TXF2TXD_START, + txf2txs); + } +} + +/* + * If there is an external 32KHz crystal available, use it + * as ref. clock instead of 32/40MHz clock and baseband clocks + * to save power during sleep or restore normal 32/40MHz + * operation. * - * Note: Band doesn't matter here, if we set the values for OFDM it works - * on both a and g modes. So all we have to do is set values for all g rates - * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ - * quarter rate mode, we need to use another set of bitrates (that's why we - * need the mode parameter) but we don't handle these proprietary modes yet. + * XXX: When operating on 32KHz certain PHY registers (27 - 31, + * 123 - 127) require delay on access. */ -static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, - unsigned int mode) +static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) { - struct ath5k_softc *sc = ah->ah_sc; - struct ieee80211_rate *rate; - unsigned int i; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 scal, spending; - /* Write rate duration table */ - for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { - u32 reg; - u16 tx_time; + /* Only set 32KHz settings if we have an external + * 32KHz crystal present */ + if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || + AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && + enable) { - rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; + /* 1 usec/cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); + /* Set up tsf increment on each cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - /* Set ACK timeout */ - reg = AR5K_RATE_DUR(rate->hw_value); + /* Set baseband sleep control registers + * and sleep control rate */ + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - /* An ACK frame consists of 10 bytes. If you add the FCS, - * which ieee80211_generic_frame_duration() adds, - * its 14 bytes. Note we use the control rate and not the - * actual rate for this rate. See mac80211 tx.c - * ieee80211_duration() for a brief description of - * what rate we should choose to TX ACKs. */ - tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, - NULL, 10, rate)); + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - ath5k_hw_reg_write(ah, tx_time, reg); + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); + } else { + ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); + } - if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) - continue; + /* Enable sleep clock operation */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); - /* - * We're not distinguishing short preamble here, - * This is true, all we'll get is a longer value here - * which is not necessarilly bad. We could use - * export ieee80211_frame_duration() but that needs to be - * fixed first to be properly used by mac802111 drivers: - * - * - remove erp stuff and let the routine figure ofdm - * erp rates - * - remove passing argument ieee80211_local as - * drivers don't have access to it - * - move drivers using ieee80211_generic_frame_duration() - * to this - */ - ath5k_hw_reg_write(ah, tx_time, - reg + (AR5K_SET_SHORT_PREAMBLE << 2)); + } else { + + /* Disable sleep clock operation and + * restore default parameters */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); + + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); + + /* Set DAC/ADC delays */ + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); + ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); + + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) + scal = AR5K_PHY_SCAL_32MHZ_2417; + else if (ee->ee_is_hb63) + scal = AR5K_PHY_SCAL_32MHZ_HB63; + else + scal = AR5K_PHY_SCAL_32MHZ; + ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); + + ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_radio == AR5K_RF2316) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); + + /* Set up tsf increment on each cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); } } + +/*********************\ +* Reset/Sleep control * +\*********************/ + /* * Reset chipset */ @@ -236,6 +363,64 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) } /* + * Reset AHB chipset + * AR5K_RESET_CTL_PCU flag resets WMAC + * AR5K_RESET_CTL_BASEBAND flag resets WBB + */ +static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) +{ + u32 mask = flags ? flags : ~0U; + volatile u32 *reg; + u32 regval; + u32 val = 0; + + /* ah->ah_mac_srev is not available at this point yet */ + if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { + reg = (u32 *) AR5K_AR2315_RESET; + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR2315_RESET_WMAC; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR2315_RESET_BB_WARM; + } else { + reg = (u32 *) AR5K_AR5312_RESET; + if (to_platform_device(ah->ah_sc->dev)->id == 0) { + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR5312_RESET_WMAC0; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR5312_RESET_BB0_COLD | + AR5K_AR5312_RESET_BB0_WARM; + } else { + if (mask & AR5K_RESET_CTL_PCU) + val |= AR5K_AR5312_RESET_WMAC1; + if (mask & AR5K_RESET_CTL_BASEBAND) + val |= AR5K_AR5312_RESET_BB1_COLD | + AR5K_AR5312_RESET_BB1_WARM; + } + } + + /* Put BB/MAC into reset */ + regval = __raw_readl(reg); + __raw_writel(regval | val, reg); + regval = __raw_readl(reg); + udelay(100); + + /* Bring BB/MAC out of reset */ + __raw_writel(regval & ~val, reg); + regval = __raw_readl(reg); + + /* + * Reset configuration register (for hw byte-swap). Note that this + * is only set for big endian. We do the necessary magic in + * AR5K_INIT_CFG. + */ + if ((flags & AR5K_RESET_CTL_PCU) == 0) + ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); + + return 0; +} + + +/* * Sleep control */ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, @@ -334,6 +519,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) u32 bus_flags; int ret; + if (ath5k_get_bus_type(ah) == ATH_AHB) + return 0; + /* Make sure device is awake */ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { @@ -349,7 +537,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + bus_flags = (pdev && pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; if (ah->ah_version == AR5K_AR5210) { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | @@ -378,7 +566,6 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) /* * Bring up MAC + PHY Chips and program PLL - * TODO: Half/Quarter rate support */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) { @@ -390,11 +577,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) mode = 0; clock = 0; - /* Wakeup the device */ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); - return ret; + if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) { + /* Wakeup the device */ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + return ret; + } } /* @@ -405,7 +594,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) * we ingore that flag for PCI-E cards. On PCI cards * this flag gets cleared after 64 PCI clocks. */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + bus_flags = (pdev && pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; if (ah->ah_version == AR5K_AR5210) { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | @@ -413,8 +602,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); mdelay(2); } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); + if (ath5k_get_bus_type(ah) == ATH_AHB) + ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND); + else + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); } if (ret) { @@ -429,9 +622,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return ret; } - /* ...clear reset control register and pull device out of - * warm reset */ - if (ath5k_hw_nic_reset(ah, 0)) { + /* ...reset configuration regiter on Wisoc ... + * ...clear reset control register and pull device out of + * warm reset on others */ + if (ath5k_get_bus_type(ah) == ATH_AHB) + ret = ath5k_hw_wisoc_reset(ah, 0); + else + ret = ath5k_hw_nic_reset(ah, 0); + + if (ret) { ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); return -EIO; } @@ -466,7 +665,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) * CCK headers) operation. We need to test * this, 5211 might support ofdm-only g after * all, there are also initial register values - * in the code for g mode (see initvals.c). */ + * in the code for g mode (see initvals.c). + */ if (ah->ah_version == AR5K_AR5211) mode |= AR5K_PHY_MODE_MOD_OFDM; else @@ -479,6 +679,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) } else if (flags & CHANNEL_5GHZ) { mode |= AR5K_PHY_MODE_FREQ_5GHZ; + /* Different PLL setting for 5413 */ if (ah->ah_radio == AR5K_RF5413) clock = AR5K_PHY_PLL_40MHZ_5413; else @@ -496,12 +697,29 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return -EINVAL; } - if (flags & CHANNEL_TURBO) - turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; + /*XXX: Can bwmode be used with dynamic mode ? + * (I don't think it supports 44MHz) */ + /* On 2425 initvals TURBO_SHORT is not pressent */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { + turbo = AR5K_PHY_TURBO_MODE | + (ah->ah_radio == AR5K_RF2425) ? 0 : + AR5K_PHY_TURBO_SHORT; + } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) { + if (ah->ah_radio == AR5K_RF5413) { + mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? + AR5K_PHY_MODE_HALF_RATE : + AR5K_PHY_MODE_QUARTER_RATE; + } else if (ah->ah_version == AR5K_AR5212) { + clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? + AR5K_PHY_PLL_HALF_RATE : + AR5K_PHY_PLL_QUARTER_RATE; + } + } + } else { /* Reset the device */ /* ...enable Atheros turbo mode if requested */ - if (flags & CHANNEL_TURBO) + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, AR5K_PHY_TURBO); } @@ -522,107 +740,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) return 0; } -/* - * If there is an external 32KHz crystal available, use it - * as ref. clock instead of 32/40MHz clock and baseband clocks - * to save power during sleep or restore normal 32/40MHz - * operation. - * - * XXX: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. - */ -static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 scal, spending, usec32; - - /* Only set 32KHz settings if we have an external - * 32KHz crystal present */ - if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || - AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && - enable) { - - /* 1 usec/cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - - /* Set baseband sleep control registers - * and sleep control rate */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); - } else { - ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); - } - - /* Enable sleep clock operation */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - } else { - - /* Disable sleep clock operation and - * restore default parameters */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); - - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); - - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - - ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413)) - usec32 = 39; - else - usec32 = 31; - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); - - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); - } -} +/**************************************\ +* Post-initvals register modifications * +\**************************************/ /* TODO: Half/Quarter rate */ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, @@ -663,22 +784,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_DCU_DBL_BUF_DIS); - /* Set DAC/ADC delays */ - if (ah->ah_version == AR5K_AR5212) { - u32 scal; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - } - /* Set fast ADC */ if ((ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + (ah->ah_radio == AR5K_RF2317) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { u32 fast_adc = true; if (channel->center_freq == 2462 || @@ -706,26 +815,54 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, } if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - u32 usec_reg; - /* 5311 has different tx/rx latency masks - * from 5211, since we deal 5311 the same - * as 5211 when setting initvals, shift - * values here to their proper locations */ - usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); - ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | - AR5K_USEC_32 | - AR5K_USEC_TX_LATENCY_5211 | - AR5K_REG_SM(29, - AR5K_USEC_RX_LATENCY_5210)), - AR5K_USEC_5211); /* Clear QCU/DCU clock gating register */ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311, + AR5K_PHY_SCAL); /* Enable PCU FIFO corruption ECO */ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, AR5K_DIAG_SW_ECO_ENABLE); } + + if (ah->ah_bwmode) { + /* Increase PHY switch and AGC settling time + * on turbo mode (ath5k_hw_commit_eeprom_settings + * will override settling time if available) */ + if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_AGC, + AR5K_AGC_SETTLING_TURBO); + + /* XXX: Initvals indicate we only increase + * switch time on AR5212, 5211 and 5210 + * only change agc time (bug?) */ + if (ah->ah_version == AR5K_AR5212) + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_SWITCH, + AR5K_SWITCH_SETTLING_TURBO); + + if (ah->ah_version == AR5K_AR5210) { + /* Set Frame Control Register */ + ath5k_hw_reg_write(ah, + (AR5K_PHY_FRAME_CTL_INI | + AR5K_PHY_TURBO_MODE | + AR5K_PHY_TURBO_SHORT | 0x2020), + AR5K_PHY_FRAME_CTL_5210); + } + /* On 5413 PHY force window length for half/quarter rate*/ + } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) && + (ah->ah_mac_srev <= AR5K_SREV_AR5414)) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211, + AR5K_PHY_FRAME_CTL_WIN_LEN, + 3); + } + } else if (ah->ah_version == AR5K_AR5210) { + /* Set Frame Control Register for normal operation */ + ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020), + AR5K_PHY_FRAME_CTL_5210); + } } static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, @@ -734,6 +871,10 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; s16 cck_ofdm_pwr_delta; + /* TODO: Add support for AR5210 EEPROM */ + if (ah->ah_version == AR5K_AR5210) + return; + /* Adjust power delta for channel 14 */ if (channel->center_freq == 2484) cck_ofdm_pwr_delta = @@ -772,7 +913,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), AR5K_PHY_NFTHRES); - if ((channel->hw_value & CHANNEL_TURBO) && + if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { /* Switch settling time (Turbo) */ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, @@ -870,143 +1011,183 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); } -/* - * Main reset function - */ + +/*********************\ +* Main reset function * +\*********************/ + int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel) + struct ieee80211_channel *channel, bool fast, bool skip_pcu) { - struct ath_common *common = ath5k_hw_common(ah); - u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; - u32 phy_tst1; + u32 s_seq[10], s_led[3], tsf_up, tsf_lo; u8 mode, freq, ee_mode; int i, ret; ee_mode = 0; - staid1_flags = 0; tsf_up = 0; tsf_lo = 0; freq = 0; mode = 0; /* - * Save some registers before a reset + * Sanity check for fast flag + * Fast channel change only available + * on AR2413/AR5413. */ - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) + fast = 0; - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - mode = AR5K_MODE_11A; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - mode = AR5K_MODE_11G; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - mode = AR5K_MODE_11B; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11B; - break; - case CHANNEL_T: - mode = AR5K_MODE_11A_TURBO; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_TG: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "TurboG mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_11G_TURBO; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_XR: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "XR mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_XR; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - default: + /* Disable sleep clock operation + * to avoid register access delay on certain + * PHY registers */ + if (ah->ah_version == AR5K_AR5212) + ath5k_hw_set_sleep_clock(ah, false); + + /* + * Stop PCU + */ + ath5k_hw_stop_rx_pcu(ah); + + /* + * Stop DMA + * + * Note: If DMA didn't stop continue + * since only a reset will fix it. + */ + ret = ath5k_hw_dma_stop(ah); + + /* RF Bus grant won't work if we have pending + * frames */ + if (ret && fast) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "DMA didn't stop, falling back to normal reset\n"); + fast = 0; + /* Non fatal, just continue with + * normal reset */ + ret = 0; + } + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + mode = AR5K_MODE_11A; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + + if (ah->ah_version <= AR5K_AR5211) { ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); + "G mode not available on 5210/5211"); return -EINVAL; } - if (change_channel) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); + mode = AR5K_MODE_11G; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); - } + if (ah->ah_version < AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "B mode not available on 5210"); + return -EINVAL; + } - /* TSF accelerates on AR5211 during reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); - } + mode = AR5K_MODE_11B; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11B; + break; + case CHANNEL_XR: + if (ah->ah_version == AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "XR mode not available on 5211"); + return -EINVAL; } + mode = AR5K_MODE_XR; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } - if (ah->ah_version == AR5K_AR5212) { - /* Restore normal 32/40MHz clock operation - * to avoid register access delay on certain - * PHY registers */ - ath5k_hw_set_sleep_clock(ah, false); + /* + * If driver requested fast channel change and DMA has stopped + * go on. If it fails continue with a normal reset. + */ + if (fast) { + ret = ath5k_hw_phy_init(ah, channel, mode, + ee_mode, freq, true); + if (ret) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "fast chan change failed, falling back to normal reset\n"); + /* Non fatal, can happen eg. + * on mode change */ + ret = 0; + } else + return 0; + } - /* Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings */ - if (change_channel && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); + /* + * Save some registers before a reset + */ + if (ah->ah_version != AR5K_AR5210) { + /* + * Save frame sequence count + * For revs. after Oahu, only save + * seq num for DCU 0 (Global seq num) + */ + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + + for (i = 0; i < 10; i++) + s_seq[i] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(i)); + + } else { + s_seq[0] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(0)); + } + + /* TSF accelerates on AR5211 during reset + * As a workaround save it here and restore + * it later so that it's back in time after + * reset. This way it'll get re-synced on the + * next beacon without breaking ad-hoc. + * + * On AR5212 TSF is almost preserved across a + * reset so it stays back in time anyway and + * we don't have to save/restore it. + * + * XXX: Since this breaks power saving we have + * to disable power saving until we receive the + * next beacon, so we can resync beacon timers */ + if (ah->ah_version == AR5K_AR5211) { + tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); } } + /*GPIOs*/ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - /* AR5K_STA_ID1 flags, only preserve antenna - * settings and ack/cts rate mode */ - staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & - (AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_DESC_ANTENNA | - AR5K_STA_ID1_RTS_DEF_ANTENNA | - AR5K_STA_ID1_ACKCTS_6MB | - AR5K_STA_ID1_BASE_RATE_11B | - AR5K_STA_ID1_SELFGEN_DEF_ANT); + + /* + * Since we are going to write rf buffer + * check if we have any pending gain_F + * optimization settings + */ + if (ah->ah_version == AR5K_AR5212 && + (ah->ah_radio <= AR5K_RF5112)) { + if (!fast && ah->ah_rf_banks != NULL) + ath5k_hw_gainf_calibrate(ah); + } /* Wakeup the device */ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); @@ -1021,121 +1202,42 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, AR5K_PHY(0)); /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, change_channel); + ret = ath5k_hw_write_initvals(ah, mode, skip_pcu); if (ret) return ret; + /* Initialize core clock settings */ + ath5k_hw_init_core_clock(ah); + /* - * 5211/5212 Specific + * Tweak initval settings for revised + * chipsets and add some more config + * bits */ - if (ah->ah_version != AR5K_AR5210) { - - /* - * Write initial RF gain settings - * This should work for both 5111/5112 - */ - ret = ath5k_hw_rfgain_init(ah, freq); - if (ret) - return ret; - - mdelay(1); - - /* - * Tweak initval settings for revised - * chipsets and add some more config - * bits - */ - ath5k_hw_tweak_initval_settings(ah, channel); - - /* - * Set TX power - */ - ret = ath5k_hw_txpower(ah, channel, ee_mode, - ah->ah_txpower.txp_max_pwr / 2); - if (ret) - return ret; + ath5k_hw_tweak_initval_settings(ah, channel); - /* Write rate duration table only on AR5212 and if - * virtual interface has already been brought up - * XXX: rethink this after new mode changes to - * mac80211 are integrated */ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_sc->nvifs) - ath5k_hw_write_rate_duration(ah, mode); + /* Commit values from EEPROM */ + ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); - /* - * Write RF buffer - */ - ret = ath5k_hw_rfregs_init(ah, channel, mode); - if (ret) - return ret; - - - /* Write OFDM timings on 5212*/ - if (ah->ah_version == AR5K_AR5212 && - channel->hw_value & CHANNEL_OFDM) { - - ret = ath5k_hw_write_ofdm_timings(ah, channel); - if (ret) - return ret; - - /* Spur info is available only from EEPROM versions - * greater than 5.3, but the EEPROM routines will use - * static values for older versions */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424) - ath5k_hw_set_spur_mitigation_filter(ah, - channel); - } - - /*Enable/disable 802.11b mode on 5111 - (enable 2111 frequency converter + CCK)*/ - if (ah->ah_radio == AR5K_RF5111) { - if (mode == AR5K_MODE_11B) - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - } - - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); - - } else { - /* - * For 5210 we do all initialization using - * initvals, so we don't have to modify - * any settings (5210 also only supports - * a/aturbo modes) - */ - mdelay(1); - /* Disable phy and wait */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - mdelay(1); - } /* * Restore saved values */ - /*DCU/Antenna selection not available on 5210*/ + /* Seqnum, TSF */ if (ah->ah_version != AR5K_AR5210) { + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + for (i = 0; i < 10; i++) + ath5k_hw_reg_write(ah, s_seq[i], + AR5K_QUEUE_DCU_SEQNUM(i)); + } else { + ath5k_hw_reg_write(ah, s_seq[0], + AR5K_QUEUE_DCU_SEQNUM(0)); + } - if (change_channel) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); - } + if (ah->ah_version == AR5K_AR5211) { + ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); + ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); } } @@ -1146,203 +1248,34 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); - /* Restore sta_id flags and preserve our mac address*/ - ath5k_hw_reg_write(ah, - get_unaligned_le32(common->macaddr), - AR5K_STA_ID0); - ath5k_hw_reg_write(ah, - staid1_flags | get_unaligned_le16(common->macaddr + 4), - AR5K_STA_ID1); - - /* - * Configure PCU + * Initialize PCU */ - - /* Restore bssid and bssid mask */ - ath5k_hw_set_bssid(ah); - - /* Set PCU config */ - ath5k_hw_set_opmode(ah, op_mode); - - /* Clear any pending interrupts - * PISR/SISR Not available on 5210 */ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); - - /* Set RSSI/BRSSI thresholds - * - * Note: If we decide to set this value - * dynamically, keep in mind that when AR5K_RSSI_THR - * register is read, it might return 0x40 if we haven't - * written anything to it. Also, BMISS RSSI threshold is zeroed. - * So doing a save/restore procedure here isn't the right - * choice. Instead, store it in ath5k_hw */ - ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | - AR5K_TUNE_BMISS_THRES << - AR5K_RSSI_THR_BMISS_S), - AR5K_RSSI_THR); - - /* MIC QoS support */ - if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { - ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); - ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); - } - - /* QoS NOACK Policy */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, - AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | - AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | - AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), - AR5K_QOS_NOACK); - } - + ath5k_hw_pcu_init(ah, op_mode, mode); /* - * Configure PHY + * Initialize PHY */ - - /* Set channel on PHY */ - ret = ath5k_hw_channel(ah, channel); - if (ret) + ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq, false); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "failed to initialize PHY (%i) !\n", ret); return ret; - - /* - * Enable the PHY and wait until completion - * This includes BaseBand and Synthesizer - * activation. - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - - /* - * On 5211+ read activation -> rx delay - * and use it. - * - * TODO: Half/quarter rate support - */ - if (ah->ah_version != AR5K_AR5210) { - u32 delay; - delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & - AR5K_PHY_RX_DELAY_M; - delay = (channel->hw_value & CHANNEL_CCK) ? - ((delay << 2) / 22) : (delay / 10); - - udelay(100 + (2 * delay)); - } else { - mdelay(1); } /* - * Perform ADC test to see if baseband is ready - * Set TX hold and check ADC test register - */ - phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); - ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); - for (i = 0; i <= 20; i++) { - if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) - break; - udelay(200); - } - ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); - - /* - * Start automatic gain control calibration - * - * During AGC calibration RX path is re-routed to - * a power detector so we don't receive anything. - * - * This method is used to calibrate some static offsets - * used together with on-the fly I/Q calibration (the - * one performed via ath5k_hw_phy_calibrate), which doesn't - * interrupt rx path. - * - * While rx path is re-routed to the power detector we also - * start a noise floor calibration to measure the - * card's noise floor (the noise we measure when we are not - * transmitting or receiving anything). - * - * If we are in a noisy environment, AGC calibration may time - * out and/or noise floor calibration might timeout. - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); - - /* At the same time start I/Q calibration for QAM constellation - * -no need for CCK- */ - ah->ah_calibration = false; - if (!(mode == AR5K_MODE_11B)) { - ah->ah_calibration = true; - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_RUN); - } - - /* Wait for gain calibration to finish (we check for I/Q calibration - * during ath5k_phy_calibrate) */ - if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - /* Restore antenna mode */ - ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); - - /* Restore slot time and ACK timeouts */ - if (ah->ah_coverage_class > 0) - ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); - - /* * Configure QCUs/DCUs */ + ret = ath5k_hw_init_queues(ah); + if (ret) + return ret; - /* TODO: HW Compression support for data queues */ - /* TODO: Burst prefetch for data queues */ - - /* - * Reset queues and start beacon timers at the end of the reset routine - * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping - * Note: If we want we can assign multiple qcus on one dcu. - */ - for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { - ret = ath5k_hw_reset_tx_queue(ah, i); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "failed to reset TX queue #%d\n", i); - return ret; - } - } - - - /* - * Configure DMA/Interrupts - */ /* - * Set Rx/Tx DMA Configuration - * - * Set standard DMA size (128). Note that - * a DMA size of 512 causes rx overruns and tx errors - * on pci-e cards (tested on 5424 but since rx overruns - * also occur on 5416/5418 with madwifi we set 128 - * for all PCI-E cards to be safe). - * - * XXX: need to check 5210 for this - * TODO: Check out tx triger level, it's always 64 on dumps but I - * guess we can tweak it and see how it goes ;-) + * Initialize DMA/Interrupts */ - if (ah->ah_version != AR5K_AR5210) { - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, - AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); - } + ath5k_hw_dma_init(ah); - /* Pre-enable interrupts on 5211/5212*/ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_set_imr(ah, ah->ah_imr); /* Enable 32KHz clock function for AR5212+ chips * Set clocks to 32KHz operation and use an diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index 3ac4cff4239d..16b67e84906d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -51,7 +51,7 @@ struct ath5k_ini_rfbuffer { u8 rfb_bank; /* RF Bank number */ u16 rfb_ctrl_register; /* RF Buffer control register */ - u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ + u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ }; /* @@ -79,8 +79,10 @@ struct ath5k_rf_reg { * life easier by using an index for each register * instead of a full rfb_field */ enum ath5k_rf_regs_idx { + /* BANK 2 */ + AR5K_RF_TURBO = 0, /* BANK 6 */ - AR5K_RF_OB_2GHZ = 0, + AR5K_RF_OB_2GHZ, AR5K_RF_OB_5GHZ, AR5K_RF_DB_2GHZ, AR5K_RF_DB_5GHZ, @@ -134,6 +136,9 @@ enum ath5k_rf_regs_idx { * RF5111 (Sombrero) * \*******************/ +/* BANK 2 len pos col */ +#define AR5K_RF5111_RF_TURBO { 1, 3, 0 } + /* BANK 6 len pos col */ #define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } #define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } @@ -158,6 +163,7 @@ enum ath5k_rf_regs_idx { #define AR5K_RF5111_MAX_TIME { 2, 49, 0 } static const struct ath5k_rf_reg rf_regs_5111[] = { + {2, AR5K_RF_TURBO, AR5K_RF5111_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, @@ -177,97 +183,52 @@ static const struct ath5k_rf_reg rf_regs_5111[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5111[] = { - { 0, 0x989c, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, - { 0, 0x989c, - { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, - { 0, 0x98d4, - { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, - { 1, 0x98d4, - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, - { 3, 0x98d8, - { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, - { 6, 0x989c, - { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, - { 6, 0x989c, - { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, - { 6, 0x989c, - { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, - { 6, 0x989c, - { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, - { 6, 0x98d4, - { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, - { 7, 0x989c, - { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, - { 7, 0x989c, - { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, - { 7, 0x989c, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 7, 0x989c, - { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, - { 7, 0x989c, - { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, - { 7, 0x989c, - { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, - { 7, 0x989c, - { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, { 0x00000000, 0x000000c0, 0x00000080 } }, + { 0, 0x989c, { 0x000400f9, 0x000400ff, 0x000400fd } }, + { 0, 0x98d4, { 0x00000000, 0x00000004, 0x00000004 } }, + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d4, { 0x00000010, 0x00000010, 0x00000010 } }, + { 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x0a000000, 0x00000000 } }, + { 6, 0x989c, { 0x003800c0, 0x023800c0, 0x003800c0 } }, + { 6, 0x989c, { 0x00020006, 0x00000006, 0x00020006 } }, + { 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089 } }, + { 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0 } }, + { 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007 } }, + { 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a } }, + { 7, 0x989c, { 0x00000040, 0x00000040, 0x00000040 } }, + { 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010 } }, + { 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008 } }, + { 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f } }, + { 7, 0x989c, { 0x000000f1, 0x00000061, 0x000000f1 } }, + { 7, 0x989c, { 0x0000904f, 0x0000904c, 0x0000904f } }, + { 7, 0x989c, { 0x0000125a, 0x0000129a, 0x0000125a } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000f, 0x0000000e } }, }; @@ -276,6 +237,9 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { * RF5112/RF2112 (Derby) * \***********************/ +/* BANK 2 (Common) len pos col */ +#define AR5K_RF5112X_RF_TURBO { 1, 1, 2 } + /* BANK 7 (Common) len pos col */ #define AR5K_RF5112X_GAIN_I { 6, 14, 0 } #define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } @@ -307,6 +271,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { #define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } static const struct ath5k_rf_reg rf_regs_5112[] = { + {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, @@ -335,115 +300,61 @@ static const struct ath5k_rf_reg rf_regs_5112[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5112[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, - { 6, 0x989c, - { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, - { 6, 0x989c, - { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, - { 6, 0x989c, - { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, - { 6, 0x989c, - { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, - { 6, 0x989c, - { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, - { 6, 0x989c, - { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, - { 6, 0x989c, - { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, - { 6, 0x989c, - { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, - { 6, 0x989c, - { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, - { 6, 0x989c, - { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, - { 6, 0x989c, - { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, - { 6, 0x989c, - { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, - { 6, 0x98d0, - { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, - { 7, 0x989c, - { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, + { 3, 0x98dc, { 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, + { 6, 0x989c, { 0x00a00000, 0x00a00000, 0x00a00000 } }, + { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00660000, 0x00660000, 0x00660000 } }, + { 6, 0x989c, { 0x00db0000, 0x00db0000, 0x00db0000 } }, + { 6, 0x989c, { 0x00f10000, 0x00f10000, 0x00f10000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x008b0000, 0x008b0000, 0x008b0000 } }, + { 6, 0x989c, { 0x00600000, 0x00600000, 0x00600000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, { 0x00640000, 0x00640000, 0x00640000 } }, + { 6, 0x989c, { 0x00200000, 0x00200000, 0x00200000 } }, + { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, { 0x00250000, 0x00250000, 0x00250000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x00510000, 0x00510000, 0x00510000 } }, + { 6, 0x989c, { 0x1c040000, 0x1c040000, 0x1c040000 } }, + { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, { 0x00a10000, 0x00a10000, 0x00a10000 } }, + { 6, 0x989c, { 0x00400000, 0x00400000, 0x00400000 } }, + { 6, 0x989c, { 0x03090000, 0x03090000, 0x03090000 } }, + { 6, 0x989c, { 0x06000000, 0x06000000, 0x06000000 } }, + { 6, 0x989c, { 0x000000b0, 0x000000a8, 0x000000a8 } }, + { 6, 0x989c, { 0x0000002e, 0x0000002e, 0x0000002e } }, + { 6, 0x989c, { 0x006c4a41, 0x006c4af1, 0x006c4a61 } }, + { 6, 0x989c, { 0x0050892a, 0x0050892b, 0x0050892b } }, + { 6, 0x989c, { 0x00842400, 0x00842400, 0x00842400 } }, + { 6, 0x989c, { 0x00c69200, 0x00c69200, 0x00c69200 } }, + { 6, 0x98d0, { 0x0002000c, 0x0002000c, 0x0002000c } }, + { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, { 0x0000000a, 0x00000012, 0x00000012 } }, + { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, { 0x000000c1, 0x000000c1, 0x000000c1 } }, + { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, { 0x00000022, 0x00000022, 0x00000022 } }, + { 7, 0x989c, { 0x00000092, 0x00000092, 0x00000092 } }, + { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, }; /* RFX112A (Derby 2) */ @@ -477,6 +388,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112[] = { #define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } static const struct ath5k_rf_reg rf_regs_5112a[] = { + {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, @@ -515,119 +427,63 @@ static const struct ath5k_rf_reg rf_regs_5112a[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5112a[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, - { 6, 0x989c, - { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, - { 6, 0x989c, - { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, - { 6, 0x989c, - { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, - { 6, 0x989c, - { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, - { 6, 0x989c, - { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, - { 6, 0x989c, - { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, - { 6, 0x989c, - { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, - { 6, 0x989c, - { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, - { 6, 0x989c, - { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, - { 6, 0x989c, - { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, - { 6, 0x989c, - { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, - { 6, 0x989c, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, - { 6, 0x989c, - { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, - { 6, 0x989c, - { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, - { 6, 0x989c, - { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, - { 6, 0x989c, - { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, - { 6, 0x98d8, - { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, - { 7, 0x989c, - { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000 } }, + { 6, 0x989c, { 0x00600000, 0x006e0000, 0x006e0000 } }, + { 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000 } }, + { 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000 } }, + { 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000 } }, + { 6, 0x989c, { 0x004c0000, 0x004c0000, 0x004c0000 } }, + { 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000 } }, + { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000 } }, + { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000 } }, + { 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000 } }, + { 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000 } }, + { 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000 } }, + { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000 } }, + { 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000 } }, + { 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080 } }, + { 6, 0x989c, { 0x00270019, 0x00270019, 0x00270019 } }, + { 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2 } }, + { 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084 } }, + { 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4 } }, + { 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220 } }, + { 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800 } }, + { 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230 } }, + { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012 } }, + { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9 } }, + { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2 } }, + { 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052 } }, + { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, }; @@ -636,11 +492,15 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = { * RF2413 (Griffin) * \******************/ +/* BANK 2 len pos col */ +#define AR5K_RF2413_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } #define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } static const struct ath5k_rf_reg rf_regs_2413[] = { + {2, AR5K_RF_TURBO, AR5K_RF2413_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, }; @@ -649,73 +509,40 @@ static const struct ath5k_rf_reg rf_regs_2413[] = { * XXX: a/aTurbo ??? */ static const struct ath5k_ini_rfbuffer rfb_2413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, - { 6, 0x989c, - { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, - { 6, 0x989c, - { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, - { 6, 0x989c, - { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, - { 6, 0x989c, - { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, - { 6, 0x989c, - { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, - { 6, 0x989c, - { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, - { 6, 0x989c, - { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, - { 6, 0x989c, - { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, - { 6, 0x989c, - { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, - { 6, 0x989c, - { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, - { 6, 0x989c, - { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, - { 6, 0x989c, - { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, - { 6, 0x98d8, - { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0xf0000000, 0xf0000000, 0xf0000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x03000000, 0x03000000, 0x03000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x40400000, 0x40400000, 0x40400000 } }, + { 6, 0x989c, { 0x65050000, 0x65050000, 0x65050000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00420000, 0x00420000, 0x00420000 } }, + { 6, 0x989c, { 0x00b50000, 0x00b50000, 0x00b50000 } }, + { 6, 0x989c, { 0x00030000, 0x00030000, 0x00030000 } }, + { 6, 0x989c, { 0x00f70000, 0x00f70000, 0x00f70000 } }, + { 6, 0x989c, { 0x009d0000, 0x009d0000, 0x009d0000 } }, + { 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000 } }, + { 6, 0x989c, { 0x04220000, 0x04220000, 0x04220000 } }, + { 6, 0x989c, { 0x00230018, 0x00230018, 0x00230018 } }, + { 6, 0x989c, { 0x00280000, 0x00280060, 0x00280060 } }, + { 6, 0x989c, { 0x005000c0, 0x005000c3, 0x005000c3 } }, + { 6, 0x989c, { 0x0004007f, 0x0004007f, 0x0004007f } }, + { 6, 0x989c, { 0x00000458, 0x00000458, 0x00000458 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x0000c000, 0x0000c000, 0x0000c000 } }, + { 6, 0x98d8, { 0x00400230, 0x00400230, 0x00400230 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -724,88 +551,57 @@ static const struct ath5k_ini_rfbuffer rfb_2413[] = { * RF2315/RF2316 (Cobra SoC) * \***************************/ +/* BANK 2 len pos col */ +#define AR5K_RF2316_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } #define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } static const struct ath5k_rf_reg rf_regs_2316[] = { + {2, AR5K_RF_TURBO, AR5K_RF2316_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, }; /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_2316[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, - { 6, 0x989c, - { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, - { 6, 0x989c, - { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, - { 6, 0x989c, - { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, - { 6, 0x989c, - { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, - { 6, 0x989c, - { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, - { 6, 0x989c, - { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, - { 6, 0x989c, - { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, - { 6, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 6, 0x989c, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 6, 0x989c, - { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, - { 6, 0x989c, - { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, - { 6, 0x98c0, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0xc0000000, 0xc0000000, 0xc0000000 } }, + { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, { 0x02000000, 0x02000000, 0x02000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0xf8000000, 0xf8000000, 0xf8000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x95150000, 0x95150000, 0x95150000 } }, + { 6, 0x989c, { 0xc1000000, 0xc1000000, 0xc1000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00080000, 0x00080000, 0x00080000 } }, + { 6, 0x989c, { 0x00d50000, 0x00d50000, 0x00d50000 } }, + { 6, 0x989c, { 0x000e0000, 0x000e0000, 0x000e0000 } }, + { 6, 0x989c, { 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, + { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, { 0x008a0000, 0x008a0000, 0x008a0000 } }, + { 6, 0x989c, { 0x10880000, 0x10880000, 0x10880000 } }, + { 6, 0x989c, { 0x008c0060, 0x008c0060, 0x008c0060 } }, + { 6, 0x989c, { 0x00a00000, 0x00a00080, 0x00a00080 } }, + { 6, 0x989c, { 0x00400000, 0x0040000d, 0x0040000d } }, + { 6, 0x989c, { 0x00110400, 0x00110400, 0x00110400 } }, + { 6, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, + { 6, 0x989c, { 0x00000001, 0x00000001, 0x00000001 } }, + { 6, 0x989c, { 0x00000b00, 0x00000b00, 0x00000b00 } }, + { 6, 0x989c, { 0x00000be8, 0x00000be8, 0x00000be8 } }, + { 6, 0x98c0, { 0x00010000, 0x00010000, 0x00010000 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -835,93 +631,50 @@ static const struct ath5k_rf_reg rf_regs_5413[] = { /* Default mode specific settings */ static const struct ath5k_ini_rfbuffer rfb_5413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 3, 0x98dc, - { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, - { 6, 0x989c, - { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, - { 6, 0x989c, - { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, - { 6, 0x989c, - { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, - { 6, 0x989c, - { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, - { 6, 0x989c, - { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, - { 6, 0x989c, - { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, - { 6, 0x989c, - { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, - { 6, 0x989c, - { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, - { 6, 0x989c, - { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, - { 6, 0x989c, - { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, - { 6, 0x989c, - { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, - { 6, 0x989c, - { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, - { 6, 0x989c, - { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, - { 6, 0x989c, - { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, - { 6, 0x98c8, - { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x00000008, 0x00000008, 0x00000008 } }, + { 3, 0x98dc, { 0x00a000c0, 0x00e000c0, 0x00e000c0 } }, + { 6, 0x989c, { 0x33000000, 0x33000000, 0x33000000 } }, + { 6, 0x989c, { 0x01000000, 0x01000000, 0x01000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x1f000000, 0x1f000000, 0x1f000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00b80000, 0x00b80000, 0x00b80000 } }, + { 6, 0x989c, { 0x00b70000, 0x00b70000, 0x00b70000 } }, + { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, { 0x00c00000, 0x00c00000, 0x00c00000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, { 0x00d70000, 0x00d70000, 0x00d70000 } }, + { 6, 0x989c, { 0x00610000, 0x00610000, 0x00610000 } }, + { 6, 0x989c, { 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, + { 6, 0x989c, { 0x00de0000, 0x00de0000, 0x00de0000 } }, + { 6, 0x989c, { 0x007f0000, 0x007f0000, 0x007f0000 } }, + { 6, 0x989c, { 0x043d0000, 0x043d0000, 0x043d0000 } }, + { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, { 0x00440000, 0x00440000, 0x00440000 } }, + { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, { 0x00100080, 0x00100080, 0x00100080 } }, + { 6, 0x989c, { 0x0005c034, 0x0005c034, 0x0005c034 } }, + { 6, 0x989c, { 0x003100f0, 0x003100f0, 0x003100f0 } }, + { 6, 0x989c, { 0x000c011f, 0x000c011f, 0x000c011f } }, + { 6, 0x989c, { 0x00510040, 0x00510040, 0x00510040 } }, + { 6, 0x989c, { 0x005000da, 0x005000da, 0x005000da } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00004044, 0x00004044, 0x00004044 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x000060c0, 0x000060c0, 0x000060c0 } }, + { 6, 0x989c, { 0x00002c00, 0x00003600, 0x00003600 } }, + { 6, 0x98c8, { 0x00000403, 0x00040403, 0x00040403 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; @@ -931,92 +684,59 @@ static const struct ath5k_ini_rfbuffer rfb_5413[] = { * AR2317 (Spider SoC) * \***************************/ +/* BANK 2 len pos col */ +#define AR5K_RF2425_RF_TURBO { 1, 1, 2 } + /* BANK 6 len pos col */ #define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } #define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } static const struct ath5k_rf_reg rf_regs_2425[] = { + {2, AR5K_RF_TURBO, AR5K_RF2425_RF_TURBO}, {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, }; /* Default mode specific settings - * XXX: a/aTurbo ? */ static const struct ath5k_ini_rfbuffer rfb_2425[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; /* @@ -1024,158 +744,85 @@ static const struct ath5k_ini_rfbuffer rfb_2425[] = { * bank modification and get rid of this */ static const struct ath5k_ini_rfbuffer rfb_2317[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, { 0x00140100, 0x00140100, 0x00140100 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00009688, 0x00009688, 0x00009688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; /* * TODO: Handle the few differences with swan during * bank modification and get rid of this - * XXX: a/aTurbo ? */ static const struct ath5k_ini_rfbuffer rfb_2417[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, + /* BANK / C.R. A/XR B G */ + { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, { 0x00e70000, 0x80e70000, 0x80e70000 } }, + { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, { 0x0007001a, 0x0207001a, 0x0207001a } }, + { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, + { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, }; diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index 90757de7bf59..929c68cdf8ab 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c @@ -95,7 +95,7 @@ static struct attribute_group ath5k_attribute_group_ani = { int ath5k_sysfs_register(struct ath5k_softc *sc) { - struct device *dev = &sc->pdev->dev; + struct device *dev = sc->dev; int err; err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); @@ -110,7 +110,7 @@ ath5k_sysfs_register(struct ath5k_softc *sc) void ath5k_sysfs_unregister(struct ath5k_softc *sc) { - struct device *dev = &sc->pdev->dev; + struct device *dev = sc->dev; sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); } diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 63ccb39cdcd4..29a045da184b 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -834,10 +834,10 @@ void ath9k_hw_ani_setup(struct ath_hw *ah) { int i; - const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; - const int coarseHigh[] = { -14, -14, -14, -14, -12 }; - const int coarseLow[] = { -64, -64, -64, -64, -70 }; - const int firpwr[] = { -78, -78, -78, -78, -80 }; + static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; + static const int coarseHigh[] = { -14, -14, -14, -14, -12 }; + static const int coarseLow[] = { -64, -64, -64, -64, -70 }; + static const int firpwr[] = { -78, -78, -78, -78, -80 }; for (i = 0; i < 5; i++) { ah->totalSizeDesired[i] = totalSizeDesired[i]; diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index ea9f4497f58c..06e34d293dc8 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -244,13 +244,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, int upper, lower, cur_vit_mask; int tmp, new; int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + static int pilot_mask_reg[4] = { + AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + static int chan_mask_reg[4] = { + AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; - int inc[4] = { 0, 100, 0, 0 }; + static int inc[4] = { 0, 100, 0, 0 }; int8_t mask_m[123]; int8_t mask_p[123]; @@ -873,7 +875,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); /* Write analog registers */ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { @@ -1084,12 +1086,12 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ - const int m1ThreshLow[] = { 127, 50 }; - const int m2ThreshLow[] = { 127, 40 }; - const int m1Thresh[] = { 127, 0x4d }; - const int m2Thresh[] = { 127, 0x40 }; - const int m2CountThr[] = { 31, 16 }; - const int m2CountThrLow[] = { 63, 48 }; + static const int m1ThreshLow[] = { 127, 50 }; + static const int m2ThreshLow[] = { 127, 40 }; + static const int m1Thresh[] = { 127, 0x4d }; + static const int m2Thresh[] = { 127, 0x40 }; + static const int m2CountThr[] = { 31, 16 }; + static const int m2CountThrLow[] = { 63, 48 }; u32 on = param ? 1 : 0; REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, @@ -1141,7 +1143,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; + static const int weakSigThrCck[] = { 8, 6 }; u32 high = param ? 1 : 0; REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, @@ -1157,7 +1159,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; + static const int firstep[] = { 0, 4, 8 }; u32 level = param; if (level >= ARRAY_SIZE(firstep)) { @@ -1178,7 +1180,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, break; } case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; u32 level = param; if (level >= ARRAY_SIZE(cycpwrThr1)) { @@ -1490,25 +1492,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); - nfarray[2] = sign_extend(nf, 9); + nfarray[2] = sign_extend32(nf, 8); if (!IS_CHAN_HT40(ah->curchan)) return; nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); - nfarray[5] = sign_extend(nf, 9); + nfarray[5] = sign_extend32(nf, 8); } /* @@ -1579,10 +1581,55 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah) ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; } +static void ar5008_hw_set_radar_params(struct ath_hw *ah, + struct ath_hw_radar_conf *conf) +{ + u32 radar_0 = 0, radar_1 = 0; + + if (!conf) { + REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + return; + } + + radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; + radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); + radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); + radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); + radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); + radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + + radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; + radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; + radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); + radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); + radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); + + REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); + REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); + if (conf->ext_channel) + REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else + REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); +} + +static void ar5008_hw_set_radar_conf(struct ath_hw *ah) +{ + struct ath_hw_radar_conf *conf = &ah->radar_conf; + + conf->fir_power = -33; + conf->radar_rssi = 20; + conf->pulse_height = 10; + conf->pulse_rssi = 24; + conf->pulse_inband = 15; + conf->pulse_maxlen = 255; + conf->pulse_inband_step = 12; + conf->radar_inband = 8; +} + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - const u32 ar5416_cca_regs[6] = { + static const u32 ar5416_cca_regs[6] = { AR_PHY_CCA, AR_PHY_CH1_CCA, AR_PHY_CH2_CCA, @@ -1609,6 +1656,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; priv_ops->do_getnf = ar5008_hw_do_getnf; + priv_ops->set_radar_params = ar5008_hw_set_radar_params; if (modparam_force_new_ani) { priv_ops->ani_control = ar5008_hw_ani_control_new; @@ -1624,5 +1672,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; ar5008_hw_set_nf_limits(ah); + ar5008_hw_set_radar_conf(ah); memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 50dda394f8be..f0268e5eab34 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked = isr & ATH9K_INT_COMMON; - if (ah->config.rx_intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM | + AR_ISR_RXOK | AR_ISR_RXERR)) *masked |= ATH9K_INT_RX; + if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { @@ -118,14 +115,6 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) "receive FIFO overrun interrupt\n"); } - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } - } - *masked |= mask2; } @@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) u32 s5_s; s5_s = REG_READ(ah, AR_ISR_S5_S); - if (isr & AR_ISR_GENTMR) { - ah->intr_gen_timer_trigger = + ah->intr_gen_timer_trigger = MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - ah->intr_gen_timer_thresh = - MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); + ah->intr_gen_timer_thresh = + MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - if (ah->intr_gen_timer_trigger) - *masked |= ATH9K_INT_GENTIMER; + if (ah->intr_gen_timer_trigger) + *masked |= ATH9K_INT_GENTIMER; - } + if ((s5_s & AR_ISR_S5_TIM_TIMER) && + !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + *masked |= ATH9K_INT_TIM_TIMER; } if (sync_cause) { @@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { struct ar5416_desc *ads = AR5416DESC(ds); + u32 status; - if ((ads->ds_txstatus9 & AR_TxDone) == 0) + status = ACCESS_ONCE(ads->ds_txstatus9); + if ((status & AR_TxDone) == 0) return -EINPROGRESS; - ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); ts->ts_tstamp = ads->AR_SendTimestamp; ts->ts_status = 0; ts->ts_flags = 0; - if (ads->ds_txstatus1 & AR_FrmXmitOK) + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + ts->tid = MS(status, AR_TxTid); + ts->ts_rateindex = MS(status, AR_FinalTxIdx); + ts->ts_seqnum = MS(status, AR_SeqNum); + + status = ACCESS_ONCE(ads->ds_txstatus0); + ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); + if (status & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->AR_BaBitmapLow; + ts->ba_high = ads->AR_BaBitmapHigh; + } + + status = ACCESS_ONCE(ads->ds_txstatus1); + if (status & AR_FrmXmitOK) ts->ts_status |= ATH9K_TX_ACKED; - if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ts->ts_status |= ATH9K_TXERR_XRETRY; - if (ads->ds_txstatus1 & AR_Filtered) - ts->ts_status |= ATH9K_TXERR_FILT; - if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ts->ts_status |= ATH9K_TXERR_FIFO; - ath9k_hw_updatetxtriglevel(ah, true); + else { + if (status & AR_ExcessiveRetries) + ts->ts_status |= ATH9K_TXERR_XRETRY; + if (status & AR_Filtered) + ts->ts_status |= ATH9K_TXERR_FILT; + if (status & AR_FIFOUnderrun) { + ts->ts_status |= ATH9K_TXERR_FIFO; + ath9k_hw_updatetxtriglevel(ah, true); + } } - if (ads->ds_txstatus9 & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; - if (ads->ds_txstatus1 & AR_TxTimerExpired) + if (status & AR_TxTimerExpired) ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->ds_txstatus1 & AR_DescCfgErr) + if (status & AR_DescCfgErr) ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->ds_txstatus1 & AR_TxDataUnderrun) { + if (status & AR_TxDataUnderrun) { ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { + if (status & AR_TxDelimUnderrun) { ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->ds_txstatus0 & AR_TxBaStatus) { - ts->ts_flags |= ATH9K_TX_BA; - ts->ba_low = ads->AR_BaBitmapLow; - ts->ba_high = ads->AR_BaBitmapHigh; - } + ts->ts_shortretry = MS(status, AR_RTSFailCnt); + ts->ts_longretry = MS(status, AR_DataFailCnt); + ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ts->ts_rateindex) { - case 0: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); - break; - case 1: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); - break; - case 2: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); - break; - case 3: - ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); - break; - } + status = ACCESS_ONCE(ads->ds_txstatus5); + ts->ts_rssi = MS(status, AR_TxRSSICombined); + ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); - ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); ts->evm0 = ads->AR_TxEVM0; ts->evm1 = ads->AR_TxEVM1; ts->evm2 = ads->AR_TxEVM2; - ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ts->tid = MS(ads->ds_txstatus9, AR_TxTid); - ts->ts_antenna = 0; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index c00cdc67b55b..7ae66a889f5a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -175,13 +175,15 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, int upper, lower, cur_vit_mask; int tmp, newVal; int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + static const int pilot_mask_reg[4] = { + AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + static const int chan_mask_reg[4] = { + AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; - int inc[4] = { 0, 100, 0, 0 }; + static const int inc[4] = { 0, 100, 0, 0 }; struct chan_centers centers; int8_t mask_m[123]; @@ -473,21 +475,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); if (IS_CHAN_HT40(ah->curchan)) - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) return; nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); if (IS_CHAN_HT40(ah->curchan)) - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); } static void ar9002_hw_set_nf_limits(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 9e6edffe0bd1..4c94c9ed5f81 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -196,7 +196,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) u32 qCoffDenom, iCoffDenom; int32_t qCoff, iCoff; int iqCorrNeg, i; - const u_int32_t offset_array[3] = { + static const u_int32_t offset_array[3] = { AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2, @@ -603,22 +603,22 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - const u32 txiqcal_status[AR9300_MAX_CHAINS] = { + static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; - const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { + static const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2, }; - const u32 rx_corr[AR9300_MAX_CHAINS] = { + static const u32 rx_corr[AR9300_MAX_CHAINS] = { AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2, }; - const u_int32_t chan_info_tab[] = { + static const u_int32_t chan_info_tab[] = { AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, @@ -718,12 +718,19 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); + int val; - /* - * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before - * running AGC/TxIQ cals - */ - ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + val = REG_READ(ah, AR_ENT_OTP); + ath_print(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); + + if (val & AR_ENT_OTP_CHAIN2_DISABLE) + ar9003_hw_set_chain_masks(ah, 0x3, 0x3); + else + /* + * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain + * mode before running AGC/TxIQ cals + */ + ar9003_hw_set_chain_masks(ah, 0x7, 0x7); /* Do Tx IQ Calibration */ ar9003_hw_tx_iq_cal(ah); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a7b82f0085d2..872b1a3b21c6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -22,12 +22,14 @@ #define COMP_CKSUM_LEN 2 #define AR_CH0_TOP (0x00016288) -#define AR_CH0_TOP_XPABIASLVL (0x3) +#define AR_CH0_TOP_XPABIASLVL (0x300) #define AR_CH0_TOP_XPABIASLVL_S (8) #define AR_CH0_THERM (0x00016290) -#define AR_CH0_THERM_SPARE (0x3f) -#define AR_CH0_THERM_SPARE_S (0) +#define AR_CH0_THERM_XPABIASLVL_MSB 0x3 +#define AR_CH0_THERM_XPABIASLVL_MSB_S 0 +#define AR_CH0_THERM_XPASHORT2GND 0x4 +#define AR_CH0_THERM_XPASHORT2GND_S 2 #define AR_SWITCH_TABLE_COM_ALL (0xffff) #define AR_SWITCH_TABLE_COM_ALL_S (0) @@ -57,6 +59,9 @@ #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6)) +static int ar9003_hw_power_interpolate(int32_t x, + int32_t *px, int32_t *py, u_int16_t np); + static const struct ar9300_eeprom ar9300_default = { .eepromVersion = 2, .templateVersion = 2, @@ -146,13 +151,16 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, - .papdRateMaskHt20 = LE32(0x80c080), - .papdRateMaskHt40 = LE32(0x80c080), + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), .futureModal = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, .calFreqPier2G = { FREQ2FBIN(2412, 1), FREQ2FBIN(2437, 1), @@ -287,8 +295,7 @@ static const struct ar9300_eeprom ar9300_default = { /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), - /* Data[11].ctlEdges[3].bChannel */ - FREQ2FBIN(2462, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), } }, .ctlPowerData_2G = { @@ -346,13 +353,20 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, - .papdRateMaskHt20 = LE32(0xf0e0e0), - .papdRateMaskHt40 = LE32(0xf0e0e0), + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), .futureModal = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, }, + .base_ext2 = { + .tempSlopeLow = 0, + .tempSlopeHigh = 0, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, .calFreqPier5G = { FREQ2FBIN(5180, 0), FREQ2FBIN(5220, 0), @@ -626,6 +640,2338 @@ static const struct ar9300_eeprom ar9300_default = { } }; +static const struct ar9300_eeprom ar9300_x113 = { + .eepromVersion = 2, + .templateVersion = 6, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"x113-023-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x21, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x11111), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 68, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 72, + .tempSlopeHigh = 105, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5785, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5190, 0), + FREQ2FBIN(5230, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5410, 0), + FREQ2FBIN(5510, 0), + FREQ2FBIN(5670, 0), + FREQ2FBIN(5755, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + { {42, 40, 40, 34} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, + { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} }, + { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, + { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} }, + { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom ar9300_h112 = { + .eepromVersion = 2, + .templateVersion = 3, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"h112-241-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x10, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x80c080), + .papdRateMaskHt40 = LE32(0x80c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2484, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x44444), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0, 0, 0}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0, 0, 0}, + .tempSlope = 45, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 40, + .tempSlopeHigh = 50, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom ar9300_x112 = { + .eepromVersion = 2, + .templateVersion = 5, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"x112-041-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastclock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x0, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x22222), + + /* + * antCtrlChain[ar9300_max_chains]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, + + /* + * xatten1DB[AR9300_max_chains]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0x1b, 0x1b, 0x1b}, + + /* + * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x15, 0x15, 0x15}, + .tempSlope = 50, + .voltSlope = 0, + + /* + * spurChans[OSPrey_eeprom_modal_sPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80c080), + .papdRateMaskHt40 = LE32(0x0080c080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11s */ + { {38, 38, 38, 38} }, + { {38, 38, 38, 38} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {38, 38, 36, 34} }, + { {38, 38, 36, 34} }, + { {38, 38, 34, 32} }, + }, + .calTargetPower2GHT20 = { + { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, + { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} }, + { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, + }, + .calTargetPower2GHT40 = { + { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, + { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} }, + { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x22222), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x0), LE16(0x0), LE16(0x0), + }, + /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0x13, 0x19, 0x17}, + + /* + * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x19, 0x19, 0x19}, + .tempSlope = 70, + .voltSlope = 15, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshch check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 72, + .tempSlopeHigh = 105, + .xatten1DBLow = {0x10, 0x14, 0x10}, + .xatten1MarginLow = {0x19, 0x19 , 0x19}, + .xatten1DBHigh = {0x1d, 0x20, 0x24}, + .xatten1MarginHigh = {0x10, 0x10, 0x10} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5725, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {32, 32, 28, 26} }, + { {32, 32, 28, 26} }, + { {32, 32, 28, 26} }, + { {32, 32, 26, 24} }, + { {32, 32, 26, 24} }, + { {32, 32, 24, 22} }, + { {30, 30, 24, 22} }, + { {30, 30, 24, 22} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} }, + { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} }, + { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, + { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} }, + { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} }, + { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctledges[6].bchannel */ 0xFF, + /* Data[3].ctledges[7].bchannel */ 0xFF, + }, + + { + /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctledges[4].bchannel */ 0xFF, + /* Data[4].ctledges[5].bchannel */ 0xFF, + /* Data[4].ctledges[6].bchannel */ 0xFF, + /* Data[4].ctledges[7].bchannel */ 0xFF, + }, + + { + /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctledges[6].bchannel */ 0xFF, + /* Data[5].ctledges[7].bchannel */ 0xFF + }, + + { + /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + +static const struct ar9300_eeprom ar9300_h116 = { + .eepromVersion = 2, + .templateVersion = 4, + .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, + .custData = {"h116-041-f0000"}, + .baseEepHeader = { + .regDmn = { LE16(0), LE16(0x1f) }, + .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ + .opCapFlags = { + .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, + .eepMisc = 0, + }, + .rfSilent = 0, + .blueToothOptions = 0, + .deviceCap = 0, + .deviceType = 5, /* takes lower byte in eeprom location */ + .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, + .params_for_tuning_caps = {0, 0}, + .featureEnable = 0x0d, + /* + * bit0 - enable tx temp comp - disabled + * bit1 - enable tx volt comp - disabled + * bit2 - enable fastClock - enabled + * bit3 - enable doubling - enabled + * bit4 - enable internal regulator - disabled + * bit5 - enable pa predistortion - disabled + */ + .miscConfiguration = 0, /* bit0 - turn down drivestrength */ + .eepromWriteEnableGpio = 6, + .wlanDisableGpio = 0, + .wlanLedGpio = 8, + .rxBandSelectGpio = 0xff, + .txrxgain = 0x10, + .swreg = 0, + }, + .modalHeader2G = { + /* ar9300_modal_eep_header 2g */ + /* 4 idle,t1,t2,b(4 bits per setting) */ + .antCtrlCommon = LE32(0x110), + /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ + .antCtrlCommon2 = LE32(0x44444), + + /* + * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, + * rx1, rx12, b (2 bits each) + */ + .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, + + /* + * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db + * for ar9280 (0xa20c/b20c 5:0) + */ + .xatten1DB = {0x1f, 0x1f, 0x1f}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for ar9280 (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x12, 0x12, 0x12}, + .tempSlope = 25, + .voltSlope = 0, + + /* + * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur + * channels in usual fbin coding format + */ + .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, + + /* + * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check + * if the register is per chain + */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {1, 1, 1},/* 3 chain */ + .db_stage2 = {1, 1, 1}, /* 3 chain */ + .db_stage3 = {0, 0, 0}, + .db_stage4 = {0, 0, 0}, + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2c, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0c80C080), + .papdRateMaskHt40 = LE32(0x0080C080), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext1 = { + .ant_div_control = 0, + .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + .calFreqPier2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1), + }, + /* ar9300_cal_data_per_freq_op_loop 2g */ + .calPierData2G = { + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, + }, + .calTarget_freqbin_Cck = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2472, 1), + }, + .calTarget_freqbin_2G = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT20 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTarget_freqbin_2GHT40 = { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2437, 1), + FREQ2FBIN(2472, 1) + }, + .calTargetPowerCck = { + /* 1L-5L,5S,11L,11S */ + { {34, 34, 34, 34} }, + { {34, 34, 34, 34} }, + }, + .calTargetPower2G = { + /* 6-24,36,48,54 */ + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + { {34, 34, 32, 32} }, + }, + .calTargetPower2GHT20 = { + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, + }, + .calTargetPower2GHT40 = { + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, + }, + .ctlIndex_2G = { + 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, + 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, + }, + .ctl_freqbin_2G = { + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2457, 1), + FREQ2FBIN(2462, 1) + }, + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + + { + FREQ2FBIN(2412, 1), + FREQ2FBIN(2417, 1), + FREQ2FBIN(2462, 1), + 0xFF, + }, + { + FREQ2FBIN(2422, 1), + FREQ2FBIN(2427, 1), + FREQ2FBIN(2447, 1), + FREQ2FBIN(2452, 1) + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + FREQ2FBIN(2472, 1), + 0, + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + }, + + { + /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), + /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), + /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), + 0 + }, + + { + /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), + /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), + /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), + /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), + } + }, + .ctlPowerData_2G = { + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, + + { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + + { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, + }, + .modalHeader5G = { + /* 4 idle,t1,t2,b (4 bits per setting) */ + .antCtrlCommon = LE32(0x220), + /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ + .antCtrlCommon2 = LE32(0x44444), + /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ + .antCtrlChain = { + LE16(0x150), LE16(0x150), LE16(0x150), + }, + /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ + .xatten1DB = {0x19, 0x19, 0x19}, + + /* + * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin + * for merlin (0xa20c/b20c 16:12 + */ + .xatten1Margin = {0x14, 0x14, 0x14}, + .tempSlope = 70, + .voltSlope = 0, + /* spurChans spur channels in usual fbin coding format */ + .spurChans = {0, 0, 0, 0, 0}, + /* noiseFloorThreshCh Check if the register is per chain */ + .noiseFloorThreshCh = {-1, 0, 0}, + .ob = {3, 3, 3}, /* 3 chain */ + .db_stage2 = {3, 3, 3}, /* 3 chain */ + .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ + .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ + .xpaBiasLvl = 0, + .txFrameToDataStart = 0x0e, + .txFrameToPaOn = 0x0e, + .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ + .antennaGain = 0, + .switchSettling = 0x2d, + .adcDesiredSize = -30, + .txEndToXpaOff = 0, + .txEndToRxOn = 0x2, + .txFrameToXpaOn = 0xe, + .thresh62 = 28, + .papdRateMaskHt20 = LE32(0x0cf0e0e0), + .papdRateMaskHt40 = LE32(0x6cf0e0e0), + .futureModal = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + }, + .base_ext2 = { + .tempSlopeLow = 35, + .tempSlopeHigh = 50, + .xatten1DBLow = {0, 0, 0}, + .xatten1MarginLow = {0, 0, 0}, + .xatten1DBHigh = {0, 0, 0}, + .xatten1MarginHigh = {0, 0, 0} + }, + .calFreqPier5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5220, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5785, 0) + }, + .calPierData5G = { + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }, + + }, + .calTarget_freqbin_5G = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5600, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT20 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTarget_freqbin_5GHT40 = { + FREQ2FBIN(5180, 0), + FREQ2FBIN(5240, 0), + FREQ2FBIN(5320, 0), + FREQ2FBIN(5400, 0), + FREQ2FBIN(5500, 0), + FREQ2FBIN(5700, 0), + FREQ2FBIN(5745, 0), + FREQ2FBIN(5825, 0) + }, + .calTargetPower5G = { + /* 6-24,36,48,54 */ + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + { {30, 30, 28, 24} }, + }, + .calTargetPower5GHT20 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, + { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, + { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, + { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, + { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, + }, + .calTargetPower5GHT40 = { + /* + * 0_8_16,1-3_9-11_17-19, + * 4,5,6,7,12,13,14,15,20,21,22,23 + */ + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, + { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, + { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, + { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, + { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, + }, + .ctlIndex_5G = { + 0x10, 0x16, 0x18, 0x40, 0x46, + 0x48, 0x30, 0x36, 0x38 + }, + .ctl_freqbin_5G = { + { + /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), + /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + { + /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), + /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), + /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), + /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), + /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), + /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), + /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) + }, + + { + /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), + /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), + /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[3].ctlEdges[6].bChannel */ 0xFF, + /* Data[3].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), + /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), + /* Data[4].ctlEdges[4].bChannel */ 0xFF, + /* Data[4].ctlEdges[5].bChannel */ 0xFF, + /* Data[4].ctlEdges[6].bChannel */ 0xFF, + /* Data[4].ctlEdges[7].bChannel */ 0xFF, + }, + + { + /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), + /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), + /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), + /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[5].ctlEdges[6].bChannel */ 0xFF, + /* Data[5].ctlEdges[7].bChannel */ 0xFF + }, + + { + /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), + /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), + /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), + /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), + /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), + /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), + /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) + }, + + { + /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), + /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), + /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), + /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), + /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), + /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), + /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), + /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) + }, + + { + /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), + /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), + /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), + /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), + /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), + /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), + /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), + /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) + } + }, + .ctlPowerData_5G = { + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), + } + }, + { + { + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), + } + }, + { + { + CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), + CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), + } + }, + } +}; + + +static const struct ar9300_eeprom *ar9300_eep_templates[] = { + &ar9300_default, + &ar9300_x112, + &ar9300_h116, + &ar9300_h112, + &ar9300_x113, +}; + +static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id) +{ +#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0])) + int it; + + for (it = 0; it < N_LOOP; it++) + if (ar9300_eep_templates[it]->templateVersion == id) + return ar9300_eep_templates[it]; + return NULL; +#undef N_LOOP +} + + static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) { if (fbin == AR9300_BCHAN_UNUSED) @@ -639,6 +2985,16 @@ static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) return 0; } +static int interpolate(int x, int xa, int xb, int ya, int yb) +{ + int bf, factor, plus; + + bf = 2 * (yb - ya) * (x - xa) / (xb - xa); + factor = bf / 2; + plus = bf % 2; + return ya + factor + plus; +} + static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, enum eeprom_param param) { @@ -676,6 +3032,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, return le32_to_cpu(pBase->swreg); case EEP_PAPRD: return !!(pBase->featureEnable & BIT(5)); + case EEP_CHAIN_MASK_REDUCE: + return (pBase->miscConfiguration >> 0x3) & 0x1; default: return 0; } @@ -751,6 +3109,36 @@ error: return false; } +static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data) +{ + REG_READ(ah, AR9300_OTP_BASE + (4 * addr)); + + if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE, + AR9300_OTP_STATUS_VALID, 1000)) + return false; + + *data = REG_READ(ah, AR9300_OTP_READ_DATA); + return true; +} + +static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer, + int count) +{ + u32 data; + int i; + + for (i = 0; i < count; i++) { + int offset = 8 * ((address - i) % 4); + if (!ar9300_otp_read_word(ah, (address - i) / 4, &data)) + return false; + + buffer[i] = (data >> offset) & 0xff; + } + + return true; +} + + static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, int *length, int *major, int *minor) { @@ -827,6 +3215,7 @@ static int ar9300_compress_decision(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); u8 *dptr; + const struct ar9300_eeprom *eep = NULL; switch (code) { case _CompressNone: @@ -844,13 +3233,14 @@ static int ar9300_compress_decision(struct ath_hw *ah, if (reference == 0) { dptr = mptr; } else { - if (reference != 2) { + eep = ar9003_eeprom_struct_find_by_id(reference); + if (eep == NULL) { ath_print(common, ATH_DBG_EEPROM, "cant find reference eeprom" "struct %d\n", reference); return -1; } - memcpy(mptr, &ar9300_default, mdata_size); + memcpy(mptr, eep, mdata_size); } ath_print(common, ATH_DBG_EEPROM, "restore eeprom %d: block, reference %d," @@ -866,6 +3256,38 @@ static int ar9300_compress_decision(struct ath_hw *ah, return 0; } +typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer, + int count); + +static bool ar9300_check_header(void *data) +{ + u32 *word = data; + return !(*word == 0 || *word == ~0); +} + +static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read, + int base_addr) +{ + u8 header[4]; + + if (!read(ah, base_addr, header, 4)) + return false; + + return ar9300_check_header(header); +} + +static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr, + int mdata_size) +{ + struct ath_common *common = ath9k_hw_common(ah); + u16 *data = (u16 *) mptr; + int i; + + for (i = 0; i < mdata_size / 2; i++, data++) + ath9k_hw_nvram_read(common, i, data); + + return 0; +} /* * Read the configuration data from the eeprom. * The data can be put in any specified memory buffer. @@ -886,6 +3308,10 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, int it; u16 checksum, mchecksum; struct ath_common *common = ath9k_hw_common(ah); + eeprom_read_op read; + + if (ath9k_hw_use_flash(ah)) + return ar9300_eeprom_restore_flash(ah, mptr, mdata_size); word = kzalloc(2048, GFP_KERNEL); if (!word) @@ -893,14 +3319,42 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, memcpy(mptr, &ar9300_default, mdata_size); + read = ar9300_read_eeprom; cptr = AR9300_BASE_ADDR; + ath_print(common, ATH_DBG_EEPROM, + "Trying EEPROM accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + cptr = AR9300_BASE_ADDR_512; + ath_print(common, ATH_DBG_EEPROM, + "Trying EEPROM accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + read = ar9300_read_otp; + cptr = AR9300_BASE_ADDR; + ath_print(common, ATH_DBG_EEPROM, + "Trying OTP accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + cptr = AR9300_BASE_ADDR_512; + ath_print(common, ATH_DBG_EEPROM, + "Trying OTP accesss at Address 0x%04x\n", cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + + goto fail; + +found: + ath_print(common, ATH_DBG_EEPROM, "Found valid EEPROM data"); + for (it = 0; it < MSTATE; it++) { - if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN)) + if (!read(ah, cptr, word, COMP_HDR_LEN)) goto fail; - if ((word[0] == 0 && word[1] == 0 && word[2] == 0 && - word[3] == 0) || (word[0] == 0xff && word[1] == 0xff - && word[2] == 0xff && word[3] == 0xff)) + if (!ar9300_check_header(word)) break; ar9300_comp_hdr_unpack(word, &code, &reference, @@ -917,8 +3371,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, } osize = length; - ar9300_read_eeprom(ah, cptr, word, - COMP_HDR_LEN + osize + COMP_CKSUM_LEN); + read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN); checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); mchecksum = word[COMP_HDR_LEN + osize] | (word[COMP_HDR_LEN + osize + 1] << 8); @@ -995,9 +3448,9 @@ static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) { int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); - REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3)); - REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE, - ((bias >> 2) & 0x3)); + REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); } static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) @@ -1100,6 +3553,82 @@ static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); } +static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain, + struct ath9k_channel *chan) +{ + int f[3], t[3]; + u16 value; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (chain >= 0 && chain < 3) { + if (IS_CHAN_2GHZ(chan)) + return eep->modalHeader2G.xatten1DB[chain]; + else if (eep->base_ext2.xatten1DBLow[chain] != 0) { + t[0] = eep->base_ext2.xatten1DBLow[chain]; + f[0] = 5180; + t[1] = eep->modalHeader5G.xatten1DB[chain]; + f[1] = 5500; + t[2] = eep->base_ext2.xatten1DBHigh[chain]; + f[2] = 5785; + value = ar9003_hw_power_interpolate((s32) chan->channel, + f, t, 3); + return value; + } else + return eep->modalHeader5G.xatten1DB[chain]; + } + + return 0; +} + + +static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain, + struct ath9k_channel *chan) +{ + int f[3], t[3]; + u16 value; + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + + if (chain >= 0 && chain < 3) { + if (IS_CHAN_2GHZ(chan)) + return eep->modalHeader2G.xatten1Margin[chain]; + else if (eep->base_ext2.xatten1MarginLow[chain] != 0) { + t[0] = eep->base_ext2.xatten1MarginLow[chain]; + f[0] = 5180; + t[1] = eep->modalHeader5G.xatten1Margin[chain]; + f[1] = 5500; + t[2] = eep->base_ext2.xatten1MarginHigh[chain]; + f[2] = 5785; + value = ar9003_hw_power_interpolate((s32) chan->channel, + f, t, 3); + return value; + } else + return eep->modalHeader5G.xatten1Margin[chain]; + } + + return 0; +} + +static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i; + u16 value; + unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0, + AR_PHY_EXT_ATTEN_CTL_1, + AR_PHY_EXT_ATTEN_CTL_2, + }; + + /* Test value. if 0 then attenuation is unused. Don't load anything. */ + for (i = 0; i < 3; i++) { + value = ar9003_hw_atten_chain_get(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); + + value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); + } +} + static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) { int internal_regulator = @@ -1131,6 +3660,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); + ar9003_hw_atten_apply(ah, chan); ar9003_hw_internal_regulator_apply(ah); } @@ -1192,7 +3722,7 @@ static int ar9003_hw_power_interpolate(int32_t x, if (hx == lx) y = ly; else /* interpolate */ - y = ly + (((x - lx) * (hy - ly)) / (hx - lx)); + y = interpolate(x, lx, hx, ly, hy); } else /* only low is good, use it */ y = ly; } else if (hhave) /* only high is good, use it */ @@ -1640,6 +4170,7 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, { int tempSlope = 0; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + int f[3], t[3]; REG_RMW(ah, AR_PHY_TPC_11_B0, (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), @@ -1668,7 +4199,16 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, */ if (frequency < 4000) tempSlope = eep->modalHeader2G.tempSlope; - else + else if (eep->base_ext2.tempSlopeLow != 0) { + t[0] = eep->base_ext2.tempSlopeLow; + f[0] = 5180; + t[1] = eep->modalHeader5G.tempSlope; + f[1] = 5500; + t[2] = eep->base_ext2.tempSlopeHigh; + f[2] = 5785; + tempSlope = ar9003_hw_power_interpolate((s32) frequency, + f, t, 3); + } else tempSlope = eep->modalHeader5G.tempSlope; REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); @@ -1772,25 +4312,23 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) /* so is the high frequency, interpolate */ if (hfrequency[ichain] - frequency < 1000) { - correction[ichain] = lcorrection[ichain] + - (((frequency - lfrequency[ichain]) * - (hcorrection[ichain] - - lcorrection[ichain])) / - (hfrequency[ichain] - lfrequency[ichain])); - - temperature[ichain] = ltemperature[ichain] + - (((frequency - lfrequency[ichain]) * - (htemperature[ichain] - - ltemperature[ichain])) / - (hfrequency[ichain] - lfrequency[ichain])); - - voltage[ichain] = - lvoltage[ichain] + - (((frequency - - lfrequency[ichain]) * (hvoltage[ichain] - - lvoltage[ichain])) - / (hfrequency[ichain] - - lfrequency[ichain])); + correction[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lcorrection[ichain], + hcorrection[ichain]); + + temperature[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + ltemperature[ichain], + htemperature[ichain]); + + voltage[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lvoltage[ichain], + hvoltage[ichain]); } /* only low is good, use it */ else { @@ -1922,14 +4460,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, int i; int16_t twiceLargestAntenna; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = { + static const u16 ctlModesFor11a[] = { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = { + static const u16 ctlModesFor11g[] = { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; u8 *ctlIndex; u8 ctlNum; @@ -2134,8 +4674,9 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); u8 targetPowerValT2[ar9300RateSize]; unsigned int i = 0; @@ -2147,7 +4688,16 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, twiceMaxRegulatoryPower, powerLimit); - while (i < ar9300RateSize) { + regulatory->max_power_level = 0; + for (i = 0; i < ar9300RateSize; i++) { + if (targetPowerValT2[i] > regulatory->max_power_level) + regulatory->max_power_level = targetPowerValT2[i]; + } + + if (test) + return; + + for (i = 0; i < ar9300RateSize; i++) { ath_print(common, ATH_DBG_EEPROM, "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); i++; @@ -2162,9 +4712,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, i++; } - /* Write target power array to registers */ - ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); - /* * This is the TX power we send back to driver core, * and it can use to pass to userspace to display our @@ -2183,7 +4730,10 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, i = ALL_TARGET_HT20_0_8_16; /* ht20 */ ah->txpower_limit = targetPowerValT2[i]; + regulatory->max_power_level = targetPowerValT2[i]; + /* Write target power array to registers */ + ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); ar9003_hw_calibration_apply(ah, chan->channel); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 655b3033396c..9c1463307f0c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -79,6 +79,15 @@ #define FIXED_CCA_THRESHOLD 15 #define AR9300_BASE_ADDR 0x3ff +#define AR9300_BASE_ADDR_512 0x1ff + +#define AR9300_OTP_BASE 0x14000 +#define AR9300_OTP_STATUS 0x15f18 +#define AR9300_OTP_STATUS_TYPE 0x7 +#define AR9300_OTP_STATUS_VALID 0x4 +#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 +#define AR9300_OTP_STATUS_SM_BUSY 0x1 +#define AR9300_OTP_READ_DATA 0x15f1c enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, @@ -236,7 +245,7 @@ struct ar9300_modal_eep_header { u8 thresh62; __le32 papdRateMaskHt20; __le32 papdRateMaskHt40; - u8 futureModal[24]; + u8 futureModal[10]; } __packed; struct ar9300_cal_data_per_freq_op_loop { @@ -269,6 +278,20 @@ struct cal_ctl_data_5g { u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G]; } __packed; +struct ar9300_BaseExtension_1 { + u8 ant_div_control; + u8 future[13]; +} __packed; + +struct ar9300_BaseExtension_2 { + int8_t tempSlopeLow; + int8_t tempSlopeHigh; + u8 xatten1DBLow[AR9300_MAX_CHAINS]; + u8 xatten1MarginLow[AR9300_MAX_CHAINS]; + u8 xatten1DBHigh[AR9300_MAX_CHAINS]; + u8 xatten1MarginHigh[AR9300_MAX_CHAINS]; +} __packed; + struct ar9300_eeprom { u8 eepromVersion; u8 templateVersion; @@ -278,6 +301,7 @@ struct ar9300_eeprom { struct ar9300_base_eep_hdr baseEepHeader; struct ar9300_modal_eep_header modalHeader2G; + struct ar9300_BaseExtension_1 base_ext1; u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; struct ar9300_cal_data_per_freq_op_loop calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; @@ -297,6 +321,7 @@ struct ar9300_eeprom { u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; struct ar9300_modal_eep_header modalHeader5G; + struct ar9300_BaseExtension_2 base_ext2; u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; struct ar9300_cal_data_per_freq_op_loop calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 3b424ca1ba84..f5896aa30005 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { struct ar9003_txs *ads; + u32 status; ads = &ah->ts_ring[ah->ts_tail]; - if ((ads->status8 & AR_TxDone) == 0) + status = ACCESS_ONCE(ads->status8); + if ((status & AR_TxDone) == 0) return -EINPROGRESS; ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; @@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, return -EIO; } + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; + ts->ts_rateindex = MS(status, AR_FinalTxIdx); + ts->ts_seqnum = MS(status, AR_SeqNum); + ts->tid = MS(status, AR_TxTid); + ts->qid = MS(ads->ds_info, AR_TxQcuNum); ts->desc_id = MS(ads->status1, AR_TxDescId); - ts->ts_seqnum = MS(ads->status8, AR_SeqNum); ts->ts_tstamp = ads->status4; ts->ts_status = 0; ts->ts_flags = 0; - if (ads->status3 & AR_ExcessiveRetries) + status = ACCESS_ONCE(ads->status2); + ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); + ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); + ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); + if (status & AR_TxBaStatus) { + ts->ts_flags |= ATH9K_TX_BA; + ts->ba_low = ads->status5; + ts->ba_high = ads->status6; + } + + status = ACCESS_ONCE(ads->status3); + if (status & AR_ExcessiveRetries) ts->ts_status |= ATH9K_TXERR_XRETRY; - if (ads->status3 & AR_Filtered) + if (status & AR_Filtered) ts->ts_status |= ATH9K_TXERR_FILT; - if (ads->status3 & AR_FIFOUnderrun) { + if (status & AR_FIFOUnderrun) { ts->ts_status |= ATH9K_TXERR_FIFO; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status8 & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; - if (ads->status3 & AR_TxTimerExpired) + if (status & AR_TxTimerExpired) ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->status3 & AR_DescCfgErr) + if (status & AR_DescCfgErr) ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->status3 & AR_TxDataUnderrun) { + if (status & AR_TxDataUnderrun) { ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status3 & AR_TxDelimUnderrun) { + if (status & AR_TxDelimUnderrun) { ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; ath9k_hw_updatetxtriglevel(ah, true); } - if (ads->status2 & AR_TxBaStatus) { - ts->ts_flags |= ATH9K_TX_BA; - ts->ba_low = ads->status5; - ts->ba_high = ads->status6; - } - - ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); - - ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); - ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00); - ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01); - ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02); - ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10); - ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11); - ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12); - ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt); - ts->ts_longretry = MS(ads->status3, AR_DataFailCnt); - ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt); - ts->ts_antenna = 0; + ts->ts_shortretry = MS(status, AR_RTSFailCnt); + ts->ts_longretry = MS(status, AR_DataFailCnt); + ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - ts->tid = MS(ads->status8, AR_TxTid); + status = ACCESS_ONCE(ads->status7); + ts->ts_rssi = MS(status, AR_TxRSSICombined); + ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); memset(ads, 0, sizeof(*ads)); @@ -407,12 +410,36 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, u32 aggrLen) { +#define FIRST_DESC_NDELIMS 60 struct ar9003_txc *ads = (struct ar9003_txc *) ds; ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); - ads->ctl17 &= ~AR_AggrLen; - ads->ctl17 |= SM(aggrLen, AR_AggrLen); + if (ah->ent_mode & AR_ENT_OTP_MPSD) { + u32 ctl17, ndelim; + /* + * Add delimiter when using RTS/CTS with aggregation + * and non enterprise AR9003 card + */ + ctl17 = ads->ctl17; + ndelim = MS(ctl17, AR_PadDelim); + + if (ndelim < FIRST_DESC_NDELIMS) { + aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; + ndelim = FIRST_DESC_NDELIMS; + } + + ctl17 &= ~AR_AggrLen; + ctl17 |= SM(aggrLen, AR_AggrLen); + + ctl17 &= ~AR_PadDelim; + ctl17 |= SM(ndelim, AR_PadDelim); + + ads->ctl17 = ctl17; + } else { + ads->ctl17 &= ~AR_AggrLen; + ads->ctl17 |= SM(aggrLen, AR_AggrLen); + } } static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 9f2cea70a840..45cc7e80436c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -65,7 +65,7 @@ struct ar9003_rxs { u32 status9; u32 status10; u32 status11; -} __packed; +} __packed __aligned(4); /* Transmit Control Descriptor */ struct ar9003_txc { @@ -93,7 +93,7 @@ struct ar9003_txc { u32 ctl21; /* DMA control 21 */ u32 ctl22; /* DMA control 22 */ u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ -} __packed; +} __packed __aligned(4); struct ar9003_txs { u32 ds_info; @@ -105,7 +105,7 @@ struct ar9003_txs { u32 status6; u32 status7; u32 status8; -} __packed; +} __packed __aligned(4); void ar9003_hw_attach_mac_ops(struct ath_hw *hw); void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 716db414c258..850bc9866c19 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -32,12 +32,12 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) { struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; struct ar9300_modal_eep_header *hdr; - const u32 ctrl0[3] = { + static const u32 ctrl0[3] = { AR_PHY_PAPRD_CTRL0_B0, AR_PHY_PAPRD_CTRL0_B1, AR_PHY_PAPRD_CTRL0_B2 }; - const u32 ctrl1[3] = { + static const u32 ctrl1[3] = { AR_PHY_PAPRD_CTRL1_B0, AR_PHY_PAPRD_CTRL1_B1, AR_PHY_PAPRD_CTRL1_B2 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 669b777729b3..b34a9e91edd8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -128,7 +128,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, struct ath9k_channel *chan) { - u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; + static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; int cur_bb_spur, negative = 0, cck_spur_freq; int i; @@ -487,7 +487,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) break; } - REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) + REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); + else + REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if (tx == 0x5) { REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); @@ -614,7 +618,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); return 0; } @@ -1023,25 +1027,25 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah, int16_t nf; nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); - nfarray[0] = sign_extend(nf, 9); + nfarray[0] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); - nfarray[1] = sign_extend(nf, 9); + nfarray[1] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); - nfarray[2] = sign_extend(nf, 9); + nfarray[2] = sign_extend32(nf, 8); if (!IS_CHAN_HT40(ah->curchan)) return; nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); - nfarray[3] = sign_extend(nf, 9); + nfarray[3] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); - nfarray[4] = sign_extend(nf, 9); + nfarray[4] = sign_extend32(nf, 8); nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); - nfarray[5] = sign_extend(nf, 9); + nfarray[5] = sign_extend32(nf, 8); } static void ar9003_hw_set_nf_limits(struct ath_hw *ah) @@ -1113,10 +1117,55 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; } +static void ar9003_hw_set_radar_params(struct ath_hw *ah, + struct ath_hw_radar_conf *conf) +{ + u32 radar_0 = 0, radar_1 = 0; + + if (!conf) { + REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + return; + } + + radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; + radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); + radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); + radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); + radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); + radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + + radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; + radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; + radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); + radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); + radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); + + REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); + REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); + if (conf->ext_channel) + REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + else + REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); +} + +static void ar9003_hw_set_radar_conf(struct ath_hw *ah) +{ + struct ath_hw_radar_conf *conf = &ah->radar_conf; + + conf->fir_power = -28; + conf->radar_rssi = 0; + conf->pulse_height = 10; + conf->pulse_rssi = 24; + conf->pulse_inband = 8; + conf->pulse_maxlen = 255; + conf->pulse_inband_step = 12; + conf->radar_inband = 8; +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - const u32 ar9300_cca_regs[6] = { + static const u32 ar9300_cca_regs[6] = { AR_PHY_CCA_0, AR_PHY_CCA_1, AR_PHY_CCA_2, @@ -1141,8 +1190,10 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->ani_control = ar9003_hw_ani_control; priv_ops->do_getnf = ar9003_hw_do_getnf; priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; + priv_ops->set_radar_params = ar9003_hw_set_radar_params; ar9003_hw_set_nf_limits(ah); + ar9003_hw_set_radar_conf(ah); memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0d0bec3628ec..4210a9306955 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -87,33 +87,19 @@ struct ath_config { /** * enum buffer_type - Buffer type flags * - * @BUF_HT: Send this buffer using HT capabilities * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) * @BUF_AGGR: Indicates whether the buffer can be aggregated * (used in aggregation scheduling) - * @BUF_RETRY: Indicates whether the buffer is retried * @BUF_XRETRY: To denote excessive retries of the buffer */ enum buffer_type { - BUF_HT = BIT(1), BUF_AMPDU = BIT(2), BUF_AGGR = BIT(3), - BUF_RETRY = BIT(4), BUF_XRETRY = BIT(5), }; -#define bf_nframes bf_state.bfs_nframes -#define bf_al bf_state.bfs_al -#define bf_frmlen bf_state.bfs_frmlen -#define bf_retries bf_state.bfs_retries -#define bf_seqno bf_state.bfs_seqno -#define bf_tidno bf_state.bfs_tidno -#define bf_keyix bf_state.bfs_keyix -#define bf_keytype bf_state.bfs_keytype -#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) -#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) #define ATH_TXSTATUS_RING_SIZE 64 @@ -178,8 +164,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, /* returns delimiter padding required given the packet length */ #define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) + (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ + DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ)) #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) @@ -196,7 +182,6 @@ enum ATH_AGGR_STATUS { #define ATH_TXFIFO_DEPTH 8 struct ath_txq { - int axq_class; u32 axq_qnum; u32 *axq_link; struct list_head axq_q; @@ -209,27 +194,28 @@ struct ath_txq { struct list_head txq_fifo_pending; u8 txq_headidx; u8 txq_tailidx; + int pending_frames; }; struct ath_atx_ac { + struct ath_txq *txq; int sched; - int qnum; struct list_head list; struct list_head tid_q; }; +struct ath_frame_info { + int framelen; + u32 keyix; + enum ath9k_key_type keytype; + u8 retries; + u16 seqno; +}; + struct ath_buf_state { - int bfs_nframes; - u16 bfs_al; - u16 bfs_frmlen; - int bfs_seqno; - int bfs_tidno; - int bfs_retries; u8 bf_type; u8 bfs_paprd; - unsigned long bfs_paprd_timestamp; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; + enum ath9k_internal_frame_type bfs_ftype; }; struct ath_buf { @@ -242,7 +228,6 @@ struct ath_buf { dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ bool bf_stale; - bool bf_tx_aborted; u16 bf_flags; struct ath_buf_state bf_state; struct ath_wiphy *aphy; @@ -271,7 +256,6 @@ struct ath_node { struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; - int last_rssi; }; #define AGGR_CLEANUP BIT(1) @@ -280,6 +264,7 @@ struct ath_node { struct ath_tx_control { struct ath_txq *txq; + struct ath_node *an; int if_id; enum ath9k_internal_frame_type frame_type; u8 paprd; @@ -292,12 +277,11 @@ struct ath_tx_control { struct ath_tx { u16 seq_no; u32 txqsetup; - int hwq_map[WME_NUM_AC]; spinlock_t txbuflock; struct list_head txbuf; struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; struct ath_descdma txdma; - int pending_frames[WME_NUM_AC]; + struct ath_txq *txq_map[WME_NUM_AC]; }; struct ath_rx_edma { @@ -311,7 +295,6 @@ struct ath_rx { u8 rxotherant; u32 *rxlink; unsigned int rxfilter; - spinlock_t pcu_lock; spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; @@ -328,7 +311,6 @@ void ath_rx_cleanup(struct ath_softc *sc); int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_setup(struct ath_softc *sc, int haltype); void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx); @@ -343,7 +325,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl); void ath_tx_tasklet(struct ath_softc *sc); void ath_tx_edma_tasklet(struct ath_softc *sc); -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, u16 *ssn); void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); @@ -564,6 +545,7 @@ struct ath_ant_comb { #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) +#define SC_OP_ENABLE_APM BIT(15) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -601,13 +583,14 @@ struct ath_softc { struct ath_hw *sc_ah; void __iomem *mem; int irq; - spinlock_t sc_resetlock; spinlock_t sc_serial_rw; spinlock_t sc_pm_lock; + spinlock_t sc_pcu_lock; struct mutex mutex; struct work_struct paprd_work; struct work_struct hw_check_work; struct completion paprd_complete; + bool paprd_pending; u32 intrstatus; u32 sc_flags; /* SC_OP_* */ @@ -665,11 +648,11 @@ struct ath_wiphy { bool idle; int chan_idx; int chan_is_ht; + int last_rssi; }; void ath9k_tasklet(unsigned long data); int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); static inline void ath_read_cachesize(struct ath_common *common, int *csz) @@ -715,10 +698,12 @@ static inline void ath_ahb_exit(void) {}; void ath9k_ps_wakeup(struct ath_softc *sc); void ath9k_ps_restore(struct ath_softc *sc); +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); + void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int ath9k_wiphy_add(struct ath_softc *sc); int ath9k_wiphy_del(struct ath_wiphy *aphy); -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype); int ath9k_wiphy_pause(struct ath_wiphy *aphy); int ath9k_wiphy_unpause(struct ath_wiphy *aphy); int ath9k_wiphy_select(struct ath_wiphy *aphy); diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 19891e7d49ae..47bedd82e9a9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi, qi_be; - int qnum; + struct ath_txq *txq; ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { @@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc *sc) qi.tqi_cwmax = 0; } else { /* Adhoc mode; important thing is to use 2x cwmin. */ - qnum = sc->tx.hwq_map[WME_AC_BE]; - ath9k_hw_get_txq_props(ah, qnum, &qi_be); + txq = sc->tx.txq_map[WME_AC_BE]; + ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; qi.tqi_cwmin = 4*qi_be.tqi_cwmin; qi.tqi_cwmax = qi_be.tqi_cwmax; @@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; - series[0].ChSel = common->tx_chainmask; + series[0].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[0].Rate); series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, series, 4, 0); } +static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_tx_control txctl; + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = sc->beacon.cabq; + + ath_print(common, ATH_DBG_XMIT, + "transmitting CABQ packet, skb: %p\n", skb); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); + dev_kfree_skb_any(skb); + } +} + static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -503,7 +523,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, /* Set the computed AP beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); @@ -638,7 +658,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc, /* Set the computed STA beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_hw_set_sta_beacon_timers(ah, &bs); ah->imask |= ATH9K_INT_BMISS; ath9k_hw_set_interrupts(ah, ah->imask); @@ -686,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, /* Set the computed ADHOC beacon timers */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 6a92e57fddf0..d33bf204c995 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -35,29 +35,6 @@ struct ath_btcoex_config { bool bt_hold_rx_clear; }; -static const u16 ath_subsysid_tbl[] = { - AR9280_COEX2WIRE_SUBSYSID, - AT9285_COEX3WIRE_SA_SUBSYSID, - AT9285_COEX3WIRE_DA_SUBSYSID -}; - -/* - * Checks the subsystem id of the device to see if it - * supports btcoex - */ -bool ath9k_hw_btcoex_supported(struct ath_hw *ah) -{ - int i; - - if (!ah->hw_version.subsysid) - return false; - - for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) - if (ah->hw_version.subsysid == ath_subsysid_tbl[i]) - return true; - - return false; -} void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) { diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 1ee5a15ccbb1..588dfd464dd1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -49,7 +49,6 @@ struct ath_btcoex_hw { u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ }; -bool ath9k_hw_btcoex_supported(struct ath_hw *ah); void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index f43a2d98421c..48b07c319a7f 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, /* * Update internal channel flags. */ -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan) +void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { - struct ieee80211_channel *chan = hw->conf.channel; - struct ieee80211_conf *conf = &hw->conf; - ichan->channel = chan->center_freq; ichan->chan = chan; @@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; } - if (conf_is_ht(conf)) - ichan->chanmode = ath9k_get_extchanmode(chan, - conf->channel_type); + if (channel_type != NL80211_CHAN_NO_HT) + ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); } EXPORT_SYMBOL(ath9k_cmn_update_ichannel); @@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, chan_idx = curchan->hw_value; channel = &ah->channels[chan_idx]; - ath9k_cmn_update_ichannel(hw, channel); + ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); return channel; } diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index fea3b3315391..4c04ee85ff0e 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -31,10 +31,11 @@ #define WME_MAX_BA WME_BA_BMP_SIZE #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) -#define WME_AC_BE 0 -#define WME_AC_BK 1 -#define WME_AC_VI 2 -#define WME_AC_VO 3 +/* These must match mac80211 skb queue mapping numbers */ +#define WME_AC_VO 0 +#define WME_AC_VI 1 +#define WME_AC_BE 2 +#define WME_AC_BK 3 #define WME_NUM_AC 4 #define ATH_RSSI_DUMMY_MARKER 0x127 @@ -62,8 +63,9 @@ enum ath_stomp_type { int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); -void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, - struct ath9k_channel *ichan); +void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, struct ath_hw *ah); int ath9k_cmn_count_streams(unsigned int chainmask, int max); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 43e71a944cb1..3586c43077a7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -24,8 +24,6 @@ #define REG_READ_D(_ah, _reg) \ ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) -static struct dentry *ath9k_debugfs_root; - static int ath9k_debugfs_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -461,16 +459,16 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, /* Put variable-length stuff down here, and check for overflows. */ for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) + struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i]; + if (aphy_tmp == NULL) continue; - chan = aphy->hw->conf.channel; + chan = aphy_tmp->hw->conf.channel; len += snprintf(buf + len, sizeof(buf) - len, "secondary: %s (%s chan=%d ht=%d)\n", - wiphy_name(aphy->hw->wiphy), - ath_wiphy_state_str(aphy->state), + wiphy_name(aphy_tmp->hw->wiphy), + ath_wiphy_state_str(aphy_tmp->state), ieee80211_frequency_to_channel(chan->center_freq), - aphy->chan_is_ht); + aphy_tmp->chan_is_ht); } if (len > sizeof(buf)) len = sizeof(buf); @@ -585,10 +583,10 @@ static const struct file_operations fops_wiphy = { do { \ len += snprintf(buf + len, size - len, \ "%s%13u%11u%10u%10u\n", str, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ + sc->debug.stats.txstats[WME_AC_BE].elem, \ + sc->debug.stats.txstats[WME_AC_BK].elem, \ + sc->debug.stats.txstats[WME_AC_VI].elem, \ + sc->debug.stats.txstats[WME_AC_VO].elem); \ } while(0) static ssize_t read_file_xmit(struct file *file, char __user *user_buf, @@ -630,33 +628,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, return retval; } -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct ath_tx_status *ts) +void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts) { - TX_STAT_INC(txq->axq_qnum, tx_pkts_all); - sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len; + int qnum = skb_get_queue_mapping(bf->bf_mpdu); + + TX_STAT_INC(qnum, tx_pkts_all); + sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; if (bf_isampdu(bf)) { if (bf_isxretried(bf)) - TX_STAT_INC(txq->axq_qnum, a_xretries); + TX_STAT_INC(qnum, a_xretries); else - TX_STAT_INC(txq->axq_qnum, a_completed); + TX_STAT_INC(qnum, a_completed); } else { - TX_STAT_INC(txq->axq_qnum, completed); + TX_STAT_INC(qnum, completed); } if (ts->ts_status & ATH9K_TXERR_FIFO) - TX_STAT_INC(txq->axq_qnum, fifo_underrun); + TX_STAT_INC(qnum, fifo_underrun); if (ts->ts_status & ATH9K_TXERR_XTXOP) - TX_STAT_INC(txq->axq_qnum, xtxop); + TX_STAT_INC(qnum, xtxop); if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) - TX_STAT_INC(txq->axq_qnum, timer_exp); + TX_STAT_INC(qnum, timer_exp); if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) - TX_STAT_INC(txq->axq_qnum, desc_cfg_err); + TX_STAT_INC(qnum, desc_cfg_err); if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, data_underrun); + TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, delim_underrun); + TX_STAT_INC(qnum, delim_underrun); } static const struct file_operations fops_xmit = { @@ -876,11 +876,8 @@ int ath9k_init_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; - if (!ath9k_debugfs_root) - return -ENOENT; - - sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath9k_debugfs_root); + sc->debug.debugfs_phy = debugfs_create_dir("ath9k", + sc->hw->wiphy->debugfsdir); if (!sc->debug.debugfs_phy) return -ENOMEM; @@ -933,29 +930,7 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.regidx = 0; return 0; err: - ath9k_exit_debug(ah); - return -ENOMEM; -} - -void ath9k_exit_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - debugfs_remove_recursive(sc->debug.debugfs_phy); -} - -int ath9k_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; + sc->debug.debugfs_phy = NULL; + return -ENOMEM; } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index bb0823242ba0..1e5078bd0344 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -164,13 +164,10 @@ struct ath9k_debug { }; int ath9k_init_debug(struct ath_hw *ah); -void ath9k_exit_debug(struct ath_hw *ah); -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct ath_tx_status *ts); +void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); #else @@ -180,26 +177,12 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } -static inline void ath9k_exit_debug(struct ath_hw *ah) -{ -} - -static inline int ath9k_debug_create_root(void) -{ - return 0; -} - -static inline void ath9k_debug_remove_root(void) -{ -} - static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { } static inline void ath_debug_stat_tx(struct ath_softc *sc, - struct ath_txq *txq, struct ath_buf *bf, struct ath_tx_status *ts) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index dd59f09441a3..8b9885b5243f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -280,6 +280,7 @@ enum eeprom_param { EEP_PAPRD, EEP_MODAL_VER, EEP_ANT_DIV_CTL1, + EEP_CHAIN_MASK_REDUCE }; enum ar5416_rates { @@ -681,7 +682,8 @@ struct eeprom_ops { void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, u8 powerLimit); + u8 twiceMaxRegulatoryPower, u8 powerLimit, + bool test); u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); }; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 4fa4d8e28c64..c2481b3ac7e6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -534,7 +534,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, u16 twiceMinEdgePower; u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; struct cal_ctl_data_4k *rep; struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; @@ -550,10 +552,10 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { 0, {0, 0, 0, 0} }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; ath9k_hw_get_channel_centers(ah, chan, ¢ers); @@ -726,7 +728,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; @@ -751,15 +753,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); if (ratesArray[i] > AR5416_MAX_RATE_POWER) ratesArray[i] = AR5416_MAX_RATE_POWER; + + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; } + if (test) + return; /* Update regulatory */ - i = rate6mb; if (IS_CHAN_HT40(chan)) i = rateHt40_0; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 195406db3bd8..bcb9ed39c047 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -37,10 +37,10 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) int addr, eep_start_loc; eep_data = (u16 *)eep; - if (AR9287_HTC_DEVID(ah)) - eep_start_loc = AR9287_HTC_EEP_START_LOC; - else + if (!common->driver_info) eep_start_loc = AR9287_EEP_START_LOC; + else + eep_start_loc = AR9287_HTC_EEP_START_LOC; if (!ath9k_hw_use_flash(ah)) { ath_print(common, ATH_DBG_EEPROM, @@ -626,13 +626,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0} }; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11g[] = {CTL_11B, - CTL_11G, - CTL_2GHT20, - CTL_11B_EXT, - CTL_11G_EXT, - CTL_2GHT40}; - u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + u16 numCtlModes = 0; + const u16 *pCtlMode = NULL; + u16 ctlMode, freq; struct chan_centers centers; int tx_chainmask; u16 twiceMinEdgePower; @@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; @@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); if (ratesArray[i] > AR9287_MAX_RATE_POWER) ratesArray[i] = AR9287_MAX_RATE_POWER; + + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; } + if (test) + return; + + if (IS_CHAN_2GHZ(chan)) + i = rate1l; + else + i = rate6mb; + + regulatory->max_power_level = ratesArray[i]; + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; @@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); } - - if (IS_CHAN_2GHZ(chan)) - i = rate1l; - else - i = rate6mb; - - if (AR_SREV_9280_20_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; } static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 526d7c933f7f..45f70b2404a1 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1022,13 +1022,16 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, 0, {0, 0, 0, 0} }; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = - { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + static const u16 ctlModesFor11a[] = { + CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 + }; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; int tx_chainmask; u16 twiceMinEdgePower; @@ -1259,7 +1262,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); @@ -1286,12 +1289,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); if (ratesArray[i] > AR5416_MAX_RATE_POWER) ratesArray[i] = AR5416_MAX_RATE_POWER; + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; + } + + if (!test) { + i = rate6mb; + + if (IS_CHAN_HT40(chan)) + i = rateHt40_0; + else if (IS_CHAN_HT20(chan)) + i = rateHt20_0; + + regulatory->max_power_level = ratesArray[i]; + } + + switch(ar5416_get_ntxchains(ah->txchainmask)) { + case 1: + break; + case 2: + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; + break; + case 3: + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; + break; + default: + ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); + break; } + if (test) + return; + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) { int8_t pwr_table_offset; @@ -1388,34 +1423,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_POWER_TX_SUB, ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_20_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; - - switch(ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } } static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 4a9a68bba324..6a1a482f9dc3 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah, ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ah->imask |= ATH9K_INT_GENTIMER; ath9k_hw_set_interrupts(ah, ah->imask); } @@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) /* if no timer is enabled, turn off interrupt mask */ if (timer_table->timer_mask.val == 0) { - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ah->imask &= ~ATH9K_INT_GENTIMER; ath9k_hw_set_interrupts(ah, ah->imask); } @@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsigned long data) timer_period = is_btscan ? btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp; - ath9k_gen_timer_start(ah, - btcoex->no_stomp_timer, - (ath9k_hw_gettsf32(ah) + - timer_period), timer_period * 10); + ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0, + timer_period * 10); btcoex->hw_timer_enabled = true; } diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index dfb6560dab92..8946e8ad1b85 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -28,10 +28,16 @@ MODULE_FIRMWARE(FIRMWARE_AR9271); static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ + { USB_DEVICE(0x0cf3, 0x7010), + .driver_info = AR7010_DEVICE }, + /* Atheros */ + { USB_DEVICE(0x0cf3, 0x7015), + .driver_info = AR7010_DEVICE | AR9287_DEVICE }, + /* Atheros */ { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ - { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ + { USB_DEVICE(0x0846, 0x9018), + .driver_info = AR7010_DEVICE }, + /* Netgear WNDA3200 */ { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ @@ -40,9 +46,13 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ - { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ + { USB_DEVICE(0x083A, 0xA704), + .driver_info = AR7010_DEVICE }, + /* SMC Networks */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ - { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */ + { USB_DEVICE(0x1668, 0x1200), + .driver_info = AR7010_DEVICE | AR9287_DEVICE }, + /* Verizon */ { }, }; @@ -353,9 +363,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, struct sk_buff *skb) { struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; - int index = 0, i = 0, chk_idx, len = skb->len; - int rx_remain_len = 0, rx_pkt_len = 0; - u16 pkt_len, pkt_tag, pool_index = 0; + int index = 0, i = 0, len = skb->len; + int rx_remain_len, rx_pkt_len; + u16 pool_index = 0; u8 *ptr; spin_lock(&hif_dev->rx_lock); @@ -389,64 +399,64 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, spin_unlock(&hif_dev->rx_lock); while (index < len) { + u16 pkt_len; + u16 pkt_tag; + u16 pad_len; + int chk_idx; + ptr = (u8 *) skb->data; pkt_len = ptr[index] + (ptr[index+1] << 8); pkt_tag = ptr[index+2] + (ptr[index+3] << 8); - if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { - u16 pad_len; - - pad_len = 4 - (pkt_len & 0x3); - if (pad_len == 4) - pad_len = 0; - - chk_idx = index; - index = index + 4 + pkt_len + pad_len; - - if (index > MAX_RX_BUF_SIZE) { - spin_lock(&hif_dev->rx_lock); - hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; - hif_dev->rx_transfer_len = - MAX_RX_BUF_SIZE - chk_idx - 4; - hif_dev->rx_pad_len = pad_len; - - nskb = __dev_alloc_skb(pkt_len + 32, - GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - spin_unlock(&hif_dev->rx_lock); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), - hif_dev->rx_transfer_len); - - /* Record the buffer pointer */ - hif_dev->remain_skb = nskb; + if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { + RX_STAT_INC(skb_dropped); + return; + } + + pad_len = 4 - (pkt_len & 0x3); + if (pad_len == 4) + pad_len = 0; + + chk_idx = index; + index = index + 4 + pkt_len + pad_len; + + if (index > MAX_RX_BUF_SIZE) { + spin_lock(&hif_dev->rx_lock); + hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; + hif_dev->rx_transfer_len = + MAX_RX_BUF_SIZE - chk_idx - 4; + hif_dev->rx_pad_len = pad_len; + + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); spin_unlock(&hif_dev->rx_lock); - } else { - nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); - skb_put(nskb, pkt_len); - skb_pool[pool_index++] = nskb; + goto err; } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), + hif_dev->rx_transfer_len); + + /* Record the buffer pointer */ + hif_dev->remain_skb = nskb; + spin_unlock(&hif_dev->rx_lock); } else { - RX_STAT_INC(skb_dropped); - return; + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); + goto err; + } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); + skb_put(nskb, pkt_len); + skb_pool[pool_index++] = nskb; } } @@ -461,7 +471,7 @@ err: static void ath9k_hif_usb_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@ -508,7 +518,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; struct sk_buff *nskb; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@ -776,7 +786,8 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) ath9k_hif_usb_dealloc_rx_urbs(hif_dev); } -static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev, + u32 drv_info) { int transfer, err; const void *data = hif_dev->firmware->data; @@ -807,18 +818,10 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) } kfree(buf); - switch (hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (drv_info & AR7010_DEVICE) firm_offset = AR7010_FIRMWARE_TEXT; - break; - default: + else firm_offset = AR9271_FIRMWARE_TEXT; - break; - } /* * Issue FW download complete command to firmware. @@ -836,7 +839,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) return 0; } -static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) { int ret, idx; struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; @@ -852,7 +855,7 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) } /* Download firmware */ - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, drv_info); if (ret) { dev_err(&hif_dev->udev->dev, "ath9k_htc: Firmware - %s download failed\n", @@ -931,23 +934,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, /* Find out which firmware to load */ - switch(hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (id->driver_info & AR7010_DEVICE) if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) hif_dev->fw_name = FIRMWARE_AR7010_1_1; else hif_dev->fw_name = FIRMWARE_AR7010; - break; - default: + else hif_dev->fw_name = FIRMWARE_AR9271; - break; - } - ret = ath9k_hif_usb_dev_init(hif_dev); + ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info); if (ret) { ret = -EINVAL; goto err_hif_init_usb; @@ -955,7 +950,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, ret = ath9k_htc_hw_init(hif_dev->htc_handle, &hif_dev->udev->dev, hif_dev->device_id, - hif_dev->udev->product); + hif_dev->udev->product, id->driver_info); if (ret) { ret = -EINVAL; goto err_htc_hw_init; @@ -998,8 +993,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) static void ath9k_hif_usb_disconnect(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); if (hif_dev) { ath9k_htc_hw_deinit(hif_dev->htc_handle, @@ -1021,8 +1015,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) static int ath9k_hif_usb_suspend(struct usb_interface *interface, pm_message_t message) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); ath9k_hif_usb_dealloc_urbs(hif_dev); @@ -1031,8 +1024,8 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, static int ath9k_hif_usb_resume(struct usb_interface *interface) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); + struct htc_target *htc_handle = hif_dev->htc_handle; int ret; ret = ath9k_hif_usb_alloc_urbs(hif_dev); @@ -1040,7 +1033,8 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) return ret; if (hif_dev->firmware) { - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, + htc_handle->drv_priv->ah->common.driver_info); if (ret) goto fail_resume; } else { @@ -1050,7 +1044,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) mdelay(100); - ret = ath9k_htc_resume(hif_dev->htc_handle); + ret = ath9k_htc_resume(htc_handle); if (ret) goto fail_resume; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 75ecf6a30d25..afe39a911906 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -368,7 +368,7 @@ struct ath9k_htc_priv { u16 seq_no; u32 bmiss_cnt; - struct ath9k_hw_cal_data caldata[38]; + struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS]; spinlock_t beacon_lock; @@ -461,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product); + u16 devid, char *product, u32 drv_info); void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); #ifdef CONFIG_PM int ath9k_htc_resume(struct htc_target *htc_handle); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 7c8a38d04561..071d0c974747 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -181,7 +181,8 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, return htc_connect_service(priv->htc, &req, ep_id); } -static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) +static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, + u32 drv_info) { int ret; @@ -245,17 +246,10 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) * the HIF layer, shouldn't matter much. */ - switch(devid) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (drv_info & AR7010_DEVICE) priv->htc->credits = 45; - break; - default: + else priv->htc->credits = 33; - } ret = htc_init(priv->htc); if (ret) @@ -308,7 +302,7 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) struct ath_hw *ah = (struct ath_hw *) hw_priv; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - __be32 buf[2] = { + const __be32 buf[2] = { cpu_to_be32(reg_offset), cpu_to_be32(val), }; @@ -627,7 +621,8 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) } static int ath9k_init_priv(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, + u32 drv_info) { struct ath_hw *ah = NULL; struct ath_common *common; @@ -641,6 +636,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ah->hw_version.devid = devid; ah->hw_version.subsysid = 0; /* FIXME */ + ah->ah_flags |= AH_USE_EEPROM; priv->ah = ah; common = ath9k_hw_common(ah); @@ -650,6 +646,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, common->hw = priv->hw; common->priv = priv; common->debug_mask = ath9k_debug; + common->driver_info = drv_info; spin_lock_init(&priv->wmi->wmi_lock); spin_lock_init(&priv->beacon_lock); @@ -762,7 +759,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, } static int ath9k_init_device(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw = priv->hw; struct ath_common *common; @@ -771,7 +768,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, struct ath_regulatory *reg; /* Bring up device */ - error = ath9k_init_priv(priv, devid, product); + error = ath9k_init_priv(priv, devid, product, drv_info); if (error != 0) goto err_init; @@ -829,7 +826,7 @@ err_init: } int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw; struct ath9k_htc_priv *priv; @@ -856,14 +853,14 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, goto err_free; } - ret = ath9k_init_htc_services(priv, devid); + ret = ath9k_init_htc_services(priv, devid, drv_info); if (ret) goto err_init; /* The device may have been unplugged earlier. */ priv->op_flags &= ~OP_UNPLUGGED; - ret = ath9k_init_device(priv, devid, product); + ret = ath9k_init_device(priv, devid, product, drv_info); if (ret) goto err_init; @@ -893,14 +890,15 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) #ifdef CONFIG_PM int ath9k_htc_resume(struct htc_target *htc_handle) { + struct ath9k_htc_priv *priv = htc_handle->drv_priv; int ret; - ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); + ret = ath9k_htc_wait_for_target(priv); if (ret) return ret; - ret = ath9k_init_htc_services(htc_handle->drv_priv, - htc_handle->drv_priv->ah->hw_version.devid); + ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, + priv->ah->common.driver_info); return ret; } #endif diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9a3be8da755d..8266ce1f02e3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9k_htc_priv *priv) struct ath_hw *ah = priv->ah; if (priv->curtxpow != priv->txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); + ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); /* read back in case value is clamped */ priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@ -1400,7 +1400,9 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", curchan->center_freq); - ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); + ath9k_cmn_update_ichannel(&priv->ah->channels[pos], + hw->conf.channel, + hw->conf.channel_type); if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { ath_print(common, ATH_DBG_FATAL, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 29d80ca78393..77958675b55f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -20,8 +20,15 @@ /* TX */ /******/ +static const int subtype_txq_to_hwq[] = { + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, +}; + #define ATH9K_HTC_INIT_TXQ(subtype) do { \ - qi.tqi_subtype = subtype; \ + qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \ qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 861ec9269309..c41ab8c30161 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -462,9 +462,10 @@ void ath9k_htc_hw_free(struct htc_target *htc) } int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid, char *product) + struct device *dev, u16 devid, + char *product, u32 drv_info) { - if (ath9k_htc_probe_device(target, dev, devid, product)) { + if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { printk(KERN_ERR "Failed to initialize the device\n"); return -ENODEV; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 07b6509d5896..ecd018798c47 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -77,20 +77,6 @@ struct htc_config_pipe_msg { u8 credits; } __packed; -struct htc_packet { - void *pktcontext; - u8 *buf; - u8 *buf_payload; - u32 buflen; - u32 payload_len; - - int endpoint; - int status; - - void *context; - u32 reserved; -}; - struct htc_ep_callbacks { void *priv; void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); @@ -123,11 +109,6 @@ struct htc_endpoint { #define HTC_CONTROL_BUFFER_SIZE \ (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) -struct htc_control_buf { - struct htc_packet htc_pkt; - u8 buf[HTC_CONTROL_BUFFER_SIZE]; -}; - #define HTC_OP_START_WAIT BIT(0) #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) @@ -239,7 +220,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, struct device *dev); void ath9k_htc_hw_free(struct htc_target *htc); int ath9k_htc_hw_init(struct htc_target *target, - struct device *dev, u16 devid, char *product); + struct device *dev, u16 devid, char *product, + u32 drv_info); void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); #endif /* HTC_HST_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c7fbe25cc128..9b1ee7fc05c1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -310,10 +310,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); u32 regAddr[2] = { AR_STA_ID0 }; u32 regHold[2]; - u32 patternData[4] = { 0x55555555, - 0xaaaaaaaa, - 0x66666666, - 0x99999999 }; + static const u32 patternData[4] = { + 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 + }; int i, j, loop_max; if (!AR_SREV_9300_20_OR_LATER(ah)) { @@ -419,10 +418,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->hw_version.magic = AR5416_MAGIC; ah->hw_version.subvendorid = 0; - ah->ah_flags = 0; - if (!AR_SREV_9100(ah)) - ah->ah_flags = AH_USE_EEPROM; - ah->atim_window = 0; ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | @@ -440,7 +435,7 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) u32 sum; int i; u16 eeval; - u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; + static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; sum = 0; for (i = 0; i < 3; i++) { @@ -1170,7 +1165,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), false); ath9k_hw_rfbus_done(ah); @@ -1833,6 +1828,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; + /* enable key search for every frame in an aggregate */ + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; + pCap->low_2ghz_chan = 2312; pCap->high_2ghz_chan = 2732; @@ -1926,8 +1925,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->num_antcfg_2ghz = ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - if (AR_SREV_9280_20_OR_LATER(ah) && - ath9k_hw_btcoex_supported(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; @@ -1963,6 +1961,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->ent_mode = REG_READ(ah, AR_ENT_OTP); + if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; @@ -1973,6 +1974,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; } + if (AR_SREV_9300_20_OR_LATER(ah)) { + if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) + pCap->hw_caps |= ATH9K_HW_CAP_APM; + } + + return 0; } @@ -2177,7 +2184,7 @@ bool ath9k_hw_disable(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable); -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath9k_channel *chan = ah->curchan; @@ -2190,7 +2197,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); + (u32) regulatory->power_limit), test); } EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); @@ -2324,11 +2331,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) return timer_table->gen_timer_index[b]; } -u32 ath9k_hw_gettsf32(struct ath_hw *ah) +static u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } -EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d47d1b4b6002..5fcfa48a45df 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -157,6 +157,13 @@ #define PAPRD_GAIN_TABLE_ENTRIES 32 #define PAPRD_TABLE_SZ 24 +enum ath_hw_txq_subtype { + ATH_TXQ_AC_BE = 0, + ATH_TXQ_AC_BK = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, +}; + enum ath_ini_subsys { ATH_INI_PRE = 0, ATH_INI_CORE, @@ -180,6 +187,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), ATH9K_HW_CAP_2GHZ = BIT(13), ATH9K_HW_CAP_5GHZ = BIT(14), + ATH9K_HW_CAP_APM = BIT(15), }; struct ath9k_hw_capabilities { @@ -478,6 +486,40 @@ struct ath_hw_antcomb_conf { }; /** + * struct ath_hw_radar_conf - radar detection initialization parameters + * + * @pulse_inband: threshold for checking the ratio of in-band power + * to total power for short radar pulses (half dB steps) + * @pulse_inband_step: threshold for checking an in-band power to total + * power ratio increase for short radar pulses (half dB steps) + * @pulse_height: threshold for detecting the beginning of a short + * radar pulse (dB step) + * @pulse_rssi: threshold for detecting if a short radar pulse is + * gone (dB step) + * @pulse_maxlen: maximum pulse length (0.8 us steps) + * + * @radar_rssi: RSSI threshold for starting long radar detection (dB steps) + * @radar_inband: threshold for checking the ratio of in-band power + * to total power for long radar pulses (half dB steps) + * @fir_power: threshold for detecting the end of a long radar pulse (dB) + * + * @ext_channel: enable extension channel radar detection + */ +struct ath_hw_radar_conf { + unsigned int pulse_inband; + unsigned int pulse_inband_step; + unsigned int pulse_height; + unsigned int pulse_rssi; + unsigned int pulse_maxlen; + + unsigned int radar_rssi; + unsigned int radar_inband; + int fir_power; + + bool ext_channel; +}; + +/** * struct ath_hw_private_ops - callbacks used internally by hardware code * * This structure contains private callbacks designed to only be used internally @@ -542,6 +584,8 @@ struct ath_hw_private_ops { bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, int param); void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); + void (*set_radar_params)(struct ath_hw *ah, + struct ath_hw_radar_conf *conf); /* ANI */ void (*ani_cache_ini_regs)(struct ath_hw *ah); @@ -740,6 +784,8 @@ struct ath_hw { u8 txchainmask; u8 rxchainmask; + struct ath_hw_radar_conf radar_conf; + u32 originalGain[22]; int initPDADC; int PDADCdelta; @@ -797,6 +843,9 @@ struct ath_hw { * this register when in sleep states. */ u32 WARegVal; + + /* Enterprise mode cap */ + u32 ent_mode; }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -819,12 +868,6 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah) return &ah->ops; } -static inline int sign_extend(int val, const int nbits) -{ - int order = BIT(nbits-1); - return (val ^ order) - order; -} - /* Initialization, Detach, Reset */ const char *ath9k_hw_probe(u16 vendorid, u16 devid); void ath9k_hw_deinit(struct ath_hw *ah); @@ -861,7 +904,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah); void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); bool ath9k_hw_phy_disable(struct ath_hw *ah); bool ath9k_hw_disable(struct ath_hw *ah); -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); void ath9k_hw_setbssidmask(struct ath_hw *ah); @@ -893,7 +936,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_isr(struct ath_hw *hw); -u32 ath9k_hw_gettsf32(struct ath_hw *ah); void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 14b8ab386daf..918308a28410 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -37,6 +37,10 @@ int led_blink; module_param_named(blink, led_blink, int, 0444); MODULE_PARM_DESC(blink, "Enable LED blink on activity"); +static int ath9k_btcoex_enable; +module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); +MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); + /* We use the hw_value as an index into our private channel structure */ #define CHAN2G(_freq, _idx) { \ @@ -395,7 +399,8 @@ static void ath9k_init_crypto(struct ath_softc *sc) static int ath9k_init_btcoex(struct ath_softc *sc) { - int r, qnum; + struct ath_txq *txq; + int r; switch (sc->sc_ah->btcoex_hw.scheme) { case ATH_BTCOEX_CFG_NONE: @@ -408,8 +413,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc) r = ath_init_btcoex_timer(sc); if (r) return -1; - qnum = sc->tx.hwq_map[WME_AC_BE]; - ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); + txq = sc->tx.txq_map[WME_AC_BE]; + ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; break; default: @@ -422,59 +427,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc) static int ath9k_init_queues(struct ath_softc *sc) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); int i = 0; - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); - if (sc->beacon.beaconq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); - goto err; - } - sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); - if (sc->beacon.cabq == NULL) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); - goto err; - } sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); - if (!ath_tx_setup(sc, WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - goto err; - } - - if (!ath_tx_setup(sc, WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - goto err; - } - if (!ath_tx_setup(sc, WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - goto err; - } - if (!ath_tx_setup(sc, WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - goto err; - } + for (i = 0; i < WME_NUM_AC; i++) + sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); return 0; - -err: - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - return -EIO; } static int ath9k_init_channels_rates(struct ath_softc *sc) @@ -570,6 +534,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; + if (!sc->dev->platform_data) + ah->ah_flags |= AH_USE_EEPROM; + common = ath9k_hw_common(ah); common->ops = &ath9k_common_ops; common->bus_ops = bus_ops; @@ -577,10 +544,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; + common->btcoex_enabled = ath9k_btcoex_enable == 1; spin_lock_init(&common->cc_lock); spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); @@ -600,13 +567,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, if (ret) goto err_hw; - ret = ath9k_init_debug(ah); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); - goto err_debug; - } - ret = ath9k_init_queues(sc); if (ret) goto err_queues; @@ -629,8 +589,6 @@ err_btcoex: if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); err_queues: - ath9k_exit_debug(ah); -err_debug: ath9k_hw_deinit(ah); err_hw: tasklet_kill(&sc->intr_tq); @@ -642,6 +600,37 @@ err_hw: return ret; } +static void ath9k_init_band_txpower(struct ath_softc *sc, int band) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct ath_hw *ah = sc->sc_ah; + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + int i; + + sband = &sc->sbands[band]; + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + ah->curchan = &ah->channels[chan->hw_value]; + ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); + ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); + chan->max_power = reg->max_power_level / 2; + } +} + +static void ath9k_init_txpower_limits(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *curchan = ah->curchan; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); + + ah->curchan = curchan; +} + void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -705,6 +694,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; + struct ath_wiphy *aphy = hw->priv; struct ath_common *common; struct ath_hw *ah; int error = 0; @@ -737,11 +727,20 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, if (error != 0) goto error_rx; + ath9k_init_txpower_limits(sc); + /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) goto error_register; + error = ath9k_init_debug(ah); + if (error) { + ath_print(common, ATH_DBG_FATAL, + "Unable to create debugfs files\n"); + goto error_world; + } + /* Handle world regulatory */ if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); @@ -754,6 +753,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); sc->wiphy_scheduler_int = msecs_to_jiffies(500); + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; ath_init_leds(sc); ath_start_rfkill_poll(sc); @@ -799,7 +799,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); - ath9k_exit_debug(sc->sc_ah); ath9k_hw_deinit(sc->sc_ah); tasklet_kill(&sc->intr_tq); @@ -866,20 +865,12 @@ static int __init ath9k_init(void) goto err_out; } - error = ath9k_debug_create_root(); - if (error) { - printk(KERN_ERR - "ath9k: Unable to create debugfs root: %d\n", - error); - goto err_rate_unregister; - } - error = ath_pci_init(); if (error < 0) { printk(KERN_ERR "ath9k: No PCI devices found, driver not installed.\n"); error = -ENODEV; - goto err_remove_root; + goto err_rate_unregister; } error = ath_ahb_init(); @@ -893,8 +884,6 @@ static int __init ath9k_init(void) err_pci_exit: ath_pci_exit(); - err_remove_root: - ath9k_debug_remove_root(); err_rate_unregister: ath_rate_control_unregister(); err_out: @@ -906,7 +895,6 @@ static void __exit ath9k_exit(void) { ath_ahb_exit(); ath_pci_exit(); - ath9k_debug_remove_root(); ath_rate_control_unregister(); printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 8c13479b17cd..b04b37b1124b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending); bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) { u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; - omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); + ath9k_hw_disable_interrupts(ah); txcfg = REG_READ(ah, AR_TXCFG); curLevel = MS(txcfg, AR_FTRIG); @@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) REG_WRITE(ah, AR_TXCFG, (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - ath9k_hw_set_interrupts(ah, omask); + ath9k_hw_enable_interrupts(ah); ah->tx_trig_level = newLevel; @@ -767,14 +766,6 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) } EXPORT_SYMBOL(ath9k_hw_startpcureceive); -void ath9k_hw_stoppcurecv(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - - ath9k_hw_disable_mib_counters(ah); -} -EXPORT_SYMBOL(ath9k_hw_stoppcurecv); - void ath9k_hw_abortpcurecv(struct ath_hw *ah) { REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); @@ -849,28 +840,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_intrpend); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, - enum ath9k_int ints) +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) REG_READ(ah, AR_IER); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); + } +} +EXPORT_SYMBOL(ath9k_hw_disable_interrupts); + +void ath9k_hw_enable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); + } + ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); +} +EXPORT_SYMBOL(ath9k_hw_enable_interrupts); + +void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) { enum ath9k_int omask = ah->imask; u32 mask, mask2; struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); - ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); - - if (omask & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + if (!(ints & ATH9K_INT_GLOBAL)) + ath9k_hw_enable_interrupts(ah); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } + ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); /* TODO: global int Ref count */ mask = ints & ATH9K_INT_COMMON; @@ -946,24 +968,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); } - if (ints & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } + ath9k_hw_enable_interrupts(ah); - return omask; + return; } EXPORT_SYMBOL(ath9k_hw_set_interrupts); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 7c1a34d64f6d..7512f97e8f49 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -104,13 +104,11 @@ struct ath_tx_status { u32 ts_tstamp; u16 ts_seqnum; u8 ts_status; - u8 ts_ratecode; u8 ts_rateindex; int8_t ts_rssi; u8 ts_shortretry; u8 ts_longretry; u8 ts_virtcol; - u8 ts_antenna; u8 ts_flags; int8_t ts_rssi_ctl0; int8_t ts_rssi_ctl1; @@ -121,7 +119,6 @@ struct ath_tx_status { u8 qid; u16 desc_id; u8 tid; - u8 pad[2]; u32 ba_low; u32 ba_high; u32 evm0; @@ -240,7 +237,7 @@ struct ath_desc { u32 ds_ctl1; u32 ds_hw[20]; void *ds_vdata; -} __packed; +} __packed __aligned(4); #define ATH9K_TXDESC_CLRDMASK 0x0001 #define ATH9K_TXDESC_NOACK 0x0002 @@ -310,7 +307,7 @@ struct ar5416_desc { u32 status8; } rx; } u; -} __packed; +} __packed __aligned(4); #define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) #define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) @@ -669,6 +666,7 @@ enum ath9k_key_type { struct ath_hw; struct ath9k_channel; +enum ath9k_int; u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); @@ -693,15 +691,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); -void ath9k_hw_stoppcurecv(struct ath_hw *ah); void ath9k_hw_abortpcurecv(struct ath_hw *ah); bool ath9k_hw_stopdmarecv(struct ath_hw *ah); int ath9k_hw_beaconq_setup(struct ath_hw *ah); /* Interrupt Handling */ bool ath9k_hw_intrpend(struct ath_hw *ah); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, - enum ath9k_int ints); +void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); +void ath9k_hw_enable_interrupts(struct ath_hw *ah); +void ath9k_hw_disable_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index dace215b693e..f026a031713b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -23,7 +23,7 @@ static void ath_update_txpow(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; if (sc->curtxpow != sc->config.txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); /* read back in case value is clamped */ sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@ -234,6 +234,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + /* * This is only performed if the channel settings have * actually changed. @@ -243,11 +245,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, false); - spin_lock_bh(&sc->rx.pcu_lock); - stopped = ath_stoprecv(sc); /* XXX: do not flush receive queue here. We don't want @@ -266,30 +266,22 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, channel->center_freq, conf_is_ht40(conf), fastcc); - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (r) { ath_print(common, ATH_DBG_FATAL, "Unable to reset channel (%u MHz), " "reset status %d\n", channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); goto ps_restore; } - spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) { ath_print(common, ATH_DBG_FATAL, "Unable to restart recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); goto ps_restore; } - spin_unlock_bh(&sc->rx.pcu_lock); - ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, ah->imask); @@ -300,6 +292,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, } ps_restore: + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); return r; } @@ -340,7 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work) struct ath_tx_control txctl; struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath_common *common = ath9k_hw_common(ah); - int qnum, ftype; + int ftype; int chain_ok = 0; int chain; int len = 1800; @@ -367,8 +361,7 @@ void ath_paprd_calibrate(struct work_struct *work) memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); memset(&txctl, 0, sizeof(txctl)); - qnum = sc->tx.hwq_map[WME_AC_BE]; - txctl.txq = &sc->tx.txq[qnum]; + txctl.txq = sc->tx.txq_map[WME_AC_BE]; ath9k_ps_wakeup(sc); ar9003_paprd_init_table(ah); @@ -386,6 +379,7 @@ void ath_paprd_calibrate(struct work_struct *work) } init_completion(&sc->paprd_complete); + sc->paprd_pending = true; ar9003_paprd_setup_gain_table(ah, chain); txctl.paprd = BIT(chain); if (ath_tx_start(hw, skb, &txctl) != 0) @@ -393,6 +387,7 @@ void ath_paprd_calibrate(struct work_struct *work) time_left = wait_for_completion_timeout(&sc->paprd_complete, msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); + sc->paprd_pending = false; if (!time_left) { ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, "Timeout waiting for paprd training on " @@ -558,15 +553,17 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an; - + struct ath_hw *ah = sc->sc_ah; an = (struct ath_node *)sta->drv_priv; + if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) + sc->sc_flags |= SC_OP_ENABLE_APM; + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); - an->last_rssi = ATH_RSSI_DUMMY_MARKER; } } @@ -614,6 +611,8 @@ void ath9k_tasklet(unsigned long data) return; } + spin_lock_bh(&sc->sc_pcu_lock); + if (!ath9k_hw_check_alive(ah)) ieee80211_queue_work(sc->hw, &sc->hw_check_work); @@ -624,15 +623,12 @@ void ath9k_tasklet(unsigned long data) rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); if (status & rxmask) { - spin_lock_bh(&sc->rx.pcu_lock); - /* Check for high priority Rx first */ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && (status & ATH9K_INT_RXHP)) ath_rx_tasklet(sc, 0, true); ath_rx_tasklet(sc, 0, false); - spin_unlock_bh(&sc->rx.pcu_lock); } if (status & ATH9K_INT_TX) { @@ -657,7 +653,9 @@ void ath9k_tasklet(unsigned long data) ath_gen_timer_isr(sc->sc_ah); /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); + + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); } @@ -756,7 +754,7 @@ irqreturn_t ath_isr(int irq, void *dev) * interrupt; otherwise it will continue to * fire. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); /* * Let the hal handle the event. We assume * it will clear whatever condition caused @@ -765,7 +763,7 @@ irqreturn_t ath_isr(int irq, void *dev) spin_lock(&common->cc_lock); ath9k_hw_proc_mib_event(ah); spin_unlock(&common->cc_lock); - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); } if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) @@ -782,8 +780,8 @@ chip_reset: ath_debug_stat_interrupt(sc, status); if (sched) { - /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); + /* turn off every interrupt */ + ath9k_hw_disable_interrupts(ah); tasklet_schedule(&sc->intr_tq); } @@ -835,9 +833,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, } static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); @@ -861,6 +861,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ath_beacon_config(sc, vif); /* Reset rssi stats */ + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_flags |= SC_OP_ANI_RUN; @@ -882,13 +883,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ath9k_hw_configpcipowersave(ah, 0, 0); if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, sc->hw); - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { ath_print(common, ATH_DBG_FATAL, @@ -896,17 +897,14 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) "reset status %d\n", channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath_update_txpow(sc); if (ath_startrecv(sc) != 0) { ath_print(common, ATH_DBG_FATAL, "Unable to restart recv logic\n"); - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); return; } - spin_unlock_bh(&sc->rx.pcu_lock); - if (sc->sc_flags & SC_OP_BEACONS) ath_beacon_config(sc, NULL); /* restart beacons */ @@ -919,6 +917,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_hw_set_gpio(ah, ah->led_pin, 0); ieee80211_wake_queues(hw); + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); } @@ -929,6 +929,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); /* @@ -941,19 +943,16 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) } /* Disable interrupts */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, false); /* clear pending tx frames */ - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); /* turn off frame recv */ ath_flushrecv(sc); /* flush recv queue */ if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, hw); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, @@ -961,14 +960,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) "reset status %d\n", channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); - spin_unlock_bh(&sc->rx.pcu_lock); - ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } @@ -982,29 +981,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Stop ANI */ del_timer_sync(&common->ani.timer); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, retry_tx); - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); ath_flushrecv(sc); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); if (r) ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d\n", r); - spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) ath_print(common, ATH_DBG_FATAL, "Unable to start recv logic\n"); - spin_unlock_bh(&sc->rx.pcu_lock); - /* * We may be doing a reset in response to a request * that changes the channel so update any state that @@ -1029,6 +1024,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } ieee80211_wake_queues(hw); + spin_unlock_bh(&sc->sc_pcu_lock); /* Start ANI */ ath_start_ani(common); @@ -1036,56 +1032,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return r; } -static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case 0: - qnum = sc->tx.hwq_map[WME_AC_VO]; - break; - case 1: - qnum = sc->tx.hwq_map[WME_AC_VI]; - break; - case 2: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - case 3: - qnum = sc->tx.hwq_map[WME_AC_BK]; - break; - default: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - } - - return qnum; -} - -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case WME_AC_VO: - qnum = 0; - break; - case WME_AC_VI: - qnum = 1; - break; - case WME_AC_BE: - qnum = 2; - break; - case WME_AC_BK: - qnum = 3; - break; - default: - qnum = -1; - break; - } - - return qnum; -} - /* XXX: Remove me once we don't depend on ath9k_channel for all * this redundant data */ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, @@ -1167,19 +1113,16 @@ static int ath9k_start(struct ieee80211_hw *hw) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); + spin_lock_bh(&sc->sc_pcu_lock); r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d " "(freq %u MHz)\n", r, curchan->center_freq); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->sc_resetlock); /* * This is needed only to setup initial state @@ -1198,10 +1141,10 @@ static int ath9k_start(struct ieee80211_hw *hw) ath_print(common, ATH_DBG_FATAL, "Unable to start recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); /* Setup our intr mask. */ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | @@ -1254,14 +1197,11 @@ mutex_unlock: static int ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_tx_control txctl; - int padpos, padsize; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int qnum; if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { ath_print(common, ATH_DBG_XMIT, @@ -1311,31 +1251,7 @@ static int ath9k_tx(struct ieee80211_hw *hw, } memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, padpos); - } - - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txctl.txq = &sc->tx.txq[qnum]; + txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)]; ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); @@ -1399,22 +1315,25 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_btcoex_timer_pause(sc); } + spin_lock_bh(&sc->sc_pcu_lock); + /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); - spin_lock_bh(&sc->rx.pcu_lock); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_drain_all_txq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->rx.rxlink = NULL; - spin_unlock_bh(&sc->rx.pcu_lock); /* disable HAL and put h/w to sleep */ ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); /* Finally, put the chip in FULL SLEEP mode */ @@ -1830,12 +1749,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_txq *txq; struct ath9k_tx_queue_info qi; - int ret = 0, qnum; + int ret = 0; if (queue >= WME_NUM_AC) return 0; + txq = sc->tx.txq_map[queue]; + mutex_lock(&sc->mutex); memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -1844,20 +1766,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, qi.tqi_cwmin = params->cw_min; qi.tqi_cwmax = params->cw_max; qi.tqi_burstTime = params->txop; - qnum = ath_get_hal_qnum(queue, sc); ath_print(common, ATH_DBG_CONFIG, "Configure tx [queue/halq] [%d/%d], " "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, + queue, txq->axq_qnum, params->aifs, params->cw_min, params->cw_max, params->txop); - ret = ath_txq_update(sc, qnum, &qi); + ret = ath_txq_update(sc, txq->axq_qnum, &qi); if (ret) ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) - if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) + if (queue == WME_AC_BE && !ret) ath_beaconq_config(sc); mutex_unlock(&sc->mutex); @@ -2019,7 +1940,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); - ath9k_bss_assoc_info(sc, vif, bss_conf); + ath9k_bss_assoc_info(sc, hw, vif, bss_conf); } mutex_unlock(&sc->mutex); @@ -2082,6 +2003,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + if (!(sc->sc_flags & SC_OP_TXAGGR)) + return -EOPNOTSUPP; + ath9k_ps_wakeup(sc); ret = ath_tx_aggr_start(sc, sta, tid, ssn); if (!ret) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b5b651413e77..09f69a9617f4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -16,6 +16,7 @@ #include <linux/nl80211.h> #include <linux/pci.h> +#include <linux/ath9k_platform.h> #include "ath9k.h" static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { @@ -53,21 +54,36 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) { - struct ath_hw *ah = (struct ath_hw *) common->ah; - - common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, - AH_WAIT_TIMEOUT)) { - return false; + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct ath9k_platform_data *pdata = sc->dev->platform_data; + + if (pdata) { + if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { + ath_print(common, ATH_DBG_FATAL, + "%s: eeprom read failed, offset %08x " + "is out of range\n", + __func__, off); + } + + *data = pdata->eeprom_data[off]; + } else { + struct ath_hw *ah = (struct ath_hw *) common->ah; + + common->ops->read(ah, AR5416_EEPROM_OFFSET + + (off << AR5416_EEPROM_S)); + + if (!ath9k_hw_wait(ah, + AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, + AH_WAIT_TIMEOUT)) { + return false; + } + + *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); } - *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - return true; } @@ -247,34 +263,25 @@ static void ath_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM -static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int ath_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } -static int ath_pci_resume(struct pci_dev *pdev) +static int ath_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; u32 val; - int err; - - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) - return err; /* * Suspend/Resume resets the PCI configuration space, so we have to @@ -293,7 +300,23 @@ static int ath_pci_resume(struct pci_dev *pdev) return 0; } -#endif /* CONFIG_PM */ +static const struct dev_pm_ops ath9k_pm_ops = { + .suspend = ath_pci_suspend, + .resume = ath_pci_resume, + .freeze = ath_pci_suspend, + .thaw = ath_pci_resume, + .poweroff = ath_pci_suspend, + .restore = ath_pci_resume, +}; + +#define ATH9K_PM_OPS (&ath9k_pm_ops) + +#else /* !CONFIG_PM */ + +#define ATH9K_PM_OPS NULL + +#endif /* !CONFIG_PM */ + MODULE_DEVICE_TABLE(pci, ath_pci_id_table); @@ -302,10 +325,7 @@ static struct pci_driver ath_pci_driver = { .id_table = ath_pci_id_table, .probe = ath_pci_probe, .remove = ath_pci_remove, -#ifdef CONFIG_PM - .suspend = ath_pci_suspend, - .resume = ath_pci_resume, -#endif /* CONFIG_PM */ + .driver.pm = ATH9K_PM_OPS, }; int ath_pci_init(void) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 89978d71617f..3e6ea3bc3d89 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -381,25 +381,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = { static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate); -static inline int8_t median(int8_t a, int8_t b, int8_t c) -{ - if (a >= b) { - if (b >= c) - return b; - else if (a > c) - return c; - else - return a; - } else { - if (a >= c) - return a; - else if (b >= c) - return c; - else - return b; - } -} - static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv) { @@ -883,7 +864,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, bool state_change = false; int count, n_bad_frames; u8 last_per; - static u32 nretry_to_per_lookup[10] = { + static const u32 nretry_to_per_lookup[10] = { 100 * 0 / 1, 100 * 1 / 4, 100 * 1 / 2, @@ -1106,13 +1087,13 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate) { int rix = 0, i = 0; - int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; + static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; while (rate->idx > mcs_rix_off[i] && - i < sizeof(mcs_rix_off)/sizeof(int)) { + i < ARRAY_SIZE(mcs_rix_off)) { rix++; i++; } @@ -1373,23 +1354,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, tx_info->status.ampdu_len = 1; } - /* - * If an underrun error is seen assume it as an excessive retry only - * if max frame trigger level has been reached (2 KB for singel stream, - * and 4 KB for dual stream). Adjust the long retry as if the frame was - * tried hw->max_rate_tries times to affect how ratectrl updates PER for - * the failed rate. In case of congestion on the bus penalizing these - * type of underruns should help hardware actually transmit new frames - * successfully by eventually preferring slower rates. This itself - * should also alleviate congestion on the bus. - */ - if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && - (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { - tx_status = 1; - is_underrun = 1; - } - - if (tx_info->pad[0] & ATH_TX_INFO_XRETRY) + if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) tx_status = 1; ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, @@ -1398,7 +1363,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, /* Check if aggregation has to be enabled for this tid */ if (conf_is_ht(&sc->hw->conf) && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { + if (ieee80211_is_data_qos(fc) && + skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { u8 *qc, tid; struct ath_node *an; @@ -1444,12 +1410,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ath_rc_priv->neg_ht_rates.rs_nrates = j; } - is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); if (is_cw40) - is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) - is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); /* Choose rate table first */ @@ -1468,10 +1434,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table = NULL; bool oper_cw40 = false, oper_sgi; - bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? - true : false; - bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? - true : false; + bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); + bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG); /* FIXME: Handle AP mode later when we support CWM */ @@ -1617,8 +1581,6 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp return NULL; } - rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; - return rate_priv; } diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 2f46a2266ba1..31a004cb60ac 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -215,7 +215,6 @@ struct ath_rate_priv { u32 per_down_time; u32 probe_interval; u32 prev_data_rix; - u32 tx_triglevel_max; struct ath_rateset neg_rates; struct ath_rateset neg_ht_rates; struct ath_rate_softc *asc; @@ -225,11 +224,6 @@ struct ath_rate_priv { struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; }; -#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) -#define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) -#define ATH_TX_INFO_XRETRY (1 << 3) -#define ATH_TX_INFO_UNDERRUN (1 << 4) - enum ath9k_internal_frame_type { ATH9K_IFT_NOT_INTERNAL, ATH9K_IFT_PAUSE, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1a62e351ec77..262c81595f6d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) struct ath_buf *bf; int error = 0; - spin_lock_init(&sc->rx.pcu_lock); + spin_lock_init(&sc->sc_pcu_lock); sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->rx.rxbuflock); @@ -528,6 +528,8 @@ bool ath_stoprecv(struct ath_softc *sc) sc->rx.rxlink = NULL; spin_unlock_bh(&sc->rx.rxbuflock); + ATH_DBG_WARN(!stopped, "Could not stop RX, we could be " + "confusing the DMA engine when we start RX up\n"); return stopped; } @@ -962,36 +964,23 @@ static void ath9k_process_rssi(struct ath_common *common, struct ieee80211_hdr *hdr, struct ath_rx_status *rx_stats) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = common->ah; - struct ieee80211_sta *sta; - struct ath_node *an; - int last_rssi = ATH_RSSI_DUMMY_MARKER; + int last_rssi; __le16 fc; + if (ah->opmode != NL80211_IFTYPE_STATION) + return; + fc = hdr->frame_control; + if (!ieee80211_is_beacon(fc) || + compare_ether_addr(hdr->addr3, common->curbssid)) + return; - rcu_read_lock(); - /* - * XXX: use ieee80211_find_sta! This requires quite a bit of work - * under the current ath9k virtual wiphy implementation as we have - * no way of tying a vif to wiphy. Typically vifs are attached to - * at least one sdata of a wiphy on mac80211 but with ath9k virtual - * wiphy you'd have to iterate over every wiphy and each sdata. - */ - if (is_multicast_ether_addr(hdr->addr1)) - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); - else - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1); - - if (sta) { - an = (struct ath_node *) sta->drv_priv; - if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && - !rx_stats->rs_moreaggr) - ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); - last_rssi = an->last_rssi; - } - rcu_read_unlock(); + if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) + ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); + last_rssi = aphy->last_rssi; if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) rx_stats->rs_rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); @@ -999,8 +988,7 @@ static void ath9k_process_rssi(struct ath_common *common, rx_stats->rs_rssi = 0; /* Update Beacon RSSI, this is used by ANI. */ - if (ieee80211_is_beacon(fc)) - ah->stats.avgbrssi = rx_stats->rs_rssi; + ah->stats.avgbrssi = rx_stats->rs_rssi; } /* diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2c6a22fbb0f0..c2472edab5e0 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -864,15 +864,7 @@ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) #define AR_DEVID_7010(_ah) \ - (((_ah)->hw_version.devid == 0x7010) || \ - ((_ah)->hw_version.devid == 0x7015) || \ - ((_ah)->hw_version.devid == 0x9018) || \ - ((_ah)->hw_version.devid == 0xA704) || \ - ((_ah)->hw_version.devid == 0x1200)) - -#define AR9287_HTC_DEVID(_ah) \ - (((_ah)->hw_version.devid == 0x7015) || \ - ((_ah)->hw_version.devid == 0x1200)) + ((_ah)->common.driver_info & AR7010_DEVICE) #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 @@ -1074,6 +1066,9 @@ enum { #define AR_INTR_PRIO_ASYNC_MASK 0x40c8 #define AR_INTR_PRIO_SYNC_MASK 0x40cc #define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 +#define AR_ENT_OTP 0x40d8 +#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 +#define AR_ENT_OTP_MPSD 0x00800000 #define AR_RTC_9300_PLL_DIV 0x000003ff #define AR_RTC_9300_PLL_DIV_S 0 @@ -1574,6 +1569,7 @@ enum { #define AR_PCU_TBTT_PROTECT 0x00200000 #define AR_PCU_CLEAR_VMF 0x01000000 #define AR_PCU_CLEAR_BA_VALID 0x04000000 +#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000 #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 #define AR_PCU_BT_ANT_PREVENT_RX_S 20 diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index ec7cf5ee56bc..d5442c3745cc 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc) aphy->sc = sc; aphy->hw = hw; sc->sec_wiphy[i] = aphy; + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; spin_unlock_bh(&sc->wiphy_lock); memcpy(addr, common->macaddr, ETH_ALEN); @@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, info->control.rates[1].idx = -1; memset(&txctl, 0, sizeof(struct ath_tx_control)); - txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; + txctl.txq = sc->tx.txq_map[WME_AC_VO]; txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; if (ath_tx_start(aphy->hw, skb, &txctl) != 0) @@ -304,13 +305,12 @@ void ath9k_wiphy_chan_work(struct work_struct *work) * ath9k version of ieee80211_tx_status() for TX frames that are generated * internally in the driver. */ -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype) { struct ath_wiphy *aphy = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) && - aphy->state == ATH_WIPHY_PAUSING) { + if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) { if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { printk(KERN_DEBUG "ath9k: %s: no ACK for pause " "frame\n", wiphy_name(hw->wiphy)); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f2ade2402ce2..821d3679c6ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -48,19 +48,17 @@ static u16 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, struct list_head *head); -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok); +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc); + int nframes, int nbad, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); @@ -124,7 +122,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; WARN_ON(!tid->paused); @@ -140,12 +138,21 @@ unlock: spin_unlock_bh(&txq->axq_lock); } +static struct ath_frame_info *get_frame_info(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + BUILD_BUG_ON(sizeof(struct ath_frame_info) > + sizeof(tx_info->rate_driver_data)); + return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; +} + static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; INIT_LIST_HEAD(&bf_head); @@ -156,12 +163,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) { - ath_tx_update_baw(sc, tid, bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } else { - ath_tx_send_ht_normal(sc, txq, tid, &bf_head); + ath_tx_send_normal(sc, txq, tid, &bf_head); } + spin_lock_bh(&txq->axq_lock); } spin_unlock_bh(&txq->axq_lock); @@ -184,14 +194,11 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, } static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf) + u16 seqno) { int index, cindex; - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); + index = ATH_BA_INDEX(tid->seq_start, seqno); cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); __set_bit(cindex, tid->tx_buf); @@ -215,6 +222,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); @@ -226,8 +234,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -239,16 +248,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) + struct sk_buff *skb) { - struct sk_buff *skb; + struct ath_frame_info *fi = get_frame_info(skb); struct ieee80211_hdr *hdr; - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; TX_STAT_INC(txq->axq_qnum, a_retries); + if (fi->retries++ > 0) + return; - skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } @@ -298,9 +306,41 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) return tbf; } +static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts, int txok, + int *nframes, int *nbad) +{ + struct ath_frame_info *fi; + u16 seq_st = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int ba_index; + int isaggr = 0; + + *nbad = 0; + *nframes = 0; + + isaggr = bf_isaggr(bf); + if (isaggr) { + seq_st = ts->ts_seqnum; + memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); + } + + while (bf) { + fi = get_frame_info(bf->bf_mpdu); + ba_index = ATH_BA_INDEX(seq_st, fi->seqno); + + (*nframes)++; + if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) + (*nbad)++; + + bf = bf->bf_next; + } +} + + static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct list_head *bf_q, - struct ath_tx_status *ts, int txok) + struct ath_tx_status *ts, int txok, bool retry) { struct ath_node *an = NULL; struct sk_buff *skb; @@ -316,7 +356,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; + struct ath_frame_info *fi; int nframes; + u8 tidno; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -325,7 +367,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, hw = bf->aphy->hw; memcpy(rates, tx_info->control.rates, sizeof(rates)); - nframes = bf->bf_nframes; rcu_read_lock(); @@ -342,7 +383,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !bf->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); - ath_tx_rc_status(bf, ts, 1, 0, false); + ath_tx_rc_status(bf, ts, 1, 1, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@ -352,14 +393,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } an = (struct ath_node *)sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(an, tidno); /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted */ - if (bf->bf_tidno != ts->tid) + if (tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@ -385,15 +427,16 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_pending); INIT_LIST_HEAD(&bf_head); - nbad = ath_tx_num_badfrms(sc, bf, ts, txok); + ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { txfail = txpending = 0; bf_next = bf->bf_next; skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); + fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@ -401,10 +444,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* transmit completion */ acked_cnt++; } else { - if (!(tid->state & AGGR_CLEANUP) && - !bf_last->bf_tx_aborted) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, txq, bf); + if (!(tid->state & AGGR_CLEANUP) && retry) { + if (fi->retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, txq, bf->bf_mpdu); txpending = 1; } else { bf->bf_state.bf_type |= BUF_XRETRY; @@ -442,16 +484,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { memcpy(tx_info->control.rates, rates, sizeof(rates)); - bf->bf_nframes = nframes; - ath_tx_rc_status(bf, ts, nbad, txok, true); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, true); rc_update = false; } else { - ath_tx_rc_status(bf, ts, nbad, txok, false); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, false); } ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, @@ -470,14 +511,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, - bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ts, nbad, - 0, false); + ath_tx_rc_status(bf, ts, nframes, + nbad, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@ -611,6 +651,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, u16 minlen; u8 flags, rix; int width, streams, half_gi, ndelim, mindelim; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); /* Select standard number of delimiters based on frame length alone */ ndelim = ATH_AGGR_GET_NDELIM(frmlen); @@ -621,7 +662,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, * TODO - this could be improved to be dependent on the rate. * The hardware can keep up at lower rates, but not higher rates */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) + if (fi->keyix != ATH9K_TXKEYIX_INVALID) ndelim += ATH_AGGR_ENCRYPTDELIM; /* @@ -665,7 +706,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct list_head *bf_q) + struct list_head *bf_q, + int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) struct ath_buf *bf, *bf_first, *bf_prev = NULL; @@ -674,14 +716,16 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; + struct ath_frame_info *fi; bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); do { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + fi = get_frame_info(bf->bf_mpdu); /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@ -692,7 +736,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } /* do not exceed aggregation limit */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; + al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; if (nframes && (aggr_limit < (al + bpad + al_delta + prev_al))) { @@ -719,14 +763,15 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, * Get the delimiters needed to meet the MPDU * density for this node. */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); + ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); bpad = PADBYTES(al_delta) + (ndelim << 2); bf->bf_next = NULL; ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); /* link buffers of this frame to the aggregate */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); list_move_tail(&bf->list, bf_q); if (bf_prev) { @@ -738,8 +783,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } while (!list_empty(&tid->buf_q)); - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; + *aggr_len = al; return status; #undef PADBYTES @@ -750,7 +794,9 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, { struct ath_buf *bf; enum ATH_AGGR_STATUS status; + struct ath_frame_info *fi; struct list_head bf_q; + int aggr_len; do { if (list_empty(&tid->buf_q)) @@ -758,7 +804,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_q); - status = ath_tx_form_aggr(sc, txq, tid, &bf_q); + status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); /* * no frames picked up to be aggregated; @@ -771,18 +817,20 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); /* if only one frame, send as non-aggregate */ - if (bf->bf_nframes == 1) { + if (bf == bf->bf_lastbf) { + fi = get_frame_info(bf->bf_mpdu); + bf->bf_state.bf_type &= ~BUF_AGGR; ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); - ath_buf_set_rate(sc, bf); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_q); continue; } /* setup first desc of aggregate */ bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); + ath_buf_set_rate(sc, bf, aggr_len); + ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len); /* anchor last desc of aggregate */ ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); @@ -817,7 +865,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) { struct ath_node *an = (struct ath_node *)sta->drv_priv; struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_txq *txq = txtid->ac->txq; if (txtid->state & AGGR_CLEANUP) return; @@ -888,10 +936,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi; + static const int subtype_txq_to_hwq[] = { + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, + }; int qnum, i; memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; + qi.tqi_subtype = subtype_txq_to_hwq[subtype]; qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; @@ -940,7 +994,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) if (!ATH_TXQ_SETUP(sc, qnum)) { struct ath_txq *txq = &sc->tx.txq[qnum]; - txq->axq_class = subtype; txq->axq_qnum = qnum; txq->axq_link = NULL; INIT_LIST_HEAD(&txq->axq_q); @@ -1062,8 +1115,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_tx_aborted = true; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { list_cut_position(&bf_head, @@ -1080,7 +1131,8 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) spin_unlock_bh(&txq->axq_lock); if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, + retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } @@ -1101,7 +1153,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) if (bf_isampdu(bf)) ath_tx_complete_aggr(sc, txq, bf, &bf_head, - &ts, 0); + &ts, 0, retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -1148,13 +1200,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA. Resetting hardware!\n"); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); if (r) ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d\n", r); - spin_unlock_bh(&sc->sc_resetlock); } for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { @@ -1212,24 +1262,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) } } -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; - - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; - } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - /***********/ /* TX, DMA */ /***********/ @@ -1299,12 +1331,11 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) + struct ath_buf *bf, struct ath_tx_control *txctl) { - struct ath_buf *bf; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); + struct list_head bf_head; - bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type |= BUF_AMPDU; TX_STAT_INC(txctl->txq->axq_qnum, a_queued); @@ -1316,56 +1347,47 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - h/w queue depth exceeds low water mark */ if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || + !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ - list_move_tail(&bf->list, &tid->buf_q); + list_add_tail(&bf->list, &tid->buf_q); ath_tx_queue_tid(txctl->txq, tid); return; } + INIT_LIST_HEAD(&bf_head); + list_add(&bf->list, &bf_head); + /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); + ath_buf_set_rate(sc, bf, fi->framelen); + ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); } -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) { + struct ath_frame_info *fi; struct ath_buf *bf; bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); - TX_STAT_INC(txq->axq_qnum, queued); -} - -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); + if (tid) + INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; - bf->bf_nframes = 1; - ath_buf_set_rate(sc, bf); + fi = get_frame_info(bf->bf_mpdu); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, bf_head); TX_STAT_INC(txq->axq_qnum, queued); } @@ -1393,40 +1415,52 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) return htype; } -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) +static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, + int framelen) { + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = tx_info->control.sta; + struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr; + struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an; struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; + enum ath9k_key_type keytype; + u16 seqno = 0; + u8 tidno; - if (!tx_info->control.sta) - return; + keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - an = (struct ath_node *)tx_info->control.sta->drv_priv; hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + if (sta && ieee80211_is_data_qos(hdr->frame_control) && + conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; + an = (struct ath_node *) sta->drv_priv; + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + + /* + * Override seqno set by upper layer with the one + * in tx aggregation state. + */ + tid = ATH_AN_2_TID(an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); } - /* - * For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); + memset(fi, 0, sizeof(*fi)); + if (hw_key) + fi->keyix = hw_key->hw_key_idx; + else + fi->keyix = ATH9K_TXKEYIX_INVALID; + fi->keytype = keytype; + fi->framelen = framelen; + fi->seqno = seqno; } -static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) +static int setup_tx_flags(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; @@ -1437,7 +1471,7 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; - if (use_ldpc) + if (tx_info->flags & IEEE80211_TX_CTL_LDPC) flags |= ATH9K_TXDESC_LDPC; return flags; @@ -1449,13 +1483,11 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, +static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; + int streams; /* find number of symbols: PLCP + data */ streams = HT_RC_2_STREAMS(rix); @@ -1474,7 +1506,19 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, return duration; } -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *curchan = ah->curchan; + if ((sc->sc_flags & SC_OP_ENABLE_APM) && + (curchan->channelFlags & CHANNEL_5GHZ) && + (chainmask == 0x7) && (rate < 0x90)) + return 0x3; + else + return chainmask; +} + +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_11n_rate_series series[4]; @@ -1514,7 +1558,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) rix = rates[i].idx; series[i].Tries = rates[i].count; - series[i].ChSel = common->tx_chainmask; if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { @@ -1537,14 +1580,16 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) if (rates[i].flags & IEEE80211_TX_RC_MCS) { /* MCS rates */ series[i].Rate = rix | 0x80; - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath_pkt_duration(sc, rix, len, is_40, is_sgi, is_sp); if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) series[i].RateFlags |= ATH9K_RATESERIES_STBC; continue; } - /* legcay rates */ + /* legacy rates */ if ((tx_info->band == IEEE80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; @@ -1560,12 +1605,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) is_sp = false; } + if (bf->bf_state.bfs_paprd) + series[i].ChSel = common->tx_chainmask; + else + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, - phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); + phy, rate->bitrate * 100, len, rix, is_sp); } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) + if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) flags &= ~ATH9K_TXDESC_RTSENA; /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ @@ -1582,67 +1633,29 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); } -static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, - struct sk_buff *skb, - struct ath_tx_control *txctl) +static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, + struct ath_txq *txq, + struct sk_buff *skb) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int hdrlen; - __le16 fc; - int padpos, padsize; - bool use_ldpc = false; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_frame_info *fi = get_frame_info(skb); + struct ath_buf *bf; + struct ath_desc *ds; + int frm_type; - tx_info->pad[0] = 0; - switch (txctl->frame_type) { - case ATH9K_IFT_NOT_INTERNAL: - break; - case ATH9K_IFT_PAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; - /* fall through */ - case ATH9K_IFT_UNPAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; - break; + bf = ath_tx_get_buffer(sc); + if (!bf) { + ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); + return NULL; } - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; ATH_TXBUF_RESET(bf); bf->aphy = aphy; - bf->bf_frmlen = skb->len + FCS_LEN; - /* Remove the padding size from bf_frmlen, if any */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos+padsize) { - bf->bf_frmlen -= padsize; - } - - if (!txctl->paprd && conf_is_ht(&hw->conf)) { - bf->bf_state.bf_type |= BUF_HT; - if (tx_info->flags & IEEE80211_TX_CTL_LDPC) - use_ldpc = true; - } - - bf->bf_state.bfs_paprd = txctl->paprd; - if (txctl->paprd) - bf->bf_state.bfs_paprd_timestamp = jiffies; - bf->bf_flags = setup_tx_flags(skb, use_ldpc); - - bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { - bf->bf_frmlen += tx_info->control.hw_key->icv_len; - bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; - } else { - bf->bf_keyix = ATH9K_TXKEYIX_INVALID; - } - - if (ieee80211_is_data_qos(fc) && bf_isht(bf) && - (sc->sc_flags & SC_OP_TXAGGR)) - assign_aggr_tid_seqno(skb, bf); - + bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, @@ -1652,40 +1665,17 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_buf_addr = 0; ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); - return -ENOMEM; + ath_tx_return_buffer(sc, bf); + return NULL; } - bf->bf_tx_aborted = false; - - return 0; -} - -/* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_control *txctl) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_node *an = NULL; - struct list_head bf_head; - struct ath_desc *ds; - struct ath_atx_tid *tid; - struct ath_hw *ah = sc->sc_ah; - int frm_type; - __le16 fc; - frm_type = get_hw_packet_type(skb); - fc = hdr->frame_control; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); ds = bf->bf_desc; ath9k_hw_set_desc_link(ah, ds, 0); - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, - bf->bf_keyix, bf->bf_keytype, bf->bf_flags); + ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER, + fi->keyix, fi->keytype, bf->bf_flags); ath9k_hw_filltxdesc(ah, ds, skb->len, /* segment length */ @@ -1693,42 +1683,50 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, true, /* last segment */ ds, /* first descriptor */ bf->bf_buf_addr, - txctl->txq->axq_qnum); + txq->axq_qnum); - if (bf->bf_state.bfs_paprd) - ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); - spin_lock_bh(&txctl->txq->axq_lock); + return bf; +} + +/* FIXME: tx power */ +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_control *txctl) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct list_head bf_head; + struct ath_atx_tid *tid; + u8 tidno; - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && - tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + spin_lock_bh(&txctl->txq->axq_lock); - if (!ieee80211_is_data_qos(fc)) { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - goto tx_done; - } + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && txctl->an) { + tidno = ieee80211_get_qos_ctl(hdr)[0] & + IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(txctl->an, tidno); - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - /* - * Try aggregation if it's a unicast data frame - * and the destination is HT capable. - */ - ath_tx_send_ampdu(sc, tid, &bf_head, txctl); - } else { - /* - * Send this frame as regular when ADDBA - * exchange is neither complete nor pending. - */ - ath_tx_send_ht_normal(sc, txctl->txq, - tid, &bf_head); - } + WARN_ON(tid->ac->txq != txctl->txq); + /* + * Try aggregation if it's a unicast data frame + * and the destination is HT capable. + */ + ath_tx_send_ampdu(sc, tid, bf, txctl); } else { - ath_tx_send_normal(sc, txctl->txq, &bf_head); + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); + + bf->bf_state.bfs_ftype = txctl->frame_type; + bf->bf_state.bfs_paprd = txctl->paprd; + + if (bf->bf_state.bfs_paprd) + ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc, + bf->bf_state.bfs_paprd); + + ath_tx_send_normal(sc, txctl->txq, NULL, &bf_head); } -tx_done: spin_unlock_bh(&txctl->txq->axq_lock); } @@ -1736,66 +1734,20 @@ tx_done: int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_txq *txq = txctl->txq; struct ath_buf *bf; - int q, r; - - bf = ath_tx_get_buffer(sc); - if (!bf) { - ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); - return -1; - } - - r = ath_tx_setup_buffer(hw, bf, skb, txctl); - if (unlikely(r)) { - ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); - - /* upon ath_tx_processq() this TX queue will be resumed, we - * guarantee this will happen by knowing beforehand that - * we will at least have to run TX completionon one buffer - * on the queue */ - spin_lock_bh(&txq->axq_lock); - if (!txq->stopped && txq->axq_depth > 1) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_return_buffer(sc, bf); - - return r; - } - - q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - spin_lock_bh(&txq->axq_lock); - if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_start_dma(sc, bf, txctl); - - return 0; -} - -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; int padpos, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; + int frmlen = skb->len + FCS_LEN; + int q; - memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl->an = (struct ath_node *)sta->drv_priv; + if (info->control.hw_key) + frmlen += info->control.hw_key->icv_len; /* * As a temporary workaround, assign seq# here; this will likely need @@ -1812,30 +1764,37 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) /* Add the padding after the header if this is not already done */ padpos = ath9k_cmn_padpos(hdr->frame_control); padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) { - ath_print(common, ATH_DBG_XMIT, - "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } + if (padsize && skb->len > padpos) { + if (skb_headroom(skb) < padsize) + return -ENOMEM; + skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); } - txctl.txq = sc->beacon.cabq; + setup_frame_info(hw, skb, frmlen); - ath_print(common, ATH_DBG_XMIT, - "transmitting CABQ packet, skb: %p\n", skb); + /* + * At this point, the vif, hw_key and sta pointers in the tx control + * info are no longer valid (overwritten by the ath_frame_info data. + */ + + bf = ath_tx_setup_buffer(hw, txctl->txq, skb); + if (unlikely(!bf)) + return -ENOMEM; - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; + q = skb_get_queue_mapping(skb); + spin_lock_bh(&txq->axq_lock); + if (txq == sc->tx.txq_map[q] && + ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { + ath_mac80211_stop_queue(sc, q); + txq->stopped = 1; } + spin_unlock_bh(&txq->axq_lock); - return; -exit: - dev_kfree_skb_any(skb); + ath_tx_start_dma(sc, bf, txctl); + + return 0; } /*****************/ @@ -1843,7 +1802,8 @@ exit: /*****************/ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_wiphy *aphy, int tx_flags) + struct ath_wiphy *aphy, int tx_flags, int ftype, + struct ath_txq *txq) { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -1886,15 +1846,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, PS_WAIT_FOR_TX_ACK)); } - if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) - ath9k_tx_status(hw, skb); + if (unlikely(ftype)) + ath9k_tx_status(hw, skb, ftype); else { q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - if (--sc->tx.pending_frames[q] < 0) - sc->tx.pending_frames[q] = 0; + if (txq == sc->tx.txq_map[q]) { + spin_lock_bh(&txq->axq_lock); + if (WARN_ON(--txq->pending_frames < 0)) + txq->pending_frames = 0; + spin_unlock_bh(&txq->axq_lock); + } ieee80211_tx_status(hw, skb); } @@ -1922,15 +1883,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, bf->bf_buf_addr = 0; if (bf->bf_state.bfs_paprd) { - if (time_after(jiffies, - bf->bf_state.bfs_paprd_timestamp + - msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) + if (!sc->paprd_pending) dev_kfree_skb_any(skb); else complete(&sc->paprd_complete); } else { - ath_debug_stat_tx(sc, txq, bf, ts); - ath_tx_complete(sc, skb, bf->aphy, tx_flags); + ath_debug_stat_tx(sc, bf, ts); + ath_tx_complete(sc, skb, bf->aphy, tx_flags, + bf->bf_state.bfs_ftype, txq); } /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't * accidentally reference it later. @@ -1945,42 +1905,15 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, spin_unlock_irqrestore(&sc->tx.txbuflock, flags); } -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok) -{ - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; - - if (bf->bf_lastbf->bf_tx_aborted) - return 0; - - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ts->ts_seqnum; - memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); - } - - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; - - bf = bf->bf_next; - } - - return nbad; -} - static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc) + int nframes, int nbad, int txok, bool update_rc) { struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = bf->aphy->hw; + struct ath_softc *sc = bf->aphy->sc; + struct ath_hw *ah = sc->sc_ah; u8 i, tx_rateindex; if (txok) @@ -1994,22 +1927,32 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - BUG_ON(nbad > bf->bf_nframes); + BUG_ON(nbad > nframes); - tx_info->status.ampdu_len = bf->bf_nframes; - tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; + tx_info->status.ampdu_len = nframes; + tx_info->status.ampdu_ack_len = nframes - nbad; } if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { - if (ieee80211_is_data(hdr->frame_control)) { - if (ts->ts_flags & - (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) - tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; - if ((ts->ts_status & ATH9K_TXERR_XRETRY) || - (ts->ts_status & ATH9K_TXERR_FIFO)) - tx_info->pad[0] |= ATH_TX_INFO_XRETRY; - } + /* + * If an underrun error is seen assume it as an excessive + * retry only if max frame trigger level has been reached + * (2 KB for single stream, and 4 KB for dual stream). + * Adjust the long retry as if the frame was tried + * hw->max_rate_tries times to affect how rate control updates + * PER for the failed rate. + * In case of congestion on the bus penalizing this type of + * underruns should help hardware actually transmit new frames + * successfully by eventually preferring slower rates. + * This itself should also alleviate congestion on the bus. + */ + if (ieee80211_is_data(hdr->frame_control) && + (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | + ATH9K_TX_DELIM_UNDERRUN)) && + ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) + tx_info->status.rates[tx_rateindex].count = + hw->max_rate_tries; } for (i = tx_rateindex + 1; i < hw->max_rates; i++) { @@ -2020,16 +1963,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; } -static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) +static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum) { - int qnum; - - qnum = ath_get_mac80211_qnum(txq->axq_class, sc); - if (qnum == -1) - return; + struct ath_txq *txq; + txq = sc->tx.txq_map[qnum]; spin_lock_bh(&txq->axq_lock); - if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { + if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { if (ath_mac80211_start_queue(sc, qnum)) txq->stopped = 0; } @@ -2046,6 +1986,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) struct ath_tx_status ts; int txok; int status; + int qnum; ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), @@ -2118,15 +2059,19 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, + true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (sc->sc_flags & SC_OP_TXAGGR) @@ -2196,6 +2141,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) struct list_head bf_head; int status; int txok; + int qnum; for (;;) { status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); @@ -2236,16 +2182,20 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) if (!bf_isampdu(bf)) { if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, + txok, true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &txs, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (!list_empty(&txq->txq_fifo_pending)) { @@ -2377,7 +2327,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) for (acno = 0, ac = &an->ac[acno]; acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; - ac->qnum = sc->tx.hwq_map[acno]; + ac->txq = sc->tx.txq_map[acno]; INIT_LIST_HEAD(&ac->tid_q); } } @@ -2387,17 +2337,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) struct ath_atx_ac *ac; struct ath_atx_tid *tid; struct ath_txq *txq; - int i, tidno; + int tidno; for (tidno = 0, tid = &an->tid[tidno]; tidno < WME_NUM_TID; tidno++, tid++) { - i = tid->ac->qnum; - - if (!ATH_TXQ_SETUP(sc, i)) - continue; - txq = &sc->tx.txq[i]; ac = tid->ac; + txq = ac->txq; spin_lock_bh(&txq->axq_lock); diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 6cf0c9ef47aa..d07ff7f2fd92 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -48,7 +48,7 @@ #include <linux/usb.h> #ifdef CONFIG_CARL9170_LEDS #include <linux/leds.h> -#endif /* CONFIG_CARL170_LEDS */ +#endif /* CONFIG_CARL9170_LEDS */ #ifdef CONFIG_CARL9170_WPC #include <linux/input.h> #endif /* CONFIG_CARL9170_WPC */ @@ -215,7 +215,7 @@ enum carl9170_restart_reasons { CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS, CARL9170_RR_WATCHDOG, CARL9170_RR_STUCK_TX, - CARL9170_RR_SLOW_SYSTEM, + CARL9170_RR_UNRESPONSIVE_DEVICE, CARL9170_RR_COMMAND_TIMEOUT, CARL9170_RR_TOO_MANY_PHY_ERRORS, CARL9170_RR_LOST_RSP, @@ -287,6 +287,7 @@ struct ar9170 { /* reset / stuck frames/queue detection */ struct work_struct restart_work; + struct work_struct ping_work; unsigned int restart_counter; unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index c21f3364bfec..cdfc94c371b4 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -41,7 +41,7 @@ int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) { - __le32 buf[2] = { + const __le32 buf[2] = { cpu_to_le32(reg), cpu_to_le32(val), }; diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index d552166db505..3680dfc70f46 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -97,13 +97,13 @@ struct carl9170_set_key_cmd { __le16 type; u8 macAddr[6]; u32 key[4]; -} __packed; +} __packed __aligned(4); #define CARL9170_SET_KEY_CMD_SIZE 28 struct carl9170_disable_key_cmd { __le16 user; __le16 padding; -} __packed; +} __packed __aligned(4); #define CARL9170_DISABLE_KEY_CMD_SIZE 4 struct carl9170_u32_list { @@ -206,7 +206,7 @@ struct carl9170_cmd { struct carl9170_rx_filter_cmd rx_filter; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; -} __packed; +} __packed __aligned(4); #define CARL9170_TX_STATUS_QUEUE 3 #define CARL9170_TX_STATUS_QUEUE_S 0 @@ -216,6 +216,7 @@ struct carl9170_cmd { #define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S) #define CARL9170_TX_STATUS_SUCCESS 0x80 +#ifdef __CARL9170FW__ /* * NOTE: * Both structs [carl9170_tx_status and _carl9170_tx_status] @@ -232,6 +233,8 @@ struct carl9170_tx_status { u8 tries:3; u8 success:1; } __packed; +#endif /* __CARL9170FW__ */ + struct _carl9170_tx_status { /* * This version should be immune to all alignment bugs. @@ -272,13 +275,15 @@ struct carl9170_rsp { struct carl9170_rf_init_result rf_init_res; struct carl9170_u32_list rreg_res; struct carl9170_u32_list echo; +#ifdef __CARL9170FW__ struct carl9170_tx_status tx_status[0]; +#endif /* __CARL9170FW__ */ struct _carl9170_tx_status _tx_status[0]; struct carl9170_gpio gpio; struct carl9170_tsf_rsp tsf; struct carl9170_psm psm; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; -} __packed; +} __packed __aligned(4); #endif /* __CARL9170_SHARED_FWCMD_H */ diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 2f471b3f05af..e85df6edfed3 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -712,7 +712,8 @@ struct ar9170_stream { __le16 tag; u8 payload[0]; -}; +} __packed __aligned(4); +#define AR9170_STREAM_LEN 4 #define AR9170_MAX_ACKTABLE_ENTRIES 8 #define AR9170_MAX_VIRTUAL_MAC 7 @@ -736,4 +737,8 @@ struct ar9170_stream { #define MOD_VAL(reg, value, newvalue) \ (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) + +#define GET_VAL(reg, value) \ + (((value) & reg) >> reg##_S) + #endif /* __CARL9170_SHARED_HW_H */ diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index 2305bc27151c..385cf508479b 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar) carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); /* Aggregation MAX number and timeout */ - carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa); - carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00); + carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a); + carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07); carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, AR9170_MAC_FTF_DEFAULTS); @@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar) int carl9170_update_beacon(struct ar9170 *ar, const bool submit) { - struct sk_buff *skb; + struct sk_buff *skb = NULL; struct carl9170_vif_info *cvif; + struct ieee80211_tx_info *txinfo; __le32 *data, *old = NULL; u32 word, off, addr, len; int i = 0, err = 0; @@ -487,7 +488,13 @@ found: if (!skb) { err = -ENOMEM; - goto out_unlock; + goto err_free; + } + + txinfo = IEEE80211_SKB_CB(skb); + if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) { + err = -EINVAL; + goto err_free; } spin_lock_bh(&ar->beacon_lock); @@ -504,11 +511,8 @@ found: wiphy_err(ar->hw->wiphy, "beacon does not " "fit into device memory!\n"); } - - spin_unlock_bh(&ar->beacon_lock); - dev_kfree_skb_any(skb); err = -EINVAL; - goto out_unlock; + goto err_unlock; } if (len > AR9170_MAC_BCN_LENGTH_MAX) { @@ -518,22 +522,22 @@ found: AR9170_MAC_BCN_LENGTH_MAX, len); } - spin_unlock_bh(&ar->beacon_lock); - dev_kfree_skb_any(skb); err = -EMSGSIZE; - goto out_unlock; + goto err_unlock; } - carl9170_async_regwrite_begin(ar); + i = txinfo->control.rates[0].idx; + if (txinfo->band != IEEE80211_BAND_2GHZ) + i += 4; - /* XXX: use skb->cb info */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400); - } else { - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + FCS_LEN) << 16) + 0x001b); - } + word = __carl9170_ratetable[i].hw_value & 0xf; + if (i < 4) + word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; + else + word |= ((skb->len + FCS_LEN) << 16) + 0x0010; + + carl9170_async_regwrite_begin(ar); + carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { /* @@ -557,7 +561,7 @@ found: cvif->beacon = skb; spin_unlock_bh(&ar->beacon_lock); if (err) - goto out_unlock; + goto err_free; if (submit) { err = carl9170_bcn_ctrl(ar, cvif->id, @@ -565,10 +569,18 @@ found: addr, skb->len + FCS_LEN); if (err) - goto out_unlock; + goto err_free; } out_unlock: rcu_read_unlock(); + return 0; + +err_unlock: + spin_unlock_bh(&ar->beacon_lock); + +err_free: + rcu_read_unlock(); + dev_kfree_skb_any(skb); return err; } diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index dc7b30b170d0..870df8c42622 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar) cancel_delayed_work_sync(&ar->led_work); #endif /* CONFIG_CARL9170_LEDS */ cancel_work_sync(&ar->ps_work); + cancel_work_sync(&ar->ping_work); cancel_work_sync(&ar->ampdu_work); } @@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) */ } +static void carl9170_ping_work(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, ping_work); + int err; + + if (!IS_STARTED(ar)) + return; + + mutex_lock(&ar->mutex); + err = carl9170_echo_test(ar, 0xdeadbeef); + if (err) + carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE); + mutex_unlock(&ar->mutex); +} + static int carl9170_init_interface(struct ar9170 *ar, struct ieee80211_vif *vif) { @@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size) skb_queue_head_init(&ar->tx_pending[i]); } INIT_WORK(&ar->ps_work, carl9170_ps_work); + INIT_WORK(&ar->ping_work, carl9170_ping_work); INIT_WORK(&ar->restart_work, carl9170_restart_work); INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); @@ -1829,7 +1846,7 @@ int carl9170_register(struct ar9170 *ar) err = carl9170_led_register(ar); if (err) goto err_unreg; -#endif /* CONFIG_CAR9L170_LEDS */ +#endif /* CONFIG_CARL9170_LEDS */ #ifdef CONFIG_CARL9170_WPC err = carl9170_register_wps_button(ar); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index 89deca37a988..82bc81c4c930 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1554,15 +1554,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, return carl9170_regwrite_result(); } -/* TODO: replace this with sign_extend32(noise, 8) */ -static int carl9170_calc_noise_dbm(u32 raw_noise) -{ - if (raw_noise & 0x100) - return ~0x1ff | raw_noise; - else - return raw_noise; -} - int carl9170_get_noisefloor(struct ar9170 *ar) { static const u32 phy_regs[] = { @@ -1578,11 +1569,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar) return err; for (i = 0; i < 2; i++) { - ar->noise[i] = carl9170_calc_noise_dbm( - (phy_res[i] >> 19) & 0x1ff); + ar->noise[i] = sign_extend32(GET_VAL( + AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8); - ar->noise[i + 2] = carl9170_calc_noise_dbm( - (phy_res[i + 2] >> 23) & 0x1ff); + ar->noise[i + 2] = sign_extend32(GET_VAL( + AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); } return 0; diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h index 02c34eb4ebde..024fb42bc787 100644 --- a/drivers/net/wireless/ath/carl9170/phy.h +++ b/drivers/net/wireless/ath/carl9170/phy.h @@ -139,8 +139,8 @@ #define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 #define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064) -#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CCA_MINCCA_PWR_S 19 +#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CCA_MIN_PWR_S 19 #define AR9170_PHY_CCA_THRESH62 0x0007f000 #define AR9170_PHY_CCA_THRESH62_S 12 @@ -338,8 +338,8 @@ #define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9 #define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000 #define AR9170_PHY_EXT_CCA_THRESH62_S 16 -#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23 #define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0) #define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f @@ -546,19 +546,19 @@ #define AR9170_PHY_FORCE_XPA_CFG_S 0 #define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064) -#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CH1_MINCCA_PWR_S 19 +#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19 #define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064) -#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000 -#define AR9170_PHY_CH2_MINCCA_PWR_S 19 +#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000 +#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19 #define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc) -#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23 #define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc) -#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 -#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 +#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000 +#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23 #endif /* __CARL9170_SHARED_PHY_H */ diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 7e6506a77bbb..6cc58e052d10 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -242,9 +242,11 @@ static void carl9170_tx_release(struct kref *ref) ar->tx_ampdu_schedule = true; if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) { - txinfo->status.ampdu_len = txinfo->pad[0]; - txinfo->status.ampdu_ack_len = txinfo->pad[1]; - txinfo->pad[0] = txinfo->pad[1] = 0; + struct _carl9170_tx_superframe *super; + + super = (void *)skb->data; + txinfo->status.ampdu_len = super->s.rix; + txinfo->status.ampdu_ack_len = super->s.cnt; } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) { /* * drop redundant tx_status reports: @@ -337,7 +339,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || - txinfo->flags & IEEE80211_TX_CTL_INJECTED) + txinfo->flags & IEEE80211_TX_CTL_INJECTED || + (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; tx_info = IEEE80211_SKB_CB(skb); @@ -389,8 +392,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, sta_info->stats[tid].ampdu_ack_len++; if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) { - txinfo->pad[0] = sta_info->stats[tid].ampdu_len; - txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len; + super->s.rix = sta_info->stats[tid].ampdu_len; + super->s.cnt = sta_info->stats[tid].ampdu_ack_len; txinfo->flags |= IEEE80211_TX_STAT_AMPDU; sta_info->stats[tid].clear = true; } @@ -524,6 +527,59 @@ next: } } +static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) +{ + struct carl9170_sta_tid *iter; + struct sk_buff *skb; + struct ieee80211_tx_info *txinfo; + struct carl9170_tx_info *arinfo; + struct _carl9170_tx_superframe *super; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct ieee80211_hdr *hdr; + unsigned int vif_id; + + rcu_read_lock(); + list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { + if (iter->state < CARL9170_TID_STATE_IDLE) + continue; + + spin_lock_bh(&iter->lock); + skb = skb_peek(&iter->queue); + if (!skb) + goto unlock; + + txinfo = IEEE80211_SKB_CB(skb); + arinfo = (void *)txinfo->rate_driver_data; + if (time_is_after_jiffies(arinfo->timeout + + msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) + goto unlock; + + super = (void *) skb->data; + hdr = (void *) super->frame_data; + + vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> + CARL9170_TX_SUPER_MISC_VIF_ID_S; + + if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) + goto unlock; + + vif = rcu_dereference(ar->vif_priv[vif_id].vif); + if (WARN_ON(!vif)) + goto unlock; + + sta = ieee80211_find_sta(vif, hdr->addr1); + if (WARN_ON(!sta)) + goto unlock; + + ieee80211_stop_tx_ba_session(sta, iter->tid); +unlock: + spin_unlock_bh(&iter->lock); + + } + rcu_read_unlock(); +} + void carl9170_tx_janitor(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, @@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_struct *work) ar->tx_janitor_last_run = jiffies; carl9170_check_queue_stop_timeout(ar); + carl9170_tx_ampdu_timeout(ar); if (!atomic_read(&ar->tx_total_queued)) return; @@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) if (unlikely(!sta || !cvif)) goto err_out; - factor = min_t(unsigned int, 1u, - info->control.sta->ht_cap.ampdu_factor); - - density = info->control.sta->ht_cap.ampdu_density; + factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor); + density = sta->ht_cap.ampdu_density; if (density) { /* @@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *ar) static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, struct ieee80211_sta *sta, struct sk_buff *skb) { + struct _carl9170_tx_superframe *super = (void *) skb->data; struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *agg; struct sk_buff *iter; @@ -1274,6 +1330,7 @@ err_unlock: err_unlock_rcu: rcu_read_unlock(); + super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); carl9170_tx_status(ar, skb, false); ar->tx_dropped++; return false; @@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) */ if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (WARN_ON_ONCE(!sta)) - goto err_free; - run = carl9170_tx_ampdu_queue(ar, sta, skb); if (run) carl9170_tx_ampdu(ar); diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 7504ed14c725..2d947a30d29e 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -160,8 +160,7 @@ err_acc: static void carl9170_usb_tx_data_complete(struct urb *urb) { - struct ar9170 *ar = (struct ar9170 *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); if (WARN_ON_ONCE(!ar)) { dev_kfree_skb_irq(urb->context); @@ -433,7 +432,7 @@ static void carl9170_usb_rx_complete(struct urb *urb) * device. */ - carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM); + ieee80211_queue_work(ar->hw, &ar->ping_work); } } else { /* diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index ff53f078a0b5..ee0f84f2a2f6 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H #define CARL9170FW_VERSION_YEAR 10 -#define CARL9170FW_VERSION_MONTH 9 -#define CARL9170FW_VERSION_DAY 28 -#define CARL9170FW_VERSION_GIT "1.8.8.3" +#define CARL9170FW_VERSION_MONTH 10 +#define CARL9170FW_VERSION_DAY 29 +#define CARL9170FW_VERSION_GIT "1.9.0" #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index dacfb234f491..a9600ba8ceaa 100644 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c @@ -19,14 +19,19 @@ void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) { + struct va_format vaf; va_list args; if (likely(!(common->debug_mask & dbg_mask))) return; va_start(args, fmt); - printk(KERN_DEBUG "ath: "); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_DEBUG "ath: %pV", &vaf); + va_end(args); } EXPORT_SYMBOL(ath_print); diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 64e4af2c2887..f207007ee391 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -70,11 +70,13 @@ enum ATH_DEBUG { #ifdef CONFIG_ATH_DEBUG void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #else static inline void __attribute__ ((format (printf, 3, 4))) ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) { } +#define ATH_DBG_WARN(foo, arg) #endif /* CONFIG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index bd21a4d82085..62e3dac8f92a 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -67,7 +67,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) } EXPORT_SYMBOL(ath_hw_keyreset); -bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) +static bool ath_hw_keysetmac(struct ath_common *common, + u16 entry, const u8 *mac) { u32 macHi, macLo; u32 unicast_flag = AR_KEYTABLE_VALID; @@ -107,9 +108,9 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) return true; } -bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, - const struct ath_keyval *k, - const u8 *mac) +static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, + const struct ath_keyval *k, + const u8 *mac) { void *ah = common->ah; u32 key0, key1, key2, key3, key4; diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index c8f7090b27d3..46e382ed46aa 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1161,7 +1161,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id) struct atmel_private *priv = netdev_priv(dev); u8 isr; int i = -1; - static u8 irq_order[] = { + static const u8 irq_order[] = { ISR_OUT_OF_RANGE, ISR_RxCOMPLETE, ISR_TxCOMPLETE, @@ -3771,7 +3771,9 @@ static int probe_atmel_card(struct net_device *dev) if (rc) { if (dev->dev_addr[0] == 0xFF) { - u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00}; + static const u8 default_mac[] = { + 0x00, 0x04, 0x25, 0x00, 0x00, 0x00 + }; printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); memcpy(dev->dev_addr, default_mac, 6); } diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 72821c456b02..9aad2ca3c112 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -153,6 +153,19 @@ #define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna * with bluetooth */ +/* SPROM boardflags2_lo values */ +#define B43_BFL2_RXBB_INT_REG_DIS 0x0001 /* external RX BB regulator present */ +#define B43_BFL2_APLL_WAR 0x0002 /* alternative A-band PLL settings implemented */ +#define B43_BFL2_TXPWRCTRL_EN 0x0004 /* permits enabling TX Power Control */ +#define B43_BFL2_2X4_DIV 0x0008 /* 2x4 diversity switch */ +#define B43_BFL2_5G_PWRGAIN 0x0010 /* supports 5G band power gain */ +#define B43_BFL2_PCIEWAR_OVR 0x0020 /* overrides ASPM and Clkreq settings */ +#define B43_BFL2_CAESERS_BRD 0x0040 /* is Caesers board (unused) */ +#define B43_BFL2_BTC3WIRE 0x0080 /* used 3-wire bluetooth coexist */ +#define B43_BFL2_SKWRKFEM_BRD 0x0100 /* 4321mcm93 uses Skyworks FEM */ +#define B43_BFL2_SPUR_WAR 0x0200 /* has a workaround for clock-harmonic spurs */ +#define B43_BFL2_GPLL_WAR 0x0400 /* altenative G-band PLL settings implemented */ + /* GPIO register offset, in both ChipCommon and PCI core. */ #define B43_GPIO_CONTROL 0x6c diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 10d0aaf754c5..3d5566e7af0a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -415,11 +415,6 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - gfp_t flags = GFP_KERNEL; - - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a1186525c70d..fa4880366586 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -322,59 +322,83 @@ static int b43_ratelimit(struct b43_wl *wl) void b43info(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_INFO) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_INFO "b43-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_INFO "b43-%s: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43err(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_ERROR) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_ERR "b43-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_ERR "b43-%s ERROR: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43warn(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_WARN) return; if (!b43_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_WARNING "b43-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_WARNING "b43-%s warning: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43dbg(struct b43_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) return; + va_start(args, fmt); - printk(KERN_DEBUG "b43-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_DEBUG "b43-%s debug: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 7b2ea6781457..fa7f83fc8db9 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -427,9 +427,11 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { - u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, - 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, - 229, 115, 57, 29, }; + static const u32 arctg[] = { + 2949120, 1740967, 919879, 466945, 234379, 117304, + 58666, 29335, 14668, 7334, 3667, 1833, + 917, 458, 229, 115, 57, 29, + }; u8 i; s32 tmp; s8 signx = 1; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e0f2d122e124..905f1d7bac20 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -67,6 +67,18 @@ enum b43_nphy_rf_sequence { B43_RFSEQ_UPDATE_GAINU, }; +enum b43_nphy_rssi_type { + B43_NPHY_RSSI_X = 0, + B43_NPHY_RSSI_Y, + B43_NPHY_RSSI_Z, + B43_NPHY_RSSI_PWRDET, + B43_NPHY_RSSI_TSSI_I, + B43_NPHY_RSSI_TSSI_Q, + B43_NPHY_RSSI_TBD, +}; + +static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, + bool enable); static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, u8 *events, u8 *delays, u8 length); static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, @@ -145,9 +157,153 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ +static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) +{ + struct b43_phy_n *nphy = dev->phy.n; + u8 i; + u16 tmp; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + nphy->txpwrctrl = enable; + if (!enable) { + if (dev->phy.rev >= 3) + ; /* TODO */ + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + + tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; + if (dev->phy.rev >= 3) + tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN; + b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp); + + if (dev->phy.rev >= 3) { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); + } else { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); + } + + if (dev->phy.rev == 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x53); + else if (dev->phy.rev < 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); + + if (dev->phy.rev < 2 && 0) + ; /* TODO */ + } else { + b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n"); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) { - //TODO + struct b43_phy_n *nphy = dev->phy.n; + struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + + u8 txpi[2], bbmult, i; + u16 tmp, radio_gain, dac_gain; + u16 freq = dev->phy.channel_freq; + u32 txgain; + /* u32 gaintbl; rev3+ */ + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + if (dev->phy.rev >= 3) { + txpi[0] = 40; + txpi[1] = 40; + } else if (sprom->revision < 4) { + txpi[0] = 72; + txpi[1] = 72; + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + txpi[0] = sprom->txpid2g[0]; + txpi[1] = sprom->txpid2g[1]; + } else if (freq >= 4900 && freq < 5100) { + txpi[0] = sprom->txpid5gl[0]; + txpi[1] = sprom->txpid5gl[1]; + } else if (freq >= 5100 && freq < 5500) { + txpi[0] = sprom->txpid5g[0]; + txpi[1] = sprom->txpid5g[1]; + } else if (freq >= 5500) { + txpi[0] = sprom->txpid5gh[0]; + txpi[1] = sprom->txpid5gh[1]; + } else { + txpi[0] = 91; + txpi[1] = 91; + } + } + + /* + for (i = 0; i < 2; i++) { + nphy->txpwrindex[i].index_internal = txpi[i]; + nphy->txpwrindex[i].index_internal_save = txpi[i]; + } + */ + + for (i = 0; i < 2; i++) { + if (dev->phy.rev >= 3) { + /* TODO */ + radio_gain = (txgain >> 16) & 0x1FFFF; + } else { + txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; + radio_gain = (txgain >> 16) & 0x1FFF; + } + + dac_gain = (txgain >> 8) & 0x3F; + bbmult = txgain & 0xFF; + + if (dev->phy.rev >= 3) { + if (i == 0) + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); + else + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); + } else { + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); + } + + if (i == 0) + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain); + else + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + + if (i == 0) + tmp = (tmp & 0x00FF) | (bbmult << 8); + else + tmp = (tmp & 0xFF00) | bbmult; + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp); + + if (0) + ; /* TODO */ + } + + b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); } @@ -191,7 +347,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) binfo->type != 0x46D || binfo->rev < 0x41); else - workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0); + workaround = + !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS); b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); if (workaround) { @@ -240,10 +397,13 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) static void b43_radio_init2055(struct b43_wldev *dev) { b43_radio_init2055_pre(dev); - if (b43_status(dev) < B43_STAT_INITIALIZED) - b2055_upload_inittab(dev, 0, 1); - else - b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); + if (b43_status(dev) < B43_STAT_INITIALIZED) { + /* Follow wl, not specs. Do not force uploading all regs */ + b2055_upload_inittab(dev, 0, 0); + } else { + bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ; + b2055_upload_inittab(dev, ghz5, 0); + } b43_radio_init2055_post(dev); } @@ -569,7 +729,6 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) ii = est.i1_pwr; qq = est.q1_pwr; } else { - B43_WARN_ON(1); continue; } @@ -651,7 +810,8 @@ static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ -static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) +static void b43_nphy_write_clip_detection(struct b43_wldev *dev, + const u16 *clip_st) { b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); @@ -727,7 +887,7 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) struct b43_phy_n *nphy = phy->n; if (enable) { - u16 clip[] = { 0xFFFF, 0xFFFF }; + static const u16 clip[] = { 0xFFFF, 0xFFFF }; if (nphy->deaf_count++ == 0) { nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); b43_nphy_classifier(dev, 0x7, 0); @@ -839,7 +999,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) u16 data[4]; s16 gain[2]; u16 minmax[2]; - u16 lna_gain[4] = { -2, 10, 19, 25 }; + static const u16 lna_gain[4] = { -2, 10, 19, 25 }; if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); @@ -871,7 +1031,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) data[2] = lna_gain[2] + gain[i]; data[3] = lna_gain[3] + gain[i]; } - b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data); + b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data); minmax[i] = 23 + gain[i]; } @@ -891,6 +1051,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) struct b43_phy_n *nphy = dev->phy.n; u8 i, j; u8 code; + u16 tmp; /* TODO: for PHY >= 3 s8 *lna1_gain, *lna2_gain; @@ -913,15 +1074,15 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) B43_NPHY_C2_CGAINI_CL2DETECT); /* Set narrowband clip threshold */ - b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); - b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); + b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); + b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); if (!dev->phy.is_40mhz) { /* Set dwell lengths */ - b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); - b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); - b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); - b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); + b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); + b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); + b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); + b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); } /* Set wideband clip 2 threshold */ @@ -943,7 +1104,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); } - b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); + b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); if (nphy->gain_boost) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && @@ -964,10 +1125,10 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x7C)); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x7C)); + /* specs say about 2 loops, but wl does 4 */ + for (i = 0; i < 4; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x7C)); b43_nphy_adjust_lna_gain_table(dev); @@ -985,19 +1146,21 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x74)); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, - (code << 8 | 0x74)); + /* specs say about 2 loops, but wl does 4 */ + for (i = 0; i < 4; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x74)); } if (dev->phy.rev == 2) { for (i = 0; i < 4; i++) { b43_phy_write(dev, B43_NPHY_TABLE_ADDR, (0x0400 * i) + 0x0020); - for (j = 0; j < 21; j++) + for (j = 0; j < 21; j++) { + tmp = j * (i < 2 ? 3 : 1); b43_phy_write(dev, - B43_NPHY_TABLE_DATALO, 3 * j); + B43_NPHY_TABLE_DATALO, tmp); + } } b43_nphy_set_rf_sequence(dev, 5, @@ -1026,7 +1189,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) b43_nphy_classifier(dev, 1, 0); else b43_nphy_classifier(dev, 1, 1); @@ -1565,19 +1728,20 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ static void b43_nphy_bphy_init(struct b43_wldev *dev) { unsigned int i; u16 val; val = 0x1E1F; - for (i = 0; i < 14; i++) { + for (i = 0; i < 16; i++) { b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); val -= 0x202; } val = 0x3E3F; for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); + b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); val -= 0x202; } b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); @@ -1585,7 +1749,8 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, - s8 offset, u8 core, u8 rail, u8 type) + s8 offset, u8 core, u8 rail, + enum b43_nphy_rssi_type type) { u16 tmp; bool core1or5 = (core == 1) || (core == 5); @@ -1594,53 +1759,59 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, offset = clamp_val(offset, -32, 31); tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); - if (core1or5 && (rail == 0) && (type == 2)) + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); - if (core1or5 && (rail == 1) && (type == 2)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); - if (core2or5 && (rail == 0) && (type == 2)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); - if (core2or5 && (rail == 1) && (type == 2)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); - if (core1or5 && (rail == 0) && (type == 0)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); - if (core1or5 && (rail == 1) && (type == 0)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); - if (core2or5 && (rail == 0) && (type == 0)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); - if (core2or5 && (rail == 1) && (type == 0)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); - if (core1or5 && (rail == 0) && (type == 1)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); - if (core1or5 && (rail == 1) && (type == 1)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); - if (core2or5 && (rail == 0) && (type == 1)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); - if (core2or5 && (rail == 1) && (type == 1)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); - if (core1or5 && (rail == 0) && (type == 6)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); - if (core1or5 && (rail == 1) && (type == 6)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); - if (core2or5 && (rail == 0) && (type == 6)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); - if (core2or5 && (rail == 1) && (type == 6)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); - if (core1or5 && (rail == 0) && (type == 3)) + + if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); - if (core1or5 && (rail == 1) && (type == 3)) + if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); - if (core2or5 && (rail == 0) && (type == 3)) + if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); - if (core2or5 && (rail == 1) && (type == 3)) + if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); - if (core1or5 && (type == 4)) + + if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I)) b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); - if (core2or5 && (type == 4)) + if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I)) b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); - if (core1or5 && (type == 5)) + + if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q)) b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); - if (core2or5 && (type == 5)) + if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q)) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); } @@ -1668,27 +1839,39 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) (type + 1) << 4); } - /* TODO use some definitions */ if (code == 0) { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000); if (type < 3) { - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~(B43_NPHY_RFCTL_CMD_RXEN | + B43_NPHY_RFCTL_CMD_CORESEL)); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, + ~(0x1 << 12 | + 0x1 << 5 | + 0x1 << 1 | + 0x1)); + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, + ~B43_NPHY_RFCTL_CMD_START); udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); } } else { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, - 0x3000); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000); if (type < 3) { b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFEC7, 0x0180); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xEFDC, (code << 1 | 0x1021)); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1); + ~(B43_NPHY_RFCTL_CMD_RXEN | + B43_NPHY_RFCTL_CMD_CORESEL), + (B43_NPHY_RFCTL_CMD_RXEN | + code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT)); + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, + (0x1 << 12 | + 0x1 << 5 | + 0x1 << 1 | + 0x1)); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_START); udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); } } } @@ -1837,6 +2020,14 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); + } else if (dev->phy.rev == 2) { + save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); + save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); + save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); + save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); } b43_nphy_rssi_select(dev, 5, type); @@ -1880,6 +2071,14 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); + } else if (dev->phy.rev == 2) { + b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); + b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); + b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); + b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); } return out; @@ -1894,7 +2093,10 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) u16 class, override; u8 regs_save_radio[2]; u16 regs_save_phy[2]; + s8 offset[4]; + u8 core; + u8 rail; u16 clip_state[2]; u16 clip_off[2] = { 0xFFFF, 0xFFFF }; @@ -1995,16 +2197,15 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) if (results_min[i] == 248) offset[i] = code - 32; - if (i % 2 == 0) - b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0, - type); - else - b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1, - type); + core = (i / 2) ? 2 : 1; + rail = (i % 2) ? 1 : 0; + + b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, + type); } b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); - b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]); + b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); switch (state[2]) { case 1: @@ -2042,6 +2243,9 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) b43_nphy_classifier(dev, 7, class); b43_nphy_write_clip_detection(dev, clip_state); + /* Specs don't say about reset here, but it makes wl and b43 dumps + identical, it really seems wl performs this */ + b43_nphy_reset_cca(dev); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ @@ -2059,9 +2263,9 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev) if (dev->phy.rev >= 3) { b43_nphy_rev3_rssi_cal(dev); } else { - b43_nphy_rev2_rssi_cal(dev, 2); - b43_nphy_rev2_rssi_cal(dev, 0); - b43_nphy_rev2_rssi_cal(dev, 1); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X); + b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y); } } @@ -2295,7 +2499,7 @@ static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) { int i, j; /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ - u16 offset[] = { 0x186, 0x195, 0x2C5 }; + static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; for (i = 0; i < 3; i++) for (j = 0; j < 15; j++) @@ -2327,7 +2531,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) struct nphy_txgains target; const u32 *table = NULL; - if (nphy->txpwrctrl == 0) { + if (!nphy->txpwrctrl) { int i; if (nphy->hang_avoid) @@ -3088,7 +3292,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) { struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; - u16 buf[16]; + /* u16 buf[16]; it's rev3+ */ nphy->phyrxchain = mask; @@ -3232,10 +3436,12 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_classifier(dev, 0, 0); b43_nphy_read_clip_detection(dev, clip); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_nphy_bphy_init(dev); + tx_pwr_state = nphy->txpwrctrl; - /* TODO N PHY TX power control with argument 0 - (turning off power control) */ - /* TODO Fix the TX Power Settings */ + b43_nphy_tx_power_ctrl(dev, false); + b43_nphy_tx_power_fix(dev); /* TODO N PHY TX Power Control Idle TSSI */ /* TODO N PHY TX Power Control Setup */ @@ -3292,21 +3498,18 @@ int b43_phy_initn(struct b43_wldev *dev) /* TODO N PHY Pre Calibrate TX Gain */ target = b43_nphy_get_tx_gains(dev); } - } + if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) + if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) + b43_nphy_save_cal(dev); + } else if (nphy->mphase_cal_phase_id == 0) + ;/* N PHY Periodic Calibration with arg 3 */ + } else { + b43_nphy_restore_cal(dev); } } - if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { - if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) - b43_nphy_save_cal(dev); - else if (nphy->mphase_cal_phase_id == 0) - ;/* N PHY Periodic Calibration with argument 3 */ - } else { - b43_nphy_restore_cal(dev); - } - b43_nphy_tx_pwr_ctrl_coef_setup(dev); - /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ + b43_nphy_tx_power_ctrl(dev, tx_pwr_state); b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); if (phy->rev >= 3 && phy->rev <= 6) @@ -3357,7 +3560,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); } - if (nphy->txpwrctrl) + if (!nphy->txpwrctrl) b43_nphy_tx_power_fix(dev); if (dev->phy.rev < 3) @@ -3381,7 +3584,6 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, enum nl80211_channel_type channel_type) { struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = dev->phy.n; const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; @@ -3451,7 +3653,10 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) memset(nphy, 0, sizeof(*nphy)); - //TODO init struct b43_phy_n + nphy->gain_boost = true; /* this way we follow wl, assume it is true */ + nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ + nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ + nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ } static void b43_nphy_op_free(struct b43_wldev *dev) @@ -3524,8 +3729,6 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, bool blocked) { - struct b43_phy_n *nphy = dev->phy.n; - if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) b43err(dev->wl, "MAC not suspended\n"); diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index c144e59a708b..001e841f118c 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -782,7 +782,7 @@ struct b43_phy_n { u16 mphase_txcal_numcmds; u16 mphase_txcal_bestcoeffs[11]; - u8 txpwrctrl; + bool txpwrctrl; u16 txcal_bbmult; u16 txiqlocal_bestc[11]; bool txiqlocal_coeffsvalid; diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c index 1b5316586cbf..44c6dea66882 100644 --- a/drivers/net/wireless/b43/radio_2055.c +++ b/drivers/net/wireless/b43/radio_2055.c @@ -244,7 +244,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = { [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCE] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, @@ -256,7 +256,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = { [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDA] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, @@ -304,178 +304,178 @@ static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = { .channel = 184, .freq = 4920, /* MHz */ .unk2 = 3280, - RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEC, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602), + PHYREGS(0x07B4, 0x07B0, 0x07AC, 0x0214, 0x0215, 0x0216), }, { .channel = 186, .freq = 4930, /* MHz */ .unk2 = 3287, - RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xED, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502), + PHYREGS(0x07B8, 0x07B4, 0x07B0, 0x0213, 0x0214, 0x0215), }, { .channel = 188, .freq = 4940, /* MHz */ .unk2 = 3293, - RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEE, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402), + PHYREGS(0x07BC, 0x07B8, 0x07B4, 0x0212, 0x0213, 0x0214), }, { .channel = 190, .freq = 4950, /* MHz */ .unk2 = 3300, - RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xEF, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302), + PHYREGS(0x07C0, 0x07BC, 0x07B8, 0x0211, 0x0212, 0x0213), }, { .channel = 192, .freq = 4960, /* MHz */ .unk2 = 3307, - RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF0, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202), + PHYREGS(0x07C4, 0x07C0, 0x07BC, 0x020F, 0x0211, 0x0212), }, { .channel = 194, .freq = 4970, /* MHz */ .unk2 = 3313, - RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF1, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102), + PHYREGS(0x07C8, 0x07C4, 0x07C0, 0x020E, 0x020F, 0x0211), }, { .channel = 196, .freq = 4980, /* MHz */ .unk2 = 3320, - RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF2, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02), + PHYREGS(0x07CC, 0x07C8, 0x07C4, 0x020D, 0x020E, 0x020F), }, { .channel = 198, .freq = 4990, /* MHz */ .unk2 = 3327, - RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF3, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02), + PHYREGS(0x07D0, 0x07CC, 0x07C8, 0x020C, 0x020D, 0x020E), }, { .channel = 200, .freq = 5000, /* MHz */ .unk2 = 3333, - RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF4, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02), + PHYREGS(0x07D4, 0x07D0, 0x07CC, 0x020B, 0x020C, 0x020D), }, { .channel = 202, .freq = 5010, /* MHz */ .unk2 = 3340, - RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF5, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02), + PHYREGS(0x07D8, 0x07D4, 0x07D0, 0x020A, 0x020B, 0x020C), }, { .channel = 204, .freq = 5020, /* MHz */ .unk2 = 3347, - RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF6, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02), + PHYREGS(0x07DC, 0x07D8, 0x07D4, 0x0209, 0x020A, 0x020B), }, { .channel = 206, .freq = 5030, /* MHz */ .unk2 = 3353, - RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF7, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02), + PHYREGS(0x07E0, 0x07DC, 0x07D8, 0x0208, 0x0209, 0x020A), }, { .channel = 208, .freq = 5040, /* MHz */ .unk2 = 3360, - RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF8, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902), + PHYREGS(0x07E4, 0x07E0, 0x07DC, 0x0207, 0x0208, 0x0209), }, { .channel = 210, .freq = 5050, /* MHz */ .unk2 = 3367, - RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xF9, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802), + PHYREGS(0x07E8, 0x07E4, 0x07E0, 0x0206, 0x0207, 0x0208), }, { .channel = 212, .freq = 5060, /* MHz */ .unk2 = 3373, - RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFA, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702), + PHYREGS(0x07EC, 0x07E8, 0x07E4, 0x0205, 0x0206, 0x0207), }, { .channel = 214, .freq = 5070, /* MHz */ .unk2 = 3380, - RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFB, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A, 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602), + PHYREGS(0x07F0, 0x07EC, 0x07E8, 0x0204, 0x0205, 0x0206), }, { .channel = 216, .freq = 5080, /* MHz */ .unk2 = 3387, - RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFC, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502), + PHYREGS(0x07F4, 0x07F0, 0x07EC, 0x0203, 0x0204, 0x0205), }, { .channel = 218, .freq = 5090, /* MHz */ .unk2 = 3393, - RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFD, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402), + PHYREGS(0x07F8, 0x07F4, 0x07F0, 0x0202, 0x0203, 0x0204), }, { .channel = 220, .freq = 5100, /* MHz */ .unk2 = 3400, - RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFE, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302), + PHYREGS(0x07FC, 0x07F8, 0x07F4, 0x0201, 0x0202, 0x0203), }, { .channel = 222, .freq = 5110, /* MHz */ .unk2 = 3407, - RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0xFF, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A, 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202), + PHYREGS(0x0800, 0x07FC, 0x07F8, 0x0200, 0x0201, 0x0202), }, { .channel = 224, .freq = 5120, /* MHz */ .unk2 = 3413, - RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x00, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102), + PHYREGS(0x0804, 0x0800, 0x07FC, 0x01FF, 0x0200, 0x0201), }, { .channel = 226, .freq = 5130, /* MHz */ .unk2 = 3420, - RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x01, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01FE, 0x01FF, 0x0200), }, { .channel = 228, .freq = 5140, /* MHz */ @@ -483,815 +483,815 @@ static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B), - PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01), + PHYREGS(0x080C, 0x0808, 0x0804, 0x01FD, 0x01FE, 0x01FF), }, { .channel = 32, .freq = 5160, /* MHz */ .unk2 = 3440, - RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x04, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01), + PHYREGS(0x0814, 0x0810, 0x080C, 0x01FB, 0x01FC, 0x01FD), }, { .channel = 34, .freq = 5170, /* MHz */ .unk2 = 3447, - RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x05, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01FA, 0x01FB, 0x01FC), }, { .channel = 36, .freq = 5180, /* MHz */ .unk2 = 3453, - RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x06, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01), + PHYREGS(0x081C, 0x0818, 0x0814, 0x01F9, 0x01FA, 0x01FB), }, { .channel = 38, .freq = 5190, /* MHz */ .unk2 = 3460, - RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x07, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A, 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01), + PHYREGS(0x0820, 0x081C, 0x0818, 0x01F8, 0x01F9, 0x01FA), }, { .channel = 40, .freq = 5200, /* MHz */ .unk2 = 3467, - RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x08, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901), + PHYREGS(0x0824, 0x0820, 0x081C, 0x01F7, 0x01F8, 0x01F9), }, { .channel = 42, .freq = 5210, /* MHz */ .unk2 = 3473, - RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x09, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01F6, 0x01F7, 0x01F8), }, { .channel = 44, .freq = 5220, /* MHz */ .unk2 = 3480, - RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0A, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701), + PHYREGS(0x082C, 0x0828, 0x0824, 0x01F5, 0x01F6, 0x01F7), }, { .channel = 46, .freq = 5230, /* MHz */ .unk2 = 3487, - RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0B, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A, 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601), + PHYREGS(0x0830, 0x082C, 0x0828, 0x01F4, 0x01F5, 0x01F6), }, { .channel = 48, .freq = 5240, /* MHz */ .unk2 = 3493, - RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0C, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501), + PHYREGS(0x0834, 0x0830, 0x082C, 0x01F3, 0x01F4, 0x01F5), }, { .channel = 50, .freq = 5250, /* MHz */ .unk2 = 3500, - RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0D, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01F2, 0x01F3, 0x01F4), }, { .channel = 52, .freq = 5260, /* MHz */ .unk2 = 3507, - RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0E, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301), + PHYREGS(0x083C, 0x0838, 0x0834, 0x01F1, 0x01F2, 0x01F3), }, { .channel = 54, .freq = 5270, /* MHz */ .unk2 = 3513, - RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x0F, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A, 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201), + PHYREGS(0x0840, 0x083C, 0x0838, 0x01F0, 0x01F1, 0x01F2), }, { .channel = 56, .freq = 5280, /* MHz */ .unk2 = 3520, - RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x10, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101), + PHYREGS(0x0844, 0x0840, 0x083C, 0x01F0, 0x01F0, 0x01F1), }, { .channel = 58, .freq = 5290, /* MHz */ .unk2 = 3527, - RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x11, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01EF, 0x01F0, 0x01F0), }, { .channel = 60, .freq = 5300, /* MHz */ .unk2 = 3533, - RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x12, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001), + PHYREGS(0x084C, 0x0848, 0x0844, 0x01EE, 0x01EF, 0x01F0), }, { .channel = 62, .freq = 5310, /* MHz */ .unk2 = 3540, - RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x13, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A, 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01), + PHYREGS(0x0850, 0x084C, 0x0848, 0x01ED, 0x01EE, 0x01EF), }, { .channel = 64, .freq = 5320, /* MHz */ .unk2 = 3547, - RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x14, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01), + PHYREGS(0x0854, 0x0850, 0x084C, 0x01EC, 0x01ED, 0x01EE), }, { .channel = 66, .freq = 5330, /* MHz */ .unk2 = 3553, - RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x15, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01EB, 0x01EC, 0x01ED), }, { .channel = 68, .freq = 5340, /* MHz */ .unk2 = 3560, - RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x16, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01), + PHYREGS(0x085C, 0x0858, 0x0854, 0x01EA, 0x01EB, 0x01EC), }, { .channel = 70, .freq = 5350, /* MHz */ .unk2 = 3567, - RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x17, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A, 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01), + PHYREGS(0x0860, 0x085C, 0x0858, 0x01E9, 0x01EA, 0x01EB), }, { .channel = 72, .freq = 5360, /* MHz */ .unk2 = 3573, - RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x18, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01), + PHYREGS(0x0864, 0x0860, 0x085C, 0x01E8, 0x01E9, 0x01EA), }, { .channel = 74, .freq = 5370, /* MHz */ .unk2 = 3580, - RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x19, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01E7, 0x01E8, 0x01E9), }, { .channel = 76, .freq = 5380, /* MHz */ .unk2 = 3587, - RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1A, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801), + PHYREGS(0x086C, 0x0868, 0x0864, 0x01E6, 0x01E7, 0x01E8), }, { .channel = 78, .freq = 5390, /* MHz */ .unk2 = 3593, - RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1B, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A, 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701), + PHYREGS(0x0870, 0x086C, 0x0868, 0x01E5, 0x01E6, 0x01E7), }, { .channel = 80, .freq = 5400, /* MHz */ .unk2 = 3600, - RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1C, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601), + PHYREGS(0x0874, 0x0870, 0x086C, 0x01E5, 0x01E5, 0x01E6), }, { .channel = 82, .freq = 5410, /* MHz */ .unk2 = 3607, - RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1D, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01E4, 0x01E5, 0x01E5), }, { .channel = 84, .freq = 5420, /* MHz */ .unk2 = 3613, - RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1E, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501), + PHYREGS(0x087C, 0x0878, 0x0874, 0x01E3, 0x01E4, 0x01E5), }, { .channel = 86, .freq = 5430, /* MHz */ .unk2 = 3620, - RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x1F, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A, 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401), + PHYREGS(0x0880, 0x087C, 0x0878, 0x01E2, 0x01E3, 0x01E4), }, { .channel = 88, .freq = 5440, /* MHz */ .unk2 = 3627, - RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x20, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301), + PHYREGS(0x0884, 0x0880, 0x087C, 0x01E1, 0x01E2, 0x01E3), }, { .channel = 90, .freq = 5450, /* MHz */ .unk2 = 3633, - RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x21, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01E0, 0x01E1, 0x01E2), }, { .channel = 92, .freq = 5460, /* MHz */ .unk2 = 3640, - RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x22, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101), + PHYREGS(0x088C, 0x0888, 0x0884, 0x01DF, 0x01E0, 0x01E1), }, { .channel = 94, .freq = 5470, /* MHz */ .unk2 = 3647, - RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x23, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A, 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001), + PHYREGS(0x0890, 0x088C, 0x0888, 0x01DE, 0x01DF, 0x01E0), }, { .channel = 96, .freq = 5480, /* MHz */ .unk2 = 3653, - RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x24, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01), + PHYREGS(0x0894, 0x0890, 0x088C, 0x01DD, 0x01DE, 0x01DF), }, { .channel = 98, .freq = 5490, /* MHz */ .unk2 = 3660, - RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x25, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01DD, 0x01DD, 0x01DE), }, { .channel = 100, .freq = 5500, /* MHz */ .unk2 = 3667, - RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x26, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01), + PHYREGS(0x089C, 0x0898, 0x0894, 0x01DC, 0x01DD, 0x01DD), }, { .channel = 102, .freq = 5510, /* MHz */ .unk2 = 3673, - RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x27, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A, 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01), + PHYREGS(0x08A0, 0x089C, 0x0898, 0x01DB, 0x01DC, 0x01DD), }, { .channel = 104, .freq = 5520, /* MHz */ .unk2 = 3680, - RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x28, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01), + PHYREGS(0x08A4, 0x08A0, 0x089C, 0x01DA, 0x01DB, 0x01DC), }, { .channel = 106, .freq = 5530, /* MHz */ .unk2 = 3687, - RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x29, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01), + PHYREGS(0x08A8, 0x08A4, 0x08A0, 0x01D9, 0x01DA, 0x01DB), }, { .channel = 108, .freq = 5540, /* MHz */ .unk2 = 3693, - RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2A, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01), + PHYREGS(0x08AC, 0x08A8, 0x08A4, 0x01D8, 0x01D9, 0x01DA), }, { .channel = 110, .freq = 5550, /* MHz */ .unk2 = 3700, - RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2B, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A, 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901), + PHYREGS(0x08B0, 0x08AC, 0x08A8, 0x01D7, 0x01D8, 0x01D9), }, { .channel = 112, .freq = 5560, /* MHz */ .unk2 = 3707, - RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2C, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801), + PHYREGS(0x08B4, 0x08B0, 0x08AC, 0x01D7, 0x01D7, 0x01D8), }, { .channel = 114, .freq = 5570, /* MHz */ .unk2 = 3713, - RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2D, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701), + PHYREGS(0x08B8, 0x08B4, 0x08B0, 0x01D6, 0x01D7, 0x01D7), }, { .channel = 116, .freq = 5580, /* MHz */ .unk2 = 3720, - RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2E, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701), + PHYREGS(0x08BC, 0x08B8, 0x08B4, 0x01D5, 0x01D6, 0x01D7), }, { .channel = 118, .freq = 5590, /* MHz */ .unk2 = 3727, - RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x2F, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A, 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601), + PHYREGS(0x08C0, 0x08BC, 0x08B8, 0x01D4, 0x01D5, 0x01D6), }, { .channel = 120, .freq = 5600, /* MHz */ .unk2 = 3733, - RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x30, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501), + PHYREGS(0x08C4, 0x08C0, 0x08BC, 0x01D3, 0x01D4, 0x01D5), }, { .channel = 122, .freq = 5610, /* MHz */ .unk2 = 3740, - RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x31, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401), + PHYREGS(0x08C8, 0x08C4, 0x08C0, 0x01D2, 0x01D3, 0x01D4), }, { .channel = 124, .freq = 5620, /* MHz */ .unk2 = 3747, - RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x32, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301), + PHYREGS(0x08CC, 0x08C8, 0x08C4, 0x01D2, 0x01D2, 0x01D3), }, { .channel = 126, .freq = 5630, /* MHz */ .unk2 = 3753, - RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x33, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A, 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201), + PHYREGS(0x08D0, 0x08CC, 0x08C8, 0x01D1, 0x01D2, 0x01D2), }, { .channel = 128, .freq = 5640, /* MHz */ .unk2 = 3760, - RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x34, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201), + PHYREGS(0x08D4, 0x08D0, 0x08CC, 0x01D0, 0x01D1, 0x01D2), }, { .channel = 130, .freq = 5650, /* MHz */ .unk2 = 3767, - RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x35, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101), + PHYREGS(0x08D8, 0x08D4, 0x08D0, 0x01CF, 0x01D0, 0x01D1), }, { .channel = 132, .freq = 5660, /* MHz */ .unk2 = 3773, - RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x36, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001), + PHYREGS(0x08DC, 0x08D8, 0x08D4, 0x01CE, 0x01CF, 0x01D0), }, { .channel = 134, .freq = 5670, /* MHz */ .unk2 = 3780, - RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x37, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01), + PHYREGS(0x08E0, 0x08DC, 0x08D8, 0x01CE, 0x01CE, 0x01CF), }, { .channel = 136, .freq = 5680, /* MHz */ .unk2 = 3787, - RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x38, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01), + PHYREGS(0x08E4, 0x08E0, 0x08DC, 0x01CD, 0x01CE, 0x01CE), }, { .channel = 138, .freq = 5690, /* MHz */ .unk2 = 3793, - RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x39, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01), + PHYREGS(0x08E8, 0x08E4, 0x08E0, 0x01CC, 0x01CD, 0x01CE), }, { .channel = 140, .freq = 5700, /* MHz */ .unk2 = 3800, - RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3A, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01), + PHYREGS(0x08EC, 0x08E8, 0x08E4, 0x01CB, 0x01CC, 0x01CD), }, { .channel = 142, .freq = 5710, /* MHz */ .unk2 = 3807, - RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3B, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01), + PHYREGS(0x08F0, 0x08EC, 0x08E8, 0x01CA, 0x01CB, 0x01CC), }, { .channel = 144, .freq = 5720, /* MHz */ .unk2 = 3813, - RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3C, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01), + PHYREGS(0x08F4, 0x08F0, 0x08EC, 0x01C9, 0x01CA, 0x01CB), }, { .channel = 145, .freq = 5725, /* MHz */ .unk2 = 3817, - RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, + RADIOREGS(0x72, 0x79, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01), + PHYREGS(0x08F6, 0x08F2, 0x08EE, 0x01C9, 0x01CA, 0x01CB), }, { .channel = 146, .freq = 5730, /* MHz */ .unk2 = 3820, - RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3D, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01), + PHYREGS(0x08F8, 0x08F4, 0x08F0, 0x01C9, 0x01C9, 0x01CA), }, { .channel = 147, .freq = 5735, /* MHz */ .unk2 = 3823, - RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, + RADIOREGS(0x72, 0x7B, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01), + PHYREGS(0x08FA, 0x08F6, 0x08F2, 0x01C8, 0x01C9, 0x01CA), }, { .channel = 148, .freq = 5740, /* MHz */ .unk2 = 3827, - RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3E, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901), + PHYREGS(0x08FC, 0x08F8, 0x08F4, 0x01C8, 0x01C9, 0x01C9), }, { .channel = 149, .freq = 5745, /* MHz */ .unk2 = 3830, - RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x7D, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901), + PHYREGS(0x08FE, 0x08FA, 0x08F6, 0x01C8, 0x01C8, 0x01C9), }, { .channel = 150, .freq = 5750, /* MHz */ .unk2 = 3833, - RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x3F, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901), + PHYREGS(0x0900, 0x08FC, 0x08F8, 0x01C7, 0x01C8, 0x01C9), }, { .channel = 151, .freq = 5755, /* MHz */ .unk2 = 3837, - RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x7F, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801), + PHYREGS(0x0902, 0x08FE, 0x08FA, 0x01C7, 0x01C8, 0x01C8), }, { .channel = 152, .freq = 5760, /* MHz */ .unk2 = 3840, - RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x40, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801), + PHYREGS(0x0904, 0x0900, 0x08FC, 0x01C6, 0x01C7, 0x01C8), }, { .channel = 153, .freq = 5765, /* MHz */ .unk2 = 3843, - RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x81, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801), + PHYREGS(0x0906, 0x0902, 0x08FE, 0x01C6, 0x01C7, 0x01C8), }, { .channel = 154, .freq = 5770, /* MHz */ .unk2 = 3847, - RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x41, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01C6, 0x01C6, 0x01C7), }, { .channel = 155, .freq = 5775, /* MHz */ .unk2 = 3850, - RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x83, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701), + PHYREGS(0x090A, 0x0906, 0x0902, 0x01C5, 0x01C6, 0x01C7), }, { .channel = 156, .freq = 5780, /* MHz */ .unk2 = 3853, - RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x42, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601), + PHYREGS(0x090C, 0x0908, 0x0904, 0x01C5, 0x01C6, 0x01C6), }, { .channel = 157, .freq = 5785, /* MHz */ .unk2 = 3857, - RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x85, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601), + PHYREGS(0x090E, 0x090A, 0x0906, 0x01C4, 0x01C5, 0x01C6), }, { .channel = 158, .freq = 5790, /* MHz */ .unk2 = 3860, - RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x43, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601), + PHYREGS(0x0910, 0x090C, 0x0908, 0x01C4, 0x01C5, 0x01C6), }, { .channel = 159, .freq = 5795, /* MHz */ .unk2 = 3863, - RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x87, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501), + PHYREGS(0x0912, 0x090E, 0x090A, 0x01C4, 0x01C4, 0x01C5), }, { .channel = 160, .freq = 5800, /* MHz */ .unk2 = 3867, - RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x44, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501), + PHYREGS(0x0914, 0x0910, 0x090C, 0x01C3, 0x01C4, 0x01C5), }, { .channel = 161, .freq = 5805, /* MHz */ .unk2 = 3870, - RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x89, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401), + PHYREGS(0x0916, 0x0912, 0x090E, 0x01C3, 0x01C4, 0x01C4), }, { .channel = 162, .freq = 5810, /* MHz */ .unk2 = 3873, - RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x45, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01C2, 0x01C3, 0x01C4), }, { .channel = 163, .freq = 5815, /* MHz */ .unk2 = 3877, - RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x8B, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401), + PHYREGS(0x091A, 0x0916, 0x0912, 0x01C2, 0x01C3, 0x01C4), }, { .channel = 164, .freq = 5820, /* MHz */ .unk2 = 3880, - RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x46, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301), + PHYREGS(0x091C, 0x0918, 0x0914, 0x01C2, 0x01C2, 0x01C3), }, { .channel = 165, .freq = 5825, /* MHz */ .unk2 = 3883, - RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, + RADIOREGS(0x72, 0x8D, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301), + PHYREGS(0x091E, 0x091A, 0x0916, 0x01C1, 0x01C2, 0x01C3), }, { .channel = 166, .freq = 5830, /* MHz */ .unk2 = 3887, - RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x47, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201), + PHYREGS(0x0920, 0x091C, 0x0918, 0x01C1, 0x01C2, 0x01C2), }, { .channel = 168, .freq = 5840, /* MHz */ .unk2 = 3893, - RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, + RADIOREGS(0x71, 0x48, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201), + PHYREGS(0x0924, 0x0920, 0x091C, 0x01C0, 0x01C1, 0x01C2), }, { .channel = 170, .freq = 5850, /* MHz */ .unk2 = 3900, - RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x49, 0x02, 0x01, 0xE0, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01BF, 0x01C0, 0x01C1), }, { .channel = 172, .freq = 5860, /* MHz */ .unk2 = 3907, - RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4A, 0x02, 0x01, 0xDE, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001), + PHYREGS(0x092C, 0x0928, 0x0924, 0x01BF, 0x01BF, 0x01C0), }, { .channel = 174, .freq = 5870, /* MHz */ .unk2 = 3913, - RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4B, 0x02, 0x00, 0xDB, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01), + PHYREGS(0x0930, 0x092C, 0x0928, 0x01BE, 0x01BF, 0x01BF), }, { .channel = 176, .freq = 5880, /* MHz */ .unk2 = 3920, - RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4C, 0x02, 0x00, 0xD8, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01), + PHYREGS(0x0934, 0x0930, 0x092C, 0x01BD, 0x01BE, 0x01BF), }, { .channel = 178, .freq = 5890, /* MHz */ .unk2 = 3927, - RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4D, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01BC, 0x01BD, 0x01BE), }, { .channel = 180, .freq = 5900, /* MHz */ .unk2 = 3933, - RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4E, 0x02, 0x00, 0xD3, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01), + PHYREGS(0x093C, 0x0938, 0x0934, 0x01BC, 0x01BC, 0x01BD), }, { .channel = 182, .freq = 5910, /* MHz */ .unk2 = 3940, - RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, + RADIOREGS(0x71, 0x4F, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01), + PHYREGS(0x0940, 0x093C, 0x0938, 0x01BB, 0x01BC, 0x01BC), }, { .channel = 1, .freq = 2412, /* MHz */ .unk2 = 3216, - RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x6C, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80), - PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304), + PHYREGS(0x03C9, 0x03C5, 0x03C1, 0x043A, 0x043F, 0x0443), }, { .channel = 2, .freq = 2417, /* MHz */ .unk2 = 3223, - RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x71, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80), - PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104), + PHYREGS(0x03CB, 0x03C7, 0x03C3, 0x0438, 0x043D, 0x0441), }, { .channel = 3, .freq = 2422, /* MHz */ .unk2 = 3229, - RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x76, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04), + PHYREGS(0x03CD, 0x03C9, 0x03C5, 0x0436, 0x043A, 0x043F), }, { .channel = 4, .freq = 2427, /* MHz */ .unk2 = 3236, - RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x7B, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04), + PHYREGS(0x03CF, 0x03CB, 0x03C7, 0x0434, 0x0438, 0x043D), }, { .channel = 5, .freq = 2432, /* MHz */ .unk2 = 3243, - RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x80, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80), - PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04), + PHYREGS(0x03D1, 0x03CD, 0x03C9, 0x0431, 0x0436, 0x043A), }, { .channel = 6, .freq = 2437, /* MHz */ .unk2 = 3249, - RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x85, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80), - PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804), + PHYREGS(0x03D3, 0x03CF, 0x03CB, 0x042F, 0x0434, 0x0438), }, { .channel = 7, .freq = 2442, /* MHz */ .unk2 = 3256, - RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x8A, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80), - PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604), + PHYREGS(0x03D5, 0x03D1, 0x03CD, 0x042D, 0x0431, 0x0436), }, { .channel = 8, .freq = 2447, /* MHz */ .unk2 = 3263, - RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x8F, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80), - PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404), + PHYREGS(0x03D7, 0x03D3, 0x03CF, 0x042B, 0x042F, 0x0434), }, { .channel = 9, .freq = 2452, /* MHz */ .unk2 = 3269, - RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x94, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80), - PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104), + PHYREGS(0x03D9, 0x03D5, 0x03D1, 0x0429, 0x042D, 0x0431), }, { .channel = 10, .freq = 2457, /* MHz */ .unk2 = 3276, - RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x99, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80), - PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04), + PHYREGS(0x03DB, 0x03D7, 0x03D3, 0x0427, 0x042B, 0x042F), }, { .channel = 11, .freq = 2462, /* MHz */ .unk2 = 3283, - RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0x9E, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80), - PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04), + PHYREGS(0x03DD, 0x03D9, 0x03D5, 0x0424, 0x0429, 0x042D), }, { .channel = 12, .freq = 2467, /* MHz */ .unk2 = 3289, - RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xA3, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80), - PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04), + PHYREGS(0x03DF, 0x03DB, 0x03D7, 0x0422, 0x0427, 0x042B), }, { .channel = 13, .freq = 2472, /* MHz */ .unk2 = 3296, - RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xA8, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80), - PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904), + PHYREGS(0x03E1, 0x03DD, 0x03D9, 0x0420, 0x0424, 0x0429), }, { .channel = 14, .freq = 2484, /* MHz */ .unk2 = 3312, - RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, + RADIOREGS(0x73, 0xB4, 0x09, 0x0F, 0xFF, 0x01, 0x07, 0x15, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80), - PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404), + PHYREGS(0x03E6, 0x03E2, 0x03DE, 0x041B, 0x041F, 0x0424), }, }; @@ -1299,7 +1299,7 @@ void b2055_upload_inittab(struct b43_wldev *dev, bool ghz5, bool ignore_uploadflag) { const struct b2055_inittab_entry *e; - unsigned int i; + unsigned int i, writes = 0; u16 value; for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) { @@ -1312,6 +1312,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, else value = e->ghz2; b43_radio_write16(dev, i, value); + if (++writes % 4 == 0) + b43_read32(dev, B43_MMIO_MACCTL); /* flush */ } } } diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index d8563192ce56..0cdf6a46ba4b 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c @@ -24,9 +24,6028 @@ #include "radio_2056.h" #include "phy_common.h" +#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ + r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ + r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \ + r30, r31, r32, r33, r34, r35, r36) \ + .radio_syn_pll_vcocal1 = r00, \ + .radio_syn_pll_vcocal2 = r01, \ + .radio_syn_pll_refdiv = r02, \ + .radio_syn_pll_mmd2 = r03, \ + .radio_syn_pll_mmd1 = r04, \ + .radio_syn_pll_loopfilter1 = r05, \ + .radio_syn_pll_loopfilter2 = r06, \ + .radio_syn_pll_loopfilter3 = r07, \ + .radio_syn_pll_loopfilter4 = r08, \ + .radio_syn_pll_loopfilter5 = r09, \ + .radio_syn_reserved_addr27 = r10, \ + .radio_syn_reserved_addr28 = r11, \ + .radio_syn_reserved_addr29 = r12, \ + .radio_syn_logen_vcobuf1 = r13, \ + .radio_syn_logen_mixer2 = r14, \ + .radio_syn_logen_buf3 = r15, \ + .radio_syn_logen_buf4 = r16, \ + .radio_rx0_lnaa_tune = r17, \ + .radio_rx0_lnag_tune = r18, \ + .radio_tx0_intpaa_boost_tune = r19, \ + .radio_tx0_intpag_boost_tune = r20, \ + .radio_tx0_pada_boost_tune = r21, \ + .radio_tx0_padg_boost_tune = r22, \ + .radio_tx0_pgaa_boost_tune = r23, \ + .radio_tx0_pgag_boost_tune = r24, \ + .radio_tx0_mixa_boost_tune = r25, \ + .radio_tx0_mixg_boost_tune = r26, \ + .radio_rx1_lnaa_tune = r27, \ + .radio_rx1_lnag_tune = r28, \ + .radio_tx1_intpaa_boost_tune = r29, \ + .radio_tx1_intpag_boost_tune = r30, \ + .radio_tx1_pada_boost_tune = r31, \ + .radio_tx1_padg_boost_tune = r32, \ + .radio_tx1_pgaa_boost_tune = r33, \ + .radio_tx1_pgag_boost_tune = r34, \ + .radio_tx1_mixa_boost_tune = r35, \ + .radio_tx1_mixg_boost_tune = r36 + +#define PHYREGS(r0, r1, r2, r3, r4, r5) \ + .phy_regs.phy_bw1a = r0, \ + .phy_regs.phy_bw2 = r1, \ + .phy_regs.phy_bw3 = r2, \ + .phy_regs.phy_bw4 = r3, \ + .phy_regs.phy_bw5 = r4, \ + .phy_regs.phy_bw6 = r5 + +/* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/ChannelTable */ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xff, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xfc, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xfc, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfc, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xfa, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xfa, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x08, 0x00, 0xf8, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf8, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf6, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf6, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf4, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x06, 0x00, 0xf2, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, + 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x05, 0x00, 0xf2, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, + 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x05, 0x00, 0xf2, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0f), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0d), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev4[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xff, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfe, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfc, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xfa, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, + 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, + 0x00, 0x0f, 0x00, 0xf8, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, + 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, + 0x00, 0x0d, 0x00, 0xf6, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, + 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, + 0x00, 0x0b, 0x00, 0xf4, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, + 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, + 0x00, 0x0a, 0x00, 0xf2, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, + 0x00, 0x09, 0x00, 0xf0, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf0, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, + 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x07, 0x00, 0xf0, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0e), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev5[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6e, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5b, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, + 0xff, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x5a, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x5a, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x5a, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x59, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, + 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x78, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, + 0x84, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x75, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x75, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x75, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, + 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x74, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x83, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x82, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x72, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x71, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0b), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev6[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6d, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev7_9[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, + 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, + 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, + 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x09, 0x00, 0x6e, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6e, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, + 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, + 0x00, 0x08, 0x00, 0x6d, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6c, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, + 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x07, 0x00, 0x6b, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x6b, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7b, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x06, 0x00, 0x7a, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x7a, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x7a, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x05, 0x00, 0x79, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x79, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x79, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, + 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x04, 0x00, 0x78, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x78, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, + 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x03, 0x00, 0x77, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x76, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x86, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, + 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x02, 0x00, 0x85, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x85, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x85, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x84, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, + 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x94, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x93, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x92, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x91, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0b), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0f, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0e, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0d, 0x00, 0x08), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, +}; + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] = { + { .freq = 4920, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), + }, + { .freq = 4930, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), + }, + { .freq = 4940, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), + }, + { .freq = 4950, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), + }, + { .freq = 4960, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), + }, + { .freq = 4970, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), + }, + { .freq = 4980, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), + }, + { .freq = 4990, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), + }, + { .freq = 5000, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), + }, + { .freq = 5010, + RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), + }, + { .freq = 5020, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), + }, + { .freq = 5030, + RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), + }, + { .freq = 5040, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), + }, + { .freq = 5050, + RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), + }, + { .freq = 5060, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), + }, + { .freq = 5070, + RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), + }, + { .freq = 5080, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), + }, + { .freq = 5090, + RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), + }, + { .freq = 5100, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), + }, + { .freq = 5110, + RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), + }, + { .freq = 5120, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), + }, + { .freq = 5130, + RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), + }, + { .freq = 5140, + RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, + 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, + 0x00, 0x0f, 0x00, 0x6f, 0x00), + PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), + }, + { .freq = 5160, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), + }, + { .freq = 5170, + RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), + }, + { .freq = 5180, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0e, 0x00, 0x6f, 0x00), + PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), + }, + { .freq = 5190, + RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), + }, + { .freq = 5200, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), + }, + { .freq = 5210, + RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, + 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), + }, + { .freq = 5220, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), + }, + { .freq = 5230, + RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), + }, + { .freq = 5240, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), + }, + { .freq = 5250, + RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, + 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), + }, + { .freq = 5260, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0d, 0x00, 0x6f, 0x00), + PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), + }, + { .freq = 5270, + RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, + 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), + }, + { .freq = 5280, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), + }, + { .freq = 5290, + RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), + }, + { .freq = 5300, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), + }, + { .freq = 5310, + RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), + }, + { .freq = 5320, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, + 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, + 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0c, 0x00, 0x6f, 0x00), + PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), + }, + { .freq = 5330, + RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), + }, + { .freq = 5340, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), + }, + { .freq = 5350, + RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, + 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0b, 0x00, 0x6f, 0x00), + PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), + }, + { .freq = 5360, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), + }, + { .freq = 5370, + RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, + 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), + }, + { .freq = 5380, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), + }, + { .freq = 5390, + RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), + }, + { .freq = 5400, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), + }, + { .freq = 5410, + RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), + }, + { .freq = 5420, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, + 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), + }, + { .freq = 5430, + RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x0a, 0x00, 0x6f, 0x00), + PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), + }, + { .freq = 5440, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), + }, + { .freq = 5450, + RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), + }, + { .freq = 5460, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), + }, + { .freq = 5470, + RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, + 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), + }, + { .freq = 5480, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), + }, + { .freq = 5490, + RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), + }, + { .freq = 5500, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), + }, + { .freq = 5510, + RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), + }, + { .freq = 5520, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), + }, + { .freq = 5530, + RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), + }, + { .freq = 5540, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, + 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), + }, + { .freq = 5550, + RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), + }, + { .freq = 5560, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), + }, + { .freq = 5570, + RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, + 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x09, 0x00, 0x6f, 0x00), + PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), + }, + { .freq = 5580, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), + }, + { .freq = 5590, + RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, + 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), + }, + { .freq = 5600, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), + }, + { .freq = 5610, + RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, + 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x08, 0x00, 0x6f, 0x00), + PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), + }, + { .freq = 5620, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), + }, + { .freq = 5630, + RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), + }, + { .freq = 5640, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), + }, + { .freq = 5650, + RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x07, 0x00, 0x6f, 0x00), + PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), + }, + { .freq = 5660, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), + }, + { .freq = 5670, + RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, + 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), + }, + { .freq = 5680, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), + }, + { .freq = 5690, + RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6f, 0x00), + PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), + }, + { .freq = 5700, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), + }, + { .freq = 5710, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), + }, + { .freq = 5720, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5725, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), + }, + { .freq = 5730, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6e, 0x00), + PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), + }, + { .freq = 5735, + RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), + }, + { .freq = 5740, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), + }, + { .freq = 5745, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, + 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x06, 0x00, 0x6d, 0x00), + PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), + }, + { .freq = 5750, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6d, 0x00), + PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), + }, + { .freq = 5755, + RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), + }, + { .freq = 5760, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5765, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6c, 0x00), + PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), + }, + { .freq = 5770, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), + }, + { .freq = 5775, + RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), + }, + { .freq = 5780, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), + }, + { .freq = 5785, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5790, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), + }, + { .freq = 5795, + RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), + }, + { .freq = 5800, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6b, 0x00), + PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), + }, + { .freq = 5805, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), + }, + { .freq = 5810, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5815, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), + }, + { .freq = 5820, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x6a, 0x00), + PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), + }, + { .freq = 5825, + RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, + 0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), + }, + { .freq = 5830, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x05, 0x00, 0x69, 0x00), + PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), + }, + { .freq = 5840, + RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), + }, + { .freq = 5850, + RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), + }, + { .freq = 5860, + RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x69, 0x00), + PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), + }, + { .freq = 5870, + RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), + }, + { .freq = 5880, + RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), + }, + { .freq = 5890, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), + }, + { .freq = 5900, + RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), + }, + { .freq = 5910, + RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, + 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x04, 0x00, 0x68, 0x00), + PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), + }, + { .freq = 2412, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), + }, + { .freq = 2417, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), + }, + { .freq = 2422, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0b, 0x00, 0x0a), + PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), + }, + { .freq = 2427, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), + }, + { .freq = 2432, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), + }, + { .freq = 2437, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), + }, + { .freq = 2442, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x0a), + PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), + }, + { .freq = 2447, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), + }, + { .freq = 2452, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), + }, + { .freq = 2457, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x0a, 0x00, 0x09), + PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), + }, + { .freq = 2462, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), + }, + { .freq = 2467, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), + }, + { .freq = 2472, + RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), + }, + { .freq = 2484, + RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, + 0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x70, 0x00, 0x09, 0x00, 0x09), + PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424), + }, }; +/* TODO: add support for rev4+ devices by searching in rev4+ tables */ const struct b43_nphy_channeltab_entry_rev3 * b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) { diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h index fda6dafecb8c..302600c0afa4 100644 --- a/drivers/net/wireless/b43/radio_2056.h +++ b/drivers/net/wireless/b43/radio_2056.h @@ -4,6 +4,9 @@ Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com> + Some parts of the code in this file are derived from the brcm80211 + driver Copyright (c) 2010 Broadcom Corporation + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -28,13 +31,1085 @@ #include "tables_nphy.h" +#define B2056_SYN (0x0 << 12) +#define B2056_TX0 (0x2 << 12) +#define B2056_TX1 (0x3 << 12) +#define B2056_RX0 (0x6 << 12) +#define B2056_RX1 (0x7 << 12) +#define B2056_ALLTX (0xE << 12) +#define B2056_ALLRX (0xF << 12) + +#define B2056_SYN_RESERVED_ADDR0 0x00 +#define B2056_SYN_IDCODE 0x01 +#define B2056_SYN_RESERVED_ADDR2 0x02 +#define B2056_SYN_RESERVED_ADDR3 0x03 +#define B2056_SYN_RESERVED_ADDR4 0x04 +#define B2056_SYN_RESERVED_ADDR5 0x05 +#define B2056_SYN_RESERVED_ADDR6 0x06 +#define B2056_SYN_RESERVED_ADDR7 0x07 +#define B2056_SYN_COM_CTRL 0x08 +#define B2056_SYN_COM_PU 0x09 +#define B2056_SYN_COM_OVR 0x0A +#define B2056_SYN_COM_RESET 0x0B +#define B2056_SYN_COM_RCAL 0x0C +#define B2056_SYN_COM_RC_RXLPF 0x0D +#define B2056_SYN_COM_RC_TXLPF 0x0E +#define B2056_SYN_COM_RC_RXHPF 0x0F +#define B2056_SYN_RESERVED_ADDR16 0x10 +#define B2056_SYN_RESERVED_ADDR17 0x11 +#define B2056_SYN_RESERVED_ADDR18 0x12 +#define B2056_SYN_RESERVED_ADDR19 0x13 +#define B2056_SYN_RESERVED_ADDR20 0x14 +#define B2056_SYN_RESERVED_ADDR21 0x15 +#define B2056_SYN_RESERVED_ADDR22 0x16 +#define B2056_SYN_RESERVED_ADDR23 0x17 +#define B2056_SYN_RESERVED_ADDR24 0x18 +#define B2056_SYN_RESERVED_ADDR25 0x19 +#define B2056_SYN_RESERVED_ADDR26 0x1A +#define B2056_SYN_RESERVED_ADDR27 0x1B +#define B2056_SYN_RESERVED_ADDR28 0x1C +#define B2056_SYN_RESERVED_ADDR29 0x1D +#define B2056_SYN_RESERVED_ADDR30 0x1E +#define B2056_SYN_RESERVED_ADDR31 0x1F +#define B2056_SYN_GPIO_MASTER1 0x20 +#define B2056_SYN_GPIO_MASTER2 0x21 +#define B2056_SYN_TOPBIAS_MASTER 0x22 +#define B2056_SYN_TOPBIAS_RCAL 0x23 +#define B2056_SYN_AFEREG 0x24 +#define B2056_SYN_TEMPPROCSENSE 0x25 +#define B2056_SYN_TEMPPROCSENSEIDAC 0x26 +#define B2056_SYN_TEMPPROCSENSERCAL 0x27 +#define B2056_SYN_LPO 0x28 +#define B2056_SYN_VDDCAL_MASTER 0x29 +#define B2056_SYN_VDDCAL_IDAC 0x2A +#define B2056_SYN_VDDCAL_STATUS 0x2B +#define B2056_SYN_RCAL_MASTER 0x2C +#define B2056_SYN_RCAL_CODE_OUT 0x2D +#define B2056_SYN_RCCAL_CTRL0 0x2E +#define B2056_SYN_RCCAL_CTRL1 0x2F +#define B2056_SYN_RCCAL_CTRL2 0x30 +#define B2056_SYN_RCCAL_CTRL3 0x31 +#define B2056_SYN_RCCAL_CTRL4 0x32 +#define B2056_SYN_RCCAL_CTRL5 0x33 +#define B2056_SYN_RCCAL_CTRL6 0x34 +#define B2056_SYN_RCCAL_CTRL7 0x35 +#define B2056_SYN_RCCAL_CTRL8 0x36 +#define B2056_SYN_RCCAL_CTRL9 0x37 +#define B2056_SYN_RCCAL_CTRL10 0x38 +#define B2056_SYN_RCCAL_CTRL11 0x39 +#define B2056_SYN_ZCAL_SPARE1 0x3A +#define B2056_SYN_ZCAL_SPARE2 0x3B +#define B2056_SYN_PLL_MAST1 0x3C +#define B2056_SYN_PLL_MAST2 0x3D +#define B2056_SYN_PLL_MAST3 0x3E +#define B2056_SYN_PLL_BIAS_RESET 0x3F +#define B2056_SYN_PLL_XTAL0 0x40 +#define B2056_SYN_PLL_XTAL1 0x41 +#define B2056_SYN_PLL_XTAL3 0x42 +#define B2056_SYN_PLL_XTAL4 0x43 +#define B2056_SYN_PLL_XTAL5 0x44 +#define B2056_SYN_PLL_XTAL6 0x45 +#define B2056_SYN_PLL_REFDIV 0x46 +#define B2056_SYN_PLL_PFD 0x47 +#define B2056_SYN_PLL_CP1 0x48 +#define B2056_SYN_PLL_CP2 0x49 +#define B2056_SYN_PLL_CP3 0x4A +#define B2056_SYN_PLL_LOOPFILTER1 0x4B +#define B2056_SYN_PLL_LOOPFILTER2 0x4C +#define B2056_SYN_PLL_LOOPFILTER3 0x4D +#define B2056_SYN_PLL_LOOPFILTER4 0x4E +#define B2056_SYN_PLL_LOOPFILTER5 0x4F +#define B2056_SYN_PLL_MMD1 0x50 +#define B2056_SYN_PLL_MMD2 0x51 +#define B2056_SYN_PLL_VCO1 0x52 +#define B2056_SYN_PLL_VCO2 0x53 +#define B2056_SYN_PLL_MONITOR1 0x54 +#define B2056_SYN_PLL_MONITOR2 0x55 +#define B2056_SYN_PLL_VCOCAL1 0x56 +#define B2056_SYN_PLL_VCOCAL2 0x57 +#define B2056_SYN_PLL_VCOCAL4 0x58 +#define B2056_SYN_PLL_VCOCAL5 0x59 +#define B2056_SYN_PLL_VCOCAL6 0x5A +#define B2056_SYN_PLL_VCOCAL7 0x5B +#define B2056_SYN_PLL_VCOCAL8 0x5C +#define B2056_SYN_PLL_VCOCAL9 0x5D +#define B2056_SYN_PLL_VCOCAL10 0x5E +#define B2056_SYN_PLL_VCOCAL11 0x5F +#define B2056_SYN_PLL_VCOCAL12 0x60 +#define B2056_SYN_PLL_VCOCAL13 0x61 +#define B2056_SYN_PLL_VREG 0x62 +#define B2056_SYN_PLL_STATUS1 0x63 +#define B2056_SYN_PLL_STATUS2 0x64 +#define B2056_SYN_PLL_STATUS3 0x65 +#define B2056_SYN_LOGEN_PU0 0x66 +#define B2056_SYN_LOGEN_PU1 0x67 +#define B2056_SYN_LOGEN_PU2 0x68 +#define B2056_SYN_LOGEN_PU3 0x69 +#define B2056_SYN_LOGEN_PU5 0x6A +#define B2056_SYN_LOGEN_PU6 0x6B +#define B2056_SYN_LOGEN_PU7 0x6C +#define B2056_SYN_LOGEN_PU8 0x6D +#define B2056_SYN_LOGEN_BIAS_RESET 0x6E +#define B2056_SYN_LOGEN_RCCR1 0x6F +#define B2056_SYN_LOGEN_VCOBUF1 0x70 +#define B2056_SYN_LOGEN_MIXER1 0x71 +#define B2056_SYN_LOGEN_MIXER2 0x72 +#define B2056_SYN_LOGEN_BUF1 0x73 +#define B2056_SYN_LOGENBUF2 0x74 +#define B2056_SYN_LOGEN_BUF3 0x75 +#define B2056_SYN_LOGEN_BUF4 0x76 +#define B2056_SYN_LOGEN_DIV1 0x77 +#define B2056_SYN_LOGEN_DIV2 0x78 +#define B2056_SYN_LOGEN_DIV3 0x79 +#define B2056_SYN_LOGEN_ACL1 0x7A +#define B2056_SYN_LOGEN_ACL2 0x7B +#define B2056_SYN_LOGEN_ACL3 0x7C +#define B2056_SYN_LOGEN_ACL4 0x7D +#define B2056_SYN_LOGEN_ACL5 0x7E +#define B2056_SYN_LOGEN_ACL6 0x7F +#define B2056_SYN_LOGEN_ACLOUT 0x80 +#define B2056_SYN_LOGEN_ACLCAL1 0x81 +#define B2056_SYN_LOGEN_ACLCAL2 0x82 +#define B2056_SYN_LOGEN_ACLCAL3 0x83 +#define B2056_SYN_CALEN 0x84 +#define B2056_SYN_LOGEN_PEAKDET1 0x85 +#define B2056_SYN_LOGEN_CORE_ACL_OVR 0x86 +#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 +#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 +#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 +#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8A +#define B2056_SYN_LOGEN_VCOBUF2 0x8B +#define B2056_SYN_LOGEN_MIXER3 0x8C +#define B2056_SYN_LOGEN_BUF5 0x8D +#define B2056_SYN_LOGEN_BUF6 0x8E +#define B2056_SYN_LOGEN_CBUFRX1 0x8F +#define B2056_SYN_LOGEN_CBUFRX2 0x90 +#define B2056_SYN_LOGEN_CBUFRX3 0x91 +#define B2056_SYN_LOGEN_CBUFRX4 0x92 +#define B2056_SYN_LOGEN_CBUFTX1 0x93 +#define B2056_SYN_LOGEN_CBUFTX2 0x94 +#define B2056_SYN_LOGEN_CBUFTX3 0x95 +#define B2056_SYN_LOGEN_CBUFTX4 0x96 +#define B2056_SYN_LOGEN_CMOSRX1 0x97 +#define B2056_SYN_LOGEN_CMOSRX2 0x98 +#define B2056_SYN_LOGEN_CMOSRX3 0x99 +#define B2056_SYN_LOGEN_CMOSRX4 0x9A +#define B2056_SYN_LOGEN_CMOSTX1 0x9B +#define B2056_SYN_LOGEN_CMOSTX2 0x9C +#define B2056_SYN_LOGEN_CMOSTX3 0x9D +#define B2056_SYN_LOGEN_CMOSTX4 0x9E +#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9F +#define B2056_SYN_LOGEN_MIXER3_OVRVAL 0xA0 +#define B2056_SYN_LOGEN_BUF5_OVRVAL 0xA1 +#define B2056_SYN_LOGEN_BUF6_OVRVAL 0xA2 +#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xA3 +#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xA4 +#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xA5 +#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xA6 +#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xA7 +#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xA8 +#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xA9 +#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xAA +#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xAB +#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xAC +#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xAD +#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xAE +#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xAF +#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xB0 +#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xB1 +#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xB2 +#define B2056_SYN_LOGEN_ACL_WAITCNT 0xB3 +#define B2056_SYN_LOGEN_CORE_CALVALID 0xB4 +#define B2056_SYN_LOGEN_RX_CMOS_CALVALID 0xB5 +#define B2056_SYN_LOGEN_TX_CMOS_VALID 0xB6 + +#define B2056_TX_RESERVED_ADDR0 0x00 +#define B2056_TX_IDCODE 0x01 +#define B2056_TX_RESERVED_ADDR2 0x02 +#define B2056_TX_RESERVED_ADDR3 0x03 +#define B2056_TX_RESERVED_ADDR4 0x04 +#define B2056_TX_RESERVED_ADDR5 0x05 +#define B2056_TX_RESERVED_ADDR6 0x06 +#define B2056_TX_RESERVED_ADDR7 0x07 +#define B2056_TX_COM_CTRL 0x08 +#define B2056_TX_COM_PU 0x09 +#define B2056_TX_COM_OVR 0x0A +#define B2056_TX_COM_RESET 0x0B +#define B2056_TX_COM_RCAL 0x0C +#define B2056_TX_COM_RC_RXLPF 0x0D +#define B2056_TX_COM_RC_TXLPF 0x0E +#define B2056_TX_COM_RC_RXHPF 0x0F +#define B2056_TX_RESERVED_ADDR16 0x10 +#define B2056_TX_RESERVED_ADDR17 0x11 +#define B2056_TX_RESERVED_ADDR18 0x12 +#define B2056_TX_RESERVED_ADDR19 0x13 +#define B2056_TX_RESERVED_ADDR20 0x14 +#define B2056_TX_RESERVED_ADDR21 0x15 +#define B2056_TX_RESERVED_ADDR22 0x16 +#define B2056_TX_RESERVED_ADDR23 0x17 +#define B2056_TX_RESERVED_ADDR24 0x18 +#define B2056_TX_RESERVED_ADDR25 0x19 +#define B2056_TX_RESERVED_ADDR26 0x1A +#define B2056_TX_RESERVED_ADDR27 0x1B +#define B2056_TX_RESERVED_ADDR28 0x1C +#define B2056_TX_RESERVED_ADDR29 0x1D +#define B2056_TX_RESERVED_ADDR30 0x1E +#define B2056_TX_RESERVED_ADDR31 0x1F +#define B2056_TX_IQCAL_GAIN_BW 0x20 +#define B2056_TX_LOFT_FINE_I 0x21 +#define B2056_TX_LOFT_FINE_Q 0x22 +#define B2056_TX_LOFT_COARSE_I 0x23 +#define B2056_TX_LOFT_COARSE_Q 0x24 +#define B2056_TX_TX_COM_MASTER1 0x25 +#define B2056_TX_TX_COM_MASTER2 0x26 +#define B2056_TX_RXIQCAL_TXMUX 0x27 +#define B2056_TX_TX_SSI_MASTER 0x28 +#define B2056_TX_IQCAL_VCM_HG 0x29 +#define B2056_TX_IQCAL_IDAC 0x2A +#define B2056_TX_TSSI_VCM 0x2B +#define B2056_TX_TX_AMP_DET 0x2C +#define B2056_TX_TX_SSI_MUX 0x2D +#define B2056_TX_TSSIA 0x2E +#define B2056_TX_TSSIG 0x2F +#define B2056_TX_TSSI_MISC1 0x30 +#define B2056_TX_TSSI_MISC2 0x31 +#define B2056_TX_TSSI_MISC3 0x32 +#define B2056_TX_PA_SPARE1 0x33 +#define B2056_TX_PA_SPARE2 0x34 +#define B2056_TX_INTPAA_MASTER 0x35 +#define B2056_TX_INTPAA_GAIN 0x36 +#define B2056_TX_INTPAA_BOOST_TUNE 0x37 +#define B2056_TX_INTPAA_IAUX_STAT 0x38 +#define B2056_TX_INTPAA_IAUX_DYN 0x39 +#define B2056_TX_INTPAA_IMAIN_STAT 0x3A +#define B2056_TX_INTPAA_IMAIN_DYN 0x3B +#define B2056_TX_INTPAA_CASCBIAS 0x3C +#define B2056_TX_INTPAA_PASLOPE 0x3D +#define B2056_TX_INTPAA_PA_MISC 0x3E +#define B2056_TX_INTPAG_MASTER 0x3F +#define B2056_TX_INTPAG_GAIN 0x40 +#define B2056_TX_INTPAG_BOOST_TUNE 0x41 +#define B2056_TX_INTPAG_IAUX_STAT 0x42 +#define B2056_TX_INTPAG_IAUX_DYN 0x43 +#define B2056_TX_INTPAG_IMAIN_STAT 0x44 +#define B2056_TX_INTPAG_IMAIN_DYN 0x45 +#define B2056_TX_INTPAG_CASCBIAS 0x46 +#define B2056_TX_INTPAG_PASLOPE 0x47 +#define B2056_TX_INTPAG_PA_MISC 0x48 +#define B2056_TX_PADA_MASTER 0x49 +#define B2056_TX_PADA_IDAC 0x4A +#define B2056_TX_PADA_CASCBIAS 0x4B +#define B2056_TX_PADA_GAIN 0x4C +#define B2056_TX_PADA_BOOST_TUNE 0x4D +#define B2056_TX_PADA_SLOPE 0x4E +#define B2056_TX_PADG_MASTER 0x4F +#define B2056_TX_PADG_IDAC 0x50 +#define B2056_TX_PADG_CASCBIAS 0x51 +#define B2056_TX_PADG_GAIN 0x52 +#define B2056_TX_PADG_BOOST_TUNE 0x53 +#define B2056_TX_PADG_SLOPE 0x54 +#define B2056_TX_PGAA_MASTER 0x55 +#define B2056_TX_PGAA_IDAC 0x56 +#define B2056_TX_PGAA_GAIN 0x57 +#define B2056_TX_PGAA_BOOST_TUNE 0x58 +#define B2056_TX_PGAA_SLOPE 0x59 +#define B2056_TX_PGAA_MISC 0x5A +#define B2056_TX_PGAG_MASTER 0x5B +#define B2056_TX_PGAG_IDAC 0x5C +#define B2056_TX_PGAG_GAIN 0x5D +#define B2056_TX_PGAG_BOOST_TUNE 0x5E +#define B2056_TX_PGAG_SLOPE 0x5F +#define B2056_TX_PGAG_MISC 0x60 +#define B2056_TX_MIXA_MASTER 0x61 +#define B2056_TX_MIXA_BOOST_TUNE 0x62 +#define B2056_TX_MIXG 0x63 +#define B2056_TX_MIXG_BOOST_TUNE 0x64 +#define B2056_TX_BB_GM_MASTER 0x65 +#define B2056_TX_GMBB_GM 0x66 +#define B2056_TX_GMBB_IDAC 0x67 +#define B2056_TX_TXLPF_MASTER 0x68 +#define B2056_TX_TXLPF_RCCAL 0x69 +#define B2056_TX_TXLPF_RCCAL_OFF0 0x6A +#define B2056_TX_TXLPF_RCCAL_OFF1 0x6B +#define B2056_TX_TXLPF_RCCAL_OFF2 0x6C +#define B2056_TX_TXLPF_RCCAL_OFF3 0x6D +#define B2056_TX_TXLPF_RCCAL_OFF4 0x6E +#define B2056_TX_TXLPF_RCCAL_OFF5 0x6F +#define B2056_TX_TXLPF_RCCAL_OFF6 0x70 +#define B2056_TX_TXLPF_BW 0x71 +#define B2056_TX_TXLPF_GAIN 0x72 +#define B2056_TX_TXLPF_IDAC 0x73 +#define B2056_TX_TXLPF_IDAC_0 0x74 +#define B2056_TX_TXLPF_IDAC_1 0x75 +#define B2056_TX_TXLPF_IDAC_2 0x76 +#define B2056_TX_TXLPF_IDAC_3 0x77 +#define B2056_TX_TXLPF_IDAC_4 0x78 +#define B2056_TX_TXLPF_IDAC_5 0x79 +#define B2056_TX_TXLPF_IDAC_6 0x7A +#define B2056_TX_TXLPF_OPAMP_IDAC 0x7B +#define B2056_TX_TXLPF_MISC 0x7C +#define B2056_TX_TXSPARE1 0x7D +#define B2056_TX_TXSPARE2 0x7E +#define B2056_TX_TXSPARE3 0x7F +#define B2056_TX_TXSPARE4 0x80 +#define B2056_TX_TXSPARE5 0x81 +#define B2056_TX_TXSPARE6 0x82 +#define B2056_TX_TXSPARE7 0x83 +#define B2056_TX_TXSPARE8 0x84 +#define B2056_TX_TXSPARE9 0x85 +#define B2056_TX_TXSPARE10 0x86 +#define B2056_TX_TXSPARE11 0x87 +#define B2056_TX_TXSPARE12 0x88 +#define B2056_TX_TXSPARE13 0x89 +#define B2056_TX_TXSPARE14 0x8A +#define B2056_TX_TXSPARE15 0x8B +#define B2056_TX_TXSPARE16 0x8C +#define B2056_TX_STATUS_INTPA_GAIN 0x8D +#define B2056_TX_STATUS_PAD_GAIN 0x8E +#define B2056_TX_STATUS_PGA_GAIN 0x8F +#define B2056_TX_STATUS_GM_TXLPF_GAIN 0x90 +#define B2056_TX_STATUS_TXLPF_BW 0x91 +#define B2056_TX_STATUS_TXLPF_RC 0x92 +#define B2056_TX_GMBB_IDAC0 0x93 +#define B2056_TX_GMBB_IDAC1 0x94 +#define B2056_TX_GMBB_IDAC2 0x95 +#define B2056_TX_GMBB_IDAC3 0x96 +#define B2056_TX_GMBB_IDAC4 0x97 +#define B2056_TX_GMBB_IDAC5 0x98 +#define B2056_TX_GMBB_IDAC6 0x99 +#define B2056_TX_GMBB_IDAC7 0x9A + +#define B2056_RX_RESERVED_ADDR0 0x00 +#define B2056_RX_IDCODE 0x01 +#define B2056_RX_RESERVED_ADDR2 0x02 +#define B2056_RX_RESERVED_ADDR3 0x03 +#define B2056_RX_RESERVED_ADDR4 0x04 +#define B2056_RX_RESERVED_ADDR5 0x05 +#define B2056_RX_RESERVED_ADDR6 0x06 +#define B2056_RX_RESERVED_ADDR7 0x07 +#define B2056_RX_COM_CTRL 0x08 +#define B2056_RX_COM_PU 0x09 +#define B2056_RX_COM_OVR 0x0A +#define B2056_RX_COM_RESET 0x0B +#define B2056_RX_COM_RCAL 0x0C +#define B2056_RX_COM_RC_RXLPF 0x0D +#define B2056_RX_COM_RC_TXLPF 0x0E +#define B2056_RX_COM_RC_RXHPF 0x0F +#define B2056_RX_RESERVED_ADDR16 0x10 +#define B2056_RX_RESERVED_ADDR17 0x11 +#define B2056_RX_RESERVED_ADDR18 0x12 +#define B2056_RX_RESERVED_ADDR19 0x13 +#define B2056_RX_RESERVED_ADDR20 0x14 +#define B2056_RX_RESERVED_ADDR21 0x15 +#define B2056_RX_RESERVED_ADDR22 0x16 +#define B2056_RX_RESERVED_ADDR23 0x17 +#define B2056_RX_RESERVED_ADDR24 0x18 +#define B2056_RX_RESERVED_ADDR25 0x19 +#define B2056_RX_RESERVED_ADDR26 0x1A +#define B2056_RX_RESERVED_ADDR27 0x1B +#define B2056_RX_RESERVED_ADDR28 0x1C +#define B2056_RX_RESERVED_ADDR29 0x1D +#define B2056_RX_RESERVED_ADDR30 0x1E +#define B2056_RX_RESERVED_ADDR31 0x1F +#define B2056_RX_RXIQCAL_RXMUX 0x20 +#define B2056_RX_RSSI_PU 0x21 +#define B2056_RX_RSSI_SEL 0x22 +#define B2056_RX_RSSI_GAIN 0x23 +#define B2056_RX_RSSI_NB_IDAC 0x24 +#define B2056_RX_RSSI_WB2I_IDAC_1 0x25 +#define B2056_RX_RSSI_WB2I_IDAC_2 0x26 +#define B2056_RX_RSSI_WB2Q_IDAC_1 0x27 +#define B2056_RX_RSSI_WB2Q_IDAC_2 0x28 +#define B2056_RX_RSSI_POLE 0x29 +#define B2056_RX_RSSI_WB1_IDAC 0x2A +#define B2056_RX_RSSI_MISC 0x2B +#define B2056_RX_LNAA_MASTER 0x2C +#define B2056_RX_LNAA_TUNE 0x2D +#define B2056_RX_LNAA_GAIN 0x2E +#define B2056_RX_LNA_A_SLOPE 0x2F +#define B2056_RX_BIASPOLE_LNAA1_IDAC 0x30 +#define B2056_RX_LNAA2_IDAC 0x31 +#define B2056_RX_LNA1A_MISC 0x32 +#define B2056_RX_LNAG_MASTER 0x33 +#define B2056_RX_LNAG_TUNE 0x34 +#define B2056_RX_LNAG_GAIN 0x35 +#define B2056_RX_LNA_G_SLOPE 0x36 +#define B2056_RX_BIASPOLE_LNAG1_IDAC 0x37 +#define B2056_RX_LNAG2_IDAC 0x38 +#define B2056_RX_LNA1G_MISC 0x39 +#define B2056_RX_MIXA_MASTER 0x3A +#define B2056_RX_MIXA_VCM 0x3B +#define B2056_RX_MIXA_CTRLPTAT 0x3C +#define B2056_RX_MIXA_LOB_BIAS 0x3D +#define B2056_RX_MIXA_CORE_IDAC 0x3E +#define B2056_RX_MIXA_CMFB_IDAC 0x3F +#define B2056_RX_MIXA_BIAS_AUX 0x40 +#define B2056_RX_MIXA_BIAS_MAIN 0x41 +#define B2056_RX_MIXA_BIAS_MISC 0x42 +#define B2056_RX_MIXA_MAST_BIAS 0x43 +#define B2056_RX_MIXG_MASTER 0x44 +#define B2056_RX_MIXG_VCM 0x45 +#define B2056_RX_MIXG_CTRLPTAT 0x46 +#define B2056_RX_MIXG_LOB_BIAS 0x47 +#define B2056_RX_MIXG_CORE_IDAC 0x48 +#define B2056_RX_MIXG_CMFB_IDAC 0x49 +#define B2056_RX_MIXG_BIAS_AUX 0x4A +#define B2056_RX_MIXG_BIAS_MAIN 0x4B +#define B2056_RX_MIXG_BIAS_MISC 0x4C +#define B2056_RX_MIXG_MAST_BIAS 0x4D +#define B2056_RX_TIA_MASTER 0x4E +#define B2056_RX_TIA_IOPAMP 0x4F +#define B2056_RX_TIA_QOPAMP 0x50 +#define B2056_RX_TIA_IMISC 0x51 +#define B2056_RX_TIA_QMISC 0x52 +#define B2056_RX_TIA_GAIN 0x53 +#define B2056_RX_TIA_SPARE1 0x54 +#define B2056_RX_TIA_SPARE2 0x55 +#define B2056_RX_BB_LPF_MASTER 0x56 +#define B2056_RX_AACI_MASTER 0x57 +#define B2056_RX_RXLPF_IDAC 0x58 +#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 +#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5A +#define B2056_RX_RXLPF_BIAS_DCCANCEL 0x5B +#define B2056_RX_RXLPF_OUTVCM 0x5C +#define B2056_RX_RXLPF_INVCM_BODY 0x5D +#define B2056_RX_RXLPF_CC_OP 0x5E +#define B2056_RX_RXLPF_GAIN 0x5F +#define B2056_RX_RXLPF_Q_BW 0x60 +#define B2056_RX_RXLPF_HP_CORNER_BW 0x61 +#define B2056_RX_RXLPF_RCCAL_HPC 0x62 +#define B2056_RX_RXHPF_OFF0 0x63 +#define B2056_RX_RXHPF_OFF1 0x64 +#define B2056_RX_RXHPF_OFF2 0x65 +#define B2056_RX_RXHPF_OFF3 0x66 +#define B2056_RX_RXHPF_OFF4 0x67 +#define B2056_RX_RXHPF_OFF5 0x68 +#define B2056_RX_RXHPF_OFF6 0x69 +#define B2056_RX_RXHPF_OFF7 0x6A +#define B2056_RX_RXLPF_RCCAL_LPC 0x6B +#define B2056_RX_RXLPF_OFF_0 0x6C +#define B2056_RX_RXLPF_OFF_1 0x6D +#define B2056_RX_RXLPF_OFF_2 0x6E +#define B2056_RX_RXLPF_OFF_3 0x6F +#define B2056_RX_RXLPF_OFF_4 0x70 +#define B2056_RX_UNUSED 0x71 +#define B2056_RX_VGA_MASTER 0x72 +#define B2056_RX_VGA_BIAS 0x73 +#define B2056_RX_VGA_BIAS_DCCANCEL 0x74 +#define B2056_RX_VGA_GAIN 0x75 +#define B2056_RX_VGA_HP_CORNER_BW 0x76 +#define B2056_RX_VGABUF_BIAS 0x77 +#define B2056_RX_VGABUF_GAIN_BW 0x78 +#define B2056_RX_TXFBMIX_A 0x79 +#define B2056_RX_TXFBMIX_G 0x7A +#define B2056_RX_RXSPARE1 0x7B +#define B2056_RX_RXSPARE2 0x7C +#define B2056_RX_RXSPARE3 0x7D +#define B2056_RX_RXSPARE4 0x7E +#define B2056_RX_RXSPARE5 0x7F +#define B2056_RX_RXSPARE6 0x80 +#define B2056_RX_RXSPARE7 0x81 +#define B2056_RX_RXSPARE8 0x82 +#define B2056_RX_RXSPARE9 0x83 +#define B2056_RX_RXSPARE10 0x84 +#define B2056_RX_RXSPARE11 0x85 +#define B2056_RX_RXSPARE12 0x86 +#define B2056_RX_RXSPARE13 0x87 +#define B2056_RX_RXSPARE14 0x88 +#define B2056_RX_RXSPARE15 0x89 +#define B2056_RX_RXSPARE16 0x8A +#define B2056_RX_STATUS_LNAA_GAIN 0x8B +#define B2056_RX_STATUS_LNAG_GAIN 0x8C +#define B2056_RX_STATUS_MIXTIA_GAIN 0x8D +#define B2056_RX_STATUS_RXLPF_GAIN 0x8E +#define B2056_RX_STATUS_VGA_BUF_GAIN 0x8F +#define B2056_RX_STATUS_RXLPF_Q 0x90 +#define B2056_RX_STATUS_RXLPF_BUF_BW 0x91 +#define B2056_RX_STATUS_RXLPF_VGA_HPC 0x92 +#define B2056_RX_STATUS_RXLPF_RC 0x93 +#define B2056_RX_STATUS_HPC_RC 0x94 + +#define B2056_LNA1_A_PU 0x01 +#define B2056_LNA2_A_PU 0x02 +#define B2056_LNA1_G_PU 0x01 +#define B2056_LNA2_G_PU 0x02 +#define B2056_MIXA_PU_I 0x01 +#define B2056_MIXA_PU_Q 0x02 +#define B2056_MIXA_PU_GM 0x10 +#define B2056_MIXG_PU_I 0x01 +#define B2056_MIXG_PU_Q 0x02 +#define B2056_MIXG_PU_GM 0x10 +#define B2056_TIA_PU 0x01 +#define B2056_BB_LPF_PU 0x20 +#define B2056_W1_PU 0x02 +#define B2056_W2_PU 0x04 +#define B2056_NB_PU 0x08 +#define B2056_RSSI_W1_SEL 0x02 +#define B2056_RSSI_W2_SEL 0x04 +#define B2056_RSSI_NB_SEL 0x08 +#define B2056_VCM_MASK 0x1C +#define B2056_RSSI_VCM_SHIFT 0x02 + +#define B2056_SYN (0x0 << 12) +#define B2056_TX0 (0x2 << 12) +#define B2056_TX1 (0x3 << 12) +#define B2056_RX0 (0x6 << 12) +#define B2056_RX1 (0x7 << 12) +#define B2056_ALLTX (0xE << 12) +#define B2056_ALLRX (0xF << 12) + +#define B2056_SYN_RESERVED_ADDR0 0x00 +#define B2056_SYN_IDCODE 0x01 +#define B2056_SYN_RESERVED_ADDR2 0x02 +#define B2056_SYN_RESERVED_ADDR3 0x03 +#define B2056_SYN_RESERVED_ADDR4 0x04 +#define B2056_SYN_RESERVED_ADDR5 0x05 +#define B2056_SYN_RESERVED_ADDR6 0x06 +#define B2056_SYN_RESERVED_ADDR7 0x07 +#define B2056_SYN_COM_CTRL 0x08 +#define B2056_SYN_COM_PU 0x09 +#define B2056_SYN_COM_OVR 0x0A +#define B2056_SYN_COM_RESET 0x0B +#define B2056_SYN_COM_RCAL 0x0C +#define B2056_SYN_COM_RC_RXLPF 0x0D +#define B2056_SYN_COM_RC_TXLPF 0x0E +#define B2056_SYN_COM_RC_RXHPF 0x0F +#define B2056_SYN_RESERVED_ADDR16 0x10 +#define B2056_SYN_RESERVED_ADDR17 0x11 +#define B2056_SYN_RESERVED_ADDR18 0x12 +#define B2056_SYN_RESERVED_ADDR19 0x13 +#define B2056_SYN_RESERVED_ADDR20 0x14 +#define B2056_SYN_RESERVED_ADDR21 0x15 +#define B2056_SYN_RESERVED_ADDR22 0x16 +#define B2056_SYN_RESERVED_ADDR23 0x17 +#define B2056_SYN_RESERVED_ADDR24 0x18 +#define B2056_SYN_RESERVED_ADDR25 0x19 +#define B2056_SYN_RESERVED_ADDR26 0x1A +#define B2056_SYN_RESERVED_ADDR27 0x1B +#define B2056_SYN_RESERVED_ADDR28 0x1C +#define B2056_SYN_RESERVED_ADDR29 0x1D +#define B2056_SYN_RESERVED_ADDR30 0x1E +#define B2056_SYN_RESERVED_ADDR31 0x1F +#define B2056_SYN_GPIO_MASTER1 0x20 +#define B2056_SYN_GPIO_MASTER2 0x21 +#define B2056_SYN_TOPBIAS_MASTER 0x22 +#define B2056_SYN_TOPBIAS_RCAL 0x23 +#define B2056_SYN_AFEREG 0x24 +#define B2056_SYN_TEMPPROCSENSE 0x25 +#define B2056_SYN_TEMPPROCSENSEIDAC 0x26 +#define B2056_SYN_TEMPPROCSENSERCAL 0x27 +#define B2056_SYN_LPO 0x28 +#define B2056_SYN_VDDCAL_MASTER 0x29 +#define B2056_SYN_VDDCAL_IDAC 0x2A +#define B2056_SYN_VDDCAL_STATUS 0x2B +#define B2056_SYN_RCAL_MASTER 0x2C +#define B2056_SYN_RCAL_CODE_OUT 0x2D +#define B2056_SYN_RCCAL_CTRL0 0x2E +#define B2056_SYN_RCCAL_CTRL1 0x2F +#define B2056_SYN_RCCAL_CTRL2 0x30 +#define B2056_SYN_RCCAL_CTRL3 0x31 +#define B2056_SYN_RCCAL_CTRL4 0x32 +#define B2056_SYN_RCCAL_CTRL5 0x33 +#define B2056_SYN_RCCAL_CTRL6 0x34 +#define B2056_SYN_RCCAL_CTRL7 0x35 +#define B2056_SYN_RCCAL_CTRL8 0x36 +#define B2056_SYN_RCCAL_CTRL9 0x37 +#define B2056_SYN_RCCAL_CTRL10 0x38 +#define B2056_SYN_RCCAL_CTRL11 0x39 +#define B2056_SYN_ZCAL_SPARE1 0x3A +#define B2056_SYN_ZCAL_SPARE2 0x3B +#define B2056_SYN_PLL_MAST1 0x3C +#define B2056_SYN_PLL_MAST2 0x3D +#define B2056_SYN_PLL_MAST3 0x3E +#define B2056_SYN_PLL_BIAS_RESET 0x3F +#define B2056_SYN_PLL_XTAL0 0x40 +#define B2056_SYN_PLL_XTAL1 0x41 +#define B2056_SYN_PLL_XTAL3 0x42 +#define B2056_SYN_PLL_XTAL4 0x43 +#define B2056_SYN_PLL_XTAL5 0x44 +#define B2056_SYN_PLL_XTAL6 0x45 +#define B2056_SYN_PLL_REFDIV 0x46 +#define B2056_SYN_PLL_PFD 0x47 +#define B2056_SYN_PLL_CP1 0x48 +#define B2056_SYN_PLL_CP2 0x49 +#define B2056_SYN_PLL_CP3 0x4A +#define B2056_SYN_PLL_LOOPFILTER1 0x4B +#define B2056_SYN_PLL_LOOPFILTER2 0x4C +#define B2056_SYN_PLL_LOOPFILTER3 0x4D +#define B2056_SYN_PLL_LOOPFILTER4 0x4E +#define B2056_SYN_PLL_LOOPFILTER5 0x4F +#define B2056_SYN_PLL_MMD1 0x50 +#define B2056_SYN_PLL_MMD2 0x51 +#define B2056_SYN_PLL_VCO1 0x52 +#define B2056_SYN_PLL_VCO2 0x53 +#define B2056_SYN_PLL_MONITOR1 0x54 +#define B2056_SYN_PLL_MONITOR2 0x55 +#define B2056_SYN_PLL_VCOCAL1 0x56 +#define B2056_SYN_PLL_VCOCAL2 0x57 +#define B2056_SYN_PLL_VCOCAL4 0x58 +#define B2056_SYN_PLL_VCOCAL5 0x59 +#define B2056_SYN_PLL_VCOCAL6 0x5A +#define B2056_SYN_PLL_VCOCAL7 0x5B +#define B2056_SYN_PLL_VCOCAL8 0x5C +#define B2056_SYN_PLL_VCOCAL9 0x5D +#define B2056_SYN_PLL_VCOCAL10 0x5E +#define B2056_SYN_PLL_VCOCAL11 0x5F +#define B2056_SYN_PLL_VCOCAL12 0x60 +#define B2056_SYN_PLL_VCOCAL13 0x61 +#define B2056_SYN_PLL_VREG 0x62 +#define B2056_SYN_PLL_STATUS1 0x63 +#define B2056_SYN_PLL_STATUS2 0x64 +#define B2056_SYN_PLL_STATUS3 0x65 +#define B2056_SYN_LOGEN_PU0 0x66 +#define B2056_SYN_LOGEN_PU1 0x67 +#define B2056_SYN_LOGEN_PU2 0x68 +#define B2056_SYN_LOGEN_PU3 0x69 +#define B2056_SYN_LOGEN_PU5 0x6A +#define B2056_SYN_LOGEN_PU6 0x6B +#define B2056_SYN_LOGEN_PU7 0x6C +#define B2056_SYN_LOGEN_PU8 0x6D +#define B2056_SYN_LOGEN_BIAS_RESET 0x6E +#define B2056_SYN_LOGEN_RCCR1 0x6F +#define B2056_SYN_LOGEN_VCOBUF1 0x70 +#define B2056_SYN_LOGEN_MIXER1 0x71 +#define B2056_SYN_LOGEN_MIXER2 0x72 +#define B2056_SYN_LOGEN_BUF1 0x73 +#define B2056_SYN_LOGENBUF2 0x74 +#define B2056_SYN_LOGEN_BUF3 0x75 +#define B2056_SYN_LOGEN_BUF4 0x76 +#define B2056_SYN_LOGEN_DIV1 0x77 +#define B2056_SYN_LOGEN_DIV2 0x78 +#define B2056_SYN_LOGEN_DIV3 0x79 +#define B2056_SYN_LOGEN_ACL1 0x7A +#define B2056_SYN_LOGEN_ACL2 0x7B +#define B2056_SYN_LOGEN_ACL3 0x7C +#define B2056_SYN_LOGEN_ACL4 0x7D +#define B2056_SYN_LOGEN_ACL5 0x7E +#define B2056_SYN_LOGEN_ACL6 0x7F +#define B2056_SYN_LOGEN_ACLOUT 0x80 +#define B2056_SYN_LOGEN_ACLCAL1 0x81 +#define B2056_SYN_LOGEN_ACLCAL2 0x82 +#define B2056_SYN_LOGEN_ACLCAL3 0x83 +#define B2056_SYN_CALEN 0x84 +#define B2056_SYN_LOGEN_PEAKDET1 0x85 +#define B2056_SYN_LOGEN_CORE_ACL_OVR 0x86 +#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 +#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 +#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 +#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8A +#define B2056_SYN_LOGEN_VCOBUF2 0x8B +#define B2056_SYN_LOGEN_MIXER3 0x8C +#define B2056_SYN_LOGEN_BUF5 0x8D +#define B2056_SYN_LOGEN_BUF6 0x8E +#define B2056_SYN_LOGEN_CBUFRX1 0x8F +#define B2056_SYN_LOGEN_CBUFRX2 0x90 +#define B2056_SYN_LOGEN_CBUFRX3 0x91 +#define B2056_SYN_LOGEN_CBUFRX4 0x92 +#define B2056_SYN_LOGEN_CBUFTX1 0x93 +#define B2056_SYN_LOGEN_CBUFTX2 0x94 +#define B2056_SYN_LOGEN_CBUFTX3 0x95 +#define B2056_SYN_LOGEN_CBUFTX4 0x96 +#define B2056_SYN_LOGEN_CMOSRX1 0x97 +#define B2056_SYN_LOGEN_CMOSRX2 0x98 +#define B2056_SYN_LOGEN_CMOSRX3 0x99 +#define B2056_SYN_LOGEN_CMOSRX4 0x9A +#define B2056_SYN_LOGEN_CMOSTX1 0x9B +#define B2056_SYN_LOGEN_CMOSTX2 0x9C +#define B2056_SYN_LOGEN_CMOSTX3 0x9D +#define B2056_SYN_LOGEN_CMOSTX4 0x9E +#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9F +#define B2056_SYN_LOGEN_MIXER3_OVRVAL 0xA0 +#define B2056_SYN_LOGEN_BUF5_OVRVAL 0xA1 +#define B2056_SYN_LOGEN_BUF6_OVRVAL 0xA2 +#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xA3 +#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xA4 +#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xA5 +#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xA6 +#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xA7 +#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xA8 +#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xA9 +#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xAA +#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xAB +#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xAC +#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xAD +#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xAE +#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xAF +#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xB0 +#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xB1 +#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xB2 +#define B2056_SYN_LOGEN_ACL_WAITCNT 0xB3 +#define B2056_SYN_LOGEN_CORE_CALVALID 0xB4 +#define B2056_SYN_LOGEN_RX_CMOS_CALVALID 0xB5 +#define B2056_SYN_LOGEN_TX_CMOS_VALID 0xB6 + +#define B2056_TX_RESERVED_ADDR0 0x00 +#define B2056_TX_IDCODE 0x01 +#define B2056_TX_RESERVED_ADDR2 0x02 +#define B2056_TX_RESERVED_ADDR3 0x03 +#define B2056_TX_RESERVED_ADDR4 0x04 +#define B2056_TX_RESERVED_ADDR5 0x05 +#define B2056_TX_RESERVED_ADDR6 0x06 +#define B2056_TX_RESERVED_ADDR7 0x07 +#define B2056_TX_COM_CTRL 0x08 +#define B2056_TX_COM_PU 0x09 +#define B2056_TX_COM_OVR 0x0A +#define B2056_TX_COM_RESET 0x0B +#define B2056_TX_COM_RCAL 0x0C +#define B2056_TX_COM_RC_RXLPF 0x0D +#define B2056_TX_COM_RC_TXLPF 0x0E +#define B2056_TX_COM_RC_RXHPF 0x0F +#define B2056_TX_RESERVED_ADDR16 0x10 +#define B2056_TX_RESERVED_ADDR17 0x11 +#define B2056_TX_RESERVED_ADDR18 0x12 +#define B2056_TX_RESERVED_ADDR19 0x13 +#define B2056_TX_RESERVED_ADDR20 0x14 +#define B2056_TX_RESERVED_ADDR21 0x15 +#define B2056_TX_RESERVED_ADDR22 0x16 +#define B2056_TX_RESERVED_ADDR23 0x17 +#define B2056_TX_RESERVED_ADDR24 0x18 +#define B2056_TX_RESERVED_ADDR25 0x19 +#define B2056_TX_RESERVED_ADDR26 0x1A +#define B2056_TX_RESERVED_ADDR27 0x1B +#define B2056_TX_RESERVED_ADDR28 0x1C +#define B2056_TX_RESERVED_ADDR29 0x1D +#define B2056_TX_RESERVED_ADDR30 0x1E +#define B2056_TX_RESERVED_ADDR31 0x1F +#define B2056_TX_IQCAL_GAIN_BW 0x20 +#define B2056_TX_LOFT_FINE_I 0x21 +#define B2056_TX_LOFT_FINE_Q 0x22 +#define B2056_TX_LOFT_COARSE_I 0x23 +#define B2056_TX_LOFT_COARSE_Q 0x24 +#define B2056_TX_TX_COM_MASTER1 0x25 +#define B2056_TX_TX_COM_MASTER2 0x26 +#define B2056_TX_RXIQCAL_TXMUX 0x27 +#define B2056_TX_TX_SSI_MASTER 0x28 +#define B2056_TX_IQCAL_VCM_HG 0x29 +#define B2056_TX_IQCAL_IDAC 0x2A +#define B2056_TX_TSSI_VCM 0x2B +#define B2056_TX_TX_AMP_DET 0x2C +#define B2056_TX_TX_SSI_MUX 0x2D +#define B2056_TX_TSSIA 0x2E +#define B2056_TX_TSSIG 0x2F +#define B2056_TX_TSSI_MISC1 0x30 +#define B2056_TX_TSSI_MISC2 0x31 +#define B2056_TX_TSSI_MISC3 0x32 +#define B2056_TX_PA_SPARE1 0x33 +#define B2056_TX_PA_SPARE2 0x34 +#define B2056_TX_INTPAA_MASTER 0x35 +#define B2056_TX_INTPAA_GAIN 0x36 +#define B2056_TX_INTPAA_BOOST_TUNE 0x37 +#define B2056_TX_INTPAA_IAUX_STAT 0x38 +#define B2056_TX_INTPAA_IAUX_DYN 0x39 +#define B2056_TX_INTPAA_IMAIN_STAT 0x3A +#define B2056_TX_INTPAA_IMAIN_DYN 0x3B +#define B2056_TX_INTPAA_CASCBIAS 0x3C +#define B2056_TX_INTPAA_PASLOPE 0x3D +#define B2056_TX_INTPAA_PA_MISC 0x3E +#define B2056_TX_INTPAG_MASTER 0x3F +#define B2056_TX_INTPAG_GAIN 0x40 +#define B2056_TX_INTPAG_BOOST_TUNE 0x41 +#define B2056_TX_INTPAG_IAUX_STAT 0x42 +#define B2056_TX_INTPAG_IAUX_DYN 0x43 +#define B2056_TX_INTPAG_IMAIN_STAT 0x44 +#define B2056_TX_INTPAG_IMAIN_DYN 0x45 +#define B2056_TX_INTPAG_CASCBIAS 0x46 +#define B2056_TX_INTPAG_PASLOPE 0x47 +#define B2056_TX_INTPAG_PA_MISC 0x48 +#define B2056_TX_PADA_MASTER 0x49 +#define B2056_TX_PADA_IDAC 0x4A +#define B2056_TX_PADA_CASCBIAS 0x4B +#define B2056_TX_PADA_GAIN 0x4C +#define B2056_TX_PADA_BOOST_TUNE 0x4D +#define B2056_TX_PADA_SLOPE 0x4E +#define B2056_TX_PADG_MASTER 0x4F +#define B2056_TX_PADG_IDAC 0x50 +#define B2056_TX_PADG_CASCBIAS 0x51 +#define B2056_TX_PADG_GAIN 0x52 +#define B2056_TX_PADG_BOOST_TUNE 0x53 +#define B2056_TX_PADG_SLOPE 0x54 +#define B2056_TX_PGAA_MASTER 0x55 +#define B2056_TX_PGAA_IDAC 0x56 +#define B2056_TX_PGAA_GAIN 0x57 +#define B2056_TX_PGAA_BOOST_TUNE 0x58 +#define B2056_TX_PGAA_SLOPE 0x59 +#define B2056_TX_PGAA_MISC 0x5A +#define B2056_TX_PGAG_MASTER 0x5B +#define B2056_TX_PGAG_IDAC 0x5C +#define B2056_TX_PGAG_GAIN 0x5D +#define B2056_TX_PGAG_BOOST_TUNE 0x5E +#define B2056_TX_PGAG_SLOPE 0x5F +#define B2056_TX_PGAG_MISC 0x60 +#define B2056_TX_MIXA_MASTER 0x61 +#define B2056_TX_MIXA_BOOST_TUNE 0x62 +#define B2056_TX_MIXG 0x63 +#define B2056_TX_MIXG_BOOST_TUNE 0x64 +#define B2056_TX_BB_GM_MASTER 0x65 +#define B2056_TX_GMBB_GM 0x66 +#define B2056_TX_GMBB_IDAC 0x67 +#define B2056_TX_TXLPF_MASTER 0x68 +#define B2056_TX_TXLPF_RCCAL 0x69 +#define B2056_TX_TXLPF_RCCAL_OFF0 0x6A +#define B2056_TX_TXLPF_RCCAL_OFF1 0x6B +#define B2056_TX_TXLPF_RCCAL_OFF2 0x6C +#define B2056_TX_TXLPF_RCCAL_OFF3 0x6D +#define B2056_TX_TXLPF_RCCAL_OFF4 0x6E +#define B2056_TX_TXLPF_RCCAL_OFF5 0x6F +#define B2056_TX_TXLPF_RCCAL_OFF6 0x70 +#define B2056_TX_TXLPF_BW 0x71 +#define B2056_TX_TXLPF_GAIN 0x72 +#define B2056_TX_TXLPF_IDAC 0x73 +#define B2056_TX_TXLPF_IDAC_0 0x74 +#define B2056_TX_TXLPF_IDAC_1 0x75 +#define B2056_TX_TXLPF_IDAC_2 0x76 +#define B2056_TX_TXLPF_IDAC_3 0x77 +#define B2056_TX_TXLPF_IDAC_4 0x78 +#define B2056_TX_TXLPF_IDAC_5 0x79 +#define B2056_TX_TXLPF_IDAC_6 0x7A +#define B2056_TX_TXLPF_OPAMP_IDAC 0x7B +#define B2056_TX_TXLPF_MISC 0x7C +#define B2056_TX_TXSPARE1 0x7D +#define B2056_TX_TXSPARE2 0x7E +#define B2056_TX_TXSPARE3 0x7F +#define B2056_TX_TXSPARE4 0x80 +#define B2056_TX_TXSPARE5 0x81 +#define B2056_TX_TXSPARE6 0x82 +#define B2056_TX_TXSPARE7 0x83 +#define B2056_TX_TXSPARE8 0x84 +#define B2056_TX_TXSPARE9 0x85 +#define B2056_TX_TXSPARE10 0x86 +#define B2056_TX_TXSPARE11 0x87 +#define B2056_TX_TXSPARE12 0x88 +#define B2056_TX_TXSPARE13 0x89 +#define B2056_TX_TXSPARE14 0x8A +#define B2056_TX_TXSPARE15 0x8B +#define B2056_TX_TXSPARE16 0x8C +#define B2056_TX_STATUS_INTPA_GAIN 0x8D +#define B2056_TX_STATUS_PAD_GAIN 0x8E +#define B2056_TX_STATUS_PGA_GAIN 0x8F +#define B2056_TX_STATUS_GM_TXLPF_GAIN 0x90 +#define B2056_TX_STATUS_TXLPF_BW 0x91 +#define B2056_TX_STATUS_TXLPF_RC 0x92 +#define B2056_TX_GMBB_IDAC0 0x93 +#define B2056_TX_GMBB_IDAC1 0x94 +#define B2056_TX_GMBB_IDAC2 0x95 +#define B2056_TX_GMBB_IDAC3 0x96 +#define B2056_TX_GMBB_IDAC4 0x97 +#define B2056_TX_GMBB_IDAC5 0x98 +#define B2056_TX_GMBB_IDAC6 0x99 +#define B2056_TX_GMBB_IDAC7 0x9A + +#define B2056_RX_RESERVED_ADDR0 0x00 +#define B2056_RX_IDCODE 0x01 +#define B2056_RX_RESERVED_ADDR2 0x02 +#define B2056_RX_RESERVED_ADDR3 0x03 +#define B2056_RX_RESERVED_ADDR4 0x04 +#define B2056_RX_RESERVED_ADDR5 0x05 +#define B2056_RX_RESERVED_ADDR6 0x06 +#define B2056_RX_RESERVED_ADDR7 0x07 +#define B2056_RX_COM_CTRL 0x08 +#define B2056_RX_COM_PU 0x09 +#define B2056_RX_COM_OVR 0x0A +#define B2056_RX_COM_RESET 0x0B +#define B2056_RX_COM_RCAL 0x0C +#define B2056_RX_COM_RC_RXLPF 0x0D +#define B2056_RX_COM_RC_TXLPF 0x0E +#define B2056_RX_COM_RC_RXHPF 0x0F +#define B2056_RX_RESERVED_ADDR16 0x10 +#define B2056_RX_RESERVED_ADDR17 0x11 +#define B2056_RX_RESERVED_ADDR18 0x12 +#define B2056_RX_RESERVED_ADDR19 0x13 +#define B2056_RX_RESERVED_ADDR20 0x14 +#define B2056_RX_RESERVED_ADDR21 0x15 +#define B2056_RX_RESERVED_ADDR22 0x16 +#define B2056_RX_RESERVED_ADDR23 0x17 +#define B2056_RX_RESERVED_ADDR24 0x18 +#define B2056_RX_RESERVED_ADDR25 0x19 +#define B2056_RX_RESERVED_ADDR26 0x1A +#define B2056_RX_RESERVED_ADDR27 0x1B +#define B2056_RX_RESERVED_ADDR28 0x1C +#define B2056_RX_RESERVED_ADDR29 0x1D +#define B2056_RX_RESERVED_ADDR30 0x1E +#define B2056_RX_RESERVED_ADDR31 0x1F +#define B2056_RX_RXIQCAL_RXMUX 0x20 +#define B2056_RX_RSSI_PU 0x21 +#define B2056_RX_RSSI_SEL 0x22 +#define B2056_RX_RSSI_GAIN 0x23 +#define B2056_RX_RSSI_NB_IDAC 0x24 +#define B2056_RX_RSSI_WB2I_IDAC_1 0x25 +#define B2056_RX_RSSI_WB2I_IDAC_2 0x26 +#define B2056_RX_RSSI_WB2Q_IDAC_1 0x27 +#define B2056_RX_RSSI_WB2Q_IDAC_2 0x28 +#define B2056_RX_RSSI_POLE 0x29 +#define B2056_RX_RSSI_WB1_IDAC 0x2A +#define B2056_RX_RSSI_MISC 0x2B +#define B2056_RX_LNAA_MASTER 0x2C +#define B2056_RX_LNAA_TUNE 0x2D +#define B2056_RX_LNAA_GAIN 0x2E +#define B2056_RX_LNA_A_SLOPE 0x2F +#define B2056_RX_BIASPOLE_LNAA1_IDAC 0x30 +#define B2056_RX_LNAA2_IDAC 0x31 +#define B2056_RX_LNA1A_MISC 0x32 +#define B2056_RX_LNAG_MASTER 0x33 +#define B2056_RX_LNAG_TUNE 0x34 +#define B2056_RX_LNAG_GAIN 0x35 +#define B2056_RX_LNA_G_SLOPE 0x36 +#define B2056_RX_BIASPOLE_LNAG1_IDAC 0x37 +#define B2056_RX_LNAG2_IDAC 0x38 +#define B2056_RX_LNA1G_MISC 0x39 +#define B2056_RX_MIXA_MASTER 0x3A +#define B2056_RX_MIXA_VCM 0x3B +#define B2056_RX_MIXA_CTRLPTAT 0x3C +#define B2056_RX_MIXA_LOB_BIAS 0x3D +#define B2056_RX_MIXA_CORE_IDAC 0x3E +#define B2056_RX_MIXA_CMFB_IDAC 0x3F +#define B2056_RX_MIXA_BIAS_AUX 0x40 +#define B2056_RX_MIXA_BIAS_MAIN 0x41 +#define B2056_RX_MIXA_BIAS_MISC 0x42 +#define B2056_RX_MIXA_MAST_BIAS 0x43 +#define B2056_RX_MIXG_MASTER 0x44 +#define B2056_RX_MIXG_VCM 0x45 +#define B2056_RX_MIXG_CTRLPTAT 0x46 +#define B2056_RX_MIXG_LOB_BIAS 0x47 +#define B2056_RX_MIXG_CORE_IDAC 0x48 +#define B2056_RX_MIXG_CMFB_IDAC 0x49 +#define B2056_RX_MIXG_BIAS_AUX 0x4A +#define B2056_RX_MIXG_BIAS_MAIN 0x4B +#define B2056_RX_MIXG_BIAS_MISC 0x4C +#define B2056_RX_MIXG_MAST_BIAS 0x4D +#define B2056_RX_TIA_MASTER 0x4E +#define B2056_RX_TIA_IOPAMP 0x4F +#define B2056_RX_TIA_QOPAMP 0x50 +#define B2056_RX_TIA_IMISC 0x51 +#define B2056_RX_TIA_QMISC 0x52 +#define B2056_RX_TIA_GAIN 0x53 +#define B2056_RX_TIA_SPARE1 0x54 +#define B2056_RX_TIA_SPARE2 0x55 +#define B2056_RX_BB_LPF_MASTER 0x56 +#define B2056_RX_AACI_MASTER 0x57 +#define B2056_RX_RXLPF_IDAC 0x58 +#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 +#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5A +#define B2056_RX_RXLPF_BIAS_DCCANCEL 0x5B +#define B2056_RX_RXLPF_OUTVCM 0x5C +#define B2056_RX_RXLPF_INVCM_BODY 0x5D +#define B2056_RX_RXLPF_CC_OP 0x5E +#define B2056_RX_RXLPF_GAIN 0x5F +#define B2056_RX_RXLPF_Q_BW 0x60 +#define B2056_RX_RXLPF_HP_CORNER_BW 0x61 +#define B2056_RX_RXLPF_RCCAL_HPC 0x62 +#define B2056_RX_RXHPF_OFF0 0x63 +#define B2056_RX_RXHPF_OFF1 0x64 +#define B2056_RX_RXHPF_OFF2 0x65 +#define B2056_RX_RXHPF_OFF3 0x66 +#define B2056_RX_RXHPF_OFF4 0x67 +#define B2056_RX_RXHPF_OFF5 0x68 +#define B2056_RX_RXHPF_OFF6 0x69 +#define B2056_RX_RXHPF_OFF7 0x6A +#define B2056_RX_RXLPF_RCCAL_LPC 0x6B +#define B2056_RX_RXLPF_OFF_0 0x6C +#define B2056_RX_RXLPF_OFF_1 0x6D +#define B2056_RX_RXLPF_OFF_2 0x6E +#define B2056_RX_RXLPF_OFF_3 0x6F +#define B2056_RX_RXLPF_OFF_4 0x70 +#define B2056_RX_UNUSED 0x71 +#define B2056_RX_VGA_MASTER 0x72 +#define B2056_RX_VGA_BIAS 0x73 +#define B2056_RX_VGA_BIAS_DCCANCEL 0x74 +#define B2056_RX_VGA_GAIN 0x75 +#define B2056_RX_VGA_HP_CORNER_BW 0x76 +#define B2056_RX_VGABUF_BIAS 0x77 +#define B2056_RX_VGABUF_GAIN_BW 0x78 +#define B2056_RX_TXFBMIX_A 0x79 +#define B2056_RX_TXFBMIX_G 0x7A +#define B2056_RX_RXSPARE1 0x7B +#define B2056_RX_RXSPARE2 0x7C +#define B2056_RX_RXSPARE3 0x7D +#define B2056_RX_RXSPARE4 0x7E +#define B2056_RX_RXSPARE5 0x7F +#define B2056_RX_RXSPARE6 0x80 +#define B2056_RX_RXSPARE7 0x81 +#define B2056_RX_RXSPARE8 0x82 +#define B2056_RX_RXSPARE9 0x83 +#define B2056_RX_RXSPARE10 0x84 +#define B2056_RX_RXSPARE11 0x85 +#define B2056_RX_RXSPARE12 0x86 +#define B2056_RX_RXSPARE13 0x87 +#define B2056_RX_RXSPARE14 0x88 +#define B2056_RX_RXSPARE15 0x89 +#define B2056_RX_RXSPARE16 0x8A +#define B2056_RX_STATUS_LNAA_GAIN 0x8B +#define B2056_RX_STATUS_LNAG_GAIN 0x8C +#define B2056_RX_STATUS_MIXTIA_GAIN 0x8D +#define B2056_RX_STATUS_RXLPF_GAIN 0x8E +#define B2056_RX_STATUS_VGA_BUF_GAIN 0x8F +#define B2056_RX_STATUS_RXLPF_Q 0x90 +#define B2056_RX_STATUS_RXLPF_BUF_BW 0x91 +#define B2056_RX_STATUS_RXLPF_VGA_HPC 0x92 +#define B2056_RX_STATUS_RXLPF_RC 0x93 +#define B2056_RX_STATUS_HPC_RC 0x94 + +#define B2056_LNA1_A_PU 0x01 +#define B2056_LNA2_A_PU 0x02 +#define B2056_LNA1_G_PU 0x01 +#define B2056_LNA2_G_PU 0x02 +#define B2056_MIXA_PU_I 0x01 +#define B2056_MIXA_PU_Q 0x02 +#define B2056_MIXA_PU_GM 0x10 +#define B2056_MIXG_PU_I 0x01 +#define B2056_MIXG_PU_Q 0x02 +#define B2056_MIXG_PU_GM 0x10 +#define B2056_TIA_PU 0x01 +#define B2056_BB_LPF_PU 0x20 +#define B2056_W1_PU 0x02 +#define B2056_W2_PU 0x04 +#define B2056_NB_PU 0x08 +#define B2056_RSSI_W1_SEL 0x02 +#define B2056_RSSI_W2_SEL 0x04 +#define B2056_RSSI_NB_SEL 0x08 +#define B2056_VCM_MASK 0x1C +#define B2056_RSSI_VCM_SHIFT 0x02 + struct b43_nphy_channeltab_entry_rev3 { - /* The channel number */ - u8 channel; /* The channel frequency in MHz */ u16 freq; /* Radio register values on channelswitch */ - /* TODO */ + u8 radio_syn_pll_vcocal1; + u8 radio_syn_pll_vcocal2; + u8 radio_syn_pll_refdiv; + u8 radio_syn_pll_mmd2; + u8 radio_syn_pll_mmd1; + u8 radio_syn_pll_loopfilter1; + u8 radio_syn_pll_loopfilter2; + u8 radio_syn_pll_loopfilter3; + u8 radio_syn_pll_loopfilter4; + u8 radio_syn_pll_loopfilter5; + u8 radio_syn_reserved_addr27; + u8 radio_syn_reserved_addr28; + u8 radio_syn_reserved_addr29; + u8 radio_syn_logen_vcobuf1; + u8 radio_syn_logen_mixer2; + u8 radio_syn_logen_buf3; + u8 radio_syn_logen_buf4; + u8 radio_rx0_lnaa_tune; + u8 radio_rx0_lnag_tune; + u8 radio_tx0_intpaa_boost_tune; + u8 radio_tx0_intpag_boost_tune; + u8 radio_tx0_pada_boost_tune; + u8 radio_tx0_padg_boost_tune; + u8 radio_tx0_pgaa_boost_tune; + u8 radio_tx0_pgag_boost_tune; + u8 radio_tx0_mixa_boost_tune; + u8 radio_tx0_mixg_boost_tune; + u8 radio_rx1_lnaa_tune; + u8 radio_rx1_lnag_tune; + u8 radio_tx1_intpaa_boost_tune; + u8 radio_tx1_intpag_boost_tune; + u8 radio_tx1_pada_boost_tune; + u8 radio_tx1_padg_boost_tune; + u8 radio_tx1_pgaa_boost_tune; + u8 radio_tx1_pgag_boost_tune; + u8 radio_tx1_mixa_boost_tune; + u8 radio_tx1_mixg_boost_tune; /* PHY register values on channelswitch */ struct b43_phy_n_sfo_cfg phy_regs; }; diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 78016ae21c50..86bc0a0f735c 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -28,23 +28,8 @@ /* Returns TRUE, if the radio is enabled in hardware. */ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) { - if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { - if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) - & B43_MMIO_RADIO_HWENABLED_HI_MASK)) - return 1; - } else { - /* To prevent CPU fault on PPC, do not read a register - * unless the interface is started; however, on resume - * for hibernation, this routine is entered early. When - * that happens, unconditionally return TRUE. - */ - if (b43_status(dev) < B43_STAT_STARTED) - return 1; - if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) - & B43_MMIO_RADIO_HWENABLED_LO_MASK) - return 1; - } - return 0; + return !(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) + & B43_MMIO_RADIO_HWENABLED_HI_MASK); } /* The poll callback for the hardware button. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 67f18ecdb3bf..1f11e1670bf0 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -181,52 +181,75 @@ static int b43legacy_ratelimit(struct b43legacy_wl *wl) void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_INFO "b43legacy-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_INFO "b43legacy-%s: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_ERR "b43legacy-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_ERR "b43legacy-%s ERROR: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; if (!b43legacy_ratelimit(wl)) return; + va_start(args, fmt); - printk(KERN_WARNING "b43legacy-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_WARNING "b43legacy-%s warning: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } #if B43legacy_DEBUG void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...) { + struct va_format vaf; va_list args; va_start(args, fmt); - printk(KERN_DEBUG "b43legacy-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + printk(KERN_DEBUG "b43legacy-%s debug: %pV", + (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf); + va_end(args); } #endif /* DEBUG */ diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index d579df72b783..b90f223fb31c 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -29,7 +29,7 @@ /* Returns TRUE, if the radio is enabled in hardware. */ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) { - if (dev->phy.rev >= 3) { + if (dev->dev->id.revision >= 3) { if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b82364258dc5..ed424574160e 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -106,6 +106,9 @@ config IWL5000 Intel WiFi Link 1000BGN Intel Wireless WiFi 5150AGN Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN + Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B) + Intel WIreless WiFi Link 6050BGN Gen 2 Adapter + Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 63edbe2e557f..93380f97835f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -2,20 +2,27 @@ obj-$(CONFIG_IWLWIFI) += iwlcore.o iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwlcore-objs += iwl-scan.o iwl-led.o +iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o +iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o +# If 3945 is selected only, iwl-legacy.o will be added +# to iwlcore-m above, but it needs to be built in. +iwlcore-objs += $(iwlcore-m) + CFLAGS_iwl-devtrace.o := -I$(src) # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o -iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o +iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o +iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o iwlagn-$(CONFIG_IWL5000) += iwl-6000.o iwlagn-$(CONFIG_IWL5000) += iwl-1000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index db540910b110..fb3e3713bae4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -211,14 +211,16 @@ static struct iwl_lib_ops iwl1000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -243,6 +245,7 @@ static const struct iwl_ops iwl1000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl1000_base_params = { @@ -275,15 +278,13 @@ struct iwl_cfg iwl1000_bgn_cfg = { .fw_name_pre = IWL1000_FW_PRE, .ucode_api_max = IWL1000_UCODE_API_MAX, .ucode_api_min = IWL1000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .ops = &iwl1000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl1000_base_params, .ht_params = &iwl1000_ht_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -291,45 +292,39 @@ struct iwl_cfg iwl1000_bg_cfg = { .fw_name_pre = IWL1000_FW_PRE, .ucode_api_max = IWL1000_UCODE_API_MAX, .ucode_api_min = IWL1000_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .ops = &iwl1000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl1000_base_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl100_bgn_cfg = { - .name = "Intel(R) 100 Series 1x1 BGN", + .name = "Intel(R) Centrino(R) Wireless-N 100 BGN", .fw_name_pre = IWL100_FW_PRE, .ucode_api_max = IWL100_UCODE_API_MAX, .ucode_api_min = IWL100_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .ops = &iwl1000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl1000_base_params, .ht_params = &iwl1000_ht_params, + .led_mode = IWL_LED_RF_STATE, }; struct iwl_cfg iwl100_bg_cfg = { - .name = "Intel(R) 100 Series 1x1 BG", + .name = "Intel(R) Centrino(R) Wireless-N 100 BG", .fw_name_pre = IWL100_FW_PRE, .ucode_api_max = IWL100_UCODE_API_MAX, .ucode_api_min = IWL100_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, .eeprom_ver = EEPROM_1000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, .ops = &iwl1000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl1000_base_params, + .led_mode = IWL_LED_RF_STATE, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 176e52577673..d39f449a9bb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -51,6 +51,7 @@ #include "iwl-led.h" #include "iwl-3945-led.h" #include "iwl-3945-debugfs.h" +#include "iwl-legacy.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -115,7 +116,7 @@ void iwl3945_disable_events(struct iwl_priv *priv) u32 base; /* SRAM address of event log header */ u32 disable_ptr; /* SRAM address of event-disable bitmap array */ u32 array_size; /* # of u32 entries in array */ - u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { + static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { 0x00000000, /* 31 - 0 Event id numbers */ 0x00000000, /* 63 - 32 */ 0x00000000, /* 95 - 64 */ @@ -296,7 +297,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && (txq_id != IWL39_CMD_QUEUE_NUM) && priv->mac80211_registered) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } /** @@ -1451,6 +1452,10 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) }; u16 chan; + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) + return -EAGAIN; + chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel); txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; @@ -2722,10 +2727,9 @@ static struct iwl_lib_ops iwl3945_lib = { }, .send_tx_power = iwl3945_send_tx_power, .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, - .post_associate = iwl3945_post_associate, - .isr = iwl_isr_legacy, - .config_ap = iwl3945_config_ap, - .manage_ibss_station = iwl3945_manage_ibss_station, + .isr_ops = { + .isr = iwl_isr_legacy, + }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl3945_good_plcp_health, @@ -2736,10 +2740,16 @@ static struct iwl_lib_ops iwl3945_lib = { }, }; +static const struct iwl_legacy_ops iwl3945_legacy_ops = { + .post_associate = iwl3945_post_associate, + .config_ap = iwl3945_config_ap, + .manage_ibss_station = iwl3945_manage_ibss_station, +}; + static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .get_hcmd_size = iwl3945_get_hcmd_size, .build_addsta_hcmd = iwl3945_build_addsta_hcmd, - .tx_cmd_protection = iwlcore_tx_cmd_protection, + .tx_cmd_protection = iwl_legacy_tx_cmd_protection, .request_scan = iwl3945_request_scan, .post_scan = iwl3945_post_scan, }; @@ -2749,6 +2759,8 @@ static const struct iwl_ops iwl3945_ops = { .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, .led = &iwl3945_led_ops, + .legacy = &iwl3945_legacy_ops, + .ieee80211_ops = &iwl3945_hw_ops, }; static struct iwl_base_params iwl3945_base_params = { @@ -2776,6 +2788,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, .base_params = &iwl3945_base_params, + .led_mode = IWL_LED_BLINK, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2788,6 +2801,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, .base_params = &iwl3945_base_params, + .led_mode = IWL_LED_BLINK, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 09391f0ee61f..3eef1eb74a78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); -extern void iwl3945_post_associate(struct iwl_priv *priv, - struct ieee80211_vif *vif); -extern void iwl3945_config_ap(struct iwl_priv *priv, - struct ieee80211_vif *vif); +extern void iwl3945_post_associate(struct iwl_priv *priv); +extern void iwl3945_config_ap(struct iwl_priv *priv); extern int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -282,6 +280,8 @@ extern int iwl3945_commit_rxon(struct iwl_priv *priv, */ extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); +extern struct ieee80211_ops iwl3945_hw_ops; + /* * Forward declare iwl-3945.c functions for iwl-base.c */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b207e3e9299f..6788ceb37686 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -48,6 +48,7 @@ #include "iwl-agn-led.h" #include "iwl-agn.h" #include "iwl-agn-debugfs.h" +#include "iwl-legacy.h" static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(struct iwl_priv *priv); @@ -1377,13 +1378,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) u8 ctrl_chan_high = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_SCANNING, &priv->status)) { - /* If this gets hit a lot, switch it to a BUG() and catch - * the stack trace to find out who is calling this during - * a scan. */ - IWL_WARN(priv, "TX Power requested while scanning!\n"); + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) return -EAGAIN; - } band = priv->band == IEEE80211_BAND_2GHZ; @@ -1447,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv, return ret; } +static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + /* cast away the const for active_rxon in this function */ + struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; + int ret; + bool new_assoc = + !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + + if (!iwl_is_alive(priv)) + return -EBUSY; + + if (!ctx->is_active) + return 0; + + /* always get timestamp with Rx frame */ + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + + ret = iwl_check_rxon_cmd(priv, ctx); + if (ret) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* + * receive commit_rxon request + * abort any previous channel switch if still in process + */ + if (priv->switch_rxon.switch_in_progress && + (priv->switch_rxon.channel != ctx->staging.channel)) { + IWL_DEBUG_11H(priv, "abort channel switch on %d\n", + le16_to_cpu(priv->switch_rxon.channel)); + iwl_chswitch_done(priv, false); + } + + /* If we don't need to send a full RXON, we can use + * iwl_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. */ + if (!iwl_full_rxon_required(priv, ctx)) { + ret = iwl_send_rxon_assoc(priv, ctx); + if (ret) { + IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); + return ret; + } + + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + iwl_print_rx_config_cmd(priv, ctx); + return 0; + } + + /* If we are currently associated and the new config requires + * an RXON_ASSOC and the new config wants the associated mask enabled, + * we must clear the associated from the active configuration + * before we apply the new config */ + if (iwl_is_associated_ctx(ctx) && new_assoc) { + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); + active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), + active_rxon); + + /* If the mask clearing failed then we set + * active_rxon back to what it was previously */ + if (ret) { + active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; + IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); + return ret; + } + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + + IWL_DEBUG_INFO(priv, "Sending RXON\n" + "* with%s RXON_FILTER_ASSOC_MSK\n" + "* channel = %d\n" + "* bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(ctx->staging.channel), + ctx->staging.bssid_addr); + + iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + + /* Apply the new configuration + * RXON unassoc clears the station table in uCode so restoration of + * stations is needed after it (the RXON command) completes + */ + if (!new_assoc) { + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + if (new_assoc) { + priv->start_calib = 0; + /* Apply the new configuration + * RXON assoc doesn't clear the station table in uCode, + */ + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + } + iwl_print_rx_config_cmd(priv, ctx); + + iwl_init_sensitivity(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; + } + + return 0; +} + static int iwl4965_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch) { @@ -1554,22 +1687,6 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, } /** - * sign_extend - Sign extend a value using specified bit as sign-bit - * - * Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1 - * and bit0..2 is 001b which when sign extended to 1111111111111001b is -7. - * - * @param oper value to sign extend - * @param index 0 based bit index (0<=index<32) to sign bit - */ -static s32 sign_extend(u32 oper, int index) -{ - u8 shift = 31 - index; - - return (s32)(oper << shift) >> shift; -} - -/** * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin) * @statistics: Provides the temperature reading from the uCode * @@ -1606,9 +1723,9 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) * "initialize" ALIVE response. */ if (!test_bit(STATUS_TEMPERATURE, &priv->status)) - vt = sign_extend(R4, 23); + vt = sign_extend32(R4, 23); else - vt = sign_extend(le32_to_cpu(priv->_agn.statistics. + vt = sign_extend32(le32_to_cpu(priv->_agn.statistics. general.common.temperature), 23); IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); @@ -2121,12 +2238,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); } } else { info->status.rates[0].count = tx_resp->failure_frame + 1; @@ -2150,7 +2263,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } if (qc && likely(sta_id != IWL_INVALID_STATION)) iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); @@ -2216,7 +2329,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, - .commit_rxon = iwlagn_commit_rxon, + .commit_rxon = iwl4965_commit_rxon, .set_rxon_chain = iwlagn_set_rxon_chain, .send_bt_config = iwl_send_bt_config, }; @@ -2233,12 +2346,155 @@ static void iwl4965_post_scan(struct iwl_priv *priv) iwlcore_commit_rxon(priv, ctx); } +static void iwl4965_post_associate(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_conf *conf = NULL; + int ret = 0; + + if (!vif || !priv->is_open) + return; + + if (vif->type == NL80211_IFTYPE_AP) { + IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); + return; + } + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + iwl_scan_cancel_timeout(priv, 200); + + conf = ieee80211_get_hw_conf(priv->hw); + + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) + IWL_WARN(priv, "RXON timing - " + "Attempting to continue.\n"); + + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + + iwl_set_rxon_ht(priv, &priv->current_ht_config); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + + IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", + vif->bss_conf.aid, vif->bss_conf.beacon_int); + + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (vif->bss_conf.use_short_slot) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + } + + iwlcore_commit_rxon(priv, ctx); + + IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", + vif->bss_conf.aid, ctx->active.bssid_addr); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_ADHOC: + iwlagn_send_beacon_cmd(priv); + break; + default: + IWL_ERR(priv, "%s Should not be called in %d mode\n", + __func__, vif->type); + break; + } + + /* the chain noise calibration will enabled PM upon completion + * If chain noise has already been run, then we need to enable + * power management here */ + if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) + iwl_power_update_mode(priv, false); + + /* Enable Rx differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; +} + +static void iwl4965_config_ap(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; + int ret = 0; + + lockdep_assert_held(&priv->mutex); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* The following should be done only at AP bring up */ + if (!iwl_is_associated_ctx(ctx)) { + + /* RXON - unassoc (to set timing command) */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + /* RXON Timing */ + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) + IWL_WARN(priv, "RXON timing failed - " + "Attempting to continue.\n"); + + /* AP has all antennas */ + priv->chain_noise_data.active_chains = + priv->hw_params.valid_rx_ant; + iwl_set_rxon_ht(priv, &priv->current_ht_config); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + ctx->staging.assoc_id = 0; + + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= + RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= + ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (vif->bss_conf.use_short_slot) + ctx->staging.flags |= + RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= + ~RXON_FLG_SHORT_SLOT_MSK; + } + /* need to send beacon cmd before committing assoc RXON! */ + iwlagn_send_beacon_cmd(priv); + /* restore RXON assoc */ + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + } + iwlagn_send_beacon_cmd(priv); + + /* FIXME - we need to add code here to detect a totally new + * configuration, reset the AP, unassoc, rxon timing, assoc, + * clear sta table, add BCAST sta... */ +} + static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, - .tx_cmd_protection = iwlcore_tx_cmd_protection, + .tx_cmd_protection = iwl_legacy_tx_cmd_protection, .calc_rssi = iwl4965_calc_rssi, .request_scan = iwlagn_request_scan, .post_scan = iwl4965_post_scan, @@ -2285,14 +2541,12 @@ static struct iwl_lib_ops iwl4965_lib = { }, .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl_update_chain_flags, - .post_associate = iwl_post_associate, - .config_ap = iwl_config_ap, - .isr = iwl_isr_legacy, + .isr_ops = { + .isr = iwl_isr_legacy, + }, .temp_ops = { .temperature = iwl4965_temperature_calib, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -2304,11 +2558,43 @@ static struct iwl_lib_ops iwl4965_lib = { .check_plcp_health = iwl_good_plcp_health, }; +static const struct iwl_legacy_ops iwl4965_legacy_ops = { + .post_associate = iwl4965_post_associate, + .config_ap = iwl4965_config_ap, + .manage_ibss_station = iwlagn_manage_ibss_station, + .update_bcast_stations = iwl_update_bcast_stations, +}; + +struct ieee80211_ops iwl4965_hw_ops = { + .tx = iwlagn_mac_tx, + .start = iwlagn_mac_start, + .stop = iwlagn_mac_stop, + .add_interface = iwl_mac_add_interface, + .remove_interface = iwl_mac_remove_interface, + .change_interface = iwl_mac_change_interface, + .config = iwl_legacy_mac_config, + .configure_filter = iwlagn_configure_filter, + .set_key = iwlagn_mac_set_key, + .update_tkip_key = iwlagn_mac_update_tkip_key, + .conf_tx = iwl_mac_conf_tx, + .reset_tsf = iwl_legacy_mac_reset_tsf, + .bss_info_changed = iwl_legacy_mac_bss_info_changed, + .ampdu_action = iwlagn_mac_ampdu_action, + .hw_scan = iwl_mac_hw_scan, + .sta_add = iwlagn_mac_sta_add, + .sta_remove = iwl_mac_sta_remove, + .channel_switch = iwlagn_mac_channel_switch, + .flush = iwlagn_mac_flush, + .tx_last_beacon = iwl_mac_tx_last_beacon, +}; + static const struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, .led = &iwlagn_led_ops, + .legacy = &iwl4965_legacy_ops, + .ieee80211_ops = &iwl4965_hw_ops, }; static struct iwl_base_params iwl4965_base_params = { @@ -2330,6 +2616,7 @@ static struct iwl_base_params iwl4965_base_params = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .no_agg_framecnt_info = true, }; struct iwl_cfg iwl4965_agn_cfg = { @@ -2337,7 +2624,6 @@ struct iwl_cfg iwl4965_agn_cfg = { .fw_name_pre = IWL4965_FW_PRE, .ucode_api_max = IWL4965_UCODE_API_MAX, .ucode_api_min = IWL4965_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_4965_EEPROM_VERSION, @@ -2345,6 +2631,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .ops = &iwl4965_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl4965_base_params, + .led_mode = IWL_LED_BLINK, /* * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index fd9fbc93ea1b..cf74edb82a70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -385,14 +385,16 @@ static struct iwl_lib_ops iwl5000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -453,14 +455,16 @@ static struct iwl_lib_ops iwl5150_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwl5150_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -485,6 +489,7 @@ static const struct iwl_ops iwl5000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl5150_ops = { @@ -492,6 +497,7 @@ static const struct iwl_ops iwl5150_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl5000_base_params = { @@ -521,15 +527,13 @@ struct iwl_cfg iwl5300_agn_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -537,15 +541,15 @@ struct iwl_cfg iwl5100_bgn_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -553,14 +557,14 @@ struct iwl_cfg iwl5100_abg_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -568,15 +572,15 @@ struct iwl_cfg iwl5100_agn_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, + .valid_tx_ant = ANT_B, /* .cfg overwrite */ + .valid_rx_ant = ANT_AB, /* .cfg overwrite */ .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -584,15 +588,13 @@ struct iwl_cfg iwl5350_agn_cfg = { .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .ops = &iwl5000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -600,9 +602,6 @@ struct iwl_cfg iwl5150_agn_cfg = { .fw_name_pre = IWL5150_FW_PRE, .ucode_api_max = IWL5150_UCODE_API_MAX, .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .ops = &iwl5150_ops, @@ -610,6 +609,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, .need_dc_calib = true, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -617,15 +617,13 @@ struct iwl_cfg iwl5150_abg_cfg = { .fw_name_pre = IWL5150_FW_PRE, .ucode_api_max = IWL5150_UCODE_API_MAX, .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .ops = &iwl5150_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .need_dc_calib = true, + .led_mode = IWL_LED_BLINK, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 11e6532fc573..ec41f2725292 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -53,13 +53,11 @@ #define IWL6000_UCODE_API_MAX 4 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 5 -#define IWL130_UCODE_API_MAX 5 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 #define IWL6000G2_UCODE_API_MIN 4 -#define IWL130_UCODE_API_MIN 5 #define IWL6000_FW_PRE "iwlwifi-6000-" #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" @@ -77,10 +75,6 @@ #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) -#define IWL130_FW_PRE "iwlwifi-130-" -#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode" -#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api) - static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ @@ -328,14 +322,16 @@ static struct iwl_lib_ops iwl6000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -399,14 +395,16 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, - .manage_ibss_station = iwlagn_manage_ibss_station, - .update_bcast_stations = iwl_update_bcast_stations, .debugfs_ops = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, @@ -439,6 +437,7 @@ static const struct iwl_ops iwl6000_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050_ops = { @@ -447,6 +446,7 @@ static const struct iwl_ops iwl6050_ops = { .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, .nic = &iwl6050_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050g2_ops = { @@ -455,6 +455,7 @@ static const struct iwl_ops iwl6050g2_ops = { .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, .nic = &iwl6050g2_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6000g2b_ops = { @@ -462,6 +463,7 @@ static const struct iwl_ops iwl6000g2b_ops = { .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl6000_base_params = { @@ -485,6 +487,7 @@ static struct iwl_base_params iwl6000_base_params = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; static struct iwl_base_params iwl6050_base_params = { @@ -508,6 +511,7 @@ static struct iwl_base_params iwl6050_base_params = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; static struct iwl_base_params iwl6000_coex_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, @@ -530,6 +534,7 @@ static struct iwl_base_params iwl6000_coex_base_params = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, + .shadow_reg_enable = true, }; static struct iwl_ht_params iwl6000_ht_params = { @@ -541,18 +546,17 @@ static struct iwl_bt_params iwl6000_bt_params = { .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, + .agg_time_limit = BT_AGG_THRESHOLD_DEF, .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, + .bt_sco_disable = true, }; struct iwl_cfg iwl6000g2a_2agn_cfg = { - .name = "6000 Series 2x2 AGN Gen2a", + .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN", .fw_name_pre = IWL6000G2A_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -561,16 +565,14 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .ht_params = &iwl6000_ht_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, }; struct iwl_cfg iwl6000g2a_2abg_cfg = { - .name = "6000 Series 2x2 ABG Gen2a", + .name = "Intel(R) Centrino(R) Advanced-N 6205 ABG", .fw_name_pre = IWL6000G2A_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -578,16 +580,14 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = { .base_params = &iwl6000_base_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, }; struct iwl_cfg iwl6000g2a_2bg_cfg = { - .name = "6000 Series 2x2 BG Gen2a", + .name = "Intel(R) Centrino(R) Advanced-N 6205 BG", .fw_name_pre = IWL6000G2A_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -595,16 +595,14 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = { .base_params = &iwl6000_base_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, }; struct iwl_cfg iwl6000g2b_2agn_cfg = { - .name = "6000 Series 2x2 AGN Gen2b", + .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -614,18 +612,17 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .ht_params = &iwl6000_ht_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { - .name = "6000 Series 2x2 ABG Gen2b", + .name = "Intel(R) Centrino(R) Advanced-N 6230 ABG", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -634,18 +631,17 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { - .name = "6000 Series 2x2 BGN Gen2b", + .name = "Intel(R) Centrino(R) Advanced-N 6230 BGN", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -655,18 +651,17 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .ht_params = &iwl6000_ht_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { - .name = "6000 Series 2x2 BG Gen2b", + .name = "Intel(R) Centrino(R) Advanced-N 6230 BG", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -675,18 +670,17 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { - .name = "6000 Series 1x2 BGN Gen2b", + .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -696,18 +690,17 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .ht_params = &iwl6000_ht_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl6000g2b_bg_cfg = { - .name = "6000 Series 1x2 BG Gen2b", + .name = "Intel(R) Centrino(R) Wireless-N 1030 BG", .fw_name_pre = IWL6000G2B_FW_PRE, .ucode_api_max = IWL6000G2_UCODE_API_MAX, .ucode_api_min = IWL6000G2_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -716,6 +709,8 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -728,9 +723,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, + .valid_tx_ant = ANT_BC, /* .cfg overwrite */ + .valid_rx_ant = ANT_BC, /* .cfg overwrite */ .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -738,6 +732,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .pa_type = IWL_PA_INTERNAL, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -745,15 +740,15 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, + .valid_tx_ant = ANT_BC, /* .cfg overwrite */ + .valid_rx_ant = ANT_BC, /* .cfg overwrite */ .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl6000_base_params, .pa_type = IWL_PA_INTERNAL, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -761,15 +756,15 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, + .valid_tx_ant = ANT_BC, /* .cfg overwrite */ + .valid_rx_ant = ANT_BC, /* .cfg overwrite */ .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl6000_base_params, .pa_type = IWL_PA_INTERNAL, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -777,9 +772,6 @@ struct iwl_cfg iwl6050_2agn_cfg = { .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .ops = &iwl6050_ops, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, @@ -787,16 +779,14 @@ struct iwl_cfg iwl6050_2agn_cfg = { .base_params = &iwl6050_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl6050g2_bgn_cfg = { - .name = "6050 Series 1x2 BGN Gen2", + .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, .ops = &iwl6050g2_ops, @@ -804,6 +794,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { .base_params = &iwl6050_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .led_mode = IWL_LED_RF_STATE, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -811,15 +802,13 @@ struct iwl_cfg iwl6050_2abg_cfg = { .fw_name_pre = IWL6050_FW_PRE, .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .ops = &iwl6050_ops, .mod_params = &iwlagn_mod_params, .base_params = &iwl6050_base_params, .need_dc_calib = true, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -827,9 +816,6 @@ struct iwl_cfg iwl6000_3agn_cfg = { .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, @@ -837,16 +823,14 @@ struct iwl_cfg iwl6000_3agn_cfg = { .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .led_mode = IWL_LED_BLINK, }; struct iwl_cfg iwl130_bgn_cfg = { - .name = "Intel(R) 130 Series 1x1 BGN", + .name = "Intel(R) Centrino(R) Wireless-N 130 BGN", .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL130_UCODE_API_MAX, - .ucode_api_min = IWL130_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -855,18 +839,17 @@ struct iwl_cfg iwl130_bgn_cfg = { .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; struct iwl_cfg iwl130_bg_cfg = { - .name = "Intel(R) 130 Series 1x2 BG", + .name = "Intel(R) Centrino(R) Wireless-N 130 BG", .fw_name_pre = IWL6000G2B_FW_PRE, - .ucode_api_max = IWL130_UCODE_API_MAX, - .ucode_api_min = IWL130_UCODE_API_MIN, - .sku = IWL_SKU_G, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_A, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, @@ -874,6 +857,8 @@ struct iwl_cfg iwl130_bg_cfg = { .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, + .led_mode = IWL_LED_RF_STATE, + .adv_pm = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -882,4 +867,3 @@ MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index e2019e756936..d16bb5ede014 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -732,8 +732,122 @@ static inline u8 find_first_chain(u8 mask) return CHAIN_C; } +/** + * Run disconnected antenna algorithm to find out which antennas are + * disconnected. + */ +static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, + struct iwl_chain_noise_data *data) +{ + u32 active_chains = 0; + u32 max_average_sig; + u16 max_average_sig_antenna_i; + u8 num_tx_chains; + u8 first_chain; + u16 i = 0; + + average_sig[0] = data->chain_signal_a / + priv->cfg->base_params->chain_noise_num_beacons; + average_sig[1] = data->chain_signal_b / + priv->cfg->base_params->chain_noise_num_beacons; + average_sig[2] = data->chain_signal_c / + priv->cfg->base_params->chain_noise_num_beacons; + + if (average_sig[0] >= average_sig[1]) { + max_average_sig = average_sig[0]; + max_average_sig_antenna_i = 0; + active_chains = (1 << max_average_sig_antenna_i); + } else { + max_average_sig = average_sig[1]; + max_average_sig_antenna_i = 1; + active_chains = (1 << max_average_sig_antenna_i); + } + + if (average_sig[2] >= max_average_sig) { + max_average_sig = average_sig[2]; + max_average_sig_antenna_i = 2; + active_chains = (1 << max_average_sig_antenna_i); + } + + IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", + average_sig[0], average_sig[1], average_sig[2]); + IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", + max_average_sig, max_average_sig_antenna_i); + + /* Compare signal strengths for all 3 receivers. */ + for (i = 0; i < NUM_RX_CHAINS; i++) { + if (i != max_average_sig_antenna_i) { + s32 rssi_delta = (max_average_sig - average_sig[i]); + + /* If signal is very weak, compared with + * strongest, mark it as disconnected. */ + if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) + data->disconn_array[i] = 1; + else + active_chains |= (1 << i); + IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " + "disconn_array[i] = %d\n", + i, rssi_delta, data->disconn_array[i]); + } + } + + /* + * The above algorithm sometimes fails when the ucode + * reports 0 for all chains. It's not clear why that + * happens to start with, but it is then causing trouble + * because this can make us enable more chains than the + * hardware really has. + * + * To be safe, simply mask out any chains that we know + * are not on the device. + */ + active_chains &= priv->hw_params.valid_rx_ant; + + num_tx_chains = 0; + for (i = 0; i < NUM_RX_CHAINS; i++) { + /* loops on all the bits of + * priv->hw_setting.valid_tx_ant */ + u8 ant_msk = (1 << i); + if (!(priv->hw_params.valid_tx_ant & ant_msk)) + continue; + + num_tx_chains++; + if (data->disconn_array[i] == 0) + /* there is a Tx antenna connected */ + break; + if (num_tx_chains == priv->hw_params.tx_chains_num && + data->disconn_array[i]) { + /* + * If all chains are disconnected + * connect the first valid tx chain + */ + first_chain = + find_first_chain(priv->cfg->valid_tx_ant); + data->disconn_array[first_chain] = 0; + active_chains |= BIT(first_chain); + IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \ + W/A - declare %d as connected\n", + first_chain); + break; + } + } + + if (active_chains != priv->hw_params.valid_rx_ant && + active_chains != priv->chain_noise_data.active_chains) + IWL_DEBUG_CALIB(priv, + "Detected that not all antennas are connected! " + "Connected: %#x, valid: %#x.\n", + active_chains, priv->hw_params.valid_rx_ant); + + /* Save for use within RXON, TX, SCAN commands, etc. */ + data->active_chains = active_chains; + IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", + active_chains); +} + + /* - * Accumulate 20 beacons of signal and noise statistics for each of + * Accumulate 16 beacons of signal and noise statistics for each of * 3 receivers/antennas/rx-chains, then figure out: * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. @@ -750,8 +864,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) u32 chain_sig_c; u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; - u32 max_average_sig; - u16 max_average_sig_antenna_i; u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; u16 i = 0; @@ -759,11 +871,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) u16 stat_chnum = INITIALIZATION_VALUE; u8 rxon_band24; u8 stat_band24; - u32 active_chains = 0; - u8 num_tx_chains; unsigned long flags; struct statistics_rx_non_phy *rx_info; - u8 first_chain; + /* * MULTI-FIXME: * When we support multiple interfaces on different channels, @@ -869,108 +979,16 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) return; /* Analyze signal for disconnected antenna */ - average_sig[0] = data->chain_signal_a / - priv->cfg->base_params->chain_noise_num_beacons; - average_sig[1] = data->chain_signal_b / - priv->cfg->base_params->chain_noise_num_beacons; - average_sig[2] = data->chain_signal_c / - priv->cfg->base_params->chain_noise_num_beacons; - - if (average_sig[0] >= average_sig[1]) { - max_average_sig = average_sig[0]; - max_average_sig_antenna_i = 0; - active_chains = (1 << max_average_sig_antenna_i); - } else { - max_average_sig = average_sig[1]; - max_average_sig_antenna_i = 1; - active_chains = (1 << max_average_sig_antenna_i); - } - - if (average_sig[2] >= max_average_sig) { - max_average_sig = average_sig[2]; - max_average_sig_antenna_i = 2; - active_chains = (1 << max_average_sig_antenna_i); - } - - IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", - average_sig[0], average_sig[1], average_sig[2]); - IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", - max_average_sig, max_average_sig_antenna_i); - - /* Compare signal strengths for all 3 receivers. */ - for (i = 0; i < NUM_RX_CHAINS; i++) { - if (i != max_average_sig_antenna_i) { - s32 rssi_delta = (max_average_sig - average_sig[i]); - - /* If signal is very weak, compared with - * strongest, mark it as disconnected. */ - if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) - data->disconn_array[i] = 1; - else - active_chains |= (1 << i); - IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " - "disconn_array[i] = %d\n", - i, rssi_delta, data->disconn_array[i]); - } - } - - /* - * The above algorithm sometimes fails when the ucode - * reports 0 for all chains. It's not clear why that - * happens to start with, but it is then causing trouble - * because this can make us enable more chains than the - * hardware really has. - * - * To be safe, simply mask out any chains that we know - * are not on the device. - */ if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ - active_chains &= first_antenna(priv->hw_params.valid_rx_ant); + priv->cfg->bt_params->advanced_bt_coexist) { + /* Disable disconnected antenna algorithm for advanced + bt coex, assuming valid antennas are connected */ + data->active_chains = priv->hw_params.valid_rx_ant; + for (i = 0; i < NUM_RX_CHAINS; i++) + if (!(data->active_chains & (1<<i))) + data->disconn_array[i] = 1; } else - active_chains &= priv->hw_params.valid_rx_ant; - - num_tx_chains = 0; - for (i = 0; i < NUM_RX_CHAINS; i++) { - /* loops on all the bits of - * priv->hw_setting.valid_tx_ant */ - u8 ant_msk = (1 << i); - if (!(priv->hw_params.valid_tx_ant & ant_msk)) - continue; - - num_tx_chains++; - if (data->disconn_array[i] == 0) - /* there is a Tx antenna connected */ - break; - if (num_tx_chains == priv->hw_params.tx_chains_num && - data->disconn_array[i]) { - /* - * If all chains are disconnected - * connect the first valid tx chain - */ - first_chain = - find_first_chain(priv->cfg->valid_tx_ant); - data->disconn_array[first_chain] = 0; - active_chains |= BIT(first_chain); - IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", - first_chain); - break; - } - } - - if (active_chains != priv->hw_params.valid_rx_ant && - active_chains != priv->chain_noise_data.active_chains) - IWL_DEBUG_CALIB(priv, - "Detected that not all antennas are connected! " - "Connected: %#x, valid: %#x.\n", - active_chains, priv->hw_params.valid_rx_ant); - - /* Save for use within RXON, TX, SCAN commands, etc. */ - priv->chain_noise_data.active_chains = active_chains; - IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", - active_chains); + iwl_find_disconn_antenna(priv, average_sig, data); /* Analyze noise for rx balance */ average_noise[0] = data->chain_noise_a / diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index a650baba0809..dbada761624d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -248,6 +248,47 @@ err: } +int iwl_eeprom_check_sku(struct iwl_priv *priv) +{ + u16 eeprom_sku; + u16 radio_cfg; + + eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); + + priv->cfg->sku = ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> + EEPROM_SKU_CAP_BAND_POS); + if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) + priv->cfg->sku |= IWL_SKU_N; + + if (!priv->cfg->sku) { + IWL_ERR(priv, "Invalid device sku\n"); + return -EINVAL; + } + + IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku); + + if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { + /* not using .cfg overwrite */ + radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); + priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + priv->cfg->valid_rx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { + IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n", + priv->cfg->valid_tx_ant, + priv->cfg->valid_rx_ant); + return -EINVAL; + } + IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n", + priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant); + } + /* + * for some special cases, + * EEPROM did not reflect the correct antenna setting + * so overwrite the valid tx/rx antenna from .cfg + */ + return 0; +} + void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) { const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index ffb2f4111ad0..366340f3fb0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -307,6 +307,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) if (ctx_bss->vif && ctx_pan->vif) { int bcnint = ctx_pan->vif->bss_conf.beacon_int; + int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; /* should be set, but seems unused?? */ cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); @@ -329,10 +330,10 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) if (test_bit(STATUS_SCAN_HW, &priv->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { - slot0 = bcnint * 3 - 20; + slot0 = dtim * bcnint * 3 - 20; slot1 = 20; } else if (!ctx_pan->vif->bss_conf.idle && - !ctx_pan->vif->bss_conf.assoc) { + !ctx_pan->vif->bss_conf.assoc) { slot1 = bcnint * 3 - 20; slot0 = 20; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index b555edd53354..407f0bb8422a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -445,22 +445,17 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); } } else { - BUG_ON(txq_id != txq->swq_id); iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); + iwl_wake_queue(priv, txq); } iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); @@ -496,6 +491,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + "TX Power requested while scanning!\n")) + return -EAGAIN; + /* half dBm need to multiply */ tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); @@ -522,9 +521,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, - sizeof(tx_power_cmd), &tx_power_cmd, - NULL); + return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd), + &tx_power_cmd); } void iwlagn_temperature(struct iwl_priv *priv) @@ -750,6 +748,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) } else iwlagn_txq_ctx_reset(priv); + if (priv->cfg->base_params->shadow_reg_enable) { + /* enable shadow regs in HW */ + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, + 0x800FFFFF); + } + set_bit(STATUS_INIT, &priv->status); return 0; @@ -1584,22 +1588,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return ret; } -void iwlagn_post_scan(struct iwl_priv *priv) -{ - struct iwl_rxon_context *ctx; - - /* - * Since setting the RXON may have been deferred while - * performing the scan, fire one off if needed - */ - for_each_context(priv, ctx) - if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) - iwlagn_commit_rxon(priv, ctx); - - if (priv->cfg->ops->hcmd->set_pan_params) - priv->cfg->ops->hcmd->set_pan_params(priv); -} - int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { @@ -1790,7 +1778,7 @@ static const __le32 iwlagn_def_3w_lookup[12] = { cpu_to_le32(0xc0004000), cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0004000), + cpu_to_le32(0xf0005000), }; static const __le32 iwlagn_concurrent_lookup[12] = { @@ -1826,6 +1814,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) bt_cmd.prio_boost = 0; bt_cmd.kill_ack_mask = priv->kill_ack_mask; bt_cmd.kill_cts_mask = priv->kill_cts_mask; + bt_cmd.valid = priv->bt_valid; bt_cmd.tx_prio_boost = 0; bt_cmd.rx_prio_boost = 0; @@ -1841,6 +1830,10 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) } else { bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W << IWLAGN_BT_FLAG_COEX_MODE_SHIFT; + if (priv->cfg->bt_params && + priv->cfg->bt_params->bt_sco_disable) + bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE; + if (priv->bt_ch_announce) bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION; IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags); @@ -1884,12 +1877,20 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) struct iwl_rxon_context *ctx; int smps_request = -1; + /* + * Note: bt_traffic_load can be overridden by scan complete and + * coex profile notifications. Ignore that since only bad consequence + * can be not matching debug print with actual state. + */ IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", priv->bt_traffic_load); switch (priv->bt_traffic_load) { case IWL_BT_COEX_TRAFFIC_LOAD_NONE: - smps_request = IEEE80211_SMPS_AUTOMATIC; + if (priv->bt_status) + smps_request = IEEE80211_SMPS_DYNAMIC; + else + smps_request = IEEE80211_SMPS_AUTOMATIC; break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: smps_request = IEEE80211_SMPS_DYNAMIC; @@ -1906,6 +1907,16 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) mutex_lock(&priv->mutex); + /* + * We can not send command to firmware while scanning. When the scan + * complete we will schedule this work again. We do check with mutex + * locked to prevent new scan request to arrive. We do not check + * STATUS_SCANNING to avoid race when queue_work two times from + * different notifications, but quit and not perform any work at all. + */ + if (test_bit(STATUS_SCAN_HW, &priv->status)) + goto out; + if (priv->cfg->ops->lib->update_chain_flags) priv->cfg->ops->lib->update_chain_flags(priv); @@ -1915,7 +1926,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) ieee80211_request_smps(ctx->vif, smps_request); } } - +out: mutex_unlock(&priv->mutex); } @@ -1986,24 +1997,29 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, BT_UART_MSG_FRAME7CONNECTABLE_POS); } -static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv, - struct iwl_bt_uart_msg *uart_msg) +static void iwlagn_set_kill_msk(struct iwl_priv *priv, + struct iwl_bt_uart_msg *uart_msg) { - u8 kill_ack_msk; - __le32 bt_kill_ack_msg[2] = { - cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) }; - - kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK | - BT_UART_MSG_FRAME3SNIFF_MSK | - BT_UART_MSG_FRAME3SCOESCO_MSK) & - uart_msg->frame3) == 0) ? 1 : 0; - if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) { + u8 kill_msk; + static const __le32 bt_kill_ack_msg[2] = { + IWLAGN_BT_KILL_ACK_MASK_DEFAULT, + IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; + static const __le32 bt_kill_cts_msg[2] = { + IWLAGN_BT_KILL_CTS_MASK_DEFAULT, + IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; + + kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) + ? 1 : 0; + if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] || + priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) { priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK; - priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk]; + priv->kill_ack_mask = bt_kill_ack_msg[kill_msk]; + priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK; + priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; + /* schedule to send runtime bt_config */ queue_work(priv->workqueue, &priv->bt_runtime_config); } - } void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, @@ -2014,7 +2030,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; - u8 last_traffic_load; IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status); @@ -2023,11 +2038,10 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, coex->bt_ci_compliance); iwlagn_print_uartmsg(priv, uart_msg); - last_traffic_load = priv->notif_bt_traffic_load; - priv->notif_bt_traffic_load = coex->bt_traffic_load; + priv->last_bt_traffic_load = priv->bt_traffic_load; if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { if (priv->bt_status != coex->bt_status || - last_traffic_load != coex->bt_traffic_load) { + priv->last_bt_traffic_load != coex->bt_traffic_load) { if (coex->bt_status) { /* BT on */ if (!priv->bt_ch_announce) @@ -2056,7 +2070,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, } } - iwlagn_set_kill_ack_msk(priv, uart_msg); + iwlagn_set_kill_msk(priv, uart_msg); /* FIXME: based on notification, adjust the prio_boost */ @@ -2276,7 +2290,7 @@ static const char *get_csr_string(int cmd) void iwl_dump_csr(struct iwl_priv *priv) { int i; - u32 csr_tbl[] = { + static const u32 csr_tbl[] = { CSR_HW_IF_CONFIG_REG, CSR_INT_COALESCING, CSR_INT, @@ -2335,7 +2349,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) int pos = 0; size_t bufsz = 0; #endif - u32 fh_tbl[] = { + static const u32 fh_tbl[] = { FH_RSCSR_CHNL0_STTS_WPTR_REG, FH_RSCSR_CHNL0_RBDCB_BASE_REG, FH_RSCSR_CHNL0_WPTR, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 065553629de5..f450adc72361 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -833,17 +833,23 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_lq_sta *lq_sta) { struct iwl_scale_tbl_info *tbl; - bool full_concurrent; + bool full_concurrent = priv->bt_full_concurrent; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) - full_concurrent = true; - else - full_concurrent = false; - spin_unlock_irqrestore(&priv->lock, flags); - - if (priv->bt_full_concurrent != full_concurrent) { + if (priv->bt_ant_couple_ok) { + /* + * Is there a need to switch between + * full concurrency and 3-wire? + */ + spin_lock_irqsave(&priv->lock, flags); + if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) + full_concurrent = true; + else + full_concurrent = false; + spin_unlock_irqrestore(&priv->lock, flags); + } + if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || + (priv->bt_full_concurrent != full_concurrent)) { priv->bt_full_concurrent = full_concurrent; /* Update uCode's rate table. */ @@ -1040,8 +1046,7 @@ done: if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); - /* Is there a need to switch between full concurrency and 3-wire? */ - if (priv->bt_ant_couple_ok) + if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -3010,10 +3015,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, */ if (priv && priv->cfg->bt_params && priv->cfg->bt_params->agg_time_limit && - priv->cfg->bt_params->agg_time_limit >= - LINK_QUAL_AGG_TIME_LIMIT_MIN && - priv->cfg->bt_params->agg_time_limit <= - LINK_QUAL_AGG_TIME_LIMIT_MAX) + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) lq_cmd->agg_params.agg_time_limit = cpu_to_le16(priv->cfg->bt_params->agg_time_limit); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c new file mode 100644 index 000000000000..203ee60a82b4 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -0,0 +1,632 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-agn.h" +#include "iwl-sta.h" +#include "iwl-core.h" +#include "iwl-agn-calib.h" + +static int iwlagn_disable_bss(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_rxon_cmd *send) +{ + __le32 old_filter = send->filter_flags; + int ret; + + send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); + + send->filter_flags = old_filter; + + if (ret) + IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret); + + return ret; +} + +static int iwlagn_disable_pan(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_rxon_cmd *send) +{ + __le32 old_filter = send->filter_flags; + u8 old_dev_type = send->dev_type; + int ret; + + send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + send->dev_type = RXON_DEV_TYPE_P2P; + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); + + send->filter_flags = old_filter; + send->dev_type = old_dev_type; + + if (ret) + IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); + + /* FIXME: WAIT FOR PAN DISABLE */ + msleep(300); + + return ret; +} + +static void iwlagn_update_qos(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + int ret; + + if (!ctx->is_active) + return; + + ctx->qos_data.def_qos_parm.qos_flags = 0; + + if (ctx->qos_data.qos_active) + ctx->qos_data.def_qos_parm.qos_flags |= + QOS_PARAM_FLG_UPDATE_EDCA_MSK; + + if (ctx->ht.enabled) + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", + ctx->qos_data.qos_active, + ctx->qos_data.def_qos_parm.qos_flags); + + ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd, + sizeof(struct iwl_qosparam_cmd), + &ctx->qos_data.def_qos_parm); + if (ret) + IWL_ERR(priv, "Failed to update QoS\n"); +} + +static int iwlagn_update_beacon(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + lockdep_assert_held(&priv->mutex); + + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); + if (!priv->beacon_skb) + return -ENOMEM; + return iwlagn_send_beacon_cmd(priv); +} + +/** + * iwlagn_commit_rxon - commit staging_rxon to hardware + * + * The RXON command in staging_rxon is committed to the hardware and + * the active_rxon structure is updated with the new data. This + * function correctly transitions out of the RXON_ASSOC_MSK state if + * a HW tune is required based on the RXON structure changes. + */ +int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + /* cast away the const for active_rxon in this function */ + struct iwl_rxon_cmd *active = (void *)&ctx->active; + bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); + int ret; + + lockdep_assert_held(&priv->mutex); + + if (!iwl_is_alive(priv)) + return -EBUSY; + + /* This function hardcodes a bunch of dual-mode assumptions */ + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + + if (!ctx->is_active) + return 0; + + /* always get timestamp with Rx frame */ + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || + !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + + ret = iwl_check_rxon_cmd(priv, ctx); + if (ret) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* + * receive commit_rxon request + * abort any previous channel switch if still in process + */ + if (priv->switch_rxon.switch_in_progress && + (priv->switch_rxon.channel != ctx->staging.channel)) { + IWL_DEBUG_11H(priv, "abort channel switch on %d\n", + le16_to_cpu(priv->switch_rxon.channel)); + iwl_chswitch_done(priv, false); + } + + /* + * If we don't need to send a full RXON, we can use + * iwl_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. + */ + if (!iwl_full_rxon_required(priv, ctx)) { + ret = iwl_send_rxon_assoc(priv, ctx); + if (ret) { + IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); + return ret; + } + + memcpy(active, &ctx->staging, sizeof(*active)); + iwl_print_rx_config_cmd(priv, ctx); + return 0; + } + + if (priv->cfg->ops->hcmd->set_pan_params) { + ret = priv->cfg->ops->hcmd->set_pan_params(priv); + if (ret) + return ret; + } + + iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + + IWL_DEBUG_INFO(priv, + "Going to commit RXON\n" + " * with%s RXON_FILTER_ASSOC_MSK\n" + " * channel = %d\n" + " * bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(ctx->staging.channel), + ctx->staging.bssid_addr); + + /* + * Always clear associated first, but with the correct config. + * This is required as for example station addition for the + * AP station must be done after the BSSID is set to correctly + * set up filters in the device. + */ + if ((old_assoc && new_assoc) || !new_assoc) { + if (ctx->ctxid == IWL_RXON_CTX_BSS) + ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); + else + ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); + if (ret) + return ret; + + memcpy(active, &ctx->staging, sizeof(*active)); + + /* + * Un-assoc RXON clears the station table and WEP + * keys, so we have to restore those afterwards. + */ + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + } + + /* RXON timing must be before associated RXON */ + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); + return ret; + } + + if (new_assoc) { + /* QoS info may be cleared by previous un-assoc RXON */ + iwlagn_update_qos(priv, ctx); + + /* + * We'll run into this code path when beaconing is + * enabled, but then we also need to send the beacon + * to the device. + */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { + ret = iwlagn_update_beacon(priv, ctx->vif); + if (ret) { + IWL_ERR(priv, + "Error sending required beacon (%d)!\n", + ret); + return ret; + } + } + + priv->start_calib = 0; + /* + * Apply the new configuration. + * + * Associated RXON doesn't clear the station table in uCode, + * so we don't need to restore stations etc. after this. + */ + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + memcpy(active, &ctx->staging, sizeof(*active)); + + iwl_reprogram_ap_sta(priv, ctx); + + /* IBSS beacon needs to be sent after setting assoc */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) + if (iwlagn_update_beacon(priv, ctx->vif)) + IWL_ERR(priv, "Error sending IBSS beacon\n"); + } + + iwl_print_rx_config_cmd(priv, ctx); + + iwl_init_sensitivity(priv); + + /* + * If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames. + * + * FIXME: which RXON requires a tune? Can we optimise this out in + * some cases? + */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; + } + + return 0; +} + +int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx; + struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = conf->channel; + const struct iwl_channel_info *ch_info; + int ret = 0; + bool ht_changed[NUM_IWL_RXON_CTX] = {}; + + IWL_DEBUG_MAC80211(priv, "changed %#x", changed); + + mutex_lock(&priv->mutex); + + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + goto out; + } + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + + if (changed & (IEEE80211_CONF_CHANGE_SMPS | + IEEE80211_CONF_CHANGE_CHANNEL)) { + /* mac80211 uses static for non-HT which is what we want */ + priv->current_ht_config.smps = conf->smps_mode; + + /* + * Recalculate chain counts. + * + * If monitor mode is enabled then mac80211 will + * set up the SM PS mode to OFF if an HT channel is + * configured. + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + for_each_context(priv, ctx) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + unsigned long flags; + + ch_info = iwl_get_channel_info(priv, channel->band, + channel->hw_value); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto out; + } + + spin_lock_irqsave(&priv->lock, flags); + + for_each_context(priv, ctx) { + /* Configure HT40 channels */ + if (ctx->ht.enabled != conf_is_ht(conf)) { + ctx->ht.enabled = conf_is_ht(conf); + ht_changed[ctx->ctxid] = true; + } + + if (ctx->ht.enabled) { + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } + } else + ctx->ht.is_40mhz = false; + + /* + * Default to no protection. Protection mode will + * later be set from BSS config in iwl_ht_conf + */ + ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if (le16_to_cpu(ctx->staging.channel) != + channel->hw_value) + ctx->staging.flags = 0; + + iwl_set_rxon_channel(priv, channel, ctx); + iwl_set_rxon_ht(priv, &priv->current_ht_config); + + iwl_set_flags_for_band(priv, ctx, channel->band, + ctx->vif); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_update_bcast_stations(priv); + + /* + * The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists. + */ + iwl_set_rate(priv); + } + + if (changed & (IEEE80211_CONF_CHANGE_PS | + IEEE80211_CONF_CHANGE_IDLE)) { + ret = iwl_power_update_mode(priv, false); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + for_each_context(priv, ctx) { + if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + continue; + iwlagn_commit_rxon(priv, ctx); + if (ht_changed[ctx->ctxid]) + iwlagn_update_qos(priv, ctx); + } + out: + mutex_unlock(&priv->mutex); + return ret; +} + +static void iwlagn_check_needed_chains(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_vif *vif = ctx->vif; + struct iwl_rxon_context *tmp; + struct ieee80211_sta *sta; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + bool need_multiple; + + lockdep_assert_held(&priv->mutex); + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (sta) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + int maxstreams; + + maxstreams = (ht_cap->mcs.tx_params & + IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) + >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + maxstreams += 1; + + need_multiple = true; + + if ((ht_cap->mcs.rx_mask[1] == 0) && + (ht_cap->mcs.rx_mask[2] == 0)) + need_multiple = false; + if (maxstreams <= 1) + need_multiple = false; + } else { + /* + * If at all, this can only happen through a race + * when the AP disconnects us while we're still + * setting up the connection, in that case mac80211 + * will soon tell us about that. + */ + need_multiple = false; + } + rcu_read_unlock(); + break; + case NL80211_IFTYPE_ADHOC: + /* currently */ + need_multiple = false; + break; + default: + /* only AP really */ + need_multiple = true; + break; + } + + ctx->ht_need_multiple_chains = need_multiple; + + if (!need_multiple) { + /* check all contexts */ + for_each_context(priv, tmp) { + if (!tmp->vif) + continue; + if (tmp->ht_need_multiple_chains) { + need_multiple = true; + break; + } + } + } + + ht_conf->single_chain_sufficient = !need_multiple; +} + +void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + int ret; + bool force = false; + + mutex_lock(&priv->mutex); + + if (WARN_ON(!ctx->vif)) { + mutex_unlock(&priv->mutex); + return; + } + + if (changes & BSS_CHANGED_BEACON_INT) + force = true; + + if (changes & BSS_CHANGED_QOS) { + ctx->qos_data.qos_active = bss_conf->qos; + iwlagn_update_qos(priv, ctx); + } + + ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + if (vif->bss_conf.use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + + if (changes & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + iwl_led_associate(priv); + priv->timestamp = bss_conf->timestamp; + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + } else { + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_led_disassociate(priv); + } + } + + if (ctx->ht.enabled) { + ctx->ht.protection = bss_conf->ht_operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION; + ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode & + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + iwlagn_check_needed_chains(priv, ctx, bss_conf); + iwl_set_rxon_ht(priv, &priv->current_ht_config); + } + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + + if (bss_conf->use_cts_prot) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + else + ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; + + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC) { + if (vif->bss_conf.enable_beacon) { + ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->beacon_ctx = ctx; + } else { + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->beacon_ctx = NULL; + } + } + + if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlagn_commit_rxon(priv, ctx); + + if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) { + /* + * The chain noise calibration will enable PM upon + * completion. If calibration has already been run + * then we need to enable power management here. + */ + if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) + iwl_power_update_mode(priv, false); + + /* Enable RX differential gain and sensitivity calibrations */ + iwl_chain_noise_reset(priv); + priv->start_calib = 1; + } + + if (changes & BSS_CHANGED_IBSS) { + ret = iwlagn_manage_ibss_station(priv, vif, + bss_conf->ibss_joined); + if (ret) + IWL_ERR(priv, "failed to %s IBSS station %pM\n", + bss_conf->ibss_joined ? "add" : "remove", + bss_conf->bssid); + } + + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC && + priv->beacon_ctx) { + if (iwlagn_update_beacon(priv, vif)) + IWL_ERR(priv, "Error sending IBSS beacon\n"); + } + + mutex_unlock(&priv->mutex); +} + +void iwlagn_post_scan(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + + /* + * Since setting the RXON may have been deferred while + * performing the scan, fire one off if needed + */ + for_each_context(priv, ctx) + if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlagn_commit_rxon(priv, ctx); + + if (priv->cfg->ops->hcmd->set_pan_params) + priv->cfg->ops->hcmd->set_pan_params(priv); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 35a30d2e0734..35f085ac336b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -684,7 +684,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) +static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; @@ -714,3 +714,33 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) spin_unlock_irqrestore(&priv->sta_lock, flags); } + +void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + int sta_id; + + switch (cmd) { + case STA_NOTIFY_SLEEP: + WARN_ON(!sta_priv->client); + sta_priv->asleep = true; + if (atomic_read(&sta_priv->pending_frames) > 0) + ieee80211_sta_block_awake(hw, sta, true); + break; + case STA_NOTIFY_AWAKE: + WARN_ON(!sta_priv->client); + if (!sta_priv->asleep) + break; + sta_priv->asleep = false; + sta_id = iwl_sta_id(sta); + if (sta_id != IWL_INVALID_STATION) + iwl_sta_modify_ps_wake(priv, sta_id); + break; + default: + break; + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 2b078a995729..72b1f262796c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -67,8 +67,14 @@ */ static const u8 tid_to_ac[] = { - /* this matches the mac80211 numbers */ - 2, 3, 3, 2, 1, 1, 0, 0 + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO }; static inline int get_ac_from_tid(u16 tid) @@ -518,11 +524,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_cmd_meta *out_meta; struct iwl_tx_cmd *tx_cmd; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - int swq_id, txq_id; + int txq_id; dma_addr_t phys_addr; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; - u16 len, len_org, firstlen, secondlen; + u16 len, firstlen, secondlen; u16 seq_number = 0; __le16 fc; u8 hdr_len; @@ -531,6 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 tid = 0; u8 *qc = NULL; unsigned long flags; + bool is_agg = false; if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); @@ -567,8 +574,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta) sta_priv = (void *)sta->drv_priv; - if (sta_priv && sta_priv->asleep) { - WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); + if (sta_priv && sta_priv->asleep && + (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { /* * This sends an asynchronous command to the device, * but we can rely on it being processed before the @@ -616,11 +623,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_AMPDU && priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + is_agg = true; } } txq = &priv->txq[txq_id]; - swq_id = txq->swq_id; q = &txq->q; if (unlikely(iwl_queue_space(q) < q->high_mark)) { @@ -687,30 +694,23 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) */ len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; - firstlen = len = (len + 3) & ~3; - - if (len_org != len) - len_org = 1; - else - len_org = 0; + firstlen = (len + 3) & ~3; /* Tell NIC about any 2-byte padding after MAC header */ - if (len_org) + if (firstlen != len) tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ txcmd_phys = pci_map_single(priv->pci_dev, - &out_cmd->hdr, len, + &out_cmd->hdr, firstlen, PCI_DMA_BIDIRECTIONAL); dma_unmap_addr_set(out_meta, mapping, txcmd_phys); - dma_unmap_len_set(out_meta, len, len); + dma_unmap_len_set(out_meta, len, firstlen); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, len, 1, 0); + txcmd_phys, firstlen, 1, 0); if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -721,23 +721,21 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up TFD's 2nd entry to point directly to remainder of skb, * if any (802.11 null frames have no payload). */ - secondlen = len = skb->len - hdr_len; - if (len) { + secondlen = skb->len - hdr_len; + if (secondlen > 0) { phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, - len, PCI_DMA_TODEVICE); + secondlen, PCI_DMA_TODEVICE); priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, len, + phys_addr, secondlen, 0, 0); } scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; /* take back ownership of DMA buffer to enable update */ pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); + firstlen, PCI_DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); @@ -753,7 +751,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) le16_to_cpu(tx_cmd->len)); pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); + firstlen, PCI_DMA_BIDIRECTIONAL); trace_iwlwifi_dev_tx(priv, &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], @@ -773,8 +771,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) * whether or not we should update the write pointer. */ - /* avoid atomic ops if it isn't an associated client */ - if (sta_priv && sta_priv->client) + /* + * Avoid atomic ops if it isn't an associated client. + * Also, if this is a packet for aggregation, don't + * increase the counter because the ucode will stop + * aggregation queues when their respective station + * goes to sleep. + */ + if (sta_priv && sta_priv->client && !is_agg) atomic_inc(&sta_priv->pending_frames); if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { @@ -784,7 +788,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); } else { - iwl_stop_queue(priv, txq->swq_id); + iwl_stop_queue(priv, txq); } } @@ -1013,7 +1017,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id); + iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, @@ -1153,14 +1157,15 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, return 0; } -static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) +static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + const u8 *addr1) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; struct ieee80211_sta *sta; struct iwl_station_priv *sta_priv; rcu_read_lock(); - sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1); + sta = ieee80211_find_sta(ctx->vif, addr1); if (sta) { sta_priv = (void *)sta->drv_priv; /* avoid atomic ops if this isn't a client */ @@ -1169,6 +1174,15 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) ieee80211_sta_block_awake(priv->hw, sta, false); } rcu_read_unlock(); +} + +static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info, + bool is_agg) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; + + if (!is_agg) + iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1); ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); } @@ -1193,7 +1207,8 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - iwlagn_tx_status(priv, tx_info); + iwlagn_tx_status(priv, tx_info, + txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); hdr = (struct ieee80211_hdr *)tx_info->skb->data; if (hdr && ieee80211_is_data_qos(hdr->frame_control)) @@ -1241,37 +1256,61 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, if (sh < 0) /* tbw something is wrong with indices */ sh += 0x100; - /* don't use 64-bit values for now */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - if (agg->frame_count > (64 - sh)) { IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); return -1; } - - /* check for success or failure according to the - * transmitted bitmap and block-ack bitmap */ - sent_bitmap = bitmap & agg->bitmap; - - /* For each frame attempted in aggregation, - * update driver's record of tx frame's status. */ - i = 0; - while (sent_bitmap) { - ack = sent_bitmap & 1ULL; - successes += ack; - IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", - ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, - agg->start_idx + i); - sent_bitmap >>= 1; - ++i; + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + /* + * sent and ack information provided by uCode + * use it instead of figure out ourself + */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + 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); + } else { + /* don't use 64-bit values for now */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + + /* check for success or failure according to the + * transmitted bitmap and block-ack bitmap */ + sent_bitmap = bitmap & agg->bitmap; + + /* For each frame attempted in aggregation, + * update driver's record of tx frame's status. */ + i = 0; + while (sent_bitmap) { + ack = sent_bitmap & 1ULL; + successes += ack; + IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", + ack ? "ACK" : "NACK", i, + (agg->start_idx + i) & 0xff, + agg->start_idx + i); + sent_bitmap >>= 1; + ++i; + } } - info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_len = successes; - info->status.ampdu_len = agg->frame_count; + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; + + } else { + info->status.ampdu_ack_len = successes; + info->status.ampdu_len = agg->frame_count; + } iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); @@ -1385,7 +1424,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && priv->mac80211_registered && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq->swq_id); + iwl_wake_queue(priv, txq); iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 703621107dac..0bdd2bb0bbd3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -40,30 +40,36 @@ #include "iwl-agn.h" #include "iwl-agn-calib.h" -static const s8 iwlagn_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWLAGN_CMD_FIFO_NUM, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, - IWL_TX_FIFO_UNUSED, +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, }; -static const s8 iwlagn_ipan_queue_to_tx_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - IWL_TX_FIFO_BK_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWLAGN_CMD_FIFO_NUM, +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, }; static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { @@ -429,7 +435,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwlagn_alive_notify(struct iwl_priv *priv) { - const s8 *queues; + const struct queue_to_fifo_ac *queue_to_fifo; u32 a; unsigned long flags; int i, chan; @@ -492,9 +498,9 @@ int iwlagn_alive_notify(struct iwl_priv *priv) /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - queues = iwlagn_ipan_queue_to_tx_fifo; + queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; else - queues = iwlagn_default_queue_to_tx_fifo; + queue_to_fifo = iwlagn_default_queue_to_tx_fifo; iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); @@ -510,14 +516,17 @@ int iwlagn_alive_notify(struct iwl_priv *priv) BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); for (i = 0; i < 10; i++) { - int ac = queues[i]; + int fifo = queue_to_fifo[i].fifo; + int ac = queue_to_fifo[i].ac; iwl_txq_ctx_activate(priv, i); - if (ac == IWL_TX_FIFO_UNUSED) + if (fifo == IWL_TX_FIFO_UNUSED) continue; - iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); + if (ac != IWL_AC_UNSET) + iwl_set_swq_id(&priv->txq[i], ac, i); + iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c2636a7ab9ee..50cee2b5a6b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -90,170 +90,6 @@ MODULE_ALIAS("iwl4965"); static int iwlagn_ant_coupling; static bool iwlagn_bt_ch_announce = 1; -/** - * iwlagn_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - /* cast away the const for active_rxon in this function */ - struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; - int ret; - bool new_assoc = - !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); - bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -EBUSY; - - if (!ctx->is_active) - return 0; - - /* always get timestamp with Rx frame */ - ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - - ret = iwl_check_rxon_cmd(priv, ctx); - if (ret) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* - * receive commit_rxon request - * abort any previous channel switch if still in process - */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { - IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); - iwl_chswitch_done(priv, false); - } - - /* If we don't need to send a full RXON, we can use - * iwl_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv, ctx)) { - ret = iwl_send_rxon_assoc(priv, ctx); - if (ret) { - IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); - return ret; - } - - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - iwl_print_rx_config_cmd(priv, ctx); - return 0; - } - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated_ctx(ctx) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), - active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (ret) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); - return ret; - } - iwl_clear_ucode_stations(priv, ctx); - iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); - return ret; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(ctx->staging.channel), - ctx->staging.bssid_addr); - - iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); - - if (!old_assoc) { - /* - * First of all, before setting associated, we need to - * send RXON timing so the device knows about the DTIM - * period and other timing values - */ - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) { - IWL_ERR(priv, "Error setting RXON timing!\n"); - return ret; - } - } - - if (priv->cfg->ops->hcmd->set_pan_params) { - ret = priv->cfg->ops->hcmd->set_pan_params(priv); - if (ret) - return ret; - } - - /* Apply the new configuration - * RXON unassoc clears the station table in uCode so restoration of - * stations is needed after it (the RXON command) completes - */ - if (!new_assoc) { - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), &ctx->staging); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - iwl_clear_ucode_stations(priv, ctx); - iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); - return ret; - } - } - if (new_assoc) { - priv->start_calib = 0; - /* Apply the new configuration - * RXON assoc doesn't clear the station table in uCode, - */ - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), &ctx->staging); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); - } - iwl_print_rx_config_cmd(priv, ctx); - - iwl_init_sensitivity(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; - } - - return 0; -} - void iwl_update_chain_flags(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; @@ -261,7 +97,8 @@ void iwl_update_chain_flags(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_rxon_chain) { for_each_context(priv, ctx) { priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - iwlcore_commit_rxon(priv, ctx); + if (ctx->active.rx_chain != ctx->staging.rx_chain) + iwlcore_commit_rxon(priv, ctx); } } } @@ -411,7 +248,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, return sizeof(*tx_beacon_cmd) + frame_size; } -static int iwl_send_beacon_cmd(struct iwl_priv *priv) + +int iwlagn_send_beacon_cmd(struct iwl_priv *priv) { struct iwl_frame *frame; unsigned int frame_size; @@ -661,7 +499,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) priv->beacon_skb = beacon; - iwl_send_beacon_cmd(priv); + iwlagn_send_beacon_cmd(priv); out: mutex_unlock(&priv->mutex); } @@ -2879,6 +2717,8 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); + set_bit(STATUS_READY, &priv->status); + /* Configure the adapter for unassociated operation */ iwlcore_commit_rxon(priv, ctx); @@ -2888,7 +2728,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_leds_init(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); iwl_power_update_mode(priv, true); @@ -2978,7 +2817,8 @@ static void __iwl_down(struct iwl_priv *priv) STATUS_EXIT_PENDING; /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); + if (priv->cfg->ops->lib->isr_ops.disable) + priv->cfg->ops->lib->isr_ops.disable(priv); iwlagn_txq_ctx_stop(priv); iwlagn_rxq_stop(priv); @@ -3201,7 +3041,8 @@ static void iwl_bg_alive_start(struct work_struct *data) return; /* enable dram interrupt */ - iwl_reset_ict(priv); + if (priv->cfg->ops->lib->isr_ops.reset) + priv->cfg->ops->lib->isr_ops.reset(priv); mutex_lock(&priv->mutex); iwl_alive_start(priv); @@ -3309,92 +3150,6 @@ static void iwl_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -#define IWL_DELAY_NEXT_SCAN (HZ*2) - -void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx; - struct ieee80211_conf *conf = NULL; - int ret = 0; - - if (!vif || !priv->is_open) - return; - - ctx = iwl_rxon_ctx_from_vif(vif); - - if (vif->type == NL80211_IFTYPE_AP) { - IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); - return; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - iwl_scan_cancel_timeout(priv, 200); - - conf = ieee80211_get_hw_conf(priv->hw); - - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) - IWL_WARN(priv, "RXON timing - " - "Attempting to continue.\n"); - - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - - iwl_set_rxon_ht(priv, &priv->current_ht_config); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); - - IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - vif->bss_conf.aid, vif->bss_conf.beacon_int); - - if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - } - - iwlcore_commit_rxon(priv, ctx); - - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, ctx->active.bssid_addr); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - iwl_send_beacon_cmd(priv); - break; - default: - IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, vif->type); - break; - } - - /* the chain noise calibration will enabled PM upon completion - * If chain noise has already been run, then we need to enable - * power management here */ - if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) - iwl_power_update_mode(priv, false); - - /* Enable Rx differential gain and sensitivity calibrations */ - iwl_chain_noise_reset(priv); - priv->start_calib = 1; - -} - /***************************************************************************** * * mac80211 entry point functions @@ -3420,7 +3175,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_NEED_DTIM_PERIOD | - IEEE80211_HW_SPECTRUM_MGMT; + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (!priv->cfg->base_params->broken_powersave) hw->flags |= IEEE80211_HW_SUPPORTS_PS | @@ -3474,7 +3230,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, } -static int iwl_mac_start(struct ieee80211_hw *hw) +int iwlagn_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; @@ -3515,7 +3271,7 @@ out: return 0; } -static void iwl_mac_stop(struct ieee80211_hw *hw) +void iwlagn_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; @@ -3537,7 +3293,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -3553,73 +3309,12 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - int ret = 0; - - lockdep_assert_held(&priv->mutex); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* The following should be done only at AP bring up */ - if (!iwl_is_associated_ctx(ctx)) { - - /* RXON - unassoc (to set timing command) */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - - /* RXON Timing */ - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) - IWL_WARN(priv, "RXON timing failed - " - "Attempting to continue.\n"); - - /* AP has all antennas */ - priv->chain_noise_data.active_chains = - priv->hw_params.valid_rx_ant; - iwl_set_rxon_ht(priv, &priv->current_ht_config); - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - ctx->staging.assoc_id = 0; - - if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= - RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= - RXON_FLG_SHORT_SLOT_MSK; - else - ctx->staging.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - } - /* need to send beacon cmd before committing assoc RXON! */ - iwl_send_beacon_cmd(priv); - /* restore RXON assoc */ - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); - } - iwl_send_beacon_cmd(priv); - - /* FIXME - we need to add code here to detect a totally new - * configuration, reset the AP, unassoc, rxon timing, assoc, - * clear sta table, add BCAST sta... */ -} - -static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, - u32 iv32, u16 *phase1key) +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { - struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3631,10 +3326,9 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3701,10 +3395,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_priv *priv = hw->priv; int ret = -EINVAL; @@ -3785,39 +3479,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; } -static void iwl_mac_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - int sta_id; - - switch (cmd) { - case STA_NOTIFY_SLEEP: - WARN_ON(!sta_priv->client); - sta_priv->asleep = true; - if (atomic_read(&sta_priv->pending_frames) > 0) - ieee80211_sta_block_awake(hw, sta, true); - break; - case STA_NOTIFY_AWAKE: - WARN_ON(!sta_priv->client); - if (!sta_priv->asleep) - break; - sta_priv->asleep = false; - sta_id = iwl_sta_id(sta); - if (sta_id != IWL_INVALID_STATION) - iwl_sta_modify_ps_wake(priv, sta_id); - break; - default: - break; - } -} - -static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; @@ -3858,8 +3522,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return 0; } -static void iwl_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch) +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch) { struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; @@ -3956,10 +3620,10 @@ out_exit: IWL_DEBUG_MAC80211(priv, "leave\n"); } -static void iwlagn_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; @@ -3986,7 +3650,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; ctx->staging.filter_flags |= filter_or; - iwlcore_commit_rxon(priv, ctx); + + /* + * Not committing directly because hardware can perform a scan, + * but we'll eventually commit the filter flags change anyway. + */ } mutex_unlock(&priv->mutex); @@ -4001,7 +3669,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; } -static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; @@ -4172,13 +3840,13 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->bt_on_thresh = BT_ON_THRESHOLD_DEF; priv->bt_duration = BT_DURATION_LIMIT_DEF; priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; - priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF; } /* Set the tx_power_user_lmt to the lowest power level * this value will get overwritten by channel max power avg * from eeprom */ priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; + priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; ret = iwl_init_channel_map(priv); if (ret) { @@ -4209,28 +3877,30 @@ static void iwl_uninit_drv(struct iwl_priv *priv) kfree(priv->scan_cmd); } -static struct ieee80211_ops iwl_hw_ops = { - .tx = iwl_mac_tx, - .start = iwl_mac_start, - .stop = iwl_mac_stop, +#ifdef CONFIG_IWL5000 +struct ieee80211_ops iwlagn_hw_ops = { + .tx = iwlagn_mac_tx, + .start = iwlagn_mac_start, + .stop = iwlagn_mac_stop, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, + .change_interface = iwl_mac_change_interface, + .config = iwlagn_mac_config, .configure_filter = iwlagn_configure_filter, - .set_key = iwl_mac_set_key, - .update_tkip_key = iwl_mac_update_tkip_key, + .set_key = iwlagn_mac_set_key, + .update_tkip_key = iwlagn_mac_update_tkip_key, .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, - .ampdu_action = iwl_mac_ampdu_action, + .bss_info_changed = iwlagn_bss_info_changed, + .ampdu_action = iwlagn_mac_ampdu_action, .hw_scan = iwl_mac_hw_scan, - .sta_notify = iwl_mac_sta_notify, + .sta_notify = iwlagn_mac_sta_notify, .sta_add = iwlagn_mac_sta_add, .sta_remove = iwl_mac_sta_remove, - .channel_switch = iwl_mac_channel_switch, - .flush = iwl_mac_flush, + .channel_switch = iwlagn_mac_channel_switch, + .flush = iwlagn_mac_flush, .tx_last_beacon = iwl_mac_tx_last_beacon, }; +#endif static void iwl_hw_detect(struct iwl_priv *priv) { @@ -4298,10 +3968,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (cfg->mod_params->disable_hw_scan) { dev_printk(KERN_DEBUG, &(pdev->dev), "sw scan support is deprecated\n"); - iwl_hw_ops.hw_scan = NULL; +#ifdef CONFIG_IWL5000 + iwlagn_hw_ops.hw_scan = NULL; +#endif +#ifdef CONFIG_IWL4965 + iwl4965_hw_ops.hw_scan = NULL; +#endif } - hw = iwl_alloc_all(cfg, &iwl_hw_ops); + hw = iwl_alloc_all(cfg); if (!hw) { err = -ENOMEM; goto out; @@ -4333,6 +4008,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = BIT(NL80211_IFTYPE_STATION); + priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; @@ -4461,6 +4137,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto out_free_eeprom; + err = iwl_eeprom_check_sku(priv); + if (err) + goto out_free_eeprom; + /* extract MAC Address */ iwl_eeprom_get_mac(priv, priv->addresses[0].addr); IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); @@ -4500,8 +4180,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_msi(priv->pci_dev); - iwl_alloc_isr_ict(priv); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + if (priv->cfg->ops->lib->isr_ops.alloc) + priv->cfg->ops->lib->isr_ops.alloc(priv); + + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -4548,7 +4230,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; free_irq(priv->pci_dev->irq, priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); out_disable_msi: pci_disable_msi(priv->pci_dev); iwl_uninit_drv(priv); @@ -4643,7 +4326,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_uninit_drv(priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); dev_kfree_skb(priv->beacon_skb); @@ -4735,13 +4419,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, /* 6x00 Series Gen2a */ - {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)}, @@ -4751,24 +4428,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)}, /* 6x00 Series Gen2b */ - {IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)}, - {IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)}, {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)}, {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)}, - {IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)}, {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)}, - {IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)}, + {IWL_PCI_DEVICE(0x008A, 0x5327, iwl6000g2b_bg_cfg)}, {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)}, + {IWL_PCI_DEVICE(0x008B, 0x5317, iwl6000g2b_bg_cfg)}, {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)}, {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, @@ -4812,10 +4477,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 100 Series WiFi */ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)}, + {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)}, + {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)}, {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)}, - {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, - {IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)}, + {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)}, /* 130 Series WiFi */ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)}, @@ -4836,10 +4502,7 @@ static struct pci_driver iwl_driver = { .id_table = iwl_hw_card_ids, .probe = iwl_pci_probe, .remove = __devexit_p(iwl_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif + .driver.pm = IWL_PM_OPS, }; static int __init iwl_init(void) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f525d55f2c0f..28837a185a28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -102,6 +102,9 @@ extern struct iwl_hcmd_ops iwlagn_hcmd; extern struct iwl_hcmd_ops iwlagn_bt_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; +extern struct ieee80211_ops iwlagn_hw_ops; +extern struct ieee80211_ops iwl4965_hw_ops; + int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); int iwl_alloc_isr_ict(struct iwl_priv *priv); @@ -132,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, /* RXON */ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed); +void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); @@ -249,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, int iwlagn_send_rxon_assoc(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); +int iwlagn_send_beacon_cmd(struct iwl_priv *priv); /* bt coex */ void iwlagn_send_advance_bt_config(struct iwl_priv *priv); @@ -292,9 +301,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid, u16 ssn); int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid); -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); int iwl_update_bcast_stations(struct iwl_priv *priv); +void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta); /* rate */ static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) @@ -318,4 +330,31 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); +/* mac80211 handlers (for 4965) */ +int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int iwlagn_mac_start(struct ieee80211_hw *hw); +void iwlagn_mac_stop(struct ieee80211_hw *hw); +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast); +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key); +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn); +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch); +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 424801abc80e..f893d4a6aa87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2022,6 +2022,9 @@ struct iwl_compressed_ba_resp { __le64 bitmap; __le16 scd_flow; __le16 scd_ssn; + /* following only for 5000 series and up */ + u8 txed; /* number of frames sent */ + u8 txed_2_done; /* number of frames acked */ } __packed; /* @@ -2407,9 +2410,9 @@ struct iwl_link_quality_cmd { #define BT_FRAG_THRESHOLD_MAX 0 #define BT_FRAG_THRESHOLD_MIN 0 -#define BT_AGG_THRESHOLD_DEF 0 -#define BT_AGG_THRESHOLD_MAX 0 -#define BT_AGG_THRESHOLD_MIN 0 +#define BT_AGG_THRESHOLD_DEF 1200 +#define BT_AGG_THRESHOLD_MAX 8000 +#define BT_AGG_THRESHOLD_MIN 400 /* * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) @@ -2436,8 +2439,9 @@ struct iwl_bt_cmd { #define IWLAGN_BT_FLAG_COEX_MODE_3W 2 #define IWLAGN_BT_FLAG_COEX_MODE_4W 3 -#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6) -#define IWLAGN_BT_FLAG_NOCOEX_NOTIF BIT(7) +#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6) +/* Disable Sync PSPoll on SCO/eSCO */ +#define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE BIT(7) #define IWLAGN_BT_PRIO_BOOST_MAX 0xFF #define IWLAGN_BT_PRIO_BOOST_MIN 0x00 @@ -2447,8 +2451,9 @@ struct iwl_bt_cmd { #define IWLAGN_BT3_T7_DEFAULT 1 -#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff) -#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff) +#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffff0000) +#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffff0000) +#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO cpu_to_le32(0xffffffff) #define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2 @@ -2664,9 +2669,16 @@ struct iwl_spectrum_notification { #define IWL_POWER_VEC_SIZE 5 #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0)) +#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0)) +#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1)) #define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2)) #define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3)) #define IWL_POWER_FAST_PD cpu_to_le16(BIT(4)) +#define IWL_POWER_BEACON_FILTERING cpu_to_le16(BIT(5)) +#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6)) +#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7)) +#define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) +#define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9)) struct iwl3945_powertable_cmd { __le16 flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 25fb3912342c..c41f5a878210 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -77,15 +77,15 @@ EXPORT_SYMBOL(iwl_bcast_addr); /* This function both allocates and initializes hw and priv. */ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops) +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) { struct iwl_priv *priv; - /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - struct ieee80211_hw *hw = - ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); + struct ieee80211_hw *hw; + + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), + cfg->ops->ieee80211_ops); if (hw == NULL) { pr_err("%s: Can not allocate network device\n", cfg->name); @@ -100,35 +100,6 @@ out: } EXPORT_SYMBOL(iwl_alloc_all); -/* - * QoS support -*/ -static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!ctx->is_active) - return; - - ctx->qos_data.def_qos_parm.qos_flags = 0; - - if (ctx->qos_data.qos_active) - ctx->qos_data.def_qos_parm.qos_flags |= - QOS_PARAM_FLG_UPDATE_EDCA_MSK; - - if (ctx->ht.enabled) - ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - - IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", - ctx->qos_data.qos_active, - ctx->qos_data.def_qos_parm.qos_flags); - - iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, - sizeof(struct iwl_qosparam_cmd), - &ctx->qos_data.def_qos_parm, NULL); -} - #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, @@ -317,40 +288,6 @@ void iwlcore_free_geos(struct iwl_priv *priv) } EXPORT_SYMBOL(iwlcore_free_geos); -/* - * iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this - * function. - */ -void iwlcore_tx_cmd_protection(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - __le16 fc, __le32 *tx_flags) -{ - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - *tx_flags |= TX_CMD_FLG_RTS_MSK; - *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - - if (!ieee80211_is_mgmt(fc)) - return; - - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - break; - } - } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - } -} -EXPORT_SYMBOL(iwlcore_tx_cmd_protection); - - static bool iwl_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) @@ -1206,8 +1143,16 @@ EXPORT_SYMBOL(iwl_apm_init); int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { - int ret = 0; - s8 prev_tx_power = priv->tx_power_user_lmt; + int ret; + s8 prev_tx_power; + + lockdep_assert_held(&priv->mutex); + + if (priv->tx_power_user_lmt == tx_power && !force) + return 0; + + if (!priv->cfg->ops->lib->send_tx_power) + return -EOPNOTSUPP; if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { IWL_WARN(priv, @@ -1224,93 +1169,29 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (priv->tx_power_user_lmt != tx_power) - force = true; + if (!iwl_is_ready_rf(priv)) + return -EIO; - /* if nic is not up don't send command */ - if (iwl_is_ready_rf(priv)) { - priv->tx_power_user_lmt = tx_power; - if (force && priv->cfg->ops->lib->send_tx_power) - ret = priv->cfg->ops->lib->send_tx_power(priv); - else if (!priv->cfg->ops->lib->send_tx_power) - ret = -EOPNOTSUPP; - /* - * if fail to set tx_power, restore the orig. tx power - */ - if (ret) - priv->tx_power_user_lmt = prev_tx_power; + /* scan complete use tx_power_next, need to be updated */ + priv->tx_power_next = tx_power; + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { + IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n"); + return 0; } - /* - * Even this is an async host command, the command - * will always report success from uCode - * So once driver can placing the command into the queue - * successfully, driver can use priv->tx_power_user_lmt - * to reflect the current tx power - */ - return ret; -} -EXPORT_SYMBOL(iwl_set_tx_power); - -irqreturn_t iwl_isr_legacy(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 inta_fh; - unsigned long flags; - if (!priv) - return IRQ_NONE; + prev_tx_power = priv->tx_power_user_lmt; + priv->tx_power_user_lmt = tx_power; - spin_lock_irqsave(&priv->lock, flags); + ret = priv->cfg->ops->lib->send_tx_power(priv); - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta && !inta_fh) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n"); - goto none; + /* if fail to set tx_power, restore the orig. tx power */ + if (ret) { + priv->tx_power_user_lmt = prev_tx_power; + priv->tx_power_next = prev_tx_power; } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - - inta &= ~CSR_INT_BIT_SCD; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta || inta_fh)) - tasklet_schedule(&priv->irq_tasklet); - - unplugged: - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_NONE; + return ret; } -EXPORT_SYMBOL(iwl_isr_legacy); +EXPORT_SYMBOL(iwl_set_tx_power); void iwl_send_bt_config(struct iwl_priv *priv) { @@ -1452,318 +1333,51 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); -static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_vif *vif) +static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - struct iwl_ht_config *ht_conf = &priv->current_ht_config; - struct ieee80211_sta *sta; - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - - IWL_DEBUG_MAC80211(priv, "enter:\n"); - - if (!ctx->ht.enabled) - return; - - ctx->ht.protection = - bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - ctx->ht.non_gf_sta_present = - !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - ht_conf->single_chain_sufficient = false; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - rcu_read_lock(); - sta = ieee80211_find_sta(vif, bss_conf->bssid); - if (sta) { - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - int maxstreams; - - maxstreams = (ht_cap->mcs.tx_params & - IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) - >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; - maxstreams += 1; - - if ((ht_cap->mcs.rx_mask[1] == 0) && - (ht_cap->mcs.rx_mask[2] == 0)) - ht_conf->single_chain_sufficient = true; - if (maxstreams <= 1) - ht_conf->single_chain_sufficient = true; - } else { - /* - * If at all, this can only happen through a race - * when the AP disconnects us while we're still - * setting up the connection, in that case mac80211 - * will soon tell us about that. - */ - ht_conf->single_chain_sufficient = true; - } - rcu_read_unlock(); - break; - case NL80211_IFTYPE_ADHOC: - ht_conf->single_chain_sufficient = true; - break; - default: - break; - } - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} + iwl_connection_init_rx_config(priv, ctx); -static inline void iwl_set_no_assoc(struct iwl_priv *priv, - struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - iwl_led_disassociate(priv); - /* - * inform the ucode that there is no longer an - * association and that no more packets should be - * sent - */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = 0; - iwlcore_commit_rxon(priv, ctx); + return iwlcore_commit_rxon(priv, ctx); } -static void iwlcore_beacon_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int iwl_setup_interface(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - struct sk_buff *skb = ieee80211_beacon_get(hw, vif); - - if (!skb) - return; - - IWL_DEBUG_ASSOC(priv, "enter\n"); + struct ieee80211_vif *vif = ctx->vif; + int err; lockdep_assert_held(&priv->mutex); - if (!priv->beacon_ctx) { - IWL_ERR(priv, "update beacon but no beacon context!\n"); - dev_kfree_skb(skb); - return; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); - - priv->beacon_skb = skb; - - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_ASSOC(priv, "leave\n"); - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return; - } - - priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); -} - -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - int ret; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (!iwl_is_alive(priv)) - return; - - mutex_lock(&priv->mutex); - - if (changes & BSS_CHANGED_QOS) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ctx->qos_data.qos_active = bss_conf->qos; - iwl_update_qos(priv, ctx); - spin_unlock_irqrestore(&priv->lock, flags); - } - - if (changes & BSS_CHANGED_BEACON_ENABLED) { - /* - * the add_interface code must make sure we only ever - * have a single interface that could be beaconing at - * any time. - */ - if (vif->bss_conf.enable_beacon) - priv->beacon_ctx = ctx; - else - priv->beacon_ctx = NULL; - } - - if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { - dev_kfree_skb(priv->beacon_skb); - priv->beacon_skb = ieee80211_beacon_get(hw, vif); - } - - if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) - iwl_send_rxon_timing(priv, ctx); - - if (changes & BSS_CHANGED_BSSID) { - IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); - - /* - * If there is currently a HW scan going on in the - * background then we need to cancel it else the RXON - * below/in post_associate will fail. - */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* mac80211 only sets assoc when in STATION mode */ - if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { - memcpy(ctx->staging.bssid_addr, - bss_conf->bssid, ETH_ALEN); - - /* currently needed in a few places */ - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - } else { - ctx->staging.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - } - - } - /* - * This needs to be after setting the BSSID in case - * mac80211 decides to do both changes at once because - * it will invoke post_associate. + * This variable will be correct only when there's just + * a single context, but all code using it is for hardware + * that supports only one context. */ - if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) - iwlcore_beacon_update(hw, vif); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - if (bss_conf->use_cts_prot) - ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; - else - ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; - } - - if (changes & BSS_CHANGED_BASIC_RATES) { - /* XXX use this information - * - * To do that, remove code from iwl_set_rate() and put something - * like this here: - * - if (A-band) - ctx->staging.ofdm_basic_rates = - bss_conf->basic_rates; - else - ctx->staging.ofdm_basic_rates = - bss_conf->basic_rates >> 4; - ctx->staging.cck_basic_rates = - bss_conf->basic_rates & 0xF; - */ - } - - if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, vif); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - if (bss_conf->assoc) { - priv->timestamp = bss_conf->timestamp; - - iwl_led_associate(priv); - - if (!iwl_is_rfkill(priv)) - priv->cfg->ops->lib->post_associate(priv, vif); - } else - iwl_set_no_assoc(priv, vif); - } - - if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { - IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", - changes); - ret = iwl_send_rxon_assoc(priv, ctx); - if (!ret) { - /* Sync active_rxon with latest change. */ - memcpy((void *)&ctx->active, - &ctx->staging, - sizeof(struct iwl_rxon_cmd)); - } - } + priv->iw_mode = vif->type; - if (changes & BSS_CHANGED_BEACON_ENABLED) { - if (vif->bss_conf.enable_beacon) { - memcpy(ctx->staging.bssid_addr, - bss_conf->bssid, ETH_ALEN); - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - iwl_led_associate(priv); - iwlcore_config_ap(priv, vif); - } else - iwl_set_no_assoc(priv, vif); - } + ctx->is_active = true; - if (changes & BSS_CHANGED_IBSS) { - ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif, - bss_conf->ibss_joined); - if (ret) - IWL_ERR(priv, "failed to %s IBSS station %pM\n", - bss_conf->ibss_joined ? "add" : "remove", - bss_conf->bssid); + err = iwl_set_mode(priv, ctx); + if (err) { + if (!ctx->always_active) + ctx->is_active = false; + return err; } - if (changes & BSS_CHANGED_IDLE && - priv->cfg->ops->hcmd->set_pan_params) { - if (priv->cfg->ops->hcmd->set_pan_params(priv)) - IWL_ERR(priv, "failed to update PAN params\n"); + if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && + vif->type == NL80211_IFTYPE_ADHOC) { + /* + * pretend to have high BT traffic as long as we + * are operating in IBSS mode, as this will cause + * the rate scaling etc. to behave as intended. + */ + priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} -EXPORT_SYMBOL(iwl_bss_info_changed); - -static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - - iwl_connection_init_rx_config(priv, ctx); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - - return iwlcore_commit_rxon(priv, ctx); + return 0; } int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) @@ -1771,7 +1385,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_rxon_context *tmp, *ctx = NULL; - int err = 0; + int err; IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", vif->type, vif->addr); @@ -1813,36 +1427,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) vif_priv->ctx = ctx; ctx->vif = vif; - /* - * This variable will be correct only when there's just - * a single context, but all code using it is for hardware - * that supports only one context. - */ - priv->iw_mode = vif->type; - - ctx->is_active = true; - - err = iwl_set_mode(priv, vif); - if (err) { - if (!ctx->always_active) - ctx->is_active = false; - goto out_err; - } - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - vif->type == NL80211_IFTYPE_ADHOC) { - /* - * pretend to have high BT traffic as long as we - * are operating in IBSS mode, as this will cause - * the rate scaling etc. to behave as intended. - */ - priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; - } - goto out; + err = iwl_setup_interface(priv, ctx); + if (!err) + goto out; - out_err: ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: @@ -1853,27 +1442,24 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } EXPORT_SYMBOL(iwl_mac_add_interface); -void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void iwl_teardown_interface(struct iwl_priv *priv, + struct ieee80211_vif *vif, + bool mode_change) { - struct iwl_priv *priv = hw->priv; struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - WARN_ON(ctx->vif != vif); - ctx->vif = NULL; + lockdep_assert_held(&priv->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); iwl_force_scan_end(priv); } - iwl_set_mode(priv, vif); - if (!ctx->always_active) - ctx->is_active = false; + if (!mode_change) { + iwl_set_mode(priv, ctx); + if (!ctx->always_active) + ctx->is_active = false; + } /* * When removing the IBSS interface, overwrite the @@ -1883,211 +1469,31 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, * both values are the same and zero. */ if (vif->type == NL80211_IFTYPE_ADHOC) - priv->bt_traffic_load = priv->notif_bt_traffic_load; - - memset(priv->bssid, 0, ETH_ALEN); - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - + priv->bt_traffic_load = priv->last_bt_traffic_load; } -EXPORT_SYMBOL(iwl_mac_remove_interface); - -/** - * iwl_mac_config - mac80211 config callback - */ -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - struct ieee80211_channel *channel = conf->channel; - struct iwl_ht_config *ht_conf = &priv->current_ht_config; - struct iwl_rxon_context *ctx; - unsigned long flags = 0; - int ret = 0; - u16 ch; - int scan_active = 0; - - mutex_lock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - channel->hw_value, changed); - - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - } - - if (changed & (IEEE80211_CONF_CHANGE_SMPS | - IEEE80211_CONF_CHANGE_CHANNEL)) { - /* mac80211 uses static for non-HT which is what we want */ - priv->current_ht_config.smps = conf->smps_mode; - - /* - * Recalculate chain counts. - * - * If monitor mode is enabled then mac80211 will - * set up the SM PS mode to OFF if an HT channel is - * configured. - */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - for_each_context(priv, ctx) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - } - - /* during scanning mac80211 will delay channel setting until - * scan finish with changed = 0 - */ - if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - if (scan_active) - goto set_ch_out; - - ch = channel->hw_value; - ch_info = iwl_get_channel_info(priv, channel->band, ch); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto set_ch_out; - } - spin_lock_irqsave(&priv->lock, flags); - - for_each_context(priv, ctx) { - /* Configure HT40 channels */ - ctx->ht.enabled = conf_is_ht(conf); - if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } - } else - ctx->ht.is_40mhz = false; - - /* - * Default to no protection. Protection mode will - * later be set from BSS config in iwl_ht_conf - */ - ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(ctx->staging.channel) != ch)) - ctx->staging.flags = 0; - - iwl_set_rxon_channel(priv, channel, ctx); - iwl_set_rxon_ht(priv, ht_conf); - - iwl_set_flags_for_band(priv, ctx, channel->band, - ctx->vif); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - if (priv->cfg->ops->lib->update_bcast_stations) - ret = priv->cfg->ops->lib->update_bcast_stations(priv); - - set_ch_out: - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - } - - if (changed & (IEEE80211_CONF_CHANGE_PS | - IEEE80211_CONF_CHANGE_IDLE)) { - ret = iwl_power_update_mode(priv, false); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - } - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - goto out; - } - - if (scan_active) - goto out; - - for_each_context(priv, ctx) { - if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) - iwlcore_commit_rxon(priv, ctx); - else - IWL_DEBUG_INFO(priv, - "Not re-sending same RXON configuration.\n"); - } - -out: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - return ret; -} -EXPORT_SYMBOL(iwl_mac_config); - -void iwl_mac_reset_tsf(struct ieee80211_hw *hw) +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; - unsigned long flags; - /* IBSS can only be the IWL_RXON_CTX_BSS context */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - spin_lock_irqsave(&priv->lock, flags); - memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); - spin_unlock_irqrestore(&priv->lock, flags); - - spin_lock_irqsave(&priv->lock, flags); - - /* new association get rid of ibss beacon skb */ - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); - - priv->beacon_skb = NULL; - - priv->timestamp = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_scan_cancel_timeout(priv, 100); - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } + mutex_lock(&priv->mutex); - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); + WARN_ON(ctx->vif != vif); + ctx->vif = NULL; - iwl_set_rate(priv); + iwl_teardown_interface(priv, vif, false); + memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); + } -EXPORT_SYMBOL(iwl_mac_reset_tsf); +EXPORT_SYMBOL(iwl_mac_remove_interface); int iwl_alloc_txq_mem(struct iwl_priv *priv) { @@ -2431,6 +1837,63 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) return 0; } +int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum nl80211_iftype newtype, bool newp2p) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + struct iwl_rxon_context *tmp; + u32 interface_modes; + int err; + + newtype = ieee80211_iftype_p2p(newtype, newp2p); + + mutex_lock(&priv->mutex); + + interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; + + if (!(interface_modes & BIT(newtype))) { + err = -EBUSY; + goto out; + } + + if (ctx->exclusive_interface_modes & BIT(newtype)) { + for_each_context(priv, tmp) { + if (ctx == tmp) + continue; + + if (!tmp->vif) + continue; + + /* + * The current mode switch would be exclusive, but + * another context is active ... refuse the switch. + */ + err = -EBUSY; + goto out; + } + } + + /* success */ + iwl_teardown_interface(priv, vif, true); + vif->type = newtype; + err = iwl_setup_interface(priv, ctx); + WARN_ON(err); + /* + * We've switched internally, but submitting to the + * device may have failed for some reason. Mask this + * error, because otherwise mac80211 will not switch + * (and set the interface type back) and we'll be + * out of sync with it. + */ + err = 0; + + out: + mutex_unlock(&priv->mutex); + return err; +} +EXPORT_SYMBOL(iwl_mac_change_interface); + /** * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover * @@ -2584,8 +2047,9 @@ EXPORT_SYMBOL(iwl_add_beacon_time); #ifdef CONFIG_PM -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) +int iwl_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct iwl_priv *priv = pci_get_drvdata(pdev); /* @@ -2597,18 +2061,14 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) */ iwl_apm_stop(priv); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } EXPORT_SYMBOL(iwl_pci_suspend); -int iwl_pci_resume(struct pci_dev *pdev) +int iwl_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; bool hw_rfkill = false; /* @@ -2617,11 +2077,6 @@ int iwl_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); iwl_enable_interrupts(priv); if (!(iwl_read32(priv, CSR_GP_CNTRL) & @@ -2639,4 +2094,14 @@ int iwl_pci_resume(struct pci_dev *pdev) } EXPORT_SYMBOL(iwl_pci_resume); +const struct dev_pm_ops iwl_pm_ops = { + .suspend = iwl_pci_suspend, + .resume = iwl_pci_resume, + .freeze = iwl_pci_suspend, + .thaw = iwl_pci_resume, + .poweroff = iwl_pci_suspend, + .restore = iwl_pci_resume, +}; +EXPORT_SYMBOL(iwl_pm_ops); + #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 64527def059f..808be731ecb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -120,6 +120,14 @@ struct iwl_apm_ops { void (*config)(struct iwl_priv *priv); }; +struct iwl_isr_ops { + irqreturn_t (*isr) (int irq, void *data); + void (*free)(struct iwl_priv *priv); + int (*alloc)(struct iwl_priv *priv); + int (*reset)(struct iwl_priv *priv); + void (*disable)(struct iwl_priv *priv); +}; + struct iwl_debugfs_ops { ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); @@ -193,20 +201,15 @@ struct iwl_lib_ops { /* power */ int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); - void (*post_associate)(struct iwl_priv *priv, - struct ieee80211_vif *vif); - void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif); - irqreturn_t (*isr) (int irq, void *data); + + /* isr */ + struct iwl_isr_ops isr_ops; /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; /* temperature */ struct iwl_temp_ops temp_ops; - /* station management */ - int (*manage_ibss_station)(struct iwl_priv *priv, - struct ieee80211_vif *vif, bool add); - int (*update_bcast_stations)(struct iwl_priv *priv); /* recover from tx queue stall */ void (*recover_from_tx_stall)(unsigned long data); /* check for plcp health */ @@ -235,12 +238,23 @@ struct iwl_nic_ops { void (*additional_nic_config)(struct iwl_priv *priv); }; +struct iwl_legacy_ops { + void (*post_associate)(struct iwl_priv *priv); + void (*config_ap)(struct iwl_priv *priv); + /* station management */ + int (*update_bcast_stations)(struct iwl_priv *priv); + int (*manage_ibss_station)(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add); +}; + struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; const struct iwl_led_ops *led; const struct iwl_nic_ops *nic; + const struct iwl_legacy_ops *legacy; + const struct ieee80211_ops *ieee80211_ops; }; struct iwl_mod_params { @@ -276,7 +290,10 @@ struct iwl_mod_params { * sensitivity calibration operation * @chain_noise_calib_by_driver: driver has the capability to perform * chain noise calibration operation -*/ + * @shadow_reg_enable: HW shadhow register bit + * @no_agg_framecnt_info: uCode do not provide aggregation frame count + * information + */ struct iwl_base_params { int eeprom_size; int num_of_queues; /* def: HW dependent */ @@ -306,6 +323,8 @@ struct iwl_base_params { const bool ucode_tracing; const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; + const bool shadow_reg_enable; + const bool no_agg_framecnt_info; }; /* * @advanced_bt_coexist: support advanced bt coexist @@ -315,6 +334,7 @@ struct iwl_base_params { * @agg_time_limit: maximum number of uSec in aggregation * @ampdu_factor: Maximum A-MPDU length factor * @ampdu_density: Minimum A-MPDU spacing + * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode */ struct iwl_bt_params { bool advanced_bt_coexist; @@ -324,6 +344,7 @@ struct iwl_bt_params { u16 agg_time_limit; u8 ampdu_factor; u8 ampdu_density; + bool bt_sco_disable; }; /* * @use_rts_for_aggregation: use rts/cts protection for HT traffic @@ -344,6 +365,8 @@ struct iwl_ht_params { * @need_dc_calib: need to perform init dc calibration * @need_temp_offset_calib: need to perform temperature offset calibration * @scan_antennas: available antenna for scan operation + * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) + * @adv_pm: advance power management * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -390,14 +413,15 @@ struct iwl_cfg { const bool need_temp_offset_calib; /* if used set to true */ u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; + enum iwl_led_mode led_mode; + const bool adv_pm; }; /*************************** * L i b * ***************************/ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops); +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -425,23 +449,16 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, u32 decrypt_res, struct ieee80211_rx_status *stats); void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); -void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); -void iwl_mac_reset_tsf(struct ieee80211_hw *hw); +int iwl_mac_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype newtype, bool newp2p); int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); -void iwlcore_tx_cmd_protection(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - __le16 fc, __le32 *tx_flags); + #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); @@ -598,7 +615,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); /***************************************************** * PCI * *****************************************************/ -irqreturn_t iwl_isr_legacy(int irq, void *data); static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) { @@ -615,9 +631,17 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval); #ifdef CONFIG_PM -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); -int iwl_pci_resume(struct pci_dev *pdev); -#endif /* CONFIG_PM */ +int iwl_pci_suspend(struct device *device); +int iwl_pci_resume(struct device *device); +extern const struct dev_pm_ops iwl_pm_ops; + +#define IWL_PM_OPS (&iwl_pm_ops) + +#else /* !CONFIG_PM */ + +#define IWL_PM_OPS NULL + +#endif /* !CONFIG_PM */ /***************************************************** * Error Handling Debugging @@ -724,11 +748,6 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv, { return priv->cfg->ops->hcmd->commit_rxon(priv, ctx); } -static inline void iwlcore_config_ap(struct iwl_priv *priv, - struct ieee80211_vif *vif) -{ - priv->cfg->ops->lib->config_ap(priv, vif); -} static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) { diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 2aa15ab13892..b80bf7dff55b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -132,6 +132,8 @@ #define CSR_LED_REG (CSR_BASE+0x094) #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) +#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */ + /* GIO Chicken Bits (PCI Express bus link power management) */ #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 8fdd4efdb1d3..3cc58420d445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -992,11 +992,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, q->read_ptr, q->write_ptr, !!test_bit(cnt, priv->queue_stopped), - txq->swq_id, - txq->swq_id & 0x80 ? txq->swq_id & 3 : - txq->swq_id, - txq->swq_id & 0x80 ? (txq->swq_id >> 2) & - 0x1f : txq->swq_id); + txq->swq_id, txq->swq_id & 3, + (txq->swq_id >> 2) & 0x1f); if (cnt >= 4) continue; /* for the ACs, display the stop count too */ @@ -1580,7 +1577,7 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, priv->bt_full_concurrent ? "full concurrency" : "3-wire"); pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " "last traffic notif: %d\n", - priv->bt_status ? "On" : "Off", priv->notif_bt_traffic_load); + priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " "sco_active: %d, kill_ack_mask: %x, " "kill_cts_mask: %x\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 70e07fa48405..ea81ced13756 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1162,6 +1162,8 @@ struct iwl_rxon_context { */ bool always_active, is_active; + bool ht_need_multiple_chains; + enum iwl_rxon_context_id ctxid; u32 interface_modes, exclusive_interface_modes; @@ -1469,7 +1471,7 @@ struct iwl_priv { /* bt coex */ u8 bt_status; - u8 bt_traffic_load, notif_bt_traffic_load; + u8 bt_traffic_load, last_bt_traffic_load; bool bt_ch_announce; bool bt_sco_active; bool bt_full_concurrent; @@ -1480,7 +1482,6 @@ struct iwl_priv { u16 bt_on_thresh; u16 bt_duration; u16 dynamic_frag_thresh; - u16 dynamic_agg_thresh; u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; @@ -1517,6 +1518,7 @@ struct iwl_priv { s8 tx_power_user_lmt; s8 tx_power_device_lmt; s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ + s8 tx_power_next; #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index d9b590625ae4..583916db46e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -110,9 +110,18 @@ enum { }; /* SKU Capabilities */ +/* 3945 only */ #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) +/* 5000 and up */ +#define EEPROM_SKU_CAP_BAND_POS (4) +#define EEPROM_SKU_CAP_BAND_SELECTION \ + (3 << EEPROM_SKU_CAP_BAND_POS) +#define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) +#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) +#define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) + /* *regulatory* channel data format in eeprom, one for each channel. * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ struct iwl_eeprom_channel { @@ -397,11 +406,10 @@ struct iwl_eeprom_calib_info { #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ #define EEPROM_VERSION (2*0x44) /* 2 bytes */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ +#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ -#define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ @@ -504,6 +512,7 @@ struct iwl_eeprom_ops { int iwl_eeprom_init(struct iwl_priv *priv); void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); +int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 1aaef70deaec..3f5bedd8875f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -44,15 +44,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf( return &hw->conf; } -static inline unsigned long elapsed_jiffies(unsigned long start, - unsigned long end) -{ - if (end >= start) - return end - start; - - return end + (MAX_JIFFY_OFFSET - start) + 1; -} - /** * iwl_queue_inc_wrap - increment queue index, wrap back to beginning * @index -- current index @@ -104,42 +95,36 @@ static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, * | | | | | | | | * | | | | | | +-+-------- AC queue (0-3) * | | | | | | - * | +-+-+-+-+------------ HW A-MPDU queue + * | +-+-+-+-+------------ HW queue ID * | - * +---------------------- indicates agg queue + * +---------------------- unused */ -static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq) +static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) { BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only have 5 bits */ + BUG_ON(hwq > 31); /* only use 5 bits */ - return 0x80 | (hwq << 2) | ac; + txq->swq_id = (hwq << 2) | ac; } -static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue) +static inline void iwl_wake_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) { - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; if (test_and_clear_bit(hwq, priv->queue_stopped)) if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) ieee80211_wake_queue(priv->hw, ac); } -static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) +static inline void iwl_stop_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) { - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; if (!test_and_set_bit(hwq, priv->queue_stopped)) if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 86c2b6fed0c6..516e5577ed2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -45,9 +45,8 @@ /* default: IWL_LED_BLINK(0) using blinking index table */ static int led_mode; module_param(led_mode, int, S_IRUGO); -MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " - "(default 0)"); - +MODULE_PARM_DESC(led_mode, "led mode: 0=system default, " + "1=On(RF On)/Off(RF Off), 2=blinking"); static const struct { u16 tpt; /* Mb/s */ @@ -128,12 +127,13 @@ EXPORT_SYMBOL(iwl_led_start); int iwl_led_associate(struct iwl_priv *priv) { IWL_DEBUG_LED(priv, "Associated\n"); - if (led_mode == IWL_LED_BLINK) + if (priv->cfg->led_mode == IWL_LED_BLINK) priv->allow_blinking = 1; priv->last_blink_time = jiffies; return 0; } +EXPORT_SYMBOL(iwl_led_associate); int iwl_led_disassociate(struct iwl_priv *priv) { @@ -141,6 +141,7 @@ int iwl_led_disassociate(struct iwl_priv *priv) return 0; } +EXPORT_SYMBOL(iwl_led_disassociate); /* * calculate blink rate according to last second Tx/Rx activities @@ -221,5 +222,8 @@ void iwl_leds_init(struct iwl_priv *priv) priv->last_blink_rate = 0; priv->last_blink_time = 0; priv->allow_blinking = 0; + if (led_mode != IWL_LED_DEFAULT && + led_mode != priv->cfg->led_mode) + priv->cfg->led_mode = led_mode; } EXPORT_SYMBOL(iwl_leds_init); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 49a70baa3fb6..9079b33486ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -47,14 +47,16 @@ enum led_type { /* * LED mode - * IWL_LED_BLINK: adjust led blink rate based on blink table + * IWL_LED_DEFAULT: use system default * IWL_LED_RF_STATE: turn LED on/off based on RF state * LED ON = RF ON * LED OFF = RF OFF + * IWL_LED_BLINK: adjust led blink rate based on blink table */ enum iwl_led_mode { - IWL_LED_BLINK, + IWL_LED_DEFAULT, IWL_LED_RF_STATE, + IWL_LED_BLINK, }; void iwl_leds_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c new file mode 100644 index 000000000000..a08b4e56e6b1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c @@ -0,0 +1,662 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include <linux/kernel.h> +#include <net/mac80211.h> + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-helpers.h" +#include "iwl-legacy.h" + +static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (!ctx->is_active) + return; + + ctx->qos_data.def_qos_parm.qos_flags = 0; + + if (ctx->qos_data.qos_active) + ctx->qos_data.def_qos_parm.qos_flags |= + QOS_PARAM_FLG_UPDATE_EDCA_MSK; + + if (ctx->ht.enabled) + ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", + ctx->qos_data.qos_active, + ctx->qos_data.def_qos_parm.qos_flags); + + iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, + sizeof(struct iwl_qosparam_cmd), + &ctx->qos_data.def_qos_parm, NULL); +} + +/** + * iwl_legacy_mac_config - mac80211 config callback + */ +int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + const struct iwl_channel_info *ch_info; + struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_channel *channel = conf->channel; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + struct iwl_rxon_context *ctx; + unsigned long flags = 0; + int ret = 0; + u16 ch; + int scan_active = 0; + bool ht_changed[NUM_IWL_RXON_CTX] = {}; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return -EOPNOTSUPP; + + mutex_lock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", + channel->hw_value, changed); + + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && + test_bit(STATUS_SCANNING, &priv->status))) { + scan_active = 1; + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + } + + if (changed & (IEEE80211_CONF_CHANGE_SMPS | + IEEE80211_CONF_CHANGE_CHANNEL)) { + /* mac80211 uses static for non-HT which is what we want */ + priv->current_ht_config.smps = conf->smps_mode; + + /* + * Recalculate chain counts. + * + * If monitor mode is enabled then mac80211 will + * set up the SM PS mode to OFF if an HT channel is + * configured. + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + for_each_context(priv, ctx) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + /* during scanning mac80211 will delay channel setting until + * scan finish with changed = 0 + */ + if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + if (scan_active) + goto set_ch_out; + + ch = channel->hw_value; + ch_info = iwl_get_channel_info(priv, channel->band, ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto set_ch_out; + } + + spin_lock_irqsave(&priv->lock, flags); + + for_each_context(priv, ctx) { + /* Configure HT40 channels */ + if (ctx->ht.enabled != conf_is_ht(conf)) { + ctx->ht.enabled = conf_is_ht(conf); + ht_changed[ctx->ctxid] = true; + } + if (ctx->ht.enabled) { + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } + } else + ctx->ht.is_40mhz = false; + + /* + * Default to no protection. Protection mode will + * later be set from BSS config in iwl_ht_conf + */ + ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(ctx->staging.channel) != ch)) + ctx->staging.flags = 0; + + iwl_set_rxon_channel(priv, channel, ctx); + iwl_set_rxon_ht(priv, ht_conf); + + iwl_set_flags_for_band(priv, ctx, channel->band, + ctx->vif); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + if (priv->cfg->ops->legacy->update_bcast_stations) + ret = priv->cfg->ops->legacy->update_bcast_stations(priv); + + set_ch_out: + /* The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists */ + iwl_set_rate(priv); + } + + if (changed & (IEEE80211_CONF_CHANGE_PS | + IEEE80211_CONF_CHANGE_IDLE)) { + ret = iwl_power_update_mode(priv, false); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + + if (scan_active) + goto out; + + for_each_context(priv, ctx) { + if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) + iwlcore_commit_rxon(priv, ctx); + else + IWL_DEBUG_INFO(priv, + "Not re-sending same RXON configuration.\n"); + if (ht_changed[ctx->ctxid]) + iwl_update_qos(priv, ctx); + } + +out: + IWL_DEBUG_MAC80211(priv, "leave\n"); + mutex_unlock(&priv->mutex); + return ret; +} +EXPORT_SYMBOL(iwl_legacy_mac_config); + +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + /* IBSS can only be the IWL_RXON_CTX_BSS context */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return; + + mutex_lock(&priv->mutex); + IWL_DEBUG_MAC80211(priv, "enter\n"); + + spin_lock_irqsave(&priv->lock, flags); + memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); + spin_unlock_irqrestore(&priv->lock, flags); + + spin_lock_irqsave(&priv->lock, flags); + + /* new association get rid of ibss beacon skb */ + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + + priv->beacon_skb = NULL; + + priv->timestamp = 0; + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_scan_cancel_timeout(priv, 100); + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv, ctx); + + iwl_set_rate(priv); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf); + +static void iwl_ht_conf(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + struct ieee80211_sta *sta; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + + IWL_DEBUG_ASSOC(priv, "enter:\n"); + + if (!ctx->ht.enabled) + return; + + ctx->ht.protection = + bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; + ctx->ht.non_gf_sta_present = + !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + + ht_conf->single_chain_sufficient = false; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (sta) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + int maxstreams; + + maxstreams = (ht_cap->mcs.tx_params & + IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) + >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + maxstreams += 1; + + if ((ht_cap->mcs.rx_mask[1] == 0) && + (ht_cap->mcs.rx_mask[2] == 0)) + ht_conf->single_chain_sufficient = true; + if (maxstreams <= 1) + ht_conf->single_chain_sufficient = true; + } else { + /* + * If at all, this can only happen through a race + * when the AP disconnects us while we're still + * setting up the connection, in that case mac80211 + * will soon tell us about that. + */ + ht_conf->single_chain_sufficient = true; + } + rcu_read_unlock(); + break; + case NL80211_IFTYPE_ADHOC: + ht_conf->single_chain_sufficient = true; + break; + default: + break; + } + + IWL_DEBUG_ASSOC(priv, "leave\n"); +} + +static inline void iwl_set_no_assoc(struct iwl_priv *priv, + struct ieee80211_vif *vif) +{ + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + + iwl_led_disassociate(priv); + /* + * inform the ucode that there is no longer an + * association and that no more packets should be + * sent + */ + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + ctx->staging.assoc_id = 0; + iwlcore_commit_rxon(priv, ctx); +} + +static void iwlcore_beacon_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + struct sk_buff *skb = ieee80211_beacon_get(hw, vif); + + if (!skb) + return; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "update beacon but no beacon context!\n"); + dev_kfree_skb(skb); + return; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + + priv->beacon_skb = skb; + + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return; + } + + priv->cfg->ops->legacy->post_associate(priv); +} + +void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + int ret; + + if (WARN_ON(!priv->cfg->ops->legacy)) + return; + + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + + if (!iwl_is_alive(priv)) + return; + + mutex_lock(&priv->mutex); + + if (changes & BSS_CHANGED_QOS) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + ctx->qos_data.qos_active = bss_conf->qos; + iwl_update_qos(priv, ctx); + spin_unlock_irqrestore(&priv->lock, flags); + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + /* + * the add_interface code must make sure we only ever + * have a single interface that could be beaconing at + * any time. + */ + if (vif->bss_conf.enable_beacon) + priv->beacon_ctx = ctx; + else + priv->beacon_ctx = NULL; + } + + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = ieee80211_beacon_get(hw, vif); + } + + if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) + iwl_send_rxon_timing(priv, ctx); + + if (changes & BSS_CHANGED_BSSID) { + IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); + + /* + * If there is currently a HW scan going on in the + * background then we need to cancel it else the RXON + * below/in post_associate will fail. + */ + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* mac80211 only sets assoc when in STATION mode */ + if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { + memcpy(ctx->staging.bssid_addr, + bss_conf->bssid, ETH_ALEN); + + /* currently needed in a few places */ + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + } else { + ctx->staging.filter_flags &= + ~RXON_FILTER_ASSOC_MSK; + } + + } + + /* + * This needs to be after setting the BSSID in case + * mac80211 decides to do both changes at once because + * it will invoke post_associate. + */ + if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) + iwlcore_beacon_update(hw, vif); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + if (bss_conf->use_cts_prot) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + else + ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; + } + + if (changes & BSS_CHANGED_BASIC_RATES) { + /* XXX use this information + * + * To do that, remove code from iwl_set_rate() and put something + * like this here: + * + if (A-band) + ctx->staging.ofdm_basic_rates = + bss_conf->basic_rates; + else + ctx->staging.ofdm_basic_rates = + bss_conf->basic_rates >> 4; + ctx->staging.cck_basic_rates = + bss_conf->basic_rates & 0xF; + */ + } + + if (changes & BSS_CHANGED_HT) { + iwl_ht_conf(priv, vif); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); + if (bss_conf->assoc) { + priv->timestamp = bss_conf->timestamp; + + iwl_led_associate(priv); + + if (!iwl_is_rfkill(priv)) + priv->cfg->ops->legacy->post_associate(priv); + } else + iwl_set_no_assoc(priv, vif); + } + + if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { + IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", + changes); + ret = iwl_send_rxon_assoc(priv, ctx); + if (!ret) { + /* Sync active_rxon with latest change. */ + memcpy((void *)&ctx->active, + &ctx->staging, + sizeof(struct iwl_rxon_cmd)); + } + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + if (vif->bss_conf.enable_beacon) { + memcpy(ctx->staging.bssid_addr, + bss_conf->bssid, ETH_ALEN); + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + iwl_led_associate(priv); + priv->cfg->ops->legacy->config_ap(priv); + } else + iwl_set_no_assoc(priv, vif); + } + + if (changes & BSS_CHANGED_IBSS) { + ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif, + bss_conf->ibss_joined); + if (ret) + IWL_ERR(priv, "failed to %s IBSS station %pM\n", + bss_conf->ibss_joined ? "add" : "remove", + bss_conf->bssid); + } + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed); + +irqreturn_t iwl_isr_legacy(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + u32 inta_fh; + unsigned long flags; + if (!priv) + return IRQ_NONE; + + spin_lock_irqsave(&priv->lock, flags); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(priv, CSR_INT); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!inta && !inta_fh) { + IWL_DEBUG_ISR(priv, + "Ignore interrupt, inta == 0, inta_fh == 0\n"); + goto none; + } + + if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + /* Hardware disappeared. It might have already raised + * an interrupt */ + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + goto unplugged; + } + + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + inta, inta_mask, inta_fh); + + inta &= ~CSR_INT_BIT_SCD; + + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); + +unplugged: + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + +none: + /* re-enable interrupts here since we don't have anything to service. */ + /* only Re-enable if diabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_NONE; +} +EXPORT_SYMBOL(iwl_isr_legacy); + +/* + * iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this + * function. + */ +void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags) +{ + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { + *tx_flags |= TX_CMD_FLG_RTS_MSK; + *tx_flags &= ~TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + + if (!ieee80211_is_mgmt(fc)) + return; + + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + break; + } + } else if (info->control.rates[0].flags & + IEEE80211_TX_RC_USE_CTS_PROTECT) { + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + } +} +EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection); diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.h b/drivers/net/wireless/iwlwifi/iwl-legacy.h new file mode 100644 index 000000000000..9f7b2f935964 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_legacy_h__ +#define __iwl_legacy_h__ + +/* mac80211 handlers */ +int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); +void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); +void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + __le16 fc, __le32 *tx_flags); + +irqreturn_t iwl_isr_legacy(int irq, void *data); + +#endif /* __iwl_legacy_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 49d7788937a9..1eec18d909d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -75,6 +75,10 @@ struct iwl_power_vec_entry { #define NOSLP cpu_to_le16(0), 0, 0 #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 +#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK | \ + IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \ + IWL_POWER_ADVANCE_PM_ENA_MSK) +#define ASLP_TOUT(T) cpu_to_le32(T) #define TU_TO_USEC 1024 #define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) #define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ @@ -114,6 +118,52 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; +/* advance power management */ +/* DTIM 0 - 2 */ +static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2} +}; + + +/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ +/* DTIM 3 - 10 */ +static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2} +}; + +/* for DTIM period > IWL_DTIM_RANGE_1_MAX */ +/* DTIM 11 - */ +static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = { + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0}, + {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50), + SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2} +}; + static void iwl_static_sleep_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, enum iwl_power_level lvl, int period) @@ -124,11 +174,19 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, u8 skip; u32 slp_itrvl; - table = range_2; - if (period <= IWL_DTIM_RANGE_1_MAX) - table = range_1; - if (period <= IWL_DTIM_RANGE_0_MAX) - table = range_0; + if (priv->cfg->adv_pm) { + table = apm_range_2; + if (period <= IWL_DTIM_RANGE_1_MAX) + table = apm_range_1; + if (period <= IWL_DTIM_RANGE_0_MAX) + table = apm_range_0; + } else { + table = range_2; + if (period <= IWL_DTIM_RANGE_1_MAX) + table = range_1; + if (period <= IWL_DTIM_RANGE_0_MAX) + table = range_0; + } BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); @@ -163,6 +221,20 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; + if (priv->cfg->base_params->shadow_reg_enable) + cmd->flags |= IWL_POWER_SHADOW_REG_ENA; + else + cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + if (!priv->cfg->bt_params->bt_sco_disable) + cmd->flags |= IWL_POWER_BT_SCO_ENA; + else + cmd->flags &= ~IWL_POWER_BT_SCO_ENA; + } + + slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL) cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = @@ -236,6 +308,19 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.pci_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; + if (priv->cfg->base_params->shadow_reg_enable) + cmd->flags |= IWL_POWER_SHADOW_REG_ENA; + else + cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + if (!priv->cfg->bt_params->bt_sco_disable) + cmd->flags |= IWL_POWER_BT_SCO_ENA; + else + cmd->flags &= ~IWL_POWER_BT_SCO_ENA; + } + cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms); cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms); @@ -263,70 +348,95 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) sizeof(struct iwl_powertable_cmd), cmd); } -/* priv->mutex must be held */ -int iwl_power_update_mode(struct iwl_priv *priv, bool force) +static void iwl_power_build_cmd(struct iwl_priv *priv, + struct iwl_powertable_cmd *cmd) { - int ret = 0; bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; - bool update_chains; - struct iwl_powertable_cmd cmd; int dtimper; - /* Don't update the RX chain when chain noise calibration is running */ - update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || - priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; - dtimper = priv->hw->conf.ps_dtim_period ?: 1; if (priv->cfg->base_params->broken_powersave) - iwl_power_sleep_cam_cmd(priv, &cmd); + iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->cfg->base_params->supports_idle && priv->hw->conf.flags & IEEE80211_CONF_IDLE) - iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && priv->cfg->ops->lib->tt_ops.tt_power_mode && priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { /* in thermal throttling low power state */ - iwl_static_sleep_cmd(priv, &cmd, + iwl_static_sleep_cmd(priv, cmd, priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); } else if (!enabled) - iwl_power_sleep_cam_cmd(priv, &cmd); + iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->power_data.debug_sleep_level_override >= 0) - iwl_static_sleep_cmd(priv, &cmd, + iwl_static_sleep_cmd(priv, cmd, priv->power_data.debug_sleep_level_override, dtimper); else if (no_sleep_autoadjust) - iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper); + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper); else - iwl_power_fill_sleep_cmd(priv, &cmd, + iwl_power_fill_sleep_cmd(priv, cmd, priv->hw->conf.dynamic_ps_timeout, priv->hw->conf.max_sleep_period); +} + +int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, + bool force) +{ + int ret; + bool update_chains; + + lockdep_assert_held(&priv->mutex); + + /* Don't update the RX chain when chain noise calibration is running */ + update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || + priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; + + if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) + return 0; + + if (!iwl_is_ready_rf(priv)) + return -EIO; - if (iwl_is_ready_rf(priv) && - (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) { - if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->status); - - ret = iwl_set_power(priv, &cmd); - if (!ret) { - if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->status); - - if (priv->cfg->ops->lib->update_chain_flags && - update_chains) - priv->cfg->ops->lib->update_chain_flags(priv); - else if (priv->cfg->ops->lib->update_chain_flags) - IWL_DEBUG_POWER(priv, + /* scan complete use sleep_power_next, need to be updated */ + memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { + IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); + return 0; + } + + if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) + set_bit(STATUS_POWER_PMI, &priv->status); + + ret = iwl_set_power(priv, cmd); + if (!ret) { + if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) + clear_bit(STATUS_POWER_PMI, &priv->status); + + if (priv->cfg->ops->lib->update_chain_flags && update_chains) + priv->cfg->ops->lib->update_chain_flags(priv); + else if (priv->cfg->ops->lib->update_chain_flags) + IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); - memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)); - } else - IWL_ERR(priv, "set power fail, ret = %d", ret); - } + + memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)); + } else + IWL_ERR(priv, "set power fail, ret = %d", ret); return ret; } +EXPORT_SYMBOL(iwl_power_set_mode); + +int iwl_power_update_mode(struct iwl_priv *priv, bool force) +{ + struct iwl_powertable_cmd cmd; + + iwl_power_build_cmd(priv, &cmd); + return iwl_power_set_mode(priv, &cmd, force); +} EXPORT_SYMBOL(iwl_power_update_mode); /* initialize to default */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index df81565a7cc4..fe012032c28c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -41,10 +41,13 @@ enum iwl_power_level { struct iwl_power_mgr { struct iwl_powertable_cmd sleep_cmd; + struct iwl_powertable_cmd sleep_cmd_next; int debug_sleep_level_override; bool pci_pm; }; +int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, + bool force); int iwl_power_update_mode(struct iwl_priv *priv, bool force); void iwl_power_initialize(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f436270ca39a..87a6fd84d4d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q if (q->need_update == 0) goto exit_unlock; - /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (priv->cfg->base_params->shadow_reg_enable) { + /* shadow register enabled */ + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); + } else { + /* If power-saving is in use, make sure device is awake */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", - reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - goto exit_unlock; - } + if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { + IWL_DEBUG_INFO(priv, + "Rx queue requesting wakeup," + " GP1 = 0x%x\n", reg); + iwl_set_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + goto exit_unlock; + } - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, + q->write_actual); - /* Else device is assumed to be awake */ - } else { - /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); + /* Else device is assumed to be awake */ + } else { + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, + q->write_actual); + } } - q->need_update = 0; exit_unlock: diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 67da31295781..12d9363d0afe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -252,8 +252,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", - jiffies_to_msecs(elapsed_jiffies - (priv->scan_start, jiffies))); + jiffies_to_msecs(jiffies - priv->scan_start)); queue_work(priv->workqueue, &priv->scan_completed); @@ -603,13 +602,16 @@ out_settings: if (!iwl_is_ready_rf(priv)) goto out; - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + /* + * We do not commit power settings while scan is pending, + * do it now if the settings changed. + */ + iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); + iwl_set_tx_power(priv, priv->tx_power_next, false); priv->cfg->ops->utils->post_scan(priv); - out: +out: mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7c7f7dcb1b1e..0a67b2fa52a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -400,7 +400,8 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) } static int iwl_send_remove_station(struct iwl_priv *priv, - const u8 *addr, int sta_id) + const u8 *addr, int sta_id, + bool temporary) { struct iwl_rx_packet *pkt; int ret; @@ -436,9 +437,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv, if (!ret) { switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: - spin_lock_irqsave(&priv->sta_lock, flags_spin); - iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + if (!temporary) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + iwl_sta_ucode_deactivate(priv, sta_id); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; default: @@ -505,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_remove_station(priv, addr, sta_id); + return iwl_send_remove_station(priv, addr, sta_id, false); out_err: spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; @@ -624,6 +627,44 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } EXPORT_SYMBOL(iwl_restore_stations); +void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + unsigned long flags; + int sta_id = ctx->ap_sta_id; + int ret; + struct iwl_addsta_cmd sta_cmd; + struct iwl_link_quality_cmd lq; + bool active; + + spin_lock_irqsave(&priv->sta_lock, flags); + if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { + spin_unlock_irqrestore(&priv->sta_lock, flags); + return; + } + + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); + sta_cmd.mode = 0; + memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); + + active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + if (active) { + ret = iwl_send_remove_station( + priv, priv->stations[sta_id].sta.sta.addr, + sta_id, true); + if (ret) + IWL_ERR(priv, "failed to remove STA %pM (%d)\n", + priv->stations[sta_id].sta.sta.addr, ret); + } + ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); + if (ret) + IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", + priv->stations[sta_id].sta.sta.addr, ret); + iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); +} +EXPORT_SYMBOL(iwl_reprogram_ap_sta); + int iwl_get_free_ucode_key_index(struct iwl_priv *priv) { int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 06475872eee4..206f1e1a0caf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -63,6 +63,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); +void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); /** * iwl_clear_driver_stations - clear knowledge of all stations from driver diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7261ee49f282..90659bcf5804 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - /* wake up nic if it's powered down ... - * uCode will wake up, and interrupt us again, so next - * time we'll skip this part. */ - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", - txq_id, reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - return; - } - - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - - /* else not in power-save mode, uCode will never sleep when we're - * trying to tx (during RFKILL, we're not trying to tx). */ - } else + if (priv->cfg->base_params->shadow_reg_enable) { + /* shadow register enabled */ iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); + } else { + /* if we're trying to save power */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + /* wake up nic if it's powered down ... + * uCode will wake up, and interrupt us again, so next + * time we'll skip this part. */ + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + + if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { + IWL_DEBUG_INFO(priv, + "Tx queue %d requesting wakeup," + " GP1 = 0x%x\n", txq_id, reg); + iwl_set_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + return; + } + + iwl_write_direct32(priv, HBUS_TARG_WRPTR, + txq->q.write_ptr | (txq_id << 8)); + /* + * else not in power-save mode, + * uCode will never sleep when we're + * trying to tx (during RFKILL, we're not trying to tx). + */ + } else + iwl_write32(priv, HBUS_TARG_WRPTR, + txq->q.write_ptr | (txq_id << 8)); + } txq->need_update = 0; } EXPORT_SYMBOL(iwl_txq_update_write_ptr); @@ -350,13 +359,12 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, txq->need_update = 0; /* - * Aggregation TX queues will get their ID when aggregation begins; - * they overwrite the setting done here. The command FIFO doesn't - * need an swq_id so don't set one to catch errors, all others can - * be set up to the identity mapping. + * For the default queues 0-3, set up the swq_id + * already -- all others need to get one later + * (if they need one at all). */ - if (txq_id != priv->cmd_queue) - txq->swq_id = txq_id; + if (txq_id < 4) + iwl_set_swq_id(txq, txq_id, txq_id); /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7edf8c2fb8c7..8eb1393506bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -61,6 +61,7 @@ #include "iwl-helpers.h" #include "iwl-dev.h" #include "iwl-spectrum.h" +#include "iwl-legacy.h" /* * module name, copyright, version, etc. @@ -474,7 +475,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) dma_addr_t phys_addr; dma_addr_t txcmd_phys; int txq_id = skb_get_queue_mapping(skb); - u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */ + u16 len, idx, hdr_len; u8 id; u8 unicast; u8 sta_id; @@ -611,15 +612,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) */ len = sizeof(struct iwl3945_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; len = (len + 3) & ~3; - if (len_org != len) - len_org = 1; - else - len_org = 0; - /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, @@ -661,7 +655,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock_irqrestore(&priv->lock, flags); } - iwl_stop_queue(priv, skb_get_queue_mapping(skb)); + iwl_stop_queue(priv, txq); } return 0; @@ -3057,22 +3051,22 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) +void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; struct ieee80211_conf *conf = NULL; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (!vif || !priv->is_open) + if (!ctx->vif || !priv->is_open) return; - if (vif->type == NL80211_IFTYPE_AP) { + if (ctx->vif->type == NL80211_IFTYPE_AP) { IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - vif->bss_conf.aid, ctx->active.bssid_addr); + ctx->vif->bss_conf.aid, ctx->active.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -3091,18 +3085,18 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - vif->bss_conf.aid, vif->bss_conf.beacon_int); + ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int); - if (vif->bss_conf.use_short_preamble) + if (ctx->vif->bss_conf.use_short_preamble) ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.use_short_slot) + if (ctx->vif->bss_conf.use_short_slot) ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; @@ -3110,7 +3104,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) iwl3945_commit_rxon(priv, ctx); - switch (vif->type) { + switch (ctx->vif->type) { case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; @@ -3119,7 +3113,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) break; default: IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, vif->type); + __func__, ctx->vif->type); break; } } @@ -3234,9 +3228,10 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) +void iwl3945_config_ap(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif = ctx->vif; int rc = 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -3407,9 +3402,9 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, ctx->staging.filter_flags |= filter_or; /* - * Committing directly here breaks for some reason, - * but we'll eventually commit the filter flags - * change anyway. + * Not committing directly because hardware can perform a scan, + * but even if hw is ready, committing here breaks for some reason, + * we'll eventually commit the filter flags change anyway. */ mutex_unlock(&priv->mutex); @@ -3824,18 +3819,19 @@ static struct attribute_group iwl3945_attribute_group = { .attrs = iwl3945_sysfs_entries, }; -static struct ieee80211_ops iwl3945_hw_ops = { +struct ieee80211_ops iwl3945_hw_ops = { .tx = iwl3945_mac_tx, .start = iwl3945_mac_start, .stop = iwl3945_mac_stop, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, + .change_interface = iwl_mac_change_interface, + .config = iwl_legacy_mac_config, .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, + .reset_tsf = iwl_legacy_mac_reset_tsf, + .bss_info_changed = iwl_legacy_mac_bss_info_changed, .hw_scan = iwl_mac_hw_scan, .sta_add = iwl3945_mac_sta_add, .sta_remove = iwl_mac_sta_remove, @@ -3866,6 +3862,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; + priv->tx_power_next = IWL_DEFAULT_TX_POWER; if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", @@ -3965,7 +3962,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); + hw = iwl_alloc_all(cfg); if (hw == NULL) { pr_err("Can not allocate network device\n"); err = -ENOMEM; @@ -4117,7 +4114,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_enable_msi(priv->pci_dev); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -4275,10 +4272,7 @@ static struct pci_driver iwl3945_driver = { .id_table = iwl3945_hw_card_ids, .probe = iwl3945_pci_probe, .remove = __devexit_p(iwl3945_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif + .driver.pm = IWL_PM_OPS, }; static int __init iwl3945_init(void) diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 330c7d9cf101..50dee6a0a5ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -908,7 +908,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, return ret; } - iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX; + iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX; return 0; } diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 373930afc26b..dee32d3681a5 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -9,8 +9,6 @@ #include <linux/sched.h> #include <linux/wait.h> #include <linux/slab.h> -#include <linux/sched.h> -#include <linux/wait.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> #include <asm/unaligned.h> @@ -2062,7 +2060,7 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv) }; /* Section 5.17.2 */ - static struct region_code_mapping regmap[] = { + static const struct region_code_mapping regmap[] = { {"US ", 0x10}, /* US FCC */ {"CA ", 0x20}, /* Canada */ {"EU ", 0x30}, /* ETSI */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 70745928f3f8..78c4da150a74 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -177,6 +177,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, struct cmd_ds_host_sleep cmd_config; int ret; + /* + * Certain firmware versions do not support EHS_REMOVE_WAKEUP command + * and the card will return a failure. Since we need to be + * able to reset the mask, in those cases we set a 0 mask instead. + */ + if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported) + criteria = 0; + cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); cmd_config.criteria = cpu_to_le32(criteria); cmd_config.gpio = priv->wol_gpio; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index cb14c38caf3a..18dd9a02c459 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -138,6 +138,7 @@ struct lbs_private { uint32_t wol_criteria; uint8_t wol_gpio; uint8_t wol_gap; + bool ehs_remove_supported; /* Transmitting */ int tx_pending_len; /* -1 while building packet */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index efaf85032208..6524c70363d9 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -345,6 +345,13 @@ static int if_usb_probe(struct usb_interface *intf, if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); + /* + * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. + */ + priv->wol_criteria = EHS_REMOVE_WAKEUP; + if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) + priv->ehs_remove_supported = false; + return 0; err_start_card: @@ -1090,12 +1097,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) if (priv->psstate != PS_STATE_FULL_POWER) return -1; - if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { - lbs_pr_info("Suspend attempt without " - "configuring wake params!\n"); - return -ENOSYS; - } - ret = lbs_suspend(priv); if (ret) goto out; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index fcd1bbfc632d..6836a6dd9853 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -851,9 +851,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->work_thread = create_singlethread_workqueue("lbs_worker"); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - priv->wol_criteria = 0xffffffff; + priv->wol_criteria = EHS_REMOVE_WAKEUP; priv->wol_gpio = 0xff; priv->wol_gap = 20; + priv->ehs_remove_supported = true; goto done; diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index a4d0bca9ef2c..a2b1df21d286 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -55,7 +55,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) struct rxpd *p_rx_pd; int hdrchop; struct ethhdr *p_ethhdr; - const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + static const u8 rfc1042_eth_hdr[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 + }; lbs_deb_enter(LBS_DEB_RX); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7eaaa3bab547..454f045ddff3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -309,6 +309,8 @@ struct mac80211_hwsim_data { */ u64 group; struct dentry *debugfs_group; + + int power_level; }; @@ -497,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, rx_status.band = data->channel->band; rx_status.rate_idx = info->control.rates[0].idx; /* TODO: simulate real signal strength (and optional packet loss) */ - rx_status.signal = -50; + rx_status.signal = data->power_level - 50; if (data->ps != PS_DISABLED) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); @@ -698,6 +700,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); data->channel = conf->channel; + data->power_level = conf->power_level; if (!data->started || !data->beacon_int) del_timer(&data->beacon_timer); else diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f152a25be59f..9ecf8407cb1b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -29,6 +29,12 @@ #define MWL8K_NAME KBUILD_MODNAME #define MWL8K_VERSION "0.12" +/* Module parameters */ +static unsigned ap_mode_default; +module_param(ap_mode_default, bool, 0); +MODULE_PARM_DESC(ap_mode_default, + "Set to 1 to make ap mode the default instead of sta mode"); + /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 #define MWL8K_MODE_STA 0x0000005a @@ -92,8 +98,10 @@ struct rxd_ops { struct mwl8k_device_info { char *part_name; char *helper_image; - char *fw_image; + char *fw_image_sta; + char *fw_image_ap; struct rxd_ops *ap_rxd_ops; + u32 fw_api_ap; }; struct mwl8k_rx_queue { @@ -136,8 +144,8 @@ struct mwl8k_priv { void __iomem *regs; /* firmware */ - struct firmware *fw_helper; - struct firmware *fw_ucode; + const struct firmware *fw_helper; + const struct firmware *fw_ucode; /* hardware/firmware parameters */ bool ap_fw; @@ -210,6 +218,18 @@ struct mwl8k_priv { /* Most recently reported noise in dBm */ s8 noise; + + /* + * preserve the queue configurations so they can be restored if/when + * the firmware image is swapped. + */ + struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES]; + + /* async firmware loading state */ + unsigned fw_state; + char *fw_pref; + char *fw_alt; + struct completion firmware_loading_complete; }; /* Per interface specific private data */ @@ -285,8 +305,9 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { }; /* Set or get info from Firmware */ -#define MWL8K_CMD_SET 0x0001 #define MWL8K_CMD_GET 0x0000 +#define MWL8K_CMD_SET 0x0001 +#define MWL8K_CMD_SET_LIST 0x0002 /* Firmware command codes */ #define MWL8K_CMD_CODE_DNLD 0x0001 @@ -296,6 +317,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_GET_STAT 0x0014 #define MWL8K_CMD_RADIO_CONTROL 0x001c #define MWL8K_CMD_RF_TX_POWER 0x001e +#define MWL8K_CMD_TX_POWER 0x001f #define MWL8K_CMD_RF_ANTENNA 0x0020 #define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */ #define MWL8K_CMD_SET_PRE_SCAN 0x0107 @@ -333,6 +355,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(GET_STAT); MWL8K_CMDNAME(RADIO_CONTROL); MWL8K_CMDNAME(RF_TX_POWER); + MWL8K_CMDNAME(TX_POWER); MWL8K_CMDNAME(RF_ANTENNA); MWL8K_CMDNAME(SET_BEACON); MWL8K_CMDNAME(SET_PRE_SCAN); @@ -372,7 +395,7 @@ static void mwl8k_hw_reset(struct mwl8k_priv *priv) } /* Release fw image */ -static void mwl8k_release_fw(struct firmware **fw) +static void mwl8k_release_fw(const struct firmware **fw) { if (*fw == NULL) return; @@ -386,37 +409,68 @@ static void mwl8k_release_firmware(struct mwl8k_priv *priv) mwl8k_release_fw(&priv->fw_helper); } +/* states for asynchronous f/w loading */ +static void mwl8k_fw_state_machine(const struct firmware *fw, void *context); +enum { + FW_STATE_INIT = 0, + FW_STATE_LOADING_PREF, + FW_STATE_LOADING_ALT, + FW_STATE_ERROR, +}; + /* Request fw image */ static int mwl8k_request_fw(struct mwl8k_priv *priv, - const char *fname, struct firmware **fw) + const char *fname, const struct firmware **fw, + bool nowait) { /* release current image */ if (*fw != NULL) mwl8k_release_fw(fw); - return request_firmware((const struct firmware **)fw, - fname, &priv->pdev->dev); + if (nowait) + return request_firmware_nowait(THIS_MODULE, 1, fname, + &priv->pdev->dev, GFP_KERNEL, + priv, mwl8k_fw_state_machine); + else + return request_firmware(fw, fname, &priv->pdev->dev); } -static int mwl8k_request_firmware(struct mwl8k_priv *priv) +static int mwl8k_request_firmware(struct mwl8k_priv *priv, char *fw_image, + bool nowait) { struct mwl8k_device_info *di = priv->device_info; int rc; if (di->helper_image != NULL) { - rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); - if (rc) { - printk(KERN_ERR "%s: Error requesting helper " - "firmware file %s\n", pci_name(priv->pdev), - di->helper_image); + if (nowait) + rc = mwl8k_request_fw(priv, di->helper_image, + &priv->fw_helper, true); + else + rc = mwl8k_request_fw(priv, di->helper_image, + &priv->fw_helper, false); + if (rc) + printk(KERN_ERR "%s: Error requesting helper fw %s\n", + pci_name(priv->pdev), di->helper_image); + + if (rc || nowait) return rc; - } } - rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); + if (nowait) { + /* + * if we get here, no helper image is needed. Skip the + * FW_STATE_INIT state. + */ + priv->fw_state = FW_STATE_LOADING_PREF; + rc = mwl8k_request_fw(priv, fw_image, + &priv->fw_ucode, + true); + } else + rc = mwl8k_request_fw(priv, fw_image, + &priv->fw_ucode, false); if (rc) { printk(KERN_ERR "%s: Error requesting firmware file %s\n", - pci_name(priv->pdev), di->fw_image); + pci_name(priv->pdev), fw_image); mwl8k_release_fw(&priv->fw_helper); return rc; } @@ -577,12 +631,12 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, static int mwl8k_load_firmware(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; - struct firmware *fw = priv->fw_ucode; + const struct firmware *fw = priv->fw_ucode; int rc; int loops; if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { - struct firmware *helper = priv->fw_helper; + const struct firmware *helper = priv->fw_helper; if (helper == NULL) { printk(KERN_ERR "%s: helper image needed but none " @@ -1811,6 +1865,7 @@ struct mwl8k_cmd_get_hw_spec_ap { __le32 wcbbase1; __le32 wcbbase2; __le32 wcbbase3; + __le32 fw_api_version; } __packed; static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) @@ -1818,6 +1873,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_get_hw_spec_ap *cmd; int rc; + u32 api_version; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) @@ -1834,6 +1890,16 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) if (!rc) { int off; + api_version = le32_to_cpu(cmd->fw_api_version); + if (priv->device_info->fw_api_ap != api_version) { + printk(KERN_ERR "%s: Unsupported fw API version for %s." + " Expected %d got %d.\n", MWL8K_NAME, + priv->device_info->part_name, + priv->device_info->fw_api_ap, + api_version); + rc = -EINVAL; + goto done; + } SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); @@ -1861,6 +1927,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) iowrite32(priv->txq[3].txd_dma, priv->sram + off); } +done: kfree(cmd); return rc; } @@ -2084,7 +2151,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) /* * CMD_RF_TX_POWER. */ -#define MWL8K_TX_POWER_LEVEL_TOTAL 8 +#define MWL8K_RF_TX_POWER_LEVEL_TOTAL 8 struct mwl8k_cmd_rf_tx_power { struct mwl8k_cmd_pkt header; @@ -2092,7 +2159,7 @@ struct mwl8k_cmd_rf_tx_power { __le16 support_level; __le16 current_level; __le16 reserved; - __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; + __le16 power_level_list[MWL8K_RF_TX_POWER_LEVEL_TOTAL]; } __packed; static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) @@ -2116,6 +2183,65 @@ static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) } /* + * CMD_TX_POWER. + */ +#define MWL8K_TX_POWER_LEVEL_TOTAL 12 + +struct mwl8k_cmd_tx_power { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 band; + __le16 channel; + __le16 bw; + __le16 sub_ch; + __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; +} __attribute__((packed)); + +static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, + struct ieee80211_conf *conf, + unsigned short pwr) +{ + struct ieee80211_channel *channel = conf->channel; + struct mwl8k_cmd_tx_power *cmd; + int rc; + int i; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_TX_POWER); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST); + + if (channel->band == IEEE80211_BAND_2GHZ) + cmd->band = cpu_to_le16(0x1); + else if (channel->band == IEEE80211_BAND_5GHZ) + cmd->band = cpu_to_le16(0x4); + + cmd->channel = channel->hw_value; + + if (conf->channel_type == NL80211_CHAN_NO_HT || + conf->channel_type == NL80211_CHAN_HT20) { + cmd->bw = cpu_to_le16(0x2); + } else { + cmd->bw = cpu_to_le16(0x4); + if (conf->channel_type == NL80211_CHAN_HT40MINUS) + cmd->sub_ch = cpu_to_le16(0x3); + else if (conf->channel_type == NL80211_CHAN_HT40PLUS) + cmd->sub_ch = cpu_to_le16(0x1); + } + + for (i = 0; i < MWL8K_TX_POWER_LEVEL_TOTAL; i++) + cmd->power_level_list[i] = cpu_to_le16(pwr); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* * CMD_RF_ANTENNA. */ struct mwl8k_cmd_rf_antenna { @@ -3283,13 +3409,16 @@ static void mwl8k_stop(struct ieee80211_hw *hw) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); } +static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image); + static int mwl8k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; u32 macids_supported; - int macid; + int macid, rc; + struct mwl8k_device_info *di; /* * Reject interface creation if sniffer mode is active, as @@ -3302,12 +3431,28 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, return -EINVAL; } - + di = priv->device_info; switch (vif->type) { case NL80211_IFTYPE_AP: + if (!priv->ap_fw && di->fw_image_ap) { + /* we must load the ap fw to meet this request */ + if (!list_empty(&priv->vif_list)) + return -EBUSY; + rc = mwl8k_reload_firmware(hw, di->fw_image_ap); + if (rc) + return rc; + } macids_supported = priv->ap_macids_supported; break; case NL80211_IFTYPE_STATION: + if (priv->ap_fw && di->fw_image_sta) { + /* we must load the sta fw to meet this request */ + if (!list_empty(&priv->vif_list)) + return -EBUSY; + rc = mwl8k_reload_firmware(hw, di->fw_image_sta); + if (rc) + return rc; + } macids_supported = priv->sta_macids_supported; break; default: @@ -3377,15 +3522,19 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (conf->power_level > 18) conf->power_level = 18; - rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); - if (rc) - goto out; if (priv->ap_fw) { + rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); + if (rc) + goto out; + rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7); if (!rc) rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7); } else { + rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); + if (rc) + goto out; rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7); } @@ -3739,6 +3888,9 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, rc = mwl8k_fw_lock(hw); if (!rc) { + BUG_ON(queue > MWL8K_TX_QUEUES - 1); + memcpy(&priv->wmm_params[queue], params, sizeof(*params)); + if (!priv->wmm_enabled) rc = mwl8k_cmd_set_wmm_mode(hw, 1); @@ -3838,21 +3990,27 @@ enum { MWL8366, }; +#define MWL8K_8366_AP_FW_API 1 +#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" +#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) + static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { [MWL8363] = { .part_name = "88w8363", .helper_image = "mwl8k/helper_8363.fw", - .fw_image = "mwl8k/fmimage_8363.fw", + .fw_image_sta = "mwl8k/fmimage_8363.fw", }, [MWL8687] = { .part_name = "88w8687", .helper_image = "mwl8k/helper_8687.fw", - .fw_image = "mwl8k/fmimage_8687.fw", + .fw_image_sta = "mwl8k/fmimage_8687.fw", }, [MWL8366] = { .part_name = "88w8366", .helper_image = "mwl8k/helper_8366.fw", - .fw_image = "mwl8k/fmimage_8366.fw", + .fw_image_sta = "mwl8k/fmimage_8366.fw", + .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), + .fw_api_ap = MWL8K_8366_AP_FW_API, .ap_rxd_ops = &rxd_8366_ap_ops, }, }; @@ -3863,6 +4021,7 @@ MODULE_FIRMWARE("mwl8k/helper_8687.fw"); MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); MODULE_FIRMWARE("mwl8k/helper_8366.fw"); MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); +MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, @@ -3876,94 +4035,133 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { }; MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); -static int __devinit mwl8k_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int mwl8k_request_alt_fw(struct mwl8k_priv *priv) { - static int printed_version = 0; - struct ieee80211_hw *hw; - struct mwl8k_priv *priv; int rc; - int i; - - if (!printed_version) { - printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); - printed_version = 1; - } - - - rc = pci_enable_device(pdev); + printk(KERN_ERR "%s: Error requesting preferred fw %s.\n" + "Trying alternative firmware %s\n", pci_name(priv->pdev), + priv->fw_pref, priv->fw_alt); + rc = mwl8k_request_fw(priv, priv->fw_alt, &priv->fw_ucode, true); if (rc) { - printk(KERN_ERR "%s: Cannot enable new PCI device\n", - MWL8K_NAME); + printk(KERN_ERR "%s: Error requesting alt fw %s\n", + pci_name(priv->pdev), priv->fw_alt); return rc; } + return 0; +} - rc = pci_request_regions(pdev, MWL8K_NAME); - if (rc) { - printk(KERN_ERR "%s: Cannot obtain PCI resources\n", - MWL8K_NAME); - goto err_disable_device; - } - - pci_set_master(pdev); - - - hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); - if (hw == NULL) { - printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); - rc = -ENOMEM; - goto err_free_reg; - } +static int mwl8k_firmware_load_success(struct mwl8k_priv *priv); +static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) +{ + struct mwl8k_priv *priv = context; + struct mwl8k_device_info *di = priv->device_info; + int rc; - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); + switch (priv->fw_state) { + case FW_STATE_INIT: + if (!fw) { + printk(KERN_ERR "%s: Error requesting helper fw %s\n", + pci_name(priv->pdev), di->helper_image); + goto fail; + } + priv->fw_helper = fw; + rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode, + true); + if (rc && priv->fw_alt) { + rc = mwl8k_request_alt_fw(priv); + if (rc) + goto fail; + priv->fw_state = FW_STATE_LOADING_ALT; + } else if (rc) + goto fail; + else + priv->fw_state = FW_STATE_LOADING_PREF; + break; - priv = hw->priv; - priv->hw = hw; - priv->pdev = pdev; - priv->device_info = &mwl8k_info_tbl[id->driver_data]; + case FW_STATE_LOADING_PREF: + if (!fw) { + if (priv->fw_alt) { + rc = mwl8k_request_alt_fw(priv); + if (rc) + goto fail; + priv->fw_state = FW_STATE_LOADING_ALT; + } else + goto fail; + } else { + priv->fw_ucode = fw; + rc = mwl8k_firmware_load_success(priv); + if (rc) + goto fail; + else + complete(&priv->firmware_loading_complete); + } + break; + case FW_STATE_LOADING_ALT: + if (!fw) { + printk(KERN_ERR "%s: Error requesting alt fw %s\n", + pci_name(priv->pdev), di->helper_image); + goto fail; + } + priv->fw_ucode = fw; + rc = mwl8k_firmware_load_success(priv); + if (rc) + goto fail; + else + complete(&priv->firmware_loading_complete); + break; - priv->sram = pci_iomap(pdev, 0, 0x10000); - if (priv->sram == NULL) { - wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); - goto err_iounmap; + default: + printk(KERN_ERR "%s: Unexpected firmware loading state: %d\n", + MWL8K_NAME, priv->fw_state); + BUG_ON(1); } - /* - * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. - * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. - */ - priv->regs = pci_iomap(pdev, 1, 0x10000); - if (priv->regs == NULL) { - priv->regs = pci_iomap(pdev, 2, 0x10000); - if (priv->regs == NULL) { - wiphy_err(hw->wiphy, "Cannot map device registers\n"); - goto err_iounmap; - } - } + return; +fail: + priv->fw_state = FW_STATE_ERROR; + complete(&priv->firmware_loading_complete); + device_release_driver(&priv->pdev->dev); + mwl8k_release_firmware(priv); +} + +static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image, + bool nowait) +{ + struct mwl8k_priv *priv = hw->priv; + int rc; /* Reset firmware and hardware */ mwl8k_hw_reset(priv); /* Ask userland hotplug daemon for the device firmware */ - rc = mwl8k_request_firmware(priv); + rc = mwl8k_request_firmware(priv, fw_image, nowait); if (rc) { wiphy_err(hw->wiphy, "Firmware files not found\n"); - goto err_stop_firmware; + return rc; } + if (nowait) + return rc; + /* Load firmware into hardware */ rc = mwl8k_load_firmware(hw); - if (rc) { + if (rc) wiphy_err(hw->wiphy, "Cannot start firmware\n"); - goto err_stop_firmware; - } /* Reclaim memory once firmware is successfully loaded */ mwl8k_release_firmware(priv); + return rc; +} + +/* initialize hw after successfully loading a firmware image */ +static int mwl8k_probe_hw(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + int i; if (priv->ap_fw) { priv->rxd_ops = priv->device_info->ap_rxd_ops; @@ -3980,58 +4178,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->wmm_enabled = false; priv->pending_tx_pkts = 0; - - /* - * Extra headroom is the size of the required DMA header - * minus the size of the smallest 802.11 frame (CTS frame). - */ - hw->extra_tx_headroom = - sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); - - hw->channel_change_time = 10; - - hw->queues = MWL8K_TX_QUEUES; - - /* Set rssi values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM; - hw->vif_data_size = sizeof(struct mwl8k_vif); - hw->sta_data_size = sizeof(struct mwl8k_sta); - - priv->macids_used = 0; - INIT_LIST_HEAD(&priv->vif_list); - - /* Set default radio state and preamble */ - priv->radio_on = 0; - priv->radio_short_preamble = 0; - - /* Finalize join worker */ - INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); - - /* TX reclaim and RX tasklets. */ - tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); - tasklet_disable(&priv->poll_tx_task); - tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); - tasklet_disable(&priv->poll_rx_task); - - /* Power management cookie */ - priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); - if (priv->cookie == NULL) - goto err_stop_firmware; - rc = mwl8k_rxq_init(hw, 0); if (rc) - goto err_free_cookie; + goto err_stop_firmware; rxq_refill(hw, 0, INT_MAX); - mutex_init(&priv->fw_mutex); - priv->fw_mutex_owner = NULL; - priv->fw_mutex_depth = 0; - priv->hostcmd_wait = NULL; - - spin_lock_init(&priv->tx_lock); - - priv->tx_wait = NULL; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { rc = mwl8k_txq_init(hw, i); if (rc) @@ -4071,13 +4222,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_free_irq; } - hw->wiphy->interface_modes = 0; - if (priv->ap_macids_supported) - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); - if (priv->sta_macids_supported) - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); - - /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { @@ -4096,12 +4240,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); - rc = ieee80211_register_hw(hw); - if (rc) { - wiphy_err(hw->wiphy, "Cannot register device\n"); - goto err_free_queues; - } - wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n", priv->device_info->part_name, priv->hw_rev, hw->wiphy->perm_addr, @@ -4120,14 +4258,238 @@ err_free_queues: mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); +err_stop_firmware: + mwl8k_hw_reset(priv); + + return rc; +} + +/* + * invoke mwl8k_reload_firmware to change the firmware image after the device + * has already been registered + */ +static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) +{ + int i, rc = 0; + struct mwl8k_priv *priv = hw->priv; + + mwl8k_stop(hw); + mwl8k_rxq_deinit(hw, 0); + + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + + rc = mwl8k_init_firmware(hw, fw_image, false); + if (rc) + goto fail; + + rc = mwl8k_probe_hw(hw); + if (rc) + goto fail; + + rc = mwl8k_start(hw); + if (rc) + goto fail; + + rc = mwl8k_config(hw, ~0); + if (rc) + goto fail; + + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); + if (rc) + goto fail; + } + + return rc; + +fail: + printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n"); + return rc; +} + +static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) +{ + struct ieee80211_hw *hw = priv->hw; + int i, rc; + + rc = mwl8k_load_firmware(hw); + mwl8k_release_firmware(priv); + if (rc) { + wiphy_err(hw->wiphy, "Cannot start firmware\n"); + return rc; + } + + /* + * Extra headroom is the size of the required DMA header + * minus the size of the smallest 802.11 frame (CTS frame). + */ + hw->extra_tx_headroom = + sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); + + hw->channel_change_time = 10; + + hw->queues = MWL8K_TX_QUEUES; + + /* Set rssi values to dBm */ + hw->flags |= IEEE80211_HW_SIGNAL_DBM; + hw->vif_data_size = sizeof(struct mwl8k_vif); + hw->sta_data_size = sizeof(struct mwl8k_sta); + + priv->macids_used = 0; + INIT_LIST_HEAD(&priv->vif_list); + + /* Set default radio state and preamble */ + priv->radio_on = 0; + priv->radio_short_preamble = 0; + + /* Finalize join worker */ + INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); + + /* TX reclaim and RX tasklets. */ + tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_tx_task); + tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_rx_task); + + /* Power management cookie */ + priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); + if (priv->cookie == NULL) + return -ENOMEM; + + mutex_init(&priv->fw_mutex); + priv->fw_mutex_owner = NULL; + priv->fw_mutex_depth = 0; + priv->hostcmd_wait = NULL; + + spin_lock_init(&priv->tx_lock); + + priv->tx_wait = NULL; + + rc = mwl8k_probe_hw(hw); + if (rc) + goto err_free_cookie; + + hw->wiphy->interface_modes = 0; + if (priv->ap_macids_supported || priv->device_info->fw_image_ap) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); + if (priv->sta_macids_supported || priv->device_info->fw_image_sta) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); + + rc = ieee80211_register_hw(hw); + if (rc) { + wiphy_err(hw->wiphy, "Cannot register device\n"); + goto err_unprobe_hw; + } + + return 0; + +err_unprobe_hw: + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + mwl8k_rxq_deinit(hw, 0); + err_free_cookie: if (priv->cookie != NULL) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); + return rc; +} +static int __devinit mwl8k_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + static int printed_version; + struct ieee80211_hw *hw; + struct mwl8k_priv *priv; + struct mwl8k_device_info *di; + int rc; + + if (!printed_version) { + printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); + printed_version = 1; + } + + + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR "%s: Cannot enable new PCI device\n", + MWL8K_NAME); + return rc; + } + + rc = pci_request_regions(pdev, MWL8K_NAME); + if (rc) { + printk(KERN_ERR "%s: Cannot obtain PCI resources\n", + MWL8K_NAME); + goto err_disable_device; + } + + pci_set_master(pdev); + + + hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); + if (hw == NULL) { + printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); + rc = -ENOMEM; + goto err_free_reg; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + priv = hw->priv; + priv->hw = hw; + priv->pdev = pdev; + priv->device_info = &mwl8k_info_tbl[id->driver_data]; + + + priv->sram = pci_iomap(pdev, 0, 0x10000); + if (priv->sram == NULL) { + wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); + goto err_iounmap; + } + + /* + * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. + * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. + */ + priv->regs = pci_iomap(pdev, 1, 0x10000); + if (priv->regs == NULL) { + priv->regs = pci_iomap(pdev, 2, 0x10000); + if (priv->regs == NULL) { + wiphy_err(hw->wiphy, "Cannot map device registers\n"); + goto err_iounmap; + } + } + + /* + * Choose the initial fw image depending on user input. If a second + * image is available, make it the alternative image that will be + * loaded if the first one fails. + */ + init_completion(&priv->firmware_loading_complete); + di = priv->device_info; + if (ap_mode_default && di->fw_image_ap) { + priv->fw_pref = di->fw_image_ap; + priv->fw_alt = di->fw_image_sta; + } else if (!ap_mode_default && di->fw_image_sta) { + priv->fw_pref = di->fw_image_sta; + priv->fw_alt = di->fw_image_ap; + } else if (ap_mode_default && !di->fw_image_ap && di->fw_image_sta) { + printk(KERN_WARNING "AP fw is unavailable. Using STA fw."); + priv->fw_pref = di->fw_image_sta; + } else if (!ap_mode_default && !di->fw_image_sta && di->fw_image_ap) { + printk(KERN_WARNING "STA fw is unavailable. Using AP fw."); + priv->fw_pref = di->fw_image_ap; + } + rc = mwl8k_init_firmware(hw, priv->fw_pref, true); + if (rc) + goto err_stop_firmware; + return rc; + err_stop_firmware: mwl8k_hw_reset(priv); - mwl8k_release_firmware(priv); err_iounmap: if (priv->regs != NULL) @@ -4163,6 +4525,13 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) return; priv = hw->priv; + wait_for_completion(&priv->firmware_loading_complete); + + if (priv->fw_state == FW_STATE_ERROR) { + mwl8k_hw_reset(priv); + goto unmap; + } + ieee80211_stop_queues(hw); ieee80211_unregister_hw(hw); @@ -4185,6 +4554,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); +unmap: pci_iounmap(pdev, priv->regs); pci_iounmap(pdev, priv->sram); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index d5bc21e5a02c..dd4d8fc9ad7a 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -183,7 +183,7 @@ static void p54u_rx_cb(struct urb *urb) static void p54u_tx_cb(struct urb *urb) { struct sk_buff *skb = urb->context; - struct ieee80211_hw *dev = (struct ieee80211_hw *) + struct ieee80211_hw *dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); p54_free_skb(dev, skb); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 97007d9e2c1f..0764d1a30d13 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1776,11 +1776,8 @@ static void ray_update_multi_list(struct net_device *dev, int all) /* Copy the kernel's list of MC addresses to card */ netdev_for_each_mc_addr(ha, dev) { memcpy_toio(p, ha->addr, ETH_ALEN); - dev_dbg(&link->dev, - "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", - ha->addr[0], ha->addr[1], - ha->addr[2], ha->addr[3], - ha->addr[4], ha->addr[5]); + dev_dbg(&link->dev, "ray_update_multi add addr %pm\n", + ha->addr); p += ETH_ALEN; i++; } @@ -2015,11 +2012,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete. bssid, ADDRLEN); - dev_dbg(&link->dev, - "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n", - local->bss_id[0], local->bss_id[1], - local->bss_id[2], local->bss_id[3], - local->bss_id[4], local->bss_id[5]); + dev_dbg(&link->dev, "ray_cs new BSSID = %pm\n", + local->bss_id); if (!sniffer) authenticate(local); } @@ -2286,8 +2280,8 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) struct ethhdr *peth; UCHAR srcaddr[ADDRLEN]; UCHAR destaddr[ADDRLEN]; - static UCHAR org_bridge[3] = { 0, 0, 0xf8 }; - static UCHAR org_1042[3] = { 0, 0, 0 }; + static const UCHAR org_bridge[3] = { 0, 0, 0xf8 }; + static const UCHAR org_1042[3] = { 0, 0, 0 }; memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 71b5971da597..19f3d568f700 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -156,6 +156,12 @@ MODULE_PARM_DESC(workaround_interval, #define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) +/* Known device types */ +#define RNDIS_UNKNOWN 0 +#define RNDIS_BCM4320A 1 +#define RNDIS_BCM4320B 2 + + /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c * slightly modified for datatype endianess, etc */ @@ -478,6 +484,7 @@ struct rndis_wlan_private { struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; + int device_type; int caps; int multicast_size; @@ -810,7 +817,8 @@ exit_unlock: return ret; } -static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) +static int rndis_set_oid(struct usbnet *dev, __le32 oid, const void *data, + int len) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); union { @@ -994,7 +1002,18 @@ static int level_to_qual(int level) */ static int set_infra_mode(struct usbnet *usbdev, int mode); static void restore_keys(struct usbnet *usbdev); -static int rndis_check_bssid_list(struct usbnet *usbdev); +static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, + bool *matched); + +static int rndis_start_bssid_list_scan(struct usbnet *usbdev) +{ + __le32 tmp; + + /* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */ + tmp = cpu_to_le32(1); + return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); +} static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) { @@ -1015,7 +1034,7 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) return ret; } -static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) +static int set_bssid(struct usbnet *usbdev, const u8 *bssid) { int ret; @@ -1031,7 +1050,9 @@ static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) static int clear_bssid(struct usbnet *usbdev) { - u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static const u8 broadcast_mac[ETH_ALEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; return set_bssid(usbdev, broadcast_mac); } @@ -1904,14 +1925,14 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, struct usbnet *usbdev = netdev_priv(dev); struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret; - __le32 tmp; + int delay = SCAN_DELAY_JIFFIES; netdev_dbg(usbdev->net, "cfg80211.scan\n"); /* Get current bssid list from device before new scan, as new scan * clears internal bssid list. */ - rndis_check_bssid_list(usbdev); + rndis_check_bssid_list(usbdev, NULL, NULL); if (!request) return -EINVAL; @@ -1921,13 +1942,13 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, priv->scan_request = request; - tmp = cpu_to_le32(1); - ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); + ret = rndis_start_bssid_list_scan(usbdev); if (ret == 0) { + if (priv->device_type == RNDIS_BCM4320A) + delay = HZ; + /* Wait before retrieving scan results from device */ - queue_delayed_work(priv->workqueue, &priv->scan_work, - SCAN_DELAY_JIFFIES); + queue_delayed_work(priv->workqueue, &priv->scan_work, delay); } return ret; @@ -1981,7 +2002,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, GFP_KERNEL); } -static int rndis_check_bssid_list(struct usbnet *usbdev) +static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, + bool *matched) { void *buf = NULL; struct ndis_80211_bssid_list_ex *bssid_list; @@ -2017,7 +2039,11 @@ resize_buf: count, len); while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - rndis_bss_info_update(usbdev, bssid); + if (rndis_bss_info_update(usbdev, bssid) && match_bssid && + matched) { + if (compare_ether_addr(bssid->mac, match_bssid)) + *matched = true; + } bssid = (void *)bssid + bssid_len; bssid_len = le32_to_cpu(bssid->length); @@ -2041,7 +2067,7 @@ static void rndis_get_scan_results(struct work_struct *work) if (!priv->scan_request) return; - ret = rndis_check_bssid_list(usbdev); + ret = rndis_check_bssid_list(usbdev, NULL, NULL); cfg80211_scan_done(priv->scan_request, ret < 0); @@ -2495,6 +2521,91 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); } +static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, + struct ndis_80211_assoc_info *info) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + struct ieee80211_channel *channel; + struct ndis_80211_conf config; + struct ndis_80211_ssid ssid; + s32 signal; + u64 timestamp; + u16 capability; + u16 beacon_interval; + __le32 rssi; + u8 ie_buf[34]; + int len, ret, ie_len; + + /* Get signal quality, in case of error use rssi=0 and ignore error. */ + len = sizeof(rssi); + rssi = 0; + ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); + signal = level_to_qual(le32_to_cpu(rssi)); + + netdev_dbg(usbdev->net, "%s(): OID_802_11_RSSI -> %d, " + "rssi:%d, qual: %d\n", __func__, ret, le32_to_cpu(rssi), + level_to_qual(le32_to_cpu(rssi))); + + /* Get AP capabilities */ + if (info) { + capability = le16_to_cpu(info->resp_ie.capa); + } else { + /* Set atleast ESS/IBSS capability */ + capability = (priv->infra_mode == NDIS_80211_INFRA_INFRA) ? + WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS; + } + + /* Get channel and beacon interval */ + len = sizeof(config); + ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); + netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n", + __func__, ret); + if (ret >= 0) { + beacon_interval = le16_to_cpu(config.beacon_period); + channel = ieee80211_get_channel(priv->wdev.wiphy, + KHZ_TO_MHZ(le32_to_cpu(config.ds_config))); + if (!channel) { + netdev_warn(usbdev->net, "%s(): could not get channel." + "\n", __func__); + return; + } + } else { + netdev_warn(usbdev->net, "%s(): could not get configuration.\n", + __func__); + return; + } + + /* Get SSID, in case of error, use zero length SSID and ignore error. */ + len = sizeof(ssid); + memset(&ssid, 0, sizeof(ssid)); + ret = rndis_query_oid(usbdev, OID_802_11_SSID, &ssid, &len); + netdev_dbg(usbdev->net, "%s(): OID_802_11_SSID -> %d, len: %d, ssid: " + "'%.32s'\n", __func__, ret, + le32_to_cpu(ssid.length), ssid.essid); + + if (le32_to_cpu(ssid.length) > 32) + ssid.length = cpu_to_le32(32); + + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = le32_to_cpu(ssid.length); + memcpy(&ie_buf[2], ssid.essid, le32_to_cpu(ssid.length)); + + ie_len = le32_to_cpu(ssid.length) + 2; + + /* no tsf */ + timestamp = 0; + + netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " + "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " + "signal:%d\n", __func__, (channel ? channel->center_freq : -1), + bssid, (u32)timestamp, capability, beacon_interval, ie_len, + ssid.essid, signal); + + cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, + timestamp, capability, beacon_interval, ie_buf, ie_len, + signal, GFP_KERNEL); +} + /* * workers, indication handlers, device poller */ @@ -2507,6 +2618,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) u8 *req_ie, *resp_ie; int ret, offset; bool roamed = false; + bool match_bss; if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { /* received media connect indication while connected, either @@ -2558,6 +2670,13 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) resp_ie_len = CONTROL_BUFFER_SIZE - offset; } + } else { + /* Since rndis_wlan_craft_connected_bss() might use info + * later and expects info to contain valid data if + * non-null, free info and set NULL here. + */ + kfree(info); + info = NULL; } } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) return; @@ -2569,13 +2688,26 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", bssid, roamed ? " roamed" : ""); - /* Internal bss list in device always contains at least the currently + /* Internal bss list in device should contain at least the currently * connected bss and we can get it to cfg80211 with * rndis_check_bssid_list(). - * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS - * spec. + * + * NDIS spec says: "If the device is associated, but the associated + * BSSID is not in its BSSID scan list, then the driver must add an + * entry for the BSSID at the end of the data that it returns in + * response to query of OID_802_11_BSSID_LIST." + * + * NOTE: Seems to be true for BCM4320b variant, but not BCM4320a. */ - rndis_check_bssid_list(usbdev); + match_bss = false; + rndis_check_bssid_list(usbdev, bssid, &match_bss); + + if (!is_zero_ether_addr(bssid) && !match_bss) { + /* Couldn't get bss from device, we need to manually craft bss + * for cfg80211. + */ + rndis_wlan_craft_connected_bss(usbdev, bssid, info); + } if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { if (!roamed) @@ -2934,8 +3066,21 @@ static void rndis_device_poller(struct work_struct *work) * also polls device with rndis_command() and catches for media link * indications. */ - if (!is_associated(usbdev)) + if (!is_associated(usbdev)) { + /* Workaround bad scanning in BCM4320a devices with active + * background scanning when not associated. + */ + if (priv->device_type == RNDIS_BCM4320A && priv->radio_on && + !priv->scan_request) { + /* Get previous scan results */ + rndis_check_bssid_list(usbdev, NULL, NULL); + + /* Initiate new scan */ + rndis_start_bssid_list_scan(usbdev); + } + goto end; + } len = sizeof(rssi); ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); @@ -2992,10 +3137,12 @@ end: /* * driver/device initialization */ -static void rndis_copy_module_params(struct usbnet *usbdev) +static void rndis_copy_module_params(struct usbnet *usbdev, int device_type) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + priv->device_type = device_type; + priv->param_country[0] = modparam_country[0]; priv->param_country[1] = modparam_country[1]; priv->param_country[2] = 0; @@ -3038,12 +3185,25 @@ static void rndis_copy_module_params(struct usbnet *usbdev) priv->param_workaround_interval = modparam_workaround_interval; } +static int unknown_early_init(struct usbnet *usbdev) +{ + /* copy module parameters for unknown so that iwconfig reports txpower + * and workaround parameter is copied to private structure correctly. + */ + rndis_copy_module_params(usbdev, RNDIS_UNKNOWN); + + /* This is unknown device, so do not try set configuration parameters. + */ + + return 0; +} + static int bcm4320a_early_init(struct usbnet *usbdev) { /* copy module parameters for bcm4320a so that iwconfig reports txpower * and workaround parameter is copied to private structure correctly. */ - rndis_copy_module_params(usbdev); + rndis_copy_module_params(usbdev, RNDIS_BCM4320A); /* bcm4320a doesn't handle configuration parameters well. Try * set any and you get partially zeroed mac and broken device. @@ -3057,7 +3217,7 @@ static int bcm4320b_early_init(struct usbnet *usbdev) struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); char buf[8]; - rndis_copy_module_params(usbdev); + rndis_copy_module_params(usbdev, RNDIS_BCM4320B); /* Early initialization settings, setting these won't have effect * if called after generic_rndis_bind(). @@ -3320,7 +3480,7 @@ static const struct driver_info rndis_wlan_info = { .tx_fixup = rndis_tx_fixup, .reset = rndis_wlan_reset, .stop = rndis_wlan_stop, - .early_init = bcm4320a_early_init, + .early_init = unknown_early_init, .indication = rndis_wlan_indication, }; diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index eea1ef2f502b..ade30251608e 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -53,51 +53,41 @@ config RT61PCI When compiled as a module, this driver will be called rt61pci. -config RT2800PCI_PCI - boolean - depends on PCI - default y - -config RT2800PCI_SOC - boolean - depends on RALINK_RT288X || RALINK_RT305X - default y - config RT2800PCI - tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" - depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" + depends on PCI || RALINK_RT288X || RALINK_RT305X select RT2800_LIB - select RT2X00_LIB_PCI if RT2800PCI_PCI - select RT2X00_LIB_SOC if RT2800PCI_SOC + select RT2X00_LIB_PCI if PCI + select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT select EEPROM_93CX6 ---help--- - This adds support for rt2800/rt3000/rt3500 wireless chipset family. - Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 - - This driver is non-functional at the moment and is intended for - developers. + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052, + RT3090, RT3091 & RT3092 When compiled as a module, this driver will be called "rt2800pci.ko". if RT2800PCI -config RT2800PCI_RT30XX - bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" - default y +config RT2800PCI_RT33XX + bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800pci driver. - Supported chips: RT3090, RT3091 & RT3092 + Supported chips: RT3390 Support for these devices is non-functional at the moment and is intended for testers and developers. config RT2800PCI_RT35XX - bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices" + bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -134,8 +124,8 @@ config RT73USB When compiled as a module, this driver will be called rt73usb. config RT2800USB - tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)" - depends on USB && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support" + depends on USB select RT2800_LIB select RT2X00_LIB_USB select RT2X00_LIB_HT @@ -143,30 +133,28 @@ config RT2800USB select RT2X00_LIB_CRYPTO select CRC_CCITT ---help--- - This adds experimental support for rt2800 wireless chipset family. - Supported chips: RT2770, RT2870 & RT3070. - - Known issues: - - support for RT2870 chips doesn't work with 802.11n APs yet - - support for RT3070 chips is non-functional at the moment + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072 When compiled as a module, this driver will be called "rt2800usb.ko". if RT2800USB -config RT2800USB_RT30XX - bool "rt2800usb - Include support for rt30xx (USB) devices" - default y +config RT2800USB_RT33XX + bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800usb driver. - Supported chips: RT3070, RT3071 & RT3072 + Supported chips: RT3370 Support for these devices is non-functional at the moment and is intended for testers and developers. config RT2800USB_RT35XX - bool "rt2800usb - Include support for rt35xx (USB) devices" + bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -180,9 +168,9 @@ config RT2800USB_UNKNOWN bool "rt2800usb - Include support for unknown (USB) devices" default n ---help--- - This adds support for rt2800 family devices that are known to - have a rt2800 family chipset, but for which the exact chipset - is unknown. + This adds support for rt2800usb devices that are known to + have a rt28xx family compatible chipset, but for which the exact + chipset is unknown. Support status for these devices is unknown, and enabling these devices may or may not work. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4f420a9ec5dc..9ec6691adf0d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -885,8 +885,7 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); + (state == STATE_RADIO_RX_OFF)); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } @@ -989,9 +988,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2400pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt2400pci_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -1612,6 +1609,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .get_tsf = rt2400pci_get_tsf, .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { @@ -1640,28 +1638,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { }; static const struct data_queue_desc rt2400pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index c048b18f4133..d3a4a68cc439 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -809,8 +809,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 8 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 8 * sizeof(__le32) ) +#define TXD_DESC_SIZE (8 * sizeof(__le32)) +#define RXD_DESC_SIZE (8 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. @@ -948,6 +948,6 @@ ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER) #define TXPOWER_TO_DEV(__txpower) \ - MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER) + (MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)) #endif /* RT2400PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 97feb7aef809..3e7f20346243 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1040,8 +1040,7 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); + (state == STATE_RADIO_RX_OFF)); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } @@ -1144,9 +1143,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2500pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt2500pci_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -1193,9 +1190,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -1909,6 +1906,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .get_tsf = rt2500pci_get_tsf, .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { @@ -1937,28 +1935,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { }; static const struct data_queue_desc rt2500pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index d708031361ac..2aad7ba8a100 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1088,8 +1088,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 11 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 11 * sizeof(__le32) ) +#define TXD_DESC_SIZE (11 * sizeof(__le32)) +#define RXD_DESC_SIZE (11 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 93e44c7f3a74..8152fec31753 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -39,7 +39,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -938,8 +938,7 @@ static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); + (state == STATE_RADIO_RX_OFF)); rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); } @@ -1019,9 +1018,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt2500usb_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt2500usb_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -1081,9 +1078,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1801,6 +1798,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1829,28 +1827,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { }; static const struct data_queue_desc rt2500usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_bcn), }; static const struct data_queue_desc rt2500usb_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index eb8b6cab9925..a81c4371835b 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -47,6 +47,7 @@ * RF3021 2.4G 1T2R * RF3022 2.4G 2T2R * RF3052 2.4G 2T2R + * RF3320 2.4G 1T1R */ #define RF2820 0x0001 #define RF2850 0x0002 @@ -412,10 +413,22 @@ #define BCN_OFFSET1_BCN7 FIELD32(0xff000000) /* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. + * TXRXQ_PCNT: PBF register + * PCNT_TX0Q: Page count for TX hardware queue 0 + * PCNT_TX1Q: Page count for TX hardware queue 1 + * PCNT_TX2Q: Page count for TX hardware queue 2 + * PCNT_RX0Q: Page count for RX hardware queue */ #define TXRXQ_PCNT 0x0438 +#define TXRXQ_PCNT_TX0Q FIELD32(0x000000ff) +#define TXRXQ_PCNT_TX1Q FIELD32(0x0000ff00) +#define TXRXQ_PCNT_TX2Q FIELD32(0x00ff0000) +#define TXRXQ_PCNT_RX0Q FIELD32(0xff000000) + +/* + * PBF register + * Debug. Driver doesn't touch PBF register. + */ #define PBF_DBG 0x043c /* @@ -960,8 +973,31 @@ /* * TXOP_CTRL_CFG: + * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation + * AC_TRUN_EN: Enable/Disable truncation for AC change + * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change + * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode + * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS + * RESERVED_TRUN_EN: Reserved + * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection + * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz + * transmissions if extension CCA is clear). + * EXT_CCA_DLY: Extension CCA signal delay time (unit: us) + * EXT_CWMIN: CwMin for extension channel backoff + * 0: Disabled + * */ #define TXOP_CTRL_CFG 0x1340 +#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN FIELD32(0x00000001) +#define TXOP_CTRL_CFG_AC_TRUN_EN FIELD32(0x00000002) +#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN FIELD32(0x00000004) +#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN FIELD32(0x00000008) +#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN FIELD32(0x00000010) +#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020) +#define TXOP_CTRL_CFG_LSIG_TXOP_EN FIELD32(0x00000040) +#define TXOP_CTRL_CFG_EXT_CCA_EN FIELD32(0x00000080) +#define TXOP_CTRL_CFG_EXT_CCA_DLY FIELD32(0x0000ff00) +#define TXOP_CTRL_CFG_EXT_CWMIN FIELD32(0x000f0000) /* * TX_RTS_CFG: @@ -1485,17 +1521,17 @@ #define SHARED_KEY_MODE_BASE 0x7000 #define MAC_WCID_ENTRY(__idx) \ - ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) + (MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry))) #define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) ) + (MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry))) #define MAC_WCID_ATTR_ENTRY(__idx) \ - ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) + (MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32))) #define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define SHARED_KEY_MODE_ENTRY(__idx) \ - ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + (SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32))) struct mac_wcid_entry { u8 mac[6]; @@ -1635,9 +1671,9 @@ struct mac_iveiv_entry { #define HW_BEACON_BASE7 0x5bc0 #define HW_BEACON_OFFSET(__index) \ - ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ - (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ - (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) + (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \ + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) /* * BBP registers. @@ -1987,8 +2023,8 @@ struct mac_iveiv_entry { /* * DMA descriptor defines. */ -#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXWI_DESC_SIZE (4 * sizeof(__le32)) +#define RXWI_DESC_SIZE (4 * sizeof(__le32)) /* * TX WI structure diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5f00e00789d8..75631614aba3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) unsigned int i; u32 reg; + /* + * Some devices are really slow to respond here. Wait a whole second + * before timing out. + */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; - msleep(1); + msleep(10); } ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); @@ -483,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid); + rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1); rt2x00_desc_write(txwi, 1, word); @@ -727,7 +731,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; @@ -824,7 +828,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) } EXPORT_SYMBOL_GPL(rt2800_write_beacon); -static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, +static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, unsigned int beacon_base) { int i; @@ -1144,6 +1148,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, const unsigned int flags) { u32 reg; + bool update_bssid = false; if (flags & CONFIG_UPDATE_TYPE) { /* @@ -1173,6 +1178,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, } if (flags & CONFIG_UPDATE_MAC) { + if (flags & CONFIG_UPDATE_TYPE && + conf->sync == TSF_SYNC_AP_NONE) { + /* + * The BSSID register has to be set to our own mac + * address in AP mode. + */ + memcpy(conf->bssid, conf->mac, sizeof(conf->mac)); + update_bssid = true; + } + if (!is_zero_ether_addr((const u8 *)conf->mac)) { reg = le32_to_cpu(conf->mac[1]); rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); @@ -1183,7 +1198,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, conf->mac, sizeof(conf->mac)); } - if (flags & CONFIG_UPDATE_BSSID) { + if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) { if (!is_zero_ether_addr((const u8 *)conf->bssid)) { reg = le32_to_cpu(conf->bssid[1]); rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); @@ -1529,7 +1544,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF3021) || rt2x00_rf(rt2x00dev, RF3022) || - rt2x00_rf(rt2x00dev, RF3052)) + rt2x00_rf(rt2x00dev, RF3052) || + rt2x00_rf(rt2x00dev, RF3320)) rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); else rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); @@ -2097,7 +2113,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); } - rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + /* + * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1 + * although it is reserved. + */ + rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, ®); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_AC_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_DLY, 88); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); + rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); + rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); @@ -2134,7 +2166,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) SHARED_KEY_MODE_ENTRY(i), 0); for (i = 0; i < 256; i++) { - u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), wcid, sizeof(wcid)); @@ -2981,7 +3013,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) !rt2x00_rf(rt2x00dev, RF2020) && !rt2x00_rf(rt2x00dev, RF3021) && !rt2x00_rf(rt2x00dev, RF3022) && - !rt2x00_rf(rt2x00dev, RF3052)) { + !rt2x00_rf(rt2x00dev, RF3052) && + !rt2x00_rf(rt2x00dev, RF3320)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -3245,7 +3278,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) } else if (rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3021) || - rt2x00_rf(rt2x00dev, RF3022)) { + rt2x00_rf(rt2x00dev, RF3022) || + rt2x00_rf(rt2x00dev, RF3320)) { spec->num_channels = 14; spec->channels = rf_vals_3x; } else if (rt2x00_rf(rt2x00dev, RF3052)) { diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b26739535986..b989b0d3ed49 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -84,20 +84,22 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { - u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ + void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); + + iounmap(base_addr); } #else static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { struct rt2x00_dev *rt2x00dev = eeprom->data; @@ -181,7 +183,7 @@ static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ /* * Firmware functions @@ -328,8 +330,7 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); + (state == STATE_RADIO_RX_ON)); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } @@ -442,7 +443,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, * if the device is booting and wasn't asleep it will return * failure when attempting to wakeup. */ - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); if (state == STATE_AWAKE) { rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); @@ -477,9 +478,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800pci_set_state(rt2x00dev, STATE_SLEEP); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt2800pci_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -777,7 +776,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * Since we have only one producer and one consumer we don't * need to lock the kfifo. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) @@ -912,6 +911,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags); if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); @@ -943,6 +943,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, }; static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -991,21 +992,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { }; static const struct data_queue_desc rt2800pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), @@ -1033,12 +1034,15 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1046,12 +1050,10 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, -#ifdef CONFIG_RT2800PCI_RT30XX - { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#ifdef CONFIG_RT2800PCI_RT33XX + { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif #ifdef CONFIG_RT2800PCI_RT35XX { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1062,19 +1064,19 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { #endif { 0, } }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI MODULE_FIRMWARE(FIRMWARE_RT2860); MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_LICENSE("GPL"); -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static int rt2800soc_probe(struct platform_device *pdev) { return rt2x00soc_probe(pdev, &rt2800pci_ops); @@ -1091,9 +1093,9 @@ static struct platform_driver rt2800soc_driver = { .suspend = rt2x00soc_suspend, .resume = rt2x00soc_resume, }; -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static struct pci_driver rt2800pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2800pci_device_table, @@ -1102,21 +1104,21 @@ static struct pci_driver rt2800pci_driver = { .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ static int __init rt2800pci_init(void) { int ret = 0; -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) ret = platform_driver_register(&rt2800soc_driver); if (ret) return ret; #endif -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI ret = pci_register_driver(&rt2800pci_driver); if (ret) { -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif return ret; @@ -1128,10 +1130,10 @@ static int __init rt2800pci_init(void) static void __exit rt2800pci_exit(void) { -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI pci_unregister_driver(&rt2800pci_driver); #endif -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index 5a8dda9b5b5a..70e050d904c8 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -38,10 +38,10 @@ * Queue register offset macros */ #define TX_QUEUE_REG_OFFSET 0x10 -#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) /* * 8051 firmware image. @@ -52,8 +52,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXD_DESC_SIZE (4 * sizeof(__le32)) +#define RXD_DESC_SIZE (4 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3dff56ec195a..935b76d3ce4f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -45,7 +45,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -114,8 +114,7 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); + (state == STATE_RADIO_RX_ON)); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } @@ -165,7 +164,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, - ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); + ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE) + / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); @@ -183,9 +183,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { if (state == STATE_AWAKE) - rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2); else - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); return 0; } @@ -215,9 +215,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800usb_set_state(rt2x00dev, STATE_SLEEP); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt2800usb_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -245,6 +243,49 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, } /* + * Watchdog handlers + */ +static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { + WARNING(rt2x00dev, "TX HW queue 0 timed out," + " invoke forced kick"); + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { + WARNING(rt2x00dev, "TX HW queue 1 timed out," + " invoke forced kick"); + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2x00usb_watchdog(rt2x00dev); +} + +/* * TX descriptor initialization */ static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) @@ -266,8 +307,14 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, * Initialize TXINFO descriptor */ rt2x00_desc_read(txi, 0, &word); + + /* + * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is + * TXWI + 802.11 header + L2 pad + payload + pad, + * so need to decrease size of TXINFO and USB end pad. + */ rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - entry->skb->len - TXINFO_DESC_SIZE); + entry->skb->len - TXINFO_DESC_SIZE - 4); rt2x00_set_field32(&word, TXINFO_W0_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); @@ -285,22 +332,29 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; } -/* - * TX data initialization - */ -static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +static void rt2800usb_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { - int length; + u8 padding_len; /* - * The length _must_ include 4 bytes padding, - * it should always be multiple of 4, - * but it must _not_ be a multiple of the USB packet size. + * pad(1~3 bytes) is added after each 802.11 payload. + * USB end pad(4 bytes) is added at each USB bulk out packet end. + * TX frame format is : + * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad | + * |<------------- tx_pkt_len ------------->| */ - length = roundup(entry->skb->len + 4, 4); - length += (4 * !(length % entry->queue->usb_maxpacket)); + rt2800_write_tx_data(entry, txdesc); + padding_len = roundup(entry->skb->len + 4, 4) - entry->skb->len; + memset(skb_put(entry->skb, padding_len), 0, padding_len); +} - return length; +/* + * TX data initialization + */ +static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +{ + return entry->skb->len; } /* @@ -507,6 +561,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, }; static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -535,9 +590,9 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, - .watchdog = rt2x00usb_watchdog, + .watchdog = rt2800usb_watchdog, .write_tx_desc = rt2800usb_write_tx_desc, - .write_tx_data = rt2800_write_tx_data, + .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, @@ -553,21 +608,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { }; static const struct data_queue_desc rt2800usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), @@ -599,11 +654,19 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Abocom */ { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Allwin */ { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ @@ -612,8 +675,13 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -624,6 +692,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -632,17 +701,36 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, /* D-Link */ { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ + { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Hawking */ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -651,6 +739,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -658,17 +750,44 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ + { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Philips */ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Samsung */ { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Siemens */ @@ -681,13 +800,22 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sparklan */ { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -701,101 +829,16 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Zinwell */ { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, -#ifdef CONFIG_RT2800USB_RT30XX - /* Abocom */ - { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Allwin */ - { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Corega */ - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Draytek */ - { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Encore */ - { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* EnGenius */ - { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* MSI */ - { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Para */ - { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Planex */ - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, +#ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ - { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* SMC */ - { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ @@ -809,12 +852,9 @@ static struct usb_device_id rt2800usb_device_table[] = { /* I-O DATA */ { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 0722badccf86..671ea3592610 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -40,8 +40,8 @@ /* * DMA descriptor defines. */ -#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXINFO_DESC_SIZE (1 * sizeof(__le32)) +#define RXINFO_DESC_SIZE (1 * sizeof(__le32)) /* * TX Info structure diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 94fe589acfaa..e72117f3fdf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -664,6 +664,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_COPY_IV, DRIVER_REQUIRE_L2PAD, DRIVER_REQUIRE_TXSTATUS_FIFO, + DRIVER_REQUIRE_TASKLET_CONTEXT, /* * Driver features @@ -915,7 +916,7 @@ struct rt2x00_dev { * in those cases REGISTER_BUSY_COUNT attempts should be * taken with a REGISTER_BUSY_DELAY interval. */ -#define REGISTER_BUSY_COUNT 5 +#define REGISTER_BUSY_COUNT 100 #define REGISTER_BUSY_DELAY 100 /* @@ -1133,6 +1134,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); +void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); /* * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 54ffb5aeb34e..a238e908c854 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -133,7 +133,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, */ if (!(ant->flags & ANTENNA_RX_DIVERSITY)) config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); - else if(config.rx == ANTENNA_SW_DIVERSITY) + else if (config.rx == ANTENNA_SW_DIVERSITY) config.rx = active->rx; if (!(ant->flags & ANTENNA_TX_DIVERSITY)) @@ -146,7 +146,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * else the changes will be ignored by the device. */ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, + STATE_RADIO_RX_OFF); /* * Write new antenna setup to device and reset the link tuner. @@ -160,7 +161,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, memcpy(active, &config, sizeof(config)); if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, + STATE_RADIO_RX_ON); } void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index fcdb6b0dc40f..64dfb1f6823e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct timeval timestamp; u32 data_len; - do_gettimeofday(×tamp); - - if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) + if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))) return; + do_gettimeofday(×tamp); + if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); return; @@ -342,7 +342,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); queue_for_each(intf->rt2x00dev, queue) { - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, queue->count, queue->limit, queue->length, @@ -350,7 +350,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, queue->index[Q_INDEX_DMA_DONE], queue->index[Q_INDEX_DONE]); - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } size = strlen(data); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 5ba79b935f09..bd3afc92f434 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -68,7 +68,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Enable RX. */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON); + rt2x00link_start_tuner(rt2x00dev); /* * Start watchdog monitoring. @@ -102,7 +103,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Disable RX. */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2x00link_stop_tuner(rt2x00dev); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF); /* * Disable radio. @@ -113,23 +115,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00leds_led_radio(rt2x00dev, false); } -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - /* - * When we are disabling the RX, we should also stop the link tuner. - */ - if (state == STATE_RADIO_RX_OFF) - rt2x00link_stop_tuner(rt2x00dev); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - /* - * When we are enabling the RX, we should also start the link tuner. - */ - if (state == STATE_RADIO_RX_ON) - rt2x00link_start_tuner(rt2x00dev); -} - static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { @@ -265,10 +250,9 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + unsigned int header_length, i; u8 rate_idx, rate_flags, retry_rates; u8 skbdesc_flags = skbdesc->flags; - unsigned int i; bool success; /* @@ -287,6 +271,11 @@ void rt2x00lib_txdone(struct queue_entry *entry, skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; /* + * Determine the length of 802.11 header. + */ + header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + + /* * Remove L2 padding which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) @@ -390,9 +379,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, * through a mac80211 library call (RTS/CTS) then we should not * send the status report back. */ - if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) - ieee80211_tx_status(rt2x00dev->hw, entry->skb); - else + if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { + if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags)) + ieee80211_tx_status(rt2x00dev->hw, entry->skb); + else + ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); + } else dev_kfree_skb_any(entry->skb); /* @@ -483,6 +475,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry) unsigned int header_length; int rate_idx; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || + !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + goto submit_entry; + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) goto submit_entry; @@ -567,9 +563,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry) entry->skb = skb; submit_entry: - rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry->queue, Q_INDEX); + entry->flags = 0; rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { + rt2x00dev->ops->lib->clear_entry(entry); + rt2x00queue_index_inc(entry->queue, Q_INDEX); + } } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -678,7 +678,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, { entry->flags = 0; entry->bitrate = rate->bitrate; - entry->hw_value =index; + entry->hw_value = index; entry->hw_value_short = index; if (rate->flags & DEV_RATE_SHORT_PREAMBLE) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 619da23b7b56..2cf68f82674b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -57,7 +57,7 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) } #define RATE_MCS(__mode, __mcs) \ - ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) + ((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff)) static inline int rt2x00_get_rate_mcs(const u16 mcs_value) { @@ -69,7 +69,6 @@ static inline int rt2x00_get_rate_mcs(const u16 mcs_value) */ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state); /* * Initialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index b971d8798ebf..bfda60eaf4ef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -67,7 +67,7 @@ (__avg).avg_weight ? \ ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ ((__val) * (AVG_FACTOR))) / \ - (AVG_SAMPLES) ) : \ + (AVG_SAMPLES)) : \ ((__val) * (AVG_FACTOR)); \ __new.avg = __new.avg_weight / (AVG_FACTOR); \ __new; \ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c3c206a97d54..829bf4be9bc3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -283,14 +283,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * invalid behavior in the device. */ memcpy(&intf->mac, vif->addr, ETH_ALEN); - if (vif->type == NL80211_IFTYPE_AP) { - memcpy(&intf->bssid, vif->addr, ETH_ALEN); - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, intf->bssid); - } else { - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, NULL); - } + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, + intf->mac, NULL); /* * Some filters depend on the current working mode. We can force @@ -358,7 +352,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) * if for any reason the link tuner must be reset, this will be * handled by rt2x00lib_config(). */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF); /* * When we've just turned on the radio, we want to reprogram @@ -376,7 +370,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); /* Turn RX back on */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON); return 0; } @@ -719,3 +713,41 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) wiphy_rfkill_set_hw_state(hw->wiphy, !active); } EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); + +void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + unsigned int i = 0; + + ieee80211_stop_queues(hw); + + /* + * Run over all queues to kick them, this will force + * any pending frames to be transmitted. + */ + tx_queue_for_each(rt2x00dev, queue) { + rt2x00dev->ops->lib->kick_tx_queue(queue); + } + + /** + * All queues have been kicked, now wait for each queue + * to become empty. With a bit of luck, we only have to wait + * for the first queue to become empty, because while waiting + * for the that queue, the other queues will have transmitted + * all their frames as well (since they were already kicked). + */ + tx_queue_for_each(rt2x00dev, queue) { + for (i = 0; i < 10; i++) { + if (rt2x00queue_empty(queue)) + break; + msleep(100); + } + + if (!rt2x00queue_empty(queue)) + WARNING(rt2x00dev, "Failed to flush queue %d", queue->qid); + } + + ieee80211_wake_queues(hw); +} +EXPORT_SYMBOL_GPL(rt2x00mac_flush); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 2449d785cf8d..868ca19b13ea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -105,7 +105,7 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, */ addr = dma_alloc_coherent(rt2x00dev->dev, queue->limit * queue->desc_size, - &dma, GFP_KERNEL | GFP_DMA); + &dma, GFP_KERNEL); if (!addr) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e360d287defb..a3d79c7a21c6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -204,8 +204,10 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) if (!l2pad) return; - memmove(skb->data + l2pad, skb->data, header_length); - skb_pull(skb, l2pad); + memmove(skb->data + header_length, skb->data + header_length + l2pad, + skb->len - header_length - l2pad); + + skb_trim(skb, skb->len - l2pad); } static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, @@ -311,14 +313,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, memset(txdesc, 0, sizeof(*txdesc)); /* - * Initialize information from queue - */ - txdesc->qid = entry->queue->qid; - txdesc->cw_min = entry->queue->cw_min; - txdesc->cw_max = entry->queue->cw_max; - txdesc->aifs = entry->queue->aifs; - - /* * Header and frame information. */ txdesc->length = entry->skb->len; @@ -460,12 +454,9 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb); } -static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, +static void rt2x00queue_kick_tx_queue(struct data_queue *queue, struct txentry_desc *txdesc) { - struct data_queue *queue = entry->queue; - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - /* * Check if we need to kick the queue, there are however a few rules * 1) Don't kick unless this is the last in frame in a burst. @@ -477,7 +468,7 @@ static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, */ if (rt2x00queue_threshold(queue) || !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) - rt2x00dev->ops->lib->kick_tx_queue(queue); + queue->rt2x00dev->ops->lib->kick_tx_queue(queue); } int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, @@ -567,7 +558,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, rt2x00queue_index_inc(queue, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); - rt2x00queue_kick_tx_queue(entry, &txdesc); + rt2x00queue_kick_tx_queue(queue, &txdesc); return 0; } @@ -649,10 +640,10 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, * it should not be kicked during this run, since it * is part of another TX operation. */ - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); index_start = queue->index[start]; index_end = queue->index[end]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); /* * Start from the TX done pointer, this guarentees that we will @@ -706,11 +697,11 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, return NULL; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); entry = &queue->entries[queue->index[index]]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); return entry; } @@ -726,7 +717,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) return; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->index[index]++; if (queue->index[index] >= queue->limit) @@ -741,7 +732,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) queue->count++; } - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } static void rt2x00queue_reset(struct data_queue *queue) @@ -749,7 +740,7 @@ static void rt2x00queue_reset(struct data_queue *queue) unsigned long irqflags; unsigned int i; - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->count = 0; queue->length = 0; @@ -759,7 +750,7 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->last_action[i] = jiffies; } - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) @@ -809,8 +800,8 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return -ENOMEM; #define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ - ( ((char *)(__base)) + ((__limit) * (__esize)) + \ - ((__index) * (__psize)) ) + (((char *)(__base)) + ((__limit) * (__esize)) + \ + ((__index) * (__psize))) for (i = 0; i < queue->limit; i++) { entries[i].flags = 0; @@ -911,7 +902,7 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { - spin_lock_init(&queue->lock); + spin_lock_init(&queue->index_lock); queue->rt2x00dev = rt2x00dev; queue->qid = qid; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index d81d85f34866..29b051ac6401 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -43,22 +43,6 @@ #define AGGREGATION_SIZE 3840 /** - * DOC: Number of entries per queue - * - * Under normal load without fragmentation, 12 entries are sufficient - * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code, we need to add some additional margins to - * make sure the queue will never (or only under extreme load) fill up - * completely. - * Since we don't use preallocated DMA, having a large number of queue entries - * will have minimal impact on the memory requirements for the queue. - */ -#define RX_ENTRIES 24 -#define TX_ENTRIES 24 -#define BEACON_ENTRIES 1 -#define ATIM_ENTRIES 8 - -/** * enum data_queue_qid: Queue identification * * @QID_AC_BE: AC BE queue @@ -296,7 +280,6 @@ enum txentry_desc_flags { * Summary of information for the frame descriptor before sending a TX frame. * * @flags: Descriptor flags (See &enum queue_entry_flags). - * @qid: Queue identification (See &enum data_queue_qid). * @length: Length of the entire frame. * @header_length: Length of 802.11 header. * @length_high: PLCP length high word. @@ -309,11 +292,8 @@ enum txentry_desc_flags { * @rate_mode: Rate mode (See @enum rate_modulation). * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. - * @aifs: AIFS value. * @ifs: IFS value. * @txop: IFS value for 11n capable chips. - * @cw_min: cwmin value. - * @cw_max: cwmax value. * @cipher: Cipher type used for encryption. * @key_idx: Key index used for encryption. * @iv_offset: Position where IV should be inserted by hardware. @@ -322,8 +302,6 @@ enum txentry_desc_flags { struct txentry_desc { unsigned long flags; - enum data_queue_qid qid; - u16 length; u16 header_length; @@ -339,11 +317,8 @@ struct txentry_desc { u16 mpdu_density; short retry_limit; - short aifs; short ifs; short txop; - short cw_min; - short cw_max; enum cipher cipher; u16 key_idx; @@ -423,7 +398,7 @@ enum queue_index { * @entries: Base address of the &struct queue_entry which are * part of this queue. * @qid: The queue identification, see &enum data_queue_qid. - * @lock: Spinlock to protect index handling. Whenever @index, @index_done or + * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or * @index_crypt needs to be changed this lock should be grabbed to prevent * index corruption due to concurrency. * @count: Number of frames handled in the queue. @@ -447,7 +422,7 @@ struct data_queue { enum data_queue_qid qid; - spinlock_t lock; + spinlock_t index_lock; unsigned int count; unsigned short limit; unsigned short threshold; @@ -618,10 +593,10 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) } /** - * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts + * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports * @queue: Queue to check. */ -static inline int rt2x00queue_timeout(struct data_queue *queue) +static inline int rt2x00queue_status_timeout(struct data_queue *queue) { return time_after(queue->last_action[Q_INDEX_DMA_DONE], queue->last_action[Q_INDEX_DONE] + (HZ / 10)); diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index cef94621cef7..ed71be95136d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -85,8 +85,6 @@ enum dev_state { STATE_RADIO_OFF, STATE_RADIO_RX_ON, STATE_RADIO_RX_OFF, - STATE_RADIO_RX_ON_LINK, - STATE_RADIO_RX_OFF_LINK, STATE_RADIO_IRQ_ON, STATE_RADIO_IRQ_OFF, STATE_RADIO_IRQ_ON_ISR, diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index fc98063de71d..2aa5c38022f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -40,6 +40,8 @@ static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev) kfree(rt2x00dev->eeprom); rt2x00dev->eeprom = NULL; + + iounmap(rt2x00dev->csr.base); } static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) @@ -51,9 +53,9 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) if (!res) return -ENODEV; - rt2x00dev->csr.base = (void __iomem *)KSEG1ADDR(res->start); + rt2x00dev->csr.base = ioremap(res->start, resource_size(res)); if (!rt2x00dev->csr.base) - goto exit; + return -ENOMEM; rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); if (!rt2x00dev->eeprom) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index b3317df7a7d4..9ac14598e2a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -226,9 +226,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); } static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) @@ -323,21 +321,6 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); /* - * Security measure: if the driver did override the - * txdone_work function, and the hardware did arrive - * in a state which causes it to malfunction, it is - * possible that the driver couldn't handle the txdone - * event correctly. So after giving the driver the - * chance to cleanup, we now force a cleanup of any - * leftovers. - */ - if (!rt2x00queue_empty(queue)) { - WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," - " status handling failed, invoke hard reset", queue->qid); - rt2x00usb_work_txdone(&rt2x00dev->txdone_work); - } - - /* * The queue has been reset, and mac80211 is allowed to use the * queue again. */ @@ -361,7 +344,7 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) if (!rt2x00queue_empty(queue)) { if (rt2x00queue_dma_timeout(queue)) rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00queue_timeout(queue)) + if (rt2x00queue_status_timeout(queue)) rt2x00usb_watchdog_tx_status(queue); } } @@ -424,9 +407,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * Schedule the delayed work for reading the RX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index af548c87f108..6b09b01f634f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1623,8 +1623,7 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); + (state == STATE_RADIO_RX_OFF)); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1745,9 +1744,7 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt61pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt61pci_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -1789,10 +1786,10 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -1820,7 +1817,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - if (txdesc->qid != QID_BEACON) { + if (entry->queue->qid != QID_BEACON) { rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, skbdesc->skb_dma); @@ -1866,8 +1863,8 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Register descriptor details in skb frame descriptor. */ skbdesc->desc = txd; - skbdesc->desc_len = - (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; + skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE : + TXD_DESC_SIZE; } /* @@ -2078,7 +2075,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; @@ -2824,6 +2821,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt61pci_conf_tx, .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -2857,21 +2855,21 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { }; static const struct data_queue_desc rt61pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e2e728ab0b2e..afc803b7959f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -412,7 +412,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 9be8089317e4..6f04552f5819 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -40,7 +40,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -1331,8 +1331,7 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); + (state == STATE_RADIO_RX_OFF)); rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1403,9 +1402,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt73usb_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: rt73usb_toggle_rx(rt2x00dev, state); break; case STATE_RADIO_IRQ_ON: @@ -1472,10 +1469,10 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_write(txd, 0, word); rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -2264,6 +2261,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt73usb_conf_tx, .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2296,21 +2294,21 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { }; static const struct data_queue_desc rt73usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 44d5b2bebd39..1315ce5c992f 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -322,7 +322,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 38fa8244cc96..eeee244fcaab 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -553,6 +553,46 @@ static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) return ret; } +static void rtl8187_set_anaparam(struct rtl8187_priv *priv, bool rfon) +{ + u32 anaparam, anaparam2; + u8 anaparam3, reg; + + if (!priv->is_rtl8187b) { + if (rfon) { + anaparam = RTL8187_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_ON; + } else { + anaparam = RTL8187_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_OFF; + } + } else { + if (rfon) { + anaparam = RTL8187B_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_ON; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_ON; + } else { + anaparam = RTL8187B_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_OFF; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_OFF; + } + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); + if (priv->is_rtl8187b) + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, anaparam3); + reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + static int rtl8187_cmd_reset(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; @@ -603,19 +643,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) int res; /* reset */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | - RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & - ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); + rtl8187_set_anaparam(priv, true); rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); @@ -629,17 +657,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) if (res) return res; - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + rtl8187_set_anaparam(priv, true); /* setup card */ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); @@ -712,10 +730,9 @@ static const u8 rtl8187b_reg_table[][3] = { {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, - {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, - {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, - {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, - {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, + {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, + {0xF2, 0x02, 1}, {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, + {0xF6, 0x06, 1}, {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, @@ -723,14 +740,13 @@ static const u8 rtl8187b_reg_table[][3] = { {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, - {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, - {0x73, 0x9A, 2}, + {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, - {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, - {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, - {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, - {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, - {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, + {0x5B, 0x40, 0}, {0x84, 0x88, 0}, {0x85, 0x24, 0}, {0x88, 0x54, 0}, + {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, + {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, + {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, + {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, {0x8F, 0x00, 0} @@ -742,48 +758,34 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) int res, i; u8 reg; - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_ON); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_ON); + rtl8187_set_anaparam(priv, true); + /* Reset PLL sequence on 8187B. Realtek note: reduces power + * consumption about 30 mA */ rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); reg = rtl818x_ioread8(priv, (u8 *)0xFF62); rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - res = rtl8187_cmd_reset(dev); if (res) return res; - rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); + rtl8187_set_anaparam(priv, true); + + /* BRSR (Basic Rate Set Register) on 8187B looks to be the same as + * RESP_RATE on 8187L in Realtek sources: each bit should be each + * one of the 12 rates, all are enabled */ + rtl818x_iowrite16(priv, (__le16 *)0xFF34, 0x0FFF); + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | - RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + /* Auto Rate Fallback Register (ARFR): 1M-54M setting */ rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFE2, 0x00, 1); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, @@ -811,16 +813,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); + /* RFSW_CTRL register */ rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); @@ -929,6 +924,12 @@ static int rtl8187_start(struct ieee80211_hw *dev) priv->rx_conf = reg; rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + rtl818x_iowrite32(priv, &priv->map->TX_CONF, RTL818X_TX_CONF_HW_SEQNUM | RTL818X_TX_CONF_DISREQQSIZE | @@ -1002,6 +1003,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) rtl818x_iowrite8(priv, &priv->map->CMD, reg); priv->rf->stop(dev); + rtl8187_set_anaparam(priv, false); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index 97eebdcf7eb9..5c6666f09ac1 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c @@ -898,29 +898,7 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) static void rtl8225_rf_stop(struct ieee80211_hw *dev) { - u8 reg; - struct rtl8187_priv *priv = dev->priv; - rtl8225_write(dev, 0x4, 0x1f); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - if (!priv->is_rtl8187b) { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_OFF); - } else { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_OFF); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_OFF); - } - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); } static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 7a8762553cdc..012e1a4016fe 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -52,14 +52,14 @@ void wl1251_disable_interrupts(struct wl1251 *wl) wl->if_ops->disable_irq(wl); } -static void wl1251_power_off(struct wl1251 *wl) +static int wl1251_power_off(struct wl1251 *wl) { - wl->set_power(false); + return wl->if_ops->power(wl, false); } -static void wl1251_power_on(struct wl1251 *wl) +static int wl1251_power_on(struct wl1251 *wl) { - wl->set_power(true); + return wl->if_ops->power(wl, true); } static int wl1251_fetch_firmware(struct wl1251 *wl) @@ -152,9 +152,12 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) static int wl1251_chip_wakeup(struct wl1251 *wl) { - int ret = 0; + int ret; + + ret = wl1251_power_on(wl); + if (ret < 0) + return ret; - wl1251_power_on(wl); msleep(WL1251_POWER_ON_SLEEP); wl->if_ops->reset(wl); diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index 74ba9ced5393..596d90ecba33 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -26,6 +26,7 @@ #include <linux/platform_device.h> #include <linux/wl12xx.h> #include <linux/irq.h> +#include <linux/pm_runtime.h> #include "wl1251.h" @@ -42,8 +43,6 @@ struct wl1251_sdio { u32 elp_val; }; -static struct wl12xx_platform_data *wl12xx_board_data; - static struct sdio_func *wl_to_func(struct wl1251 *wl) { struct wl1251_sdio *wl_sdio = wl->if_priv; @@ -171,8 +170,42 @@ static void wl1251_disable_line_irq(struct wl1251 *wl) return disable_irq(wl->irq); } -static void wl1251_sdio_set_power(bool enable) +static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) { + struct sdio_func *func = wl_to_func(wl); + int ret; + + if (enable) { + /* + * Power is controlled by runtime PM, but we still call board + * callback in case it wants to do any additional setup, + * for example enabling clock buffer for the module. + */ + if (wl->set_power) + wl->set_power(true); + + ret = pm_runtime_get_sync(&func->dev); + if (ret < 0) + goto out; + + sdio_claim_host(func); + sdio_enable_func(func); + sdio_release_host(func); + } else { + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + ret = pm_runtime_put_sync(&func->dev); + if (ret < 0) + goto out; + + if (wl->set_power) + wl->set_power(false); + } + +out: + return ret; } static struct wl1251_if_operations wl1251_sdio_ops = { @@ -181,30 +214,7 @@ static struct wl1251_if_operations wl1251_sdio_ops = { .write_elp = wl1251_sdio_write_elp, .read_elp = wl1251_sdio_read_elp, .reset = wl1251_sdio_reset, -}; - -static int wl1251_platform_probe(struct platform_device *pdev) -{ - if (pdev->id != -1) { - wl1251_error("can only handle single device"); - return -ENODEV; - } - - wl12xx_board_data = pdev->dev.platform_data; - return 0; -} - -/* - * Dummy platform_driver for passing platform_data to this driver, - * until we have a way to pass this through SDIO subsystem or - * some other way. - */ -static struct platform_driver wl1251_platform_driver = { - .driver = { - .name = "wl1251_data", - .owner = THIS_MODULE, - }, - .probe = wl1251_platform_probe, + .power = wl1251_sdio_set_power, }; static int wl1251_sdio_probe(struct sdio_func *func, @@ -214,6 +224,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, struct wl1251 *wl; struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; + const struct wl12xx_platform_data *wl12xx_board_data; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) @@ -239,8 +250,8 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl_sdio->func = func; wl->if_priv = wl_sdio; wl->if_ops = &wl1251_sdio_ops; - wl->set_power = wl1251_sdio_set_power; + wl12xx_board_data = wl12xx_get_platform_data(); if (wl12xx_board_data != NULL) { wl->set_power = wl12xx_board_data->set_power; wl->irq = wl12xx_board_data->irq; @@ -273,6 +284,10 @@ static int wl1251_sdio_probe(struct sdio_func *func, goto out_free_irq; sdio_set_drvdata(func, wl); + + /* Tell PM core that we don't need the card to be powered now */ + pm_runtime_put_noidle(&func->dev); + return ret; out_free_irq: @@ -294,6 +309,9 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) struct wl1251 *wl = sdio_get_drvdata(func); struct wl1251_sdio *wl_sdio = wl->if_priv; + /* Undo decrement done above in wl1251_probe */ + pm_runtime_get_noresume(&func->dev); + if (wl->irq) free_irq(wl->irq, wl); kfree(wl_sdio); @@ -305,23 +323,37 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) sdio_release_host(func); } +static int wl1251_suspend(struct device *dev) +{ + /* + * Tell MMC/SDIO core it's OK to power down the card + * (if it isn't already), but not to remove it completely. + */ + return 0; +} + +static int wl1251_resume(struct device *dev) +{ + return 0; +} + +static const struct dev_pm_ops wl1251_sdio_pm_ops = { + .suspend = wl1251_suspend, + .resume = wl1251_resume, +}; + static struct sdio_driver wl1251_sdio_driver = { .name = "wl1251_sdio", .id_table = wl1251_devices, .probe = wl1251_sdio_probe, .remove = __devexit_p(wl1251_sdio_remove), + .drv.pm = &wl1251_sdio_pm_ops, }; static int __init wl1251_sdio_init(void) { int err; - err = platform_driver_register(&wl1251_platform_driver); - if (err) { - wl1251_error("failed to register platform driver: %d", err); - return err; - } - err = sdio_register_driver(&wl1251_sdio_driver); if (err) wl1251_error("failed to register sdio driver: %d", err); @@ -331,7 +363,6 @@ static int __init wl1251_sdio_init(void) static void __exit wl1251_sdio_exit(void) { sdio_unregister_driver(&wl1251_sdio_driver); - platform_driver_unregister(&wl1251_platform_driver); wl1251_notice("unloaded"); } diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c index 88fa8e69d0d1..ac872b38960f 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -215,12 +215,21 @@ static void wl1251_spi_disable_irq(struct wl1251 *wl) return disable_irq(wl->irq); } +static int wl1251_spi_set_power(struct wl1251 *wl, bool enable) +{ + if (wl->set_power) + wl->set_power(enable); + + return 0; +} + static const struct wl1251_if_operations wl1251_spi_ops = { .read = wl1251_spi_read, .write = wl1251_spi_write, .reset = wl1251_spi_reset_wake, .enable_irq = wl1251_spi_enable_irq, .disable_irq = wl1251_spi_disable_irq, + .power = wl1251_spi_set_power, }; static int __devinit wl1251_spi_probe(struct spi_device *spi) diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index e113d4c1fb35..13fbeeccf609 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h @@ -256,6 +256,7 @@ struct wl1251_if_operations { void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); void (*write_elp)(struct wl1251 *wl, int addr, u32 val); + int (*power)(struct wl1251 *wl, bool enable); void (*reset)(struct wl1251 *wl); void (*enable_irq)(struct wl1251 *wl); void (*disable_irq)(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index b447559f1db5..d2adeb1f72b7 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -1,46 +1,58 @@ -menuconfig WL12XX +menuconfig WL12XX_MENU tristate "TI wl12xx driver support" depends on MAC80211 && EXPERIMENTAL ---help--- - This will enable TI wl12xx driver support. The drivers make - use of the mac80211 stack. + This will enable TI wl12xx driver support for the following chips: + wl1271 and wl1273. + The drivers make use of the mac80211 stack. -config WL1271 - tristate "TI wl1271 support" - depends on WL12XX && GENERIC_HARDIRQS +config WL12XX + tristate "TI wl12xx support" + depends on WL12XX_MENU && GENERIC_HARDIRQS depends on INET select FW_LOADER select CRC7 ---help--- - This module adds support for wireless adapters based on the - TI wl1271 chipset. + This module adds support for wireless adapters based on TI wl1271 and + TI wl1273 chipsets. This module does *not* include support for wl1251. + For wl1251 support, use the separate homonymous driver instead. - If you choose to build a module, it'll be called wl1271. Say N if + If you choose to build a module, it will be called wl12xx. Say N if unsure. -config WL1271_SPI - tristate "TI wl1271 SPI support" - depends on WL1271 && SPI_MASTER +config WL12XX_HT + bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)" + depends on WL12XX && EXPERIMENTAL + default n + ---help--- + This will enable 802.11 HT support in the wl12xx module. + + That configuration is temporary due to the code incomplete and + still in testing process. + +config WL12XX_SPI + tristate "TI wl12xx SPI support" + depends on WL12XX && SPI_MASTER ---help--- This module adds support for the SPI interface of adapters using - TI wl1271 chipset. Select this if your platform is using + TI wl12xx chipsets. Select this if your platform is using the SPI bus. - If you choose to build a module, it'll be called wl1251_spi. + If you choose to build a module, it'll be called wl12xx_spi. Say N if unsure. -config WL1271_SDIO - tristate "TI wl1271 SDIO support" - depends on WL1271 && MMC +config WL12XX_SDIO + tristate "TI wl12xx SDIO support" + depends on WL12XX && MMC ---help--- This module adds support for the SDIO interface of adapters using - TI wl1271 chipset. Select this if your platform is using + TI wl12xx chipsets. Select this if your platform is using the SDIO bus. - If you choose to build a module, it'll be called - wl1271_sdio. Say N if unsure. + If you choose to build a module, it'll be called wl12xx_sdio. + Say N if unsure. config WL12XX_PLATFORM_DATA bool - depends on WL1271_SDIO != n + depends on WL12XX_SDIO != n || WL1251_SDIO != n default y diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 3a807444b2af..005a758174d9 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -1,12 +1,13 @@ -wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ - wl1271_event.o wl1271_tx.o wl1271_rx.o \ - wl1271_ps.o wl1271_acx.o wl1271_boot.o \ - wl1271_init.o wl1271_debugfs.o wl1271_scan.o +wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ + boot.o init.o debugfs.o scan.o -wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o -obj-$(CONFIG_WL1271) += wl1271.o -obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o -obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o +wl12xx_spi-objs = spi.o +wl12xx_sdio-objs = sdio.o + +wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o +obj-$(CONFIG_WL12XX) += wl12xx.o +obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o +obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/acx.c index 618993405262..7cbaeb6d2a37 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -21,7 +21,7 @@ * */ -#include "wl1271_acx.h" +#include "acx.h" #include <linux/module.h> #include <linux/platform_device.h> @@ -29,10 +29,10 @@ #include <linux/spi/spi.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_ps.h" +#include "reg.h" +#include "ps.h" int wl1271_acx_wake_up_conditions(struct wl1271 *wl) { @@ -862,7 +862,7 @@ out: return ret; } -int wl1271_acx_frag_threshold(struct wl1271 *wl) +int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) { struct acx_frag_threshold *acx; int ret = 0; @@ -876,7 +876,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl) goto out; } - acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold); + acx->frag_threshold = cpu_to_le16(frag_threshold); ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); if (ret < 0) { wl1271_warning("Setting of frag threshold failed: %d", ret); @@ -1226,6 +1226,89 @@ out: return ret; } +int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, + struct ieee80211_sta_ht_cap *ht_cap, + bool allow_ht_operation) +{ + struct wl1271_acx_ht_capabilities *acx; + u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + /* Allow HT Operation ? */ + if (allow_ht_operation) { + acx->ht_capabilites = + WL1271_ACX_FW_CAP_HT_OPERATION; + if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; + if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) + acx->ht_capabilites |= + WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; + + /* get data from A-MPDU parameters field */ + acx->ampdu_max_length = ht_cap->ampdu_factor; + acx->ampdu_min_spacing = ht_cap->ampdu_density; + + memcpy(acx->mac_address, mac_address, ETH_ALEN); + } else { /* HT operations are not allowed */ + acx->ht_capabilites = 0; + } + + ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx ht capabilities setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + +int wl1271_acx_set_ht_information(struct wl1271 *wl, + u16 ht_operation_mode) +{ + struct wl1271_acx_ht_information *acx; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx ht information setting"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->ht_protection = + (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); + acx->rifs_mode = 0; + acx->gf_protection = 0; + acx->ht_tx_burst_limit = 0; + acx->dual_cts_protection = 0; + + ret = wl1271_cmd_configure(wl, ACX_HT_BSS_OPERATION, acx, sizeof(*acx)); + + if (ret < 0) { + wl1271_warning("acx ht information setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) { struct wl1271_acx_fw_tsf_information *tsf_info; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/acx.h index ebb341d36e8c..75a6306ff554 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -22,11 +22,11 @@ * */ -#ifndef __WL1271_ACX_H__ -#define __WL1271_ACX_H__ +#ifndef __ACX_H__ +#define __ACX_H__ -#include "wl1271.h" -#include "wl1271_cmd.h" +#include "wl12xx.h" +#include "cmd.h" /************************************************************************* @@ -61,7 +61,8 @@ WL1271_ACX_INTR_HW_AVAILABLE | \ WL1271_ACX_INTR_DATA) -#define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \ +#define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ + WL1271_ACX_INTR_EVENT_A | \ WL1271_ACX_INTR_EVENT_B | \ WL1271_ACX_INTR_HW_AVAILABLE | \ WL1271_ACX_INTR_DATA) @@ -964,6 +965,87 @@ struct wl1271_acx_rssi_snr_avg_weights { u8 snr_data; }; +/* + * ACX_PEER_HT_CAP + * Configure HT capabilities - declare the capabilities of the peer + * we are connected to. + */ +struct wl1271_acx_ht_capabilities { + struct acx_header header; + + /* + * bit 0 - Allow HT Operation + * bit 1 - Allow Greenfield format in TX + * bit 2 - Allow Short GI in TX + * bit 3 - Allow L-SIG TXOP Protection in TX + * bit 4 - Allow HT Control fields in TX. + * Note, driver will still leave space for HT control in packets + * regardless of the value of this field. FW will be responsible + * to drop the HT field from any frame when this Bit set to 0. + * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD. + * Exact policy setting for this feature is TBD. + * Note, this bit can only be set to 1 if bit 3 is set to 1. + */ + __le32 ht_capabilites; + + /* + * Indicates to which peer these capabilities apply. + * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance + * for all peers. + * Only valid for IBSS/DLS operation. + */ + u8 mac_address[ETH_ALEN]; + + /* + * This the maximum A-MPDU length supported by the AP. The FW may not + * exceed this length when sending A-MPDUs + */ + u8 ampdu_max_length; + + /* This is the minimal spacing required when sending A-MPDUs to the AP*/ + u8 ampdu_min_spacing; +} __packed; + +/* HT Capabilites Fw Bit Mask Mapping */ +#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0) +#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1) +#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2) +#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3) +#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4) +#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5) + + +/* + * ACX_HT_BSS_OPERATION + * Configure HT capabilities - AP rules for behavior in the BSS. + */ +struct wl1271_acx_ht_information { + struct acx_header header; + + /* Values: 0 - RIFS not allowed, 1 - RIFS allowed */ + u8 rifs_mode; + + /* Values: 0 - 3 like in spec */ + u8 ht_protection; + + /* Values: 0 - GF protection not required, 1 - GF protection required */ + u8 gf_protection; + + /*Values: 0 - TX Burst limit not required, 1 - TX Burst Limit required*/ + u8 ht_tx_burst_limit; + + /* + * Values: 0 - Dual CTS protection not required, + * 1 - Dual CTS Protection required + * Note: When this value is set to 1 FW will protect all TXOP with RTS + * frame and will not use CTS-to-self regardless of the value of the + * ACX_CTS_PROTECTION information element + */ + u8 dual_cts_protection; + + u8 padding[3]; +} __packed; + struct wl1271_acx_fw_tsf_information { struct acx_header header; @@ -1079,7 +1161,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1); -int wl1271_acx_frag_threshold(struct wl1271 *wl); +int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); @@ -1093,6 +1175,11 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, s16 thold, u8 hyst); int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); +int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, + struct ieee80211_sta_ht_cap *ht_cap, + bool allow_ht_operation); +int wl1271_acx_set_ht_information(struct wl1271 *wl, + u16 ht_operation_mode); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/boot.c index b91021242098..1eafb8175832 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -24,11 +24,11 @@ #include <linux/gpio.h> #include <linux/slab.h> -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_boot.h" -#include "wl1271_io.h" -#include "wl1271_event.h" +#include "acx.h" +#include "reg.h" +#include "boot.h" +#include "io.h" +#include "event.h" static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { [PART_DOWN] = { @@ -471,20 +471,19 @@ int wl1271_boot(struct wl1271 *wl) { int ret = 0; u32 tmp, clk, pause; - int ref_clock = wl->ref_clock; wl1271_boot_hw_version(wl); - if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4) + if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (ref_clock == 1 || ref_clock == 3) + else if (wl->ref_clock == 1 || wl->ref_clock == 3) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (ref_clock != 0) { + if (wl->ref_clock != 0) { u16 val; /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -529,8 +528,7 @@ int wl1271_boot(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - /* 2 */ - clk |= (ref_clock << 1) << 4; + clk |= (wl->ref_clock << 1) << 4; wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/boot.h index f73b0b15a280..c7d771959f3a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -24,7 +24,7 @@ #ifndef __BOOT_H__ #define __BOOT_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_boot(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 5d3e8485ea4e..f3d0541aaad6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -29,13 +29,13 @@ #include <linux/ieee80211.h> #include <linux/slab.h> -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "reg.h" +#include "io.h" +#include "acx.h" #include "wl12xx_80211.h" -#include "wl1271_cmd.h" -#include "wl1271_event.h" +#include "cmd.h" +#include "event.h" #define WL1271_CMD_FAST_POLL_COUNT 50 diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/cmd.h index a0caf4fc37b1..16d1bf814e76 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -22,10 +22,10 @@ * */ -#ifndef __WL1271_CMD_H__ -#define __WL1271_CMD_H__ +#ifndef __CMD_H__ +#define __CMD_H__ -#include "wl1271.h" +#include "wl12xx.h" struct acx_header; @@ -327,9 +327,6 @@ enum wl1271_channel_tune_bands { #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 -#define TEST_CMD_P2G_CAL 0x02 -#define TEST_CMD_CHANNEL_TUNE 0x0d -#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 @@ -375,51 +372,6 @@ struct wl1271_ext_radio_parms_cmd { u8 padding[3]; } __packed; -struct wl1271_cmd_cal_channel_tune { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - u8 band; - u8 channel; - - __le16 radio_status; -} __packed; - -struct wl1271_cmd_cal_update_ref_point { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - __le32 ref_power; - __le32 ref_detector; - u8 sub_band; - u8 padding[3]; -} __packed; - -#define MAX_TLV_LENGTH 400 -#define MAX_NVS_VERSION_LENGTH 12 - -#define WL1271_CAL_P2G_BAND_B_G BIT(0) - -struct wl1271_cmd_cal_p2g { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - __le16 len; - u8 buf[MAX_TLV_LENGTH]; - u8 type; - u8 padding; - - __le16 radio_status; - u8 nvs_version[MAX_NVS_VERSION_LENGTH]; - - u8 sub_band_mask; - u8 padding2; -} __packed; - - /* * There are three types of disconnections: * diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/conf.h index 5f78a6cb1433..a16b3616e430 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_CONF_H__ -#define __WL1271_CONF_H__ +#ifndef __CONF_H__ +#define __CONF_H__ enum { CONF_HW_BIT_RATE_1MBPS = BIT(0), diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 66c2b90ddfd4..dd71b7d2105c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -21,31 +21,42 @@ * */ -#include "wl1271_debugfs.h" +#include "debugfs.h" #include <linux/skbuff.h> #include <linux/slab.h> -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_ps.h" -#include "wl1271_io.h" +#include "wl12xx.h" +#include "acx.h" +#include "ps.h" +#include "io.h" /* ms */ #define WL1271_DEBUGFS_STATS_LIFETIME 1000 /* debugfs macros idea from mac80211 */ +#define DEBUGFS_FORMAT_BUFFER_SIZE 100 +static int wl1271_format_buffer(char __user *userbuf, size_t count, + loff_t *ppos, char *fmt, ...) +{ + va_list args; + char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; + int res; -#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ + va_start(args, fmt); + res = vscnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ static ssize_t name## _read(struct file *file, char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - res = scnprintf(buf, buflen, fmt "\n", ##value); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ + return wl1271_format_buffer(userbuf, count, ppos, \ + fmt "\n", ##value); \ } \ \ static const struct file_operations name## _ops = { \ @@ -69,20 +80,17 @@ static const struct file_operations name## _ops = { \ wl->debugfs.name = NULL; \ } while (0) -#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ +#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ static ssize_t sub## _ ##name## _read(struct file *file, \ char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ \ wl1271_debugfs_update_stats(wl); \ \ - res = scnprintf(buf, buflen, fmt "\n", \ - wl->stats.fw_stats->sub.name); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ + return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ + wl->stats.fw_stats->sub.name); \ } \ \ static const struct file_operations sub## _ ##name## _ops = { \ @@ -126,100 +134,99 @@ static int wl1271_open_file_generic(struct inode *inode, struct file *file) return 0; } -DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); +DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); + +DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); +DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); +DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); +DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); +DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); +DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); + +DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); + +DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); +DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); +DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); +DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); +DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); +DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); +DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); +DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); + +DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); +DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); /* skipping wep.reserved */ -DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); +DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); +DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); +DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); /* skipping cont_miss_bcns_spread for now */ -DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, - 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); - -DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); -DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", +DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); + +DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); +DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); + +DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); +DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); +DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); +DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); +DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); + +DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); + +DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); + +DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); +DEBUGFS_READONLY_FILE(excessive_retries, "%u", wl->stats.excessive_retries); static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.h b/drivers/net/wireless/wl12xx/debugfs.h index 00a45b2669ad..254c5b292cf6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.h +++ b/drivers/net/wireless/wl12xx/debugfs.h @@ -21,10 +21,10 @@ * */ -#ifndef WL1271_DEBUGFS_H -#define WL1271_DEBUGFS_H +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_debugfs_init(struct wl1271 *wl); void wl1271_debugfs_exit(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/event.c index 7b3f50382963..f9146f5242fb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -21,12 +21,12 @@ * */ -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_event.h" -#include "wl1271_ps.h" -#include "wl1271_scan.h" +#include "wl12xx.h" +#include "reg.h" +#include "io.h" +#include "event.h" +#include "ps.h" +#include "scan.h" #include "wl12xx_80211.h" void wl1271_pspoll_work(struct work_struct *work) @@ -134,8 +134,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* go to extremely low power mode */ wl1271_ps_elp_sleep(wl); - if (ret < 0) - break; break; case EVENT_EXIT_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM exit failed"); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/event.h index e4751667cf5e..6cce0143adb5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_EVENT_H__ -#define __WL1271_EVENT_H__ +#ifndef __EVENT_H__ +#define __EVENT_H__ /* * Mbox events diff --git a/drivers/net/wireless/wl12xx/wl1271_ini.h b/drivers/net/wireless/wl12xx/ini.h index 2313047d4015..c330a2583dfd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ini.h +++ b/drivers/net/wireless/wl12xx/ini.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_INI_H__ -#define __WL1271_INI_H__ +#ifndef __INI_H__ +#define __INI_H__ #define WL1271_INI_MAX_SMART_REFLEX_PARAM 16 diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/init.c index 8044bba70ee7..7949d346aadb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -25,11 +25,11 @@ #include <linux/module.h> #include <linux/slab.h> -#include "wl1271_init.h" +#include "init.h" #include "wl12xx_80211.h" -#include "wl1271_acx.h" -#include "wl1271_cmd.h" -#include "wl1271_reg.h" +#include "acx.h" +#include "cmd.h" +#include "reg.h" static int wl1271_init_hwenc_config(struct wl1271 *wl) { @@ -290,7 +290,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl); + ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/init.h index bc26f8c53b91..7762421f8602 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -21,10 +21,10 @@ * */ -#ifndef __WL1271_INIT_H__ -#define __WL1271_INIT_H__ +#ifndef __INIT_H__ +#define __INIT_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); int wl1271_init_templates_config(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/io.c index c8759acef131..35c2f1aca6ba 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -26,9 +26,9 @@ #include <linux/crc7.h> #include <linux/spi/spi.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" #define OCP_CMD_LOOP 32 diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/io.h index c1f92e65ded0..844b32b170bb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -22,10 +22,10 @@ * */ -#ifndef __WL1271_IO_H__ -#define __WL1271_IO_H__ +#ifndef __IO_H__ +#define __IO_H__ -#include "wl1271_reg.h" +#include "reg.h" #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/main.c index 48a4b9961ae6..708ffe304c6d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -31,20 +31,20 @@ #include <linux/platform_device.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_io.h" -#include "wl1271_event.h" -#include "wl1271_tx.h" -#include "wl1271_rx.h" -#include "wl1271_ps.h" -#include "wl1271_init.h" -#include "wl1271_debugfs.h" -#include "wl1271_cmd.h" -#include "wl1271_boot.h" -#include "wl1271_testmode.h" -#include "wl1271_scan.h" +#include "reg.h" +#include "io.h" +#include "event.h" +#include "tx.h" +#include "rx.h" +#include "ps.h" +#include "init.h" +#include "debugfs.h" +#include "cmd.h" +#include "boot.h" +#include "testmode.h" +#include "scan.h" #define WL1271_BOOT_RETRIES 3 @@ -335,6 +335,27 @@ out: return NOTIFY_OK; } +static int wl1271_reg_notify(struct wiphy *wiphy, + struct regulatory_request *request) { + struct ieee80211_supported_band *band; + struct ieee80211_channel *ch; + int i; + + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + for (i = 0; i < band->n_channels; i++) { + ch = &band->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (ch->flags & IEEE80211_CHAN_RADAR) + ch->flags |= IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + + } + + return 0; +} + static void wl1271_conf_init(struct wl1271 *wl) { @@ -404,7 +425,7 @@ static int wl1271_plt_init(struct wl1271 *wl) goto out_free_memmap; /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl); + ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); if (ret < 0) goto out_free_memmap; @@ -481,9 +502,9 @@ static void wl1271_fw_status(struct wl1271 *wl, total += cnt; } - /* if more blocks are available now, schedule some tx work */ - if (total && !skb_queue_empty(&wl->tx_queue)) - ieee80211_queue_work(wl->hw, &wl->tx_work); + /* if more blocks are available now, tx work can be scheduled */ + if (total) + clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -529,6 +550,15 @@ static void wl1271_irq_work(struct work_struct *work) intr &= WL1271_INTR_MASK; + if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { + wl1271_error("watchdog interrupt received! " + "starting recovery."); + ieee80211_queue_work(wl->hw, &wl->recovery_work); + + /* restarting the chip. ignore any other interrupt. */ + goto out; + } + if (intr & WL1271_ACX_INTR_DATA) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); @@ -537,6 +567,16 @@ static void wl1271_irq_work(struct work_struct *work) (wl->tx_results_count & 0xff)) wl1271_tx_complete(wl); + /* Check if any tx blocks were freed */ + if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && + !skb_queue_empty(&wl->tx_queue)) { + /* + * In order to avoid starvation of the TX path, + * call the work function directly. + */ + wl1271_tx_work_locked(wl); + } + wl1271_rx(wl, wl->fw_status); } @@ -851,12 +891,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_sta *sta = txinfo->control.sta; unsigned long flags; - /* peek into the rates configured in the STA entry */ + /* + * peek into the rates configured in the STA entry. + * The rates set after connection stage, The first block only BG sets: + * the compare is for bit 0-16 of sta_rate_set. The second block add + * HT rates in case of HT supported. + */ spin_lock_irqsave(&wl->wl_lock, flags); - if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { + if (sta && + (sta->supp_rates[conf->channel->band] != + (wl->sta_rate_set & HW_BG_RATES_MASK))) { wl->sta_rate_set = sta->supp_rates[conf->channel->band]; set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); } + +#ifdef CONFIG_WL12XX_HT + if (sta && + sta->ht_cap.ht_supported && + ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) != + sta->ht_cap.mcs.rx_mask[0])) { + /* Clean MCS bits before setting them */ + wl->sta_rate_set &= HW_BG_RATES_MASK; + wl->sta_rate_set |= + (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); + set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); + } +#endif spin_unlock_irqrestore(&wl->wl_lock, flags); /* queue the packet */ @@ -867,7 +927,8 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * before that, the tx_work will not be initialized! */ - ieee80211_queue_work(wl->hw, &wl->tx_work); + if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) + ieee80211_queue_work(wl->hw, &wl->tx_work); /* * The workqueue is slow to process the tx_queue and we need stop @@ -919,18 +980,19 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct wiphy *wiphy = hw->wiphy; int retries = WL1271_BOOT_RETRIES; int ret = 0; + bool booted = false; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { + wl1271_debug(DEBUG_MAC80211, + "multiple vifs are not supported yet"); ret = -EBUSY; goto out; } - wl->vif = vif; - switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; @@ -968,15 +1030,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto irq_disable; - wl->state = WL1271_STATE_ON; - wl1271_info("firmware booted (%s)", wl->chip.fw_ver); - - /* update hw/fw version info in wiphy struct */ - wiphy->hw_version = wl->chip.id; - strncpy(wiphy->fw_version, wl->chip.fw_ver, - sizeof(wiphy->fw_version)); - - goto out; + booted = true; + break; irq_disable: wl1271_disable_interrupts(wl); @@ -994,8 +1049,21 @@ power_off: wl1271_power_off(wl); } - wl1271_error("firmware boot failed despite %d retries", - WL1271_BOOT_RETRIES); + if (!booted) { + wl1271_error("firmware boot failed despite %d retries", + WL1271_BOOT_RETRIES); + goto out; + } + + wl->vif = vif; + wl->state = WL1271_STATE_ON; + wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip.id; + strncpy(wiphy->fw_version, wl->chip.fw_ver, + sizeof(wiphy->fw_version)); + out: mutex_unlock(&wl->mutex); @@ -1025,6 +1093,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->scan.state = WL1271_SCAN_STATE_IDLE; kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; + wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } @@ -1312,8 +1381,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; goto out; + } ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) @@ -1536,6 +1607,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out_unlock; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out_unlock; @@ -1645,6 +1721,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); + if (wl->state == WL1271_STATE_OFF) { + /* + * We cannot return -EBUSY here because cfg80211 will expect + * a call to ieee80211_scan_completed if we do - in this case + * there won't be any call. + */ + ret = -EAGAIN; + goto out; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -1659,6 +1745,34 @@ out: return ret; } +static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct wl1271 *wl = hw->priv; + int ret = 0; + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out; + } + + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + + ret = wl1271_acx_frag_threshold(wl, (u16)value); + if (ret < 0) + wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); + + wl1271_ps_elp_sleep(wl); + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; @@ -1666,8 +1780,10 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; goto out; + } ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) @@ -1709,6 +1825,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, { enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; + struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); bool do_join = false; bool set_assoc = false; int ret; @@ -1717,6 +1834,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -1891,9 +2011,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, /* Disable the keep-alive feature */ ret = wl1271_acx_keep_alive_mode(wl, false); - if (ret < 0) goto out_sleep; + + /* restore the bssid filter and go to dummy bssid */ + wl1271_unjoin(wl); + wl1271_dummy_join(wl); } } @@ -1927,6 +2050,37 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } + /* + * Takes care of: New association with HT enable, + * HT information change in beacon. + */ + if (sta && + (changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true); + if (ret < 0) { + wl1271_warning("Set ht cap true failed %d", ret); + goto out_sleep; + } + ret = wl1271_acx_set_ht_information(wl, + bss_conf->ht_operation_mode); + if (ret < 0) { + wl1271_warning("Set ht information failed %d", ret); + goto out_sleep; + } + } + /* + * Takes care of: New association without HT, + * Disassociation. + */ + else if (sta && (changed & BSS_CHANGED_ASSOC)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false); + if (ret < 0) { + wl1271_warning("Set ht cap false failed %d", ret); + goto out_sleep; + } + } + if (changed & BSS_CHANGED_ARP_FILTER) { __be32 addr = bss_conf->arp_addr_list[0]; WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); @@ -1966,6 +2120,11 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out; + } + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -2009,6 +2168,9 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) goto out; @@ -2030,14 +2192,14 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, { struct wl1271 *wl = hw->priv; struct ieee80211_conf *conf = &hw->conf; - + if (idx != 0) return -ENOENT; - + survey->channel = conf->channel; survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = wl->noise; - + return 0; } @@ -2084,37 +2246,34 @@ static struct ieee80211_rate wl1271_rates[] = { .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, }; -/* - * Can't be const, mac80211 writes to this. The order of the channels here - * is designed to improve scanning. - */ +/* can't be const, mac80211 writes to this */ static struct ieee80211_channel wl1271_channels[] = { { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, - { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, - { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, - { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, - { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, - { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, - { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, - { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, - { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, - { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, + { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, + { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, + { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, + { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, + { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, + { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, + { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, + { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, + { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, }; /* mapping to indexes for wl1271_rates */ static const u8 wl1271_rate_to_idx_2ghz[] = { /* MCS rates are used only with 11n */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + 7, /* CONF_HW_RXTX_RATE_MCS7 */ + 6, /* CONF_HW_RXTX_RATE_MCS6 */ + 5, /* CONF_HW_RXTX_RATE_MCS5 */ + 4, /* CONF_HW_RXTX_RATE_MCS4 */ + 3, /* CONF_HW_RXTX_RATE_MCS3 */ + 2, /* CONF_HW_RXTX_RATE_MCS2 */ + 1, /* CONF_HW_RXTX_RATE_MCS1 */ + 0, /* CONF_HW_RXTX_RATE_MCS0 */ 11, /* CONF_HW_RXTX_RATE_54 */ 10, /* CONF_HW_RXTX_RATE_48 */ @@ -2134,12 +2293,34 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { 0 /* CONF_HW_RXTX_RATE_1 */ }; +/* 11n STA capabilities */ +#define HW_RX_HIGHEST_RATE 72 + +#ifdef CONFIG_WL12XX_HT +#define WL12XX_HT_CAP { \ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ + .ht_supported = true, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ + .mcs = { \ + .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ + .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ + }, \ +} +#else +#define WL12XX_HT_CAP { \ + .ht_supported = false, \ +} +#endif + /* can't be const, mac80211 writes to this */ static struct ieee80211_supported_band wl1271_band_2ghz = { .channels = wl1271_channels, .n_channels = ARRAY_SIZE(wl1271_channels), .bitrates = wl1271_rates, .n_bitrates = ARRAY_SIZE(wl1271_rates), + .ht_cap = WL12XX_HT_CAP, }; /* 5 GHz data rates for WL1273 */ @@ -2170,66 +2351,63 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, }; -/* - * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this. - * The order of the channels here is designed to improve scanning. - */ +/* 5 GHz band channels for WL1273 */ static struct ieee80211_channel wl1271_channels_5ghz[] = { { .hw_value = 183, .center_freq = 4915}, - { .hw_value = 188, .center_freq = 4940}, - { .hw_value = 8, .center_freq = 5040}, - { .hw_value = 34, .center_freq = 5170}, - { .hw_value = 44, .center_freq = 5220}, - { .hw_value = 60, .center_freq = 5300}, - { .hw_value = 112, .center_freq = 5560}, - { .hw_value = 132, .center_freq = 5660}, - { .hw_value = 157, .center_freq = 5785}, { .hw_value = 184, .center_freq = 4920}, + { .hw_value = 185, .center_freq = 4925}, + { .hw_value = 187, .center_freq = 4935}, + { .hw_value = 188, .center_freq = 4940}, { .hw_value = 189, .center_freq = 4945}, - { .hw_value = 9, .center_freq = 5045}, - { .hw_value = 36, .center_freq = 5180}, - { .hw_value = 46, .center_freq = 5230}, - { .hw_value = 64, .center_freq = 5320}, - { .hw_value = 116, .center_freq = 5580}, - { .hw_value = 136, .center_freq = 5680}, { .hw_value = 192, .center_freq = 4960}, - { .hw_value = 11, .center_freq = 5055}, - { .hw_value = 38, .center_freq = 5190}, - { .hw_value = 48, .center_freq = 5240}, - { .hw_value = 100, .center_freq = 5500}, - { .hw_value = 120, .center_freq = 5600}, - { .hw_value = 140, .center_freq = 5700}, - { .hw_value = 185, .center_freq = 4925}, { .hw_value = 196, .center_freq = 4980}, - { .hw_value = 12, .center_freq = 5060}, - { .hw_value = 40, .center_freq = 5200}, - { .hw_value = 52, .center_freq = 5260}, - { .hw_value = 104, .center_freq = 5520}, - { .hw_value = 124, .center_freq = 5620}, - { .hw_value = 149, .center_freq = 5745}, - { .hw_value = 161, .center_freq = 5805}, - { .hw_value = 187, .center_freq = 4935}, { .hw_value = 7, .center_freq = 5035}, + { .hw_value = 8, .center_freq = 5040}, + { .hw_value = 9, .center_freq = 5045}, + { .hw_value = 11, .center_freq = 5055}, + { .hw_value = 12, .center_freq = 5060}, { .hw_value = 16, .center_freq = 5080}, + { .hw_value = 34, .center_freq = 5170}, + { .hw_value = 36, .center_freq = 5180}, + { .hw_value = 38, .center_freq = 5190}, + { .hw_value = 40, .center_freq = 5200}, { .hw_value = 42, .center_freq = 5210}, + { .hw_value = 44, .center_freq = 5220}, + { .hw_value = 46, .center_freq = 5230}, + { .hw_value = 48, .center_freq = 5240}, + { .hw_value = 52, .center_freq = 5260}, { .hw_value = 56, .center_freq = 5280}, + { .hw_value = 60, .center_freq = 5300}, + { .hw_value = 64, .center_freq = 5320}, + { .hw_value = 100, .center_freq = 5500}, + { .hw_value = 104, .center_freq = 5520}, { .hw_value = 108, .center_freq = 5540}, + { .hw_value = 112, .center_freq = 5560}, + { .hw_value = 116, .center_freq = 5580}, + { .hw_value = 120, .center_freq = 5600}, + { .hw_value = 124, .center_freq = 5620}, { .hw_value = 128, .center_freq = 5640}, + { .hw_value = 132, .center_freq = 5660}, + { .hw_value = 136, .center_freq = 5680}, + { .hw_value = 140, .center_freq = 5700}, + { .hw_value = 149, .center_freq = 5745}, { .hw_value = 153, .center_freq = 5765}, + { .hw_value = 157, .center_freq = 5785}, + { .hw_value = 161, .center_freq = 5805}, { .hw_value = 165, .center_freq = 5825}, }; /* mapping to indexes for wl1271_rates_5ghz */ static const u8 wl1271_rate_to_idx_5ghz[] = { /* MCS rates are used only with 11n */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ + 7, /* CONF_HW_RXTX_RATE_MCS7 */ + 6, /* CONF_HW_RXTX_RATE_MCS6 */ + 5, /* CONF_HW_RXTX_RATE_MCS5 */ + 4, /* CONF_HW_RXTX_RATE_MCS4 */ + 3, /* CONF_HW_RXTX_RATE_MCS3 */ + 2, /* CONF_HW_RXTX_RATE_MCS2 */ + 1, /* CONF_HW_RXTX_RATE_MCS1 */ + 0, /* CONF_HW_RXTX_RATE_MCS0 */ 7, /* CONF_HW_RXTX_RATE_54 */ 6, /* CONF_HW_RXTX_RATE_48 */ @@ -2254,6 +2432,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), .bitrates = wl1271_rates_5ghz, .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), + .ht_cap = WL12XX_HT_CAP, }; static const u8 *wl1271_band_rate_to_idx[] = { @@ -2273,6 +2452,7 @@ static const struct ieee80211_ops wl1271_ops = { .set_key = wl1271_op_set_key, .hw_scan = wl1271_op_hw_scan, .bss_info_changed = wl1271_op_bss_info_changed, + .set_frag_threshold = wl1271_op_set_frag_threshold, .set_rts_threshold = wl1271_op_set_rts_threshold, .conf_tx = wl1271_op_conf_tx, .get_tsf = wl1271_op_get_tsf, @@ -2281,18 +2461,18 @@ static const struct ieee80211_ops wl1271_ops = { }; -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band) { u8 idx; - BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); + BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { wl1271_error("Illegal RX rate from HW: %d", rate); return 0; } - idx = wl1271_band_rate_to_idx[wl->band][rate]; + idx = wl1271_band_rate_to_idx[band][rate]; if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { wl1271_error("Unsupported RX rate from HW: %d", rate); return 0; @@ -2457,6 +2637,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->queues = 4; wl->hw->max_rates = 1; + wl->hw->wiphy->reg_notifier = wl1271_reg_notify; + SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); return 0; @@ -2521,6 +2703,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sg_enabled = true; wl->hw_pg_ver = -1; + memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/ps.c index e3c332e2f97c..60a3738eadb0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -21,9 +21,9 @@ * */ -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_io.h" +#include "reg.h" +#include "ps.h" +#include "io.h" #define WL1271_WAKEUP_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/ps.h index 6ba7b032736f..8415060f08e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/ps.h @@ -21,11 +21,11 @@ * */ -#ifndef __WL1271_PS_H__ -#define __WL1271_PS_H__ +#ifndef __PS_H__ +#define __PS_H__ -#include "wl1271.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "acx.h" int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, u32 rates, bool send); diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/reg.h index 990960771528..990960771528 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/reg.h diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/rx.c index bea133b6e489..682304c30b81 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -23,11 +23,11 @@ #include <linux/gfp.h> -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_rx.h" -#include "wl1271_io.h" +#include "wl12xx.h" +#include "acx.h" +#include "reg.h" +#include "rx.h" +#include "io.h" static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, u32 drv_rx_counter) @@ -48,10 +48,24 @@ static void wl1271_rx_status(struct wl1271 *wl, struct ieee80211_rx_status *status, u8 beacon) { + enum ieee80211_band desc_band; + memset(status, 0, sizeof(struct ieee80211_rx_status)); status->band = wl->band; - status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); + + if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) + desc_band = IEEE80211_BAND_2GHZ; + else + desc_band = IEEE80211_BAND_5GHZ; + + status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band); + +#ifdef CONFIG_WL12XX_HT + /* 11n support */ + if (desc->rate <= CONF_HW_RXTX_RATE_MCS0) + status->flag |= RX_FLAG_HT; +#endif status->signal = desc->rssi; @@ -170,10 +184,14 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) while (pkt_offset < buf_size) { pkt_length = wl1271_rx_get_buf_size(status, drv_rx_counter); - if (wl1271_rx_handle_data(wl, - wl->aggr_buf + pkt_offset, - pkt_length) < 0) - break; + /* + * the handle data call can only fail in memory-outage + * conditions, in that case the received frame will just + * be dropped. + */ + wl1271_rx_handle_data(wl, + wl->aggr_buf + pkt_offset, + pkt_length); wl->rx_counter++; drv_rx_counter++; drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/rx.h index 13a232333b13..3abb26fe0364 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_RX_H__ -#define __WL1271_RX_H__ +#ifndef __RX_H__ +#define __RX_H__ #include <linux/bitops.h> @@ -116,6 +116,6 @@ struct wl1271_rx_descriptor { } __packed; void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/scan.c index 909bb47995b6..f3f2c5b011ee 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -23,10 +23,10 @@ #include <linux/ieee80211.h> -#include "wl1271.h" -#include "wl1271_cmd.h" -#include "wl1271_scan.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "cmd.h" +#include "scan.h" +#include "acx.h" void wl1271_scan_complete_work(struct work_struct *work) { @@ -48,14 +48,15 @@ void wl1271_scan_complete_work(struct work_struct *work) wl->scan.state = WL1271_SCAN_STATE_IDLE; kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; - mutex_unlock(&wl->mutex); - + wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, false); if (wl->scan.failed) { wl1271_info("Scan completed due to error."); ieee80211_queue_work(wl->hw, &wl->recovery_work); } + mutex_unlock(&wl->mutex); + } diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/scan.h index 6d57127b5e6b..421a750add5a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -21,10 +21,10 @@ * */ -#ifndef __WL1271_SCAN_H__ -#define __WL1271_SCAN_H__ +#ifndef __SCAN_H__ +#define __SCAN_H__ -#include "wl1271.h" +#include "wl12xx.h" int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req); diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 784ef3432641..93cbb8d5aba9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -32,9 +32,9 @@ #include <linux/wl12xx.h> #include <linux/pm_runtime.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" #ifndef SDIO_VENDOR_ID_TI #define SDIO_VENDOR_ID_TI 0x0097 diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/spi.c index ef801680773f..46714910f98c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -28,11 +28,11 @@ #include <linux/wl12xx.h> #include <linux/slab.h> -#include "wl1271.h" +#include "wl12xx.h" #include "wl12xx_80211.h" -#include "wl1271_io.h" +#include "io.h" -#include "wl1271_reg.h" +#include "reg.h" #define WSPI_CMD_READ 0x40000000 #define WSPI_CMD_WRITE 0x00000000 diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/testmode.c index a3aa84386c88..e64403b6896d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -20,13 +20,13 @@ * 02110-1301 USA * */ -#include "wl1271_testmode.h" +#include "testmode.h" #include <linux/slab.h> #include <net/genetlink.h> -#include "wl1271.h" -#include "wl1271_acx.h" +#include "wl12xx.h" +#include "acx.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -37,6 +37,7 @@ enum wl1271_tm_commands { WL1271_TM_CMD_CONFIGURE, WL1271_TM_CMD_NVS_PUSH, WL1271_TM_CMD_SET_PLT_MODE, + WL1271_TM_CMD_RECOVER, __WL1271_TM_CMD_AFTER_LAST }; @@ -248,6 +249,15 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) return ret; } +static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) +{ + wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); + + ieee80211_queue_work(wl->hw, &wl->recovery_work); + + return 0; +} + int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) { struct wl1271 *wl = hw->priv; @@ -272,6 +282,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) return wl1271_tm_cmd_nvs_push(wl, tb); case WL1271_TM_CMD_SET_PLT_MODE: return wl1271_tm_cmd_set_plt_mode(wl, tb); + case WL1271_TM_CMD_RECOVER: + return wl1271_tm_cmd_recover(wl, tb); default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/testmode.h index c196d28f9d9d..8071654259ea 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.h +++ b/drivers/net/wireless/wl12xx/testmode.h @@ -21,8 +21,8 @@ * */ -#ifndef __WL1271_TESTMODE_H__ -#define __WL1271_TESTMODE_H__ +#ifndef __TESTMODE_H__ +#define __TESTMODE_H__ #include <net/mac80211.h> diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/tx.c index e3dc13c4d01a..d332b3f6d0fa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -24,23 +24,32 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "wl1271.h" -#include "wl1271_io.h" -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_tx.h" +#include "wl12xx.h" +#include "io.h" +#include "reg.h" +#include "ps.h" +#include "tx.h" -static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) +static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) { - int i; - for (i = 0; i < ACX_TX_DESCRIPTORS; i++) - if (wl->tx_frames[i] == NULL) { - wl->tx_frames[i] = skb; - wl->tx_frames_cnt++; - return i; - } + int id; + + id = find_first_zero_bit(wl->tx_frames_map, ACX_TX_DESCRIPTORS); + if (id >= ACX_TX_DESCRIPTORS) + return -EBUSY; + + __set_bit(id, wl->tx_frames_map); + wl->tx_frames[id] = skb; + wl->tx_frames_cnt++; + return id; +} - return -EBUSY; +static void wl1271_free_tx_id(struct wl1271 *wl, int id) +{ + if (__test_and_clear_bit(id, wl->tx_frames_map)) { + wl->tx_frames[id] = NULL; + wl->tx_frames_cnt--; + } } static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, @@ -52,10 +61,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, int id, ret = -EBUSY; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) - return -EBUSY; + return -EAGAIN; /* allocate free identifier for the packet */ - id = wl1271_tx_id(wl, skb); + id = wl1271_alloc_tx_id(wl, skb); if (id < 0) return id; @@ -79,8 +88,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, "tx_allocate: size: %d, blocks: %d, id: %d", total_len, total_blocks, id); } else { - wl->tx_frames[id] = NULL; - wl->tx_frames_cnt--; + wl1271_free_tx_id(wl, id); } return ret; @@ -201,41 +209,67 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) rate_set >>= 1; } +#ifdef CONFIG_WL12XX_HT + /* MCS rates indication are on bits 16 - 23 */ + rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; + + for (bit = 0; bit < 8; bit++) { + if (rate_set & 0x1) + enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); + rate_set >>= 1; + } +#endif + return enabled_rates; } -void wl1271_tx_work(struct work_struct *work) +static void handle_tx_low_watermark(struct wl1271 *wl) +{ + unsigned long flags; + + if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && + skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { + /* firmware buffer has space, restart queues */ + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + } +} + +void wl1271_tx_work_locked(struct wl1271 *wl) { - struct wl1271 *wl = container_of(work, struct wl1271, tx_work); struct sk_buff *skb; bool woken_up = false; u32 sta_rates = 0; - u32 buf_offset; + u32 buf_offset = 0; + bool sent_packets = false; int ret; /* check if the rates supported by the AP have changed */ if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags))) { unsigned long flags; + spin_lock_irqsave(&wl->wl_lock, flags); sta_rates = wl->sta_rate_set; spin_unlock_irqrestore(&wl->wl_lock, flags); } - mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* if rates have changed, re-configure the rate policy */ if (unlikely(sta_rates)) { + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + woken_up = true; + wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); wl1271_acx_rate_policies(wl); } - /* Prepare the transfer buffer, by aggregating all - * available packets */ - buf_offset = 0; while ((skb = skb_dequeue(&wl->tx_queue))) { if (!woken_up) { ret = wl1271_ps_elp_wakeup(wl, false); @@ -245,13 +279,25 @@ void wl1271_tx_work(struct work_struct *work) } ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); - if (ret == -EBUSY) { + if (ret == -EAGAIN) { + /* + * Aggregation buffer is full. + * Flush buffer and try again. + */ + skb_queue_head(&wl->tx_queue, skb); + wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, + buf_offset, true); + sent_packets = true; + buf_offset = 0; + continue; + } else if (ret == -EBUSY) { /* - * Either the firmware buffer is full, or the - * aggregation buffer is. + * Firmware buffer is full. * Queue back last skb, and stop aggregating. */ skb_queue_head(&wl->tx_queue, skb); + /* No work left, avoid scheduling redundant tx work */ + set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); goto out_ack; } else if (ret < 0) { dev_kfree_skb(skb); @@ -265,14 +311,25 @@ out_ack: if (buf_offset) { wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); + sent_packets = true; + } + if (sent_packets) { /* interrupt the firmware with the new packets */ wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); + handle_tx_low_watermark(wl); } out: if (woken_up) wl1271_ps_elp_sleep(wl); +} + +void wl1271_tx_work(struct work_struct *work) +{ + struct wl1271 *wl = container_of(work, struct wl1271, tx_work); + mutex_lock(&wl->mutex); + wl1271_tx_work_locked(wl); mutex_unlock(&wl->mutex); } @@ -298,7 +355,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - rate = wl1271_rate_to_idx(wl, result->rate_class_index); + rate = wl1271_rate_to_idx(result->rate_class_index, wl->band); retries = result->ack_failures; } else if (result->status == TX_RETRY_EXCEEDED) { wl->stats.excessive_retries++; @@ -335,8 +392,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, /* return the packet to the stack */ ieee80211_tx_status(wl->hw, skb); - wl->tx_frames[result->id] = NULL; - wl->tx_frames_cnt--; + wl1271_free_tx_id(wl, result->id); } /* Called upon reception of a TX complete interrupt */ @@ -375,19 +431,6 @@ void wl1271_tx_complete(struct wl1271 *wl) wl->tx_results_count++; } - - if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && - skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { - unsigned long flags; - - /* firmware buffer has space, restart queues */ - wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); - spin_lock_irqsave(&wl->wl_lock, flags); - ieee80211_wake_queues(wl->hw); - clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); - spin_unlock_irqrestore(&wl->wl_lock, flags); - ieee80211_queue_work(wl->hw, &wl->tx_work); - } } /* caller must hold wl->mutex */ @@ -402,14 +445,19 @@ void wl1271_tx_reset(struct wl1271 *wl) ieee80211_tx_status(wl->hw, skb); } + /* + * Make sure the driver is at a consistent state, in case this + * function is called from a context other than interface removal. + */ + handle_tx_low_watermark(wl); + for (i = 0; i < ACX_TX_DESCRIPTORS; i++) if (wl->tx_frames[i] != NULL) { skb = wl->tx_frames[i]; - wl->tx_frames[i] = NULL; + wl1271_free_tx_id(wl, i); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); ieee80211_tx_status(wl->hw, skb); } - wl->tx_frames_cnt = 0; } #define WL1271_TX_FLUSH_TIMEOUT 500000 diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/tx.h index d12a129ad11c..903e5dc69b7a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_TX_H__ -#define __WL1271_TX_H__ +#ifndef __TX_H__ +#define __TX_H__ #define TX_HW_BLOCK_SPARE 2 #define TX_HW_BLOCK_SIZE 252 @@ -140,10 +140,11 @@ static inline int wl1271_tx_get_queue(int queue) } void wl1271_tx_work(struct work_struct *work); +void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_reset(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); -u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); +u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl12xx.h index 8a4cd763e5a2..3c836e6063e6 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WL1271_H__ -#define __WL1271_H__ +#ifndef __WL12XX_H__ +#define __WL12XX_H__ #include <linux/mutex.h> #include <linux/completion.h> @@ -32,8 +32,8 @@ #include <linux/bitops.h> #include <net/mac80211.h> -#include "wl1271_conf.h" -#include "wl1271_ini.h" +#include "conf.h" +#include "ini.h" #define DRIVER_NAME "wl1271" #define DRIVER_PREFIX DRIVER_NAME ": " @@ -351,6 +351,7 @@ struct wl1271 { #define WL1271_FLAG_IDLE_REQUESTED (11) #define WL1271_FLAG_PSPOLL_FAILURE (12) #define WL1271_FLAG_STA_STATE_SENT (13) +#define WL1271_FLAG_FW_TX_BUSY (14) unsigned long flags; struct wl1271_partition_set part; @@ -397,6 +398,7 @@ struct wl1271 { struct work_struct tx_work; /* Pending TX frames */ + unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)]; struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; int tx_frames_cnt; @@ -432,7 +434,12 @@ struct wl1271 { /* Our association ID */ u16 aid; - /* currently configured rate set */ + /* + * currently configured rate set: + * bits 0-15 - 802.11abg rates + * bits 16-23 - 802.11n MCS index mask + * support only 1 stream, thus only 8 bits for the MCS rates (0-7). + */ u32 sta_rate_set; u32 basic_rate_set; u32 basic_rate; @@ -509,4 +516,8 @@ int wl1271_plt_stop(struct wl1271 *wl); #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ +/* Macros to handle wl1271.sta_rate_set */ +#define HW_BG_RATES_MASK 0xffff +#define HW_HT_RATES_OFFSET 16 + #endif diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 390d77f762c4..415eec401e2e 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -30,6 +30,7 @@ static struct usb_device_id zd1201_table[] = { {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */ {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ {} }; @@ -1829,7 +1830,7 @@ err_zd: static void zd1201_disconnect(struct usb_interface *interface) { - struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); + struct zd1201 *zd = usb_get_intfdata(interface); struct hlist_node *node, *node2; struct zd1201_frag *frag; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 87a95bcfee57..30f8d404958b 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -1448,7 +1448,7 @@ int zd_rfwritev_locked(struct zd_chip *chip, */ int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) { - struct zd_ioreq16 ioreqs[] = { + const struct zd_ioreq16 ioreqs[] = { { CR244, (value >> 16) & 0xff }, { CR243, (value >> 8) & 0xff }, { CR242, value & 0xff }, @@ -1475,7 +1475,7 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip, int zd_chip_set_multicast_hash(struct zd_chip *chip, struct zd_mc_hash *hash) { - struct zd_ioreq32 ioreqs[] = { + const struct zd_ioreq32 ioreqs[] = { { CR_GROUP_HASH_P1, hash->low }, { CR_GROUP_HASH_P2, hash->high }, }; diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 818e1480ca93..06041cb1c422 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -55,6 +55,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x14ea, 0xab10), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, @@ -92,6 +93,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x2019, 0xed01), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 630fb8664768..458bb57914a3 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1610,6 +1610,8 @@ static void netback_changed(struct xenbus_device *dev, switch (backend_state) { case XenbusStateInitialising: case XenbusStateInitialised: + case XenbusStateReconfiguring: + case XenbusStateReconfigured: case XenbusStateConnected: case XenbusStateUnknown: case XenbusStateClosed: diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index f3f8be5a35fa..14f0955eca68 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -430,8 +430,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) } /* Get the protocol type of the ethernet frame that arrived */ - proto_type = ((in_be32(addr + XEL_HEADER_OFFSET + - XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) & + proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET + + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); /* Check if received ethernet frame is a raw ethernet frame @@ -439,9 +439,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { if (proto_type == ETH_P_IP) { - length = ((in_be32(addr + + length = ((ntohl(in_be32(addr + XEL_HEADER_IP_LENGTH_OFFSET + - XEL_RXBUFF_OFFSET) >> + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); length += ETH_HLEN + ETH_FCS_LEN; |