diff options
Diffstat (limited to 'drivers/net')
356 files changed, 15531 insertions, 7625 deletions
diff --git a/drivers/net/3c527.h b/drivers/net/3c527.h index 75e28fef797b..d693b8d15cde 100644 --- a/drivers/net/3c527.h +++ b/drivers/net/3c527.h @@ -34,7 +34,7 @@ struct mc32_mailbox { u16 mbox; u16 data[1]; -} __attribute((packed)); +} __packed; struct skb_header { @@ -43,7 +43,7 @@ struct skb_header u16 next; /* Do not change! */ u16 length; u32 data; -} __attribute((packed)); +} __packed; struct mc32_stats { @@ -68,7 +68,7 @@ struct mc32_stats u32 dataA[6]; u16 dataB[5]; u32 dataC[14]; -} __attribute((packed)); +} __packed; #define STATUS_MASK 0x0F #define COMPLETED (1<<7) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 284a5f4a63ac..4a4f6b81e32d 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -322,7 +322,7 @@ struct cp_dma_stats { __le32 rx_ok_mcast; __le16 tx_abort; __le16 tx_underrun; -} __attribute__((packed)); +} __packed; struct cp_extra_stats { unsigned long rx_frags; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 97d8068b372b..f5166dccd8df 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -662,7 +662,7 @@ static const struct ethtool_ops rtl8139_ethtool_ops; /* read MMIO register */ #define RTL_R8(reg) ioread8 (ioaddr + (reg)) #define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) +#define RTL_R32(reg) ioread32 (ioaddr + (reg)) static const u16 rtl8139_intr_mask = @@ -862,7 +862,7 @@ retry: /* if unknown chip, assume array element #0, original RTL-8139 in this case */ i = 0; dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); + dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig)); tp->chipset = 0; match: @@ -1643,7 +1643,7 @@ static void rtl8139_tx_timeout_task (struct work_struct *work) netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n", + netdev_dbg(dev, "Tx descriptor %d is %08x%s\n", i, RTL_R32(TxStatus0 + (i * 4)), i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); @@ -2487,7 +2487,7 @@ static void __set_rx_mode (struct net_device *dev) int rx_mode; u32 tmp; - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08lx\n", + netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n", dev->flags, RTL_R32(RxConfig)); /* Note: do not reorder, GCC is clever about common statements. */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ce2fcdd4ab90..71e6f8fc0cf1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1659,6 +1659,7 @@ config R6040 depends on NET_PCI && PCI select CRC32 select MII + select PHYLIB help This is a driver for the R6040 Fast Ethernet MACs found in the the RDC R-321x System-on-chips. diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 355797f70048..42fce91b71fc 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -37,69 +37,6 @@ #define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n" - -static void rx(struct net_device *dev, int bufnum, - struct archdr *pkthdr, int length); -static int build_header(struct sk_buff *skb, - struct net_device *dev, - unsigned short type, - uint8_t daddr); -static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, - int bufnum); -static int ack_tx(struct net_device *dev, int acked); - - -static struct ArcProto capmode_proto = -{ - 'r', - XMTU, - 0, - rx, - build_header, - prepare_tx, - NULL, - ack_tx -}; - - -static void arcnet_cap_init(void) -{ - int count; - - for (count = 1; count <= 8; count++) - if (arc_proto_map[count] == arc_proto_default) - arc_proto_map[count] = &capmode_proto; - - /* for cap mode, we only set the bcast proto if there's no better one */ - if (arc_bcast_proto == arc_proto_default) - arc_bcast_proto = &capmode_proto; - - arc_proto_default = &capmode_proto; - arc_raw_proto = &capmode_proto; -} - - -#ifdef MODULE - -static int __init capmode_module_init(void) -{ - printk(VERSION); - arcnet_cap_init(); - return 0; -} - -static void __exit capmode_module_exit(void) -{ - arcnet_unregister_proto(&capmode_proto); -} -module_init(capmode_module_init); -module_exit(capmode_module_exit); - -MODULE_LICENSE("GPL"); -#endif /* MODULE */ - - - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -231,65 +168,107 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", length,ofs); - // Copy the arcnet-header + the protocol byte down: + /* Copy the arcnet-header + the protocol byte down: */ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft.cap.proto, sizeof(pkt->soft.cap.proto)); - // Skip the extra integer we have written into it as a cookie - // but write the rest of the message: + /* Skip the extra integer we have written into it as a cookie + but write the rest of the message: */ lp->hw.copy_to_card(dev, bufnum, ofs+1, ((unsigned char*)&pkt->soft.cap.mes),length-1); lp->lastload_dest = hard->dest; - return 1; /* done */ + return 1; /* done */ } - static int ack_tx(struct net_device *dev, int acked) { - struct arcnet_local *lp = netdev_priv(dev); - struct sk_buff *ackskb; - struct archdr *ackpkt; - int length=sizeof(struct arc_cap); + struct arcnet_local *lp = netdev_priv(dev); + struct sk_buff *ackskb; + struct archdr *ackpkt; + int length=sizeof(struct arc_cap); - BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", - lp->outgoing.skb->protocol, acked); + BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", + lp->outgoing.skb->protocol, acked); - BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); + BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); - /* Now alloc a skb to send back up through the layers: */ - ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); - if (ackskb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); - goto free_outskb; - } + /* Now alloc a skb to send back up through the layers: */ + ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); + if (ackskb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); + goto free_outskb; + } + + skb_put(ackskb, length + ARC_HDR_SIZE ); + ackskb->dev = dev; + + skb_reset_mac_header(ackskb); + ackpkt = (struct archdr *)skb_mac_header(ackskb); + /* skb_pull(ackskb, ARC_HDR_SIZE); */ - skb_put(ackskb, length + ARC_HDR_SIZE ); - ackskb->dev = dev; + skb_copy_from_linear_data(lp->outgoing.skb, ackpkt, + ARC_HDR_SIZE + sizeof(struct arc_cap)); + ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */ + ackpkt->soft.cap.mes.ack=acked; - skb_reset_mac_header(ackskb); - ackpkt = (struct archdr *)skb_mac_header(ackskb); - /* skb_pull(ackskb, ARC_HDR_SIZE); */ + BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", + *((int*)&ackpkt->soft.cap.cookie[0])); + ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); - skb_copy_from_linear_data(lp->outgoing.skb, ackpkt, - ARC_HDR_SIZE + sizeof(struct arc_cap)); - ackpkt->soft.cap.proto=0; /* using protocol 0 for acknowledge */ - ackpkt->soft.cap.mes.ack=acked; + BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); + netif_rx(ackskb); - BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", - *((int*)&ackpkt->soft.cap.cookie[0])); +free_outskb: + dev_kfree_skb_irq(lp->outgoing.skb); + lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ - ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); + return 0; +} - BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); - netif_rx(ackskb); +static struct ArcProto capmode_proto = +{ + 'r', + XMTU, + 0, + rx, + build_header, + prepare_tx, + NULL, + ack_tx +}; - free_outskb: - dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ +static void arcnet_cap_init(void) +{ + int count; - return 0; + for (count = 1; count <= 8; count++) + if (arc_proto_map[count] == arc_proto_default) + arc_proto_map[count] = &capmode_proto; + + /* for cap mode, we only set the bcast proto if there's no better one */ + if (arc_bcast_proto == arc_proto_default) + arc_bcast_proto = &capmode_proto; + + arc_proto_default = &capmode_proto; + arc_raw_proto = &capmode_proto; } + +static int __init capmode_module_init(void) +{ + printk(VERSION); + arcnet_cap_init(); + return 0; +} + +static void __exit capmode_module_exit(void) +{ + arcnet_unregister_proto(&capmode_proto); +} +module_init(capmode_module_init); +module_exit(capmode_module_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 24df0325090c..ee2f8425dbe7 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -738,6 +738,17 @@ static void eth_set_mcast_list(struct net_device *dev) struct netdev_hw_addr *ha; u8 diffs[ETH_ALEN], *addr; int i; + static const u8 allmulti[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + if (dev->flags & IFF_ALLMULTI) { + for (i = 0; i < ETH_ALEN; i++) { + __raw_writel(allmulti[i], &port->regs->mcast_addr[i]); + __raw_writel(allmulti[i], &port->regs->mcast_mask[i]); + } + __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN, + &port->regs->rx_control[0]); + return; + } if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) { __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN, diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index 84ae905bf732..52abbbdf8a08 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -73,7 +73,8 @@ #define FULL_DUPLEX 2 #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) -#define MAX_JUMBO_FRAME_SIZE (9*1024) +#define MAX_JUMBO_FRAME_SIZE (6*1024) +#define MAX_TSO_FRAME_SIZE (7*1024) #define MAX_TX_OFFLOAD_THRESH (9*1024) #define AT_MAX_RECEIVE_QUEUE 4 @@ -87,10 +88,11 @@ #define AT_MAX_INT_WORK 5 #define AT_TWSI_EEPROM_TIMEOUT 100 #define AT_HW_MAX_IDLE_DELAY 10 -#define AT_SUSPEND_LINK_TIMEOUT 28 +#define AT_SUSPEND_LINK_TIMEOUT 100 #define AT_ASPM_L0S_TIMER 6 #define AT_ASPM_L1_TIMER 12 +#define AT_LCKDET_TIMER 12 #define ATL1C_PCIE_L0S_L1_DISABLE 0x01 #define ATL1C_PCIE_PHY_RESET 0x02 @@ -316,6 +318,7 @@ enum atl1c_nic_type { athr_l2c_b, athr_l2c_b2, athr_l1d, + athr_l1d_2, }; enum atl1c_trans_queue { @@ -392,6 +395,8 @@ struct atl1c_hw { u16 subsystem_id; u16 subsystem_vendor_id; u8 revision_id; + u16 phy_id1; + u16 phy_id2; u32 intr_mask; u8 dmaw_dly_cnt; diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c index f1389d664a21..d8501f060957 100644 --- a/drivers/net/atl1c/atl1c_hw.c +++ b/drivers/net/atl1c/atl1c_hw.c @@ -37,6 +37,9 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw) if (data & TWSI_DEBUG_DEV_EXIST) return 1; + AT_READ_REG(hw, REG_MASTER_CTRL, &data); + if (data & MASTER_CTRL_OTP_SEL) + return 1; return 0; } @@ -69,6 +72,8 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) u32 i; u32 otp_ctrl_data; u32 twsi_ctrl_data; + u32 ltssm_ctrl_data; + u32 wol_data; u8 eth_addr[ETH_ALEN]; u16 phy_data; bool raise_vol = false; @@ -104,6 +109,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) udelay(20); raise_vol = true; } + /* close open bit of ReadOnly*/ + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data); + ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO; + AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data); + + /* clear any WOL settings */ + AT_WRITE_REG(hw, REG_WOL_CTRL, 0); + AT_READ_REG(hw, REG_WOL_CTRL, &wol_data); + AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; @@ -119,17 +133,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) } /* Disable OTP_CLK */ if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { - if (otp_ctrl_data & OTP_CTRL_CLK_EN) { - otp_ctrl_data &= ~OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - AT_WRITE_FLUSH(hw); - msleep(1); - } + otp_ctrl_data &= ~OTP_CTRL_CLK_EN; + AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); + msleep(1); } if (raise_vol) { if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || - hw->nic_type == athr_l1d) { + hw->nic_type == athr_l1d || + hw->nic_type == athr_l1d_2) { atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) goto out; @@ -456,14 +468,22 @@ int atl1c_phy_reset(struct atl1c_hw *hw) if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || - hw->nic_type == athr_l1d) { + hw->nic_type == athr_l1d || + hw->nic_type == athr_l1d_2) { atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); msleep(20); } - - /*Enable PHY LinkChange Interrupt */ + if (hw->nic_type == athr_l1d) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D); + } + if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2 + || hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); + } err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); if (err) { if (netif_msg_hw(adapter)) @@ -482,12 +502,10 @@ int atl1c_phy_init(struct atl1c_hw *hw) struct pci_dev *pdev = adapter->pdev; int ret_val; u16 mii_bmcr_data = BMCR_RESET; - u16 phy_id1, phy_id2; - if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) || - (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) { - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, "Error get phy ID\n"); + if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) || + (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) { + dev_err(&pdev->dev, "Error get phy ID\n"); return -1; } switch (hw->media_type) { @@ -572,6 +590,65 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) return 0; } +int atl1c_phy_power_saving(struct atl1c_hw *hw) +{ + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; + struct pci_dev *pdev = adapter->pdev; + int ret = 0; + u16 autoneg_advertised = ADVERTISED_10baseT_Half; + u16 save_autoneg_advertised; + u16 phy_data; + u16 mii_lpa_data; + u16 speed = SPEED_0; + u16 duplex = FULL_DUPLEX; + int i; + + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); + if (phy_data & BMSR_LSTATUS) { + atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data); + if (mii_lpa_data & LPA_10FULL) + autoneg_advertised = ADVERTISED_10baseT_Full; + else if (mii_lpa_data & LPA_10HALF) + autoneg_advertised = ADVERTISED_10baseT_Half; + else if (mii_lpa_data & LPA_100HALF) + autoneg_advertised = ADVERTISED_100baseT_Half; + else if (mii_lpa_data & LPA_100FULL) + autoneg_advertised = ADVERTISED_100baseT_Full; + + save_autoneg_advertised = hw->autoneg_advertised; + hw->phy_configured = false; + hw->autoneg_advertised = autoneg_advertised; + if (atl1c_restart_autoneg(hw) != 0) { + dev_dbg(&pdev->dev, "phy autoneg failed\n"); + ret = -1; + } + hw->autoneg_advertised = save_autoneg_advertised; + + if (mii_lpa_data) { + for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { + mdelay(100); + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); + if (phy_data & BMSR_LSTATUS) { + if (atl1c_get_speed_and_duplex(hw, &speed, + &duplex) != 0) + dev_dbg(&pdev->dev, + "get speed and duplex failed\n"); + break; + } + } + } + } else { + speed = SPEED_10; + duplex = HALF_DUPLEX; + } + adapter->link_speed = speed; + adapter->link_duplex = duplex; + + return ret; +} + int atl1c_restart_autoneg(struct atl1c_hw *hw) { int err = 0; diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h index 1eeb3ed9f0cb..3dd675979aa1 100644 --- a/drivers/net/atl1c/atl1c_hw.h +++ b/drivers/net/atl1c/atl1c_hw.h @@ -42,7 +42,7 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); int atl1c_phy_init(struct atl1c_hw *hw); int atl1c_check_eeprom_exist(struct atl1c_hw *hw); int atl1c_restart_autoneg(struct atl1c_hw *hw); - +int atl1c_phy_power_saving(struct atl1c_hw *hw); /* register definition */ #define REG_DEVICE_CAP 0x5C #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 @@ -120,6 +120,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define REG_PCIE_PHYMISC 0x1000 #define PCIE_PHYMISC_FORCE_RCV_DET 0x4 +#define REG_PCIE_PHYMISC2 0x1004 +#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3 +#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16 +#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3 +#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18 + #define REG_TWSI_DEBUG 0x1108 #define TWSI_DEBUG_DEV_EXIST 0x20000000 @@ -150,24 +156,28 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define PM_CTRL_ASPM_L0S_EN 0x00001000 #define PM_CTRL_CLK_SWH_L1 0x00002000 #define PM_CTRL_CLK_PWM_VER1_1 0x00004000 -#define PM_CTRL_PCIE_RECV 0x00008000 +#define PM_CTRL_RCVR_WT_TIMER 0x00008000 #define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF #define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 #define PM_CTRL_PM_REQ_TIMER_MASK 0xF #define PM_CTRL_PM_REQ_TIMER_SHIFT 20 -#define PM_CTRL_LCKDET_TIMER_MASK 0x3F +#define PM_CTRL_LCKDET_TIMER_MASK 0xF #define PM_CTRL_LCKDET_TIMER_SHIFT 24 #define PM_CTRL_EN_BUFS_RX_L0S 0x10000000 #define PM_CTRL_SA_DLY_EN 0x20000000 #define PM_CTRL_MAC_ASPM_CHK 0x40000000 #define PM_CTRL_HOTRST 0x80000000 +#define REG_LTSSM_ID_CTRL 0x12FC +#define LTSSM_ID_EN_WRO 0x1000 /* Selene Master Control Register */ #define REG_MASTER_CTRL 0x1400 #define MASTER_CTRL_SOFT_RST 0x1 #define MASTER_CTRL_TEST_MODE_MASK 0x3 #define MASTER_CTRL_TEST_MODE_SHIFT 2 #define MASTER_CTRL_BERT_START 0x10 +#define MASTER_CTRL_OOB_DIS_OFF 0x40 +#define MASTER_CTRL_SA_TIMER_EN 0x80 #define MASTER_CTRL_MTIMER_EN 0x100 #define MASTER_CTRL_MANUAL_INT 0x200 #define MASTER_CTRL_TX_ITIMER_EN 0x400 @@ -220,6 +230,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); GPHY_CTRL_PWDOWN_HW |\ GPHY_CTRL_PHY_IDDQ) +#define GPHY_CTRL_POWER_SAVING ( \ + GPHY_CTRL_SEL_ANA_RST |\ + GPHY_CTRL_HIB_EN |\ + GPHY_CTRL_HIB_PULSE |\ + GPHY_CTRL_PWDOWN_HW |\ + GPHY_CTRL_PHY_IDDQ) /* Block IDLE Status Register */ #define REG_IDLE_STATUS 0x1410 #define IDLE_STATUS_MASK 0x00FF @@ -287,6 +303,14 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal * comes from Analog SerDes */ #define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */ +#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE +#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3 +#define SERDES_OVCLK_18_25 0x0 +#define SERDES_OVCLK_12_18 0x1 +#define SERDES_OVCLK_0_4 0x2 +#define SERDES_OVCLK_4_12 0x3 +#define SERDES_MAC_CLK_SLOWDOWN 0x20000 +#define SERDES_PYH_CLK_SLOWDOWN 0x40000 /* MAC Control Register */ #define REG_MAC_CTRL 0x1480 @@ -693,6 +717,21 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define REG_MAC_TX_STATUS_BIN 0x1760 #define REG_MAC_TX_STATUS_END 0x17c0 +#define REG_CLK_GATING_CTRL 0x1814 +#define CLK_GATING_DMAW_EN 0x0001 +#define CLK_GATING_DMAR_EN 0x0002 +#define CLK_GATING_TXQ_EN 0x0004 +#define CLK_GATING_RXQ_EN 0x0008 +#define CLK_GATING_TXMAC_EN 0x0010 +#define CLK_GATING_RXMAC_EN 0x0020 + +#define CLK_GATING_EN_ALL (CLK_GATING_DMAW_EN |\ + CLK_GATING_DMAR_EN |\ + CLK_GATING_TXQ_EN |\ + CLK_GATING_RXQ_EN |\ + CLK_GATING_TXMAC_EN|\ + CLK_GATING_RXMAC_EN) + /* DEBUG ADDR */ #define REG_DEBUG_DATA0 0x1900 #define REG_DEBUG_DATA1 0x1904 @@ -734,6 +773,10 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define MII_PHYSID1 0x02 #define MII_PHYSID2 0x03 +#define L1D_MPW_PHYID1 0xD01C /* V7 */ +#define L1D_MPW_PHYID2 0xD01D /* V1-V6 */ +#define L1D_MPW_PHYID3 0xD01E /* V8 */ + /* Autoneg Advertisement Register */ #define MII_ADVERTISE 0x04 diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 1c3c046d5f34..c7b8ef507ebd 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -21,7 +21,7 @@ #include "atl1c.h" -#define ATL1C_DRV_VERSION "1.0.0.2-NAPI" +#define ATL1C_DRV_VERSION "1.0.1.0-NAPI" char atl1c_driver_name[] = "atl1c"; char atl1c_driver_version[] = ATL1C_DRV_VERSION; #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 @@ -29,7 +29,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION; #define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ #define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ #define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ - +#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ #define L2CB_V10 0xc0 #define L2CB_V11 0xc1 @@ -97,7 +97,28 @@ static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; +static void atl1c_pcie_patch(struct atl1c_hw *hw) +{ + u32 data; + AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); + data |= PCIE_PHYMISC_FORCE_RCV_DET; + AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); + + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { + AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); + + data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK << + PCIE_PHYMISC2_SERDES_CDR_SHIFT); + data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT; + data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK << + PCIE_PHYMISC2_SERDES_TH_SHIFT); + data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT; + AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); + } +} + +/* FIXME: no need any more ? */ /* * atl1c_init_pcie - init PCIE module */ @@ -127,6 +148,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) data &= ~PCIE_UC_SERVRITY_FCP; AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data); + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); + data &= ~LTSSM_ID_EN_WRO; + AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data); + + atl1c_pcie_patch(hw); if (flag & ATL1C_PCIE_L0S_L1_DISABLE) atl1c_disable_l0s_l1(hw); if (flag & ATL1C_PCIE_PHY_RESET) @@ -135,7 +161,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET); - msleep(1); + msleep(5); } /* @@ -159,6 +185,7 @@ static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) { atomic_inc(&adapter->irq_sem); AT_WRITE_REG(&adapter->hw, REG_IMR, 0); + AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT); AT_WRITE_FLUSH(&adapter->hw); synchronize_irq(adapter->pdev->irq); } @@ -231,15 +258,15 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) if ((phy_data & BMSR_LSTATUS) == 0) { /* link down */ - if (netif_carrier_ok(netdev)) { - hw->hibernate = true; - if (atl1c_stop_mac(hw) != 0) - if (netif_msg_hw(adapter)) - dev_warn(&pdev->dev, - "stop mac failed\n"); - atl1c_set_aspm(hw, false); - } + hw->hibernate = true; + if (atl1c_stop_mac(hw) != 0) + if (netif_msg_hw(adapter)) + dev_warn(&pdev->dev, "stop mac failed\n"); + atl1c_set_aspm(hw, false); netif_carrier_off(netdev); + netif_stop_queue(netdev); + atl1c_phy_reset(hw); + atl1c_phy_init(&adapter->hw); } else { /* Link Up */ hw->hibernate = false; @@ -308,6 +335,7 @@ static void atl1c_common_task(struct work_struct *work) netdev = adapter->netdev; if (adapter->work_event & ATL1C_WORK_EVENT_RESET) { + adapter->work_event &= ~ATL1C_WORK_EVENT_RESET; netif_device_detach(netdev); atl1c_down(adapter); atl1c_up(adapter); @@ -315,8 +343,11 @@ static void atl1c_common_task(struct work_struct *work) return; } - if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) + if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) { + adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE; atl1c_check_link_status(adapter); + } + return; } @@ -476,6 +507,13 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; adapter->hw.max_frame_size = new_mtu; atl1c_set_rxbufsize(adapter, netdev); + if (new_mtu > MAX_TSO_FRAME_SIZE) { + adapter->netdev->features &= ~NETIF_F_TSO; + adapter->netdev->features &= ~NETIF_F_TSO6; + } else { + adapter->netdev->features |= NETIF_F_TSO; + adapter->netdev->features |= NETIF_F_TSO6; + } atl1c_down(adapter); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); @@ -613,6 +651,9 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) case PCI_DEVICE_ID_ATHEROS_L1D: hw->nic_type = athr_l1d; break; + case PCI_DEVICE_ID_ATHEROS_L1D_2_0: + hw->nic_type = athr_l1d_2; + break; default: break; } @@ -627,9 +668,7 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data); AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); - hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ | - ATL1C_INTR_MODRT_ENABLE | - ATL1C_RX_IPV6_CHKSUM | + hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | ATL1C_TXQ_MODE_ENHANCE; if (link_ctrl_data & LINK_CTRL_L0S_EN) hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; @@ -637,12 +676,12 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; if (link_ctrl_data & LINK_CTRL_EXT_SYNC) hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; + hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; if (hw->nic_type == athr_l1c || - hw->nic_type == athr_l1d) { - hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; + hw->nic_type == athr_l1d || + hw->nic_type == athr_l1d_2) hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; - } return 0; } /* @@ -657,6 +696,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; + u32 revision; + adapter->wol = 0; adapter->link_speed = SPEED_0; @@ -669,7 +710,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) hw->device_id = pdev->device; hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_id = pdev->subsystem_device; - + AT_READ_REG(hw, PCI_CLASS_REVISION, &revision); + hw->revision_id = revision & 0xFF; /* before link up, we assume hibernate is true */ hw->hibernate = true; hw->media_type = MEDIA_TYPE_AUTO_SENSOR; @@ -974,6 +1016,7 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb; struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb; int i; + u32 data; /* TPD */ AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, @@ -1017,6 +1060,23 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32)); AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO, (u32)(smb->dma & AT_DMA_LO_ADDR_MASK)); + if (hw->nic_type == athr_l2c_b) { + AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); + AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); + AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L); + AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L); + AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L); + AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L); + AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ + AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ + } + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) { + /* Power Saving for L2c_B */ + AT_READ_REG(hw, REG_SERDES_LOCK, &data); + data |= SERDES_MAC_CLK_SLOWDOWN; + data |= SERDES_PYH_CLK_SLOWDOWN; + AT_WRITE_REG(hw, REG_SERDES_LOCK, data); + } /* Load all of base address above */ AT_WRITE_REG(hw, REG_LOAD_PTR, 1); } @@ -1029,6 +1089,7 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter) u16 tx_offload_thresh; u32 txq_ctrl_data; u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */ + u32 max_pay_load_data; extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; @@ -1046,8 +1107,11 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter) TXQ_NUM_TPD_BURST_SHIFT; if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE) txq_ctrl_data |= TXQ_CTRL_ENH_MODE; - txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] & + max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] & TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT; + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) + max_pay_load_data >>= 1; + txq_ctrl_data |= max_pay_load_data; AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); } @@ -1078,7 +1142,7 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) << RSS_HASH_BITS_SHIFT; if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON) - rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M & + rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M & ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT; AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); @@ -1198,21 +1262,23 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) { struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; struct pci_dev *pdev = adapter->pdev; - int ret; + u32 master_ctrl_data = 0; AT_WRITE_REG(hw, REG_IMR, 0); AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); - ret = atl1c_stop_mac(hw); - if (ret) - return ret; + atl1c_stop_mac(hw); /* * Issue Soft Reset to the MAC. This will reset the chip's * transmit, receive, DMA. It will not effect * the current PCI configuration. The global reset bit is self- * clearing, and should clear within a microsecond. */ - AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); + AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); + master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF; + AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST) + & 0xFFFF)); + AT_WRITE_FLUSH(hw); msleep(10); /* Wait at least 10ms for All module to be Idle */ @@ -1253,42 +1319,39 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) { u32 pm_ctrl_data; u32 link_ctrl_data; + u32 link_l1_timer = 0xF; AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); - pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; + pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << PM_CTRL_L1_ENTRY_TIMER_SHIFT); pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << - PM_CTRL_LCKDET_TIMER_SHIFT); - - pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - pm_ctrl_data |= PM_CTRL_RBER_EN; - pm_ctrl_data |= PM_CTRL_SDES_EN; + PM_CTRL_LCKDET_TIMER_SHIFT); + pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT; - if (hw->nic_type == athr_l2c_b || - hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2) { + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || + hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { - if (hw->nic_type == athr_l2c_b && - hw->revision_id == L2CB_V10) + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) link_ctrl_data |= LINK_CTRL_EXT_SYNC; } AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); - pm_ctrl_data |= PM_CTRL_PCIE_RECV; - pm_ctrl_data |= AT_ASPM_L1_TIMER << PM_CTRL_PM_REQ_TIMER_SHIFT; - pm_ctrl_data &= ~PM_CTRL_EN_BUFS_RX_L0S; + pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER; + pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK << + PM_CTRL_PM_REQ_TIMER_SHIFT); + pm_ctrl_data |= AT_ASPM_L1_TIMER << + PM_CTRL_PM_REQ_TIMER_SHIFT; pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; pm_ctrl_data &= ~PM_CTRL_HOTRST; pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; } - + pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; if (linkup) { pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; @@ -1297,27 +1360,26 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; - if (hw->nic_type == athr_l2c_b || - hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2) { + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || + hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { if (hw->nic_type == athr_l2c_b) if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) - pm_ctrl_data &= PM_CTRL_ASPM_L0S_EN; + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; - if (hw->adapter->link_speed == SPEED_100 || - hw->adapter->link_speed == SPEED_1000) { - pm_ctrl_data &= - ~(PM_CTRL_L1_ENTRY_TIMER_MASK << - PM_CTRL_L1_ENTRY_TIMER_SHIFT); - if (hw->nic_type == athr_l1d) - pm_ctrl_data |= 0xF << - PM_CTRL_L1_ENTRY_TIMER_SHIFT; - else - pm_ctrl_data |= 7 << - PM_CTRL_L1_ENTRY_TIMER_SHIFT; + if (hw->adapter->link_speed == SPEED_100 || + hw->adapter->link_speed == SPEED_1000) { + pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << + PM_CTRL_L1_ENTRY_TIMER_SHIFT); + if (hw->nic_type == athr_l2c_b) + link_l1_timer = 7; + else if (hw->nic_type == athr_l2c_b2 || + hw->nic_type == athr_l1d_2) + link_l1_timer = 4; + pm_ctrl_data |= link_l1_timer << + PM_CTRL_L1_ENTRY_TIMER_SHIFT; } } else { pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; @@ -1326,24 +1388,12 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - } - atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); - if (hw->adapter->link_speed == SPEED_10) - if (hw->nic_type == athr_l1d) - atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0xB69D); - else - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); - else if (hw->adapter->link_speed == SPEED_100) - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB2DD); - else - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x96DD); + } } else { - pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) @@ -1351,8 +1401,9 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) else pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; } - AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); + + return; } static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) @@ -1391,7 +1442,8 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; - if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2) { + if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 || + hw->nic_type == athr_l1d_2) { mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW; mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32; } @@ -1409,6 +1461,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter) struct atl1c_hw *hw = &adapter->hw; u32 master_ctrl_data = 0; u32 intr_modrt_data; + u32 data; /* clear interrupt status */ AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); @@ -1418,6 +1471,15 @@ static int atl1c_configure(struct atl1c_adapter *adapter) * HW will enable self to assert interrupt event to system after * waiting x-time for software to notify it accept interrupt. */ + + data = CLK_GATING_EN_ALL; + if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) { + if (hw->nic_type == athr_l2c_b) + data &= ~CLK_GATING_RXMAC_EN; + } else + data = 0; + AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data); + AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER, hw->ict & INT_RETRIG_TIMER_MASK); @@ -1436,6 +1498,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter) if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ) master_ctrl_data |= MASTER_CTRL_INT_RDCLR; + master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); if (hw->ctrl_flags & ATL1C_CMB_ENABLE) { @@ -1624,11 +1687,9 @@ static irqreturn_t atl1c_intr(int irq, void *data) "atl1c hardware error (status = 0x%x)\n", status & ISR_ERROR); /* reset MAC */ - hw->intr_mask &= ~ISR_ERROR; - AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); adapter->work_event |= ATL1C_WORK_EVENT_RESET; schedule_work(&adapter->common_task); - break; + return IRQ_HANDLED; } if (status & ISR_OVER) @@ -2303,7 +2364,6 @@ void atl1c_down(struct atl1c_adapter *adapter) napi_disable(&adapter->napi); atl1c_irq_disable(adapter); atl1c_free_irq(adapter); - AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT); /* reset MAC to disable all RX/TX */ atl1c_reset_mac(&adapter->hw); msleep(1); @@ -2387,79 +2447,68 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state) struct net_device *netdev = pci_get_drvdata(pdev); struct atl1c_adapter *adapter = netdev_priv(netdev); struct atl1c_hw *hw = &adapter->hw; - u32 ctrl; - u32 mac_ctrl_data; - u32 master_ctrl_data; + u32 mac_ctrl_data = 0; + u32 master_ctrl_data = 0; u32 wol_ctrl_data = 0; - u16 mii_bmsr_data; - u16 save_autoneg_advertised; - u16 mii_intr_status_data; + u16 mii_intr_status_data = 0; u32 wufc = adapter->wol; - u32 i; int retval = 0; + atl1c_disable_l0s_l1(hw); if (netif_running(netdev)) { WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); atl1c_down(adapter); } netif_device_detach(netdev); - atl1c_disable_l0s_l1(hw); retval = pci_save_state(pdev); if (retval) return retval; + + if (wufc) + if (atl1c_phy_power_saving(hw) != 0) + dev_dbg(&pdev->dev, "phy power saving failed"); + + AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); + AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); + + master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; + mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT); + mac_ctrl_data |= (((u32)adapter->hw.preamble_len & + MAC_CTRL_PRMLEN_MASK) << + MAC_CTRL_PRMLEN_SHIFT); + mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT); + mac_ctrl_data &= ~MAC_CTRL_DUPLX; + if (wufc) { - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); - master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; - - /* get link status */ - atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data); - atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data); - save_autoneg_advertised = hw->autoneg_advertised; - hw->autoneg_advertised = ADVERTISED_10baseT_Half; - if (atl1c_restart_autoneg(hw) != 0) - if (netif_msg_link(adapter)) - dev_warn(&pdev->dev, "phy autoneg failed\n"); - hw->phy_configured = false; /* re-init PHY when resume */ - hw->autoneg_advertised = save_autoneg_advertised; + mac_ctrl_data |= MAC_CTRL_RX_EN; + if (adapter->link_speed == SPEED_1000 || + adapter->link_speed == SPEED_0) { + mac_ctrl_data |= atl1c_mac_speed_1000 << + MAC_CTRL_SPEED_SHIFT; + mac_ctrl_data |= MAC_CTRL_DUPLX; + } else + mac_ctrl_data |= atl1c_mac_speed_10_100 << + MAC_CTRL_SPEED_SHIFT; + + if (adapter->link_duplex == DUPLEX_FULL) + mac_ctrl_data |= MAC_CTRL_DUPLX; + /* turn on magic packet wol */ if (wufc & AT_WUFC_MAG) - wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; + wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; if (wufc & AT_WUFC_LNKC) { - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { - msleep(100); - atl1c_read_phy_reg(hw, MII_BMSR, - (u16 *)&mii_bmsr_data); - if (mii_bmsr_data & BMSR_LSTATUS) - break; - } - if ((mii_bmsr_data & BMSR_LSTATUS) == 0) - if (netif_msg_link(adapter)) - dev_warn(&pdev->dev, - "%s: Link may change" - "when suspend\n", - atl1c_driver_name); wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; /* only link up can wake up */ if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, - "%s: read write phy " - "register failed.\n", - atl1c_driver_name); - goto wol_dis; + dev_dbg(&pdev->dev, "%s: read write phy " + "register failed.\n", + atl1c_driver_name); } } /* clear phy interrupt */ atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); /* Config MAC Ctrl register */ - mac_ctrl_data = MAC_CTRL_RX_EN; - /* set to 10/100M halt duplex */ - mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; - mac_ctrl_data |= (((u32)adapter->hw.preamble_len & - MAC_CTRL_PRMLEN_MASK) << - MAC_CTRL_PRMLEN_SHIFT); - if (adapter->vlgrp) mac_ctrl_data |= MAC_CTRL_RMV_VLAN; @@ -2467,37 +2516,30 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state) if (wufc & AT_WUFC_MAG) mac_ctrl_data |= MAC_CTRL_BC_EN; - if (netif_msg_hw(adapter)) - dev_dbg(&pdev->dev, - "%s: suspend MAC=0x%x\n", - atl1c_driver_name, mac_ctrl_data); + dev_dbg(&pdev->dev, + "%s: suspend MAC=0x%x\n", + atl1c_driver_name, mac_ctrl_data); AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); /* pcie patch */ - AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + device_set_wakeup_enable(&pdev->dev, 1); - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - goto suspend_exit; + AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | + GPHY_CTRL_EXT_RESET); + pci_prepare_to_sleep(pdev); + } else { + AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING); + master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS; + mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; + mac_ctrl_data |= MAC_CTRL_DUPLX; + AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); + AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); + AT_WRITE_REG(hw, REG_WOL_CTRL, 0); + hw->phy_configured = false; /* re-init PHY when resume */ + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); } -wol_dis: - - /* WOL disabled */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* pcie patch */ - AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); - - atl1c_phy_disable(hw); - hw->phy_configured = false; /* re-init PHY when resume */ - - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); -suspend_exit: pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -2516,9 +2558,19 @@ static int atl1c_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); + atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | + ATL1C_PCIE_PHY_RESET); atl1c_phy_reset(&adapter->hw); atl1c_reset_mac(&adapter->hw); + atl1c_phy_init(&adapter->hw); + +#if 0 + AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data); + pm_data &= ~PM_CTRLSTAT_PME_EN; + AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data); +#endif + netif_device_attach(netdev); if (netif_running(netdev)) atl1c_up(adapter); diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index 146372fd6683..9c0ddb273ac8 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -436,8 +436,8 @@ struct rx_free_desc { __le16 buf_len; /* Size of the receive buffer in host memory */ u16 coalese; /* Update consumer index to host after the * reception of this frame */ - /* __attribute__ ((packed)) is required */ -} __attribute__ ((packed)); + /* __packed is required */ +} __packed; /* * The L1 transmit packet descriptor is comprised of four 32-bit words. diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 293f9c16e786..3d52538df6c4 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -150,9 +150,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev, unsigned long offset, enum dma_data_direction dir) { - ssb_dma_sync_single_range_for_device(sdev, dma_base, - offset & dma_desc_align_mask, - dma_desc_sync_size, dir); + dma_sync_single_for_device(sdev->dma_dev, dma_base + offset, + dma_desc_sync_size, dir); } static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, @@ -160,9 +159,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, unsigned long offset, enum dma_data_direction dir) { - ssb_dma_sync_single_range_for_cpu(sdev, dma_base, - offset & dma_desc_align_mask, - dma_desc_sync_size, dir); + dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset, + dma_desc_sync_size, dir); } static inline unsigned long br32(const struct b44 *bp, unsigned long reg) @@ -608,10 +606,10 @@ static void b44_tx(struct b44 *bp) BUG_ON(skb == NULL); - ssb_dma_unmap_single(bp->sdev, - rp->mapping, - skb->len, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, + rp->mapping, + skb->len, + DMA_TO_DEVICE); rp->skb = NULL; dev_kfree_skb_irq(skb); } @@ -648,29 +646,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (skb == NULL) return -ENOMEM; - mapping = ssb_dma_map_single(bp->sdev, skb->data, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); /* Hardware bug work-around, the chip is unable to do PCI DMA to/from anything above 1GB :-( */ - if (ssb_dma_mapping_error(bp->sdev, mapping) || + if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { /* Sigh... */ - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, + if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; - mapping = ssb_dma_map_single(bp->sdev, skb->data, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || - mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + if (dma_mapping_error(bp->sdev->dma_dev, mapping) || + mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { + if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); dev_kfree_skb_any(skb); return -ENOMEM; } @@ -745,9 +743,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) dest_idx * sizeof(*dest_desc), DMA_BIDIRECTIONAL); - ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); } static int b44_rx(struct b44 *bp, int budget) @@ -767,9 +765,9 @@ static int b44_rx(struct b44 *bp, int budget) struct rx_header *rh; u16 len; - ssb_dma_sync_single_for_cpu(bp->sdev, map, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + dma_sync_single_for_cpu(bp->sdev->dma_dev, map, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); rh = (struct rx_header *) skb->data; len = le16_to_cpu(rh->len); if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) || @@ -801,8 +799,8 @@ static int b44_rx(struct b44 *bp, int budget) skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); if (skb_size < 0) goto drop_it; - ssb_dma_unmap_single(bp->sdev, map, - skb_size, DMA_FROM_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, map, + skb_size, DMA_FROM_DEVICE); /* Leave out rx_header */ skb_put(skb, len + RX_PKT_OFFSET); skb_pull(skb, RX_PKT_OFFSET); @@ -954,24 +952,24 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) goto err_out; } - mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) { + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE); + if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) { struct sk_buff *bounce_skb; /* Chip can't handle DMA to/from >1GB, use bounce buffer */ - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, len, + if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, len, DMA_TO_DEVICE); bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; - mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data, - len, DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) { - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, + mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data, + len, DMA_TO_DEVICE); + if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) { + if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, len, DMA_TO_DEVICE); dev_kfree_skb_any(bounce_skb); goto err_out; @@ -1068,8 +1066,8 @@ static void b44_free_rings(struct b44 *bp) if (rp->skb == NULL) continue; - ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); dev_kfree_skb_any(rp->skb); rp->skb = NULL; } @@ -1080,8 +1078,8 @@ static void b44_free_rings(struct b44 *bp) if (rp->skb == NULL) continue; - ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(rp->skb); rp->skb = NULL; } @@ -1103,14 +1101,12 @@ static void b44_init_rings(struct b44 *bp) memset(bp->tx_ring, 0, B44_TX_RING_BYTES); if (bp->flags & B44_FLAG_RX_RING_HACK) - ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, DMA_BIDIRECTIONAL); if (bp->flags & B44_FLAG_TX_RING_HACK) - ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma, - DMA_TABLE_BYTES, - DMA_TO_DEVICE); + dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, DMA_TO_DEVICE); for (i = 0; i < bp->rx_pending; i++) { if (b44_alloc_rx_skb(bp, -1, i) < 0) @@ -1130,27 +1126,23 @@ static void b44_free_consistent(struct b44 *bp) bp->tx_buffers = NULL; if (bp->rx_ring) { if (bp->flags & B44_FLAG_RX_RING_HACK) { - ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, DMA_BIDIRECTIONAL); kfree(bp->rx_ring); } else - ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, - bp->rx_ring, bp->rx_ring_dma, - GFP_KERNEL); + dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, + bp->rx_ring, bp->rx_ring_dma); bp->rx_ring = NULL; bp->flags &= ~B44_FLAG_RX_RING_HACK; } if (bp->tx_ring) { if (bp->flags & B44_FLAG_TX_RING_HACK) { - ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma, - DMA_TABLE_BYTES, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, DMA_TO_DEVICE); kfree(bp->tx_ring); } else - ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, - bp->tx_ring, bp->tx_ring_dma, - GFP_KERNEL); + dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, + bp->tx_ring, bp->tx_ring_dma); bp->tx_ring = NULL; bp->flags &= ~B44_FLAG_TX_RING_HACK; } @@ -1175,7 +1167,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) goto out_err; size = DMA_TABLE_BYTES; - bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp); + bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, + &bp->rx_ring_dma, gfp); if (!bp->rx_ring) { /* Allocation may have failed due to pci_alloc_consistent insisting on use of GFP_DMA, which is more restrictive @@ -1187,11 +1180,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) if (!rx_ring) goto out_err; - rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); - if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) || + if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) || rx_ring_dma + size > DMA_BIT_MASK(30)) { kfree(rx_ring); goto out_err; @@ -1202,7 +1195,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) bp->flags |= B44_FLAG_RX_RING_HACK; } - bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp); + bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, + &bp->tx_ring_dma, gfp); if (!bp->tx_ring) { /* Allocation may have failed due to ssb_dma_alloc_consistent insisting on use of GFP_DMA, which is more restrictive @@ -1214,11 +1208,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) if (!tx_ring) goto out_err; - tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring, - DMA_TABLE_BYTES, - DMA_TO_DEVICE); + tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) || + if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) || tx_ring_dma + size > DMA_BIT_MASK(30)) { kfree(tx_ring); goto out_err; @@ -2176,12 +2170,14 @@ static int __devinit b44_init_one(struct ssb_device *sdev, "Failed to powerup the bus\n"); goto err_out_free_dev; } - err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30)); - if (err) { + + if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) || + dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) { dev_err(sdev->dev, "Required 30BIT DMA mask unsupported by the system\n"); goto err_out_powerdown; } + err = b44_get_invariants(bp); if (err) { dev_err(sdev->dev, diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index b9ad799c719f..ee1ad9693c8f 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -186,7 +186,7 @@ static int be_mcc_notify_wait(struct be_adapter *adapter) static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) { - int cnt = 0, wait = 5; + int msecs = 0; u32 ready; do { @@ -201,15 +201,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (ready) break; - if (cnt > 4000000) { + if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); return -1; } - if (cnt > 50) - wait = 200; - cnt += wait; - udelay(wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(1)); + msecs++; } while (true); return 0; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 063026de4957..06839676e3c4 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -192,7 +192,7 @@ struct amap_eth_hdr_wrb { u8 event; u8 crc; u8 forward; - u8 ipsec; + u8 lso6; u8 mgmt; u8 ipcs; u8 udpcs; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 54b14272f333..01eb447f98b6 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -373,10 +373,12 @@ static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { + if (skb_is_gso(skb)) { AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, hdr, skb_shinfo(skb)->gso_size); + if (skb_is_gso_v6(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (is_tcp_pkt(skb)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); @@ -1735,6 +1737,44 @@ done: adapter->isr_registered = false; } +static int be_close(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + int vec; + + cancel_delayed_work_sync(&adapter->work); + + be_async_mcc_disable(adapter); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + adapter->link_up = false; + + be_intr_set(adapter, false); + + if (adapter->msix_enabled) { + vec = be_msix_vec_get(adapter, tx_eq->q.id); + synchronize_irq(vec); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + synchronize_irq(vec); + } else { + synchronize_irq(netdev->irq); + } + be_irq_unregister(adapter); + + napi_disable(&rx_eq->napi); + napi_disable(&tx_eq->napi); + + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ + be_tx_compl_clean(adapter); + + return 0; +} + static int be_open(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1765,27 +1805,29 @@ 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) - goto ret_sts; + goto err; be_link_status_update(adapter, link_up); - if (be_physfn(adapter)) + if (be_physfn(adapter)) { status = be_vid_config(adapter); - if (status) - goto ret_sts; + if (status) + goto err; - if (be_physfn(adapter)) { status = be_cmd_set_flow_control(adapter, adapter->tx_fc, adapter->rx_fc); if (status) - goto ret_sts; + goto err; } - schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); -ret_sts: - return status; + return 0; +err: + be_close(adapter->netdev); + return -EIO; } static int be_setup_wol(struct be_adapter *adapter, bool enable) @@ -1913,43 +1955,6 @@ static int be_clear(struct be_adapter *adapter) return 0; } -static int be_close(struct net_device *netdev) -{ - struct be_adapter *adapter = netdev_priv(netdev); - struct be_eq_obj *rx_eq = &adapter->rx_eq; - struct be_eq_obj *tx_eq = &adapter->tx_eq; - int vec; - - cancel_delayed_work_sync(&adapter->work); - - be_async_mcc_disable(adapter); - - netif_stop_queue(netdev); - netif_carrier_off(netdev); - adapter->link_up = false; - - be_intr_set(adapter, false); - - if (adapter->msix_enabled) { - vec = be_msix_vec_get(adapter, tx_eq->q.id); - synchronize_irq(vec); - vec = be_msix_vec_get(adapter, rx_eq->q.id); - synchronize_irq(vec); - } else { - synchronize_irq(netdev->irq); - } - be_irq_unregister(adapter); - - napi_disable(&rx_eq->napi); - napi_disable(&tx_eq->napi); - - /* Wait for all pending tx completions to arrive so that - * all tx skbs are freed. - */ - be_tx_compl_clean(adapter); - - return 0; -} #define FW_FILE_HDR_SIGN "ServerEngines Corp. " char flash_cookie[2][16] = {"*** SE FLAS", @@ -2183,7 +2188,7 @@ static void be_netdev_init(struct net_device *netdev) netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM | - NETIF_F_GRO; + NETIF_F_GRO | NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM; diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 368f33313fb6..012613fde3f4 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -922,61 +922,73 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev) # define bfin_tx_hwtstamp(dev, skb) #endif -static void adjust_tx_list(void) +static inline void _tx_reclaim_skb(void) +{ + do { + tx_list_head->desc_a.config &= ~DMAEN; + tx_list_head->status.status_word = 0; + if (tx_list_head->skb) { + dev_kfree_skb(tx_list_head->skb); + tx_list_head->skb = NULL; + } + tx_list_head = tx_list_head->next; + + } while (tx_list_head->status.status_word != 0); +} + +static void tx_reclaim_skb(struct bfin_mac_local *lp) { int timeout_cnt = MAX_TIMEOUT_CNT; - if (tx_list_head->status.status_word != 0 && - current_tx_ptr != tx_list_head) { - goto adjust_head; /* released something, just return; */ - } + if (tx_list_head->status.status_word != 0) + _tx_reclaim_skb(); - /* - * if nothing released, check wait condition - * current's next can not be the head, - * otherwise the dma will not stop as we want - */ - if (current_tx_ptr->next->next == tx_list_head) { + if (current_tx_ptr->next == tx_list_head) { while (tx_list_head->status.status_word == 0) { + /* slow down polling to avoid too many queue stop. */ udelay(10); - if (tx_list_head->status.status_word != 0 || - !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) { - goto adjust_head; - } - if (timeout_cnt-- < 0) { - printk(KERN_ERR DRV_NAME - ": wait for adjust tx list head timeout\n"); + /* reclaim skb if DMA is not running. */ + if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) + break; + if (timeout_cnt-- < 0) break; - } - } - if (tx_list_head->status.status_word != 0) { - goto adjust_head; } + + if (timeout_cnt >= 0) + _tx_reclaim_skb(); + else + netif_stop_queue(lp->ndev); } - return; + if (current_tx_ptr->next != tx_list_head && + netif_queue_stopped(lp->ndev)) + netif_wake_queue(lp->ndev); + + if (tx_list_head != current_tx_ptr) { + /* shorten the timer interval if tx queue is stopped */ + if (netif_queue_stopped(lp->ndev)) + lp->tx_reclaim_timer.expires = + jiffies + (TX_RECLAIM_JIFFIES >> 4); + else + lp->tx_reclaim_timer.expires = + jiffies + TX_RECLAIM_JIFFIES; + + mod_timer(&lp->tx_reclaim_timer, + lp->tx_reclaim_timer.expires); + } -adjust_head: - do { - tx_list_head->desc_a.config &= ~DMAEN; - tx_list_head->status.status_word = 0; - if (tx_list_head->skb) { - dev_kfree_skb(tx_list_head->skb); - tx_list_head->skb = NULL; - } else { - printk(KERN_ERR DRV_NAME - ": no sk_buff in a transmitted frame!\n"); - } - tx_list_head = tx_list_head->next; - } while (tx_list_head->status.status_word != 0 && - current_tx_ptr != tx_list_head); return; +} +static void tx_reclaim_skb_timeout(unsigned long lp) +{ + tx_reclaim_skb((struct bfin_mac_local *)lp); } static int bfin_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { + struct bfin_mac_local *lp = netdev_priv(dev); u16 *data; u32 data_align = (unsigned long)(skb->data) & 0x3; union skb_shared_tx *shtx = skb_tx(skb); @@ -1009,8 +1021,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, skb->len); current_tx_ptr->desc_a.start_addr = (u32)current_tx_ptr->packet; - if (current_tx_ptr->status.status_word != 0) - current_tx_ptr->status.status_word = 0; blackfin_dcache_flush_range( (u32)current_tx_ptr->packet, (u32)(current_tx_ptr->packet + skb->len + 2)); @@ -1022,6 +1032,9 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, */ SSYNC(); + /* always clear status buffer before start tx dma */ + current_tx_ptr->status.status_word = 0; + /* enable this packet's dma */ current_tx_ptr->desc_a.config |= DMAEN; @@ -1037,13 +1050,14 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); out: - adjust_tx_list(); - bfin_tx_hwtstamp(dev, skb); current_tx_ptr = current_tx_ptr->next; dev->stats.tx_packets++; dev->stats.tx_bytes += (skb->len); + + tx_reclaim_skb(lp); + return NETDEV_TX_OK; } @@ -1167,8 +1181,11 @@ real_rx: #ifdef CONFIG_NET_POLL_CONTROLLER static void bfin_mac_poll(struct net_device *dev) { + struct bfin_mac_local *lp = netdev_priv(dev); + disable_irq(IRQ_MAC_RX); bfin_mac_interrupt(IRQ_MAC_RX, dev); + tx_reclaim_skb(lp); enable_irq(IRQ_MAC_RX); } #endif /* CONFIG_NET_POLL_CONTROLLER */ @@ -1232,12 +1249,27 @@ static int bfin_mac_enable(void) /* Our watchdog timed out. Called by the networking layer */ static void bfin_mac_timeout(struct net_device *dev) { + struct bfin_mac_local *lp = netdev_priv(dev); + pr_debug("%s: %s\n", dev->name, __func__); bfin_mac_disable(); - /* reset tx queue */ - tx_list_tail = tx_list_head->next; + del_timer(&lp->tx_reclaim_timer); + + /* reset tx queue and free skb */ + while (tx_list_head != current_tx_ptr) { + tx_list_head->desc_a.config &= ~DMAEN; + tx_list_head->status.status_word = 0; + if (tx_list_head->skb) { + dev_kfree_skb(tx_list_head->skb); + tx_list_head->skb = NULL; + } + tx_list_head = tx_list_head->next; + } + + if (netif_queue_stopped(lp->ndev)) + netif_wake_queue(lp->ndev); bfin_mac_enable(); @@ -1430,6 +1462,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) SET_NETDEV_DEV(ndev, &pdev->dev); platform_set_drvdata(pdev, ndev); lp = netdev_priv(ndev); + lp->ndev = ndev; /* Grab the MAC address in the MAC */ *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); @@ -1485,6 +1518,10 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) ndev->netdev_ops = &bfin_mac_netdev_ops; ndev->ethtool_ops = &bfin_mac_ethtool_ops; + init_timer(&lp->tx_reclaim_timer); + lp->tx_reclaim_timer.data = (unsigned long)lp; + lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout; + spin_lock_init(&lp->lock); /* now, enable interrupts */ diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h index 1ae7b82ceeee..04e4050df18b 100644 --- a/drivers/net/bfin_mac.h +++ b/drivers/net/bfin_mac.h @@ -13,9 +13,12 @@ #include <linux/net_tstamp.h> #include <linux/clocksource.h> #include <linux/timecompare.h> +#include <linux/timer.h> #define BFIN_MAC_CSUM_OFFLOAD +#define TX_RECLAIM_JIFFIES (HZ / 5) + struct dma_descriptor { struct dma_descriptor *next_dma_desc; unsigned long start_addr; @@ -68,6 +71,8 @@ struct bfin_mac_local { int wol; /* Wake On Lan */ int irq_wake_requested; + struct timer_list tx_reclaim_timer; + struct net_device *ndev; /* MII and PHY stuffs */ int old_link; /* used by bf537_adjust_link */ diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 117432222a09..a5dd81face37 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1446,7 +1446,8 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp) static void bnx2_enable_forced_2g5(struct bnx2 *bp) { - u32 bmcr; + u32 uninitialized_var(bmcr); + int err; if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) return; @@ -1456,22 +1457,28 @@ bnx2_enable_forced_2g5(struct bnx2 *bp) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG); - bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val); - val &= ~MII_BNX2_SD_MISC1_FORCE_MSK; - val |= MII_BNX2_SD_MISC1_FORCE | MII_BNX2_SD_MISC1_FORCE_2_5G; - bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); + if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) { + val &= ~MII_BNX2_SD_MISC1_FORCE_MSK; + val |= MII_BNX2_SD_MISC1_FORCE | + MII_BNX2_SD_MISC1_FORCE_2_5G; + bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); + } bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); - bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); + err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { - bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); - bmcr |= BCM5708S_BMCR_FORCE_2500; + err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); + if (!err) + bmcr |= BCM5708S_BMCR_FORCE_2500; } else { return; } + if (err) + return; + if (bp->autoneg & AUTONEG_SPEED) { bmcr &= ~BMCR_ANENABLE; if (bp->req_duplex == DUPLEX_FULL) @@ -1483,7 +1490,8 @@ bnx2_enable_forced_2g5(struct bnx2 *bp) static void bnx2_disable_forced_2g5(struct bnx2 *bp) { - u32 bmcr; + u32 uninitialized_var(bmcr); + int err; if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) return; @@ -1493,21 +1501,26 @@ bnx2_disable_forced_2g5(struct bnx2 *bp) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG); - bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val); - val &= ~MII_BNX2_SD_MISC1_FORCE; - bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); + if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) { + val &= ~MII_BNX2_SD_MISC1_FORCE; + bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); + } bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); - bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); + err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { - bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); - bmcr &= ~BCM5708S_BMCR_FORCE_2500; + err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); + if (!err) + bmcr &= ~BCM5708S_BMCR_FORCE_2500; } else { return; } + if (err) + return; + if (bp->autoneg & AUTONEG_SPEED) bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART; bnx2_write_phy(bp, bp->mii_bmcr, bmcr); diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index ff70be898765..0383e3066313 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -4266,14 +4266,16 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) MDIO_PMA_REG_10G_CTRL2, 0x0008); } - /* Set 2-wire transfer rate to 400Khz since 100Khz - is not operational */ + /* Set 2-wire transfer rate of SFP+ module EEPROM + * to 100Khz since some DACs(direct attached cables) do + * not work at 400Khz. + */ bnx2x_cl45_write(bp, params->port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR, - 0xa101); + 0xa001); /* Set TX PreEmphasis if needed */ if ((params->feature_config_flags & diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 40fdc41446cc..25c14c6236f5 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -233,34 +233,27 @@ static void tlb_deinitialize(struct bonding *bond) _unlock_tx_hashtbl(bond); } +static long long compute_gap(struct slave *slave) +{ + return (s64) (slave->speed << 20) - /* Convert to Megabit per sec */ + (s64) (SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */ +} + /* Caller must hold bond lock for read */ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond) { struct slave *slave, *least_loaded; - s64 max_gap; - int i, found = 0; - - /* Find the first enabled slave */ - bond_for_each_slave(bond, slave, i) { - if (SLAVE_IS_OK(slave)) { - found = 1; - break; - } - } - - if (!found) { - return NULL; - } + long long max_gap; + int i; - least_loaded = slave; - max_gap = (s64)(slave->speed << 20) - /* Convert to Megabit per sec */ - (s64)(SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */ + least_loaded = NULL; + max_gap = LLONG_MIN; /* Find the slave with the largest gap */ - bond_for_each_slave_from(bond, slave, i, least_loaded) { + bond_for_each_slave(bond, slave, i) { if (SLAVE_IS_OK(slave)) { - s64 gap = (s64)(slave->speed << 20) - - (s64)(SLAVE_TLB_INFO(slave).load << 3); + long long gap = compute_gap(slave); + if (max_gap < gap) { least_loaded = slave; max_gap = gap; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5e12462a9d5e..a95a41b74b4e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -90,6 +90,7 @@ #define BOND_LINK_ARP_INTERV 0 static int max_bonds = BOND_DEFAULT_MAX_BONDS; +static int tx_queues = BOND_DEFAULT_TX_QUEUES; static int num_grat_arp = 1; static int num_unsol_na = 1; static int miimon = BOND_LINK_MON_INTERV; @@ -106,10 +107,13 @@ static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; static char *arp_validate; static char *fail_over_mac; +static int all_slaves_active = 0; static struct bond_params bonding_defaults; module_param(max_bonds, int, 0); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); +module_param(tx_queues, int, 0); +MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); module_param(num_grat_arp, int, 0644); MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); module_param(num_unsol_na, int, 0644); @@ -155,6 +159,10 @@ module_param(arp_validate, charp, 0); MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); module_param(fail_over_mac, charp, 0); MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. none (default), active or follow"); +module_param(all_slaves_active, int, 0); +MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface" + "by setting active flag for all slaves. " + "0 for never (default), 1 for always."); /*----------------------------- Global variables ----------------------------*/ @@ -1522,16 +1530,32 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } } + /* If this is the first slave, then we need to set the master's hardware + * address to be the same as the slave's. */ + if (bond->slave_cnt == 0) + memcpy(bond->dev->dev_addr, slave_dev->dev_addr, + slave_dev->addr_len); + + new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { res = -ENOMEM; goto err_undo_flags; } - /* save slave's original flags before calling - * netdev_set_master and dev_open + /* + * Set the new_slave's queue_id to be zero. Queue ID mapping + * is set via sysfs or module option if desired. */ - new_slave->original_flags = slave_dev->flags; + new_slave->queue_id = 0; + + /* Save slave's original mtu and then set it to match the bond */ + new_slave->original_mtu = slave_dev->mtu; + res = dev_set_mtu(slave_dev, bond->dev->mtu); + if (res) { + pr_debug("Error %d calling dev_set_mtu\n", res); + goto err_free; + } /* * Save slave's original ("permanent") mac address for modes @@ -1550,7 +1574,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = dev_set_mac_address(slave_dev, &addr); if (res) { pr_debug("Error %d calling set_mac_address\n", res); - goto err_free; + goto err_restore_mtu; } } @@ -1785,6 +1809,9 @@ err_restore_mac: dev_set_mac_address(slave_dev, &addr); } +err_restore_mtu: + dev_set_mtu(slave_dev, new_slave->original_mtu); + err_free: kfree(new_slave); @@ -1969,6 +1996,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) dev_set_mac_address(slave_dev, &addr); } + dev_set_mtu(slave_dev, slave->original_mtu); + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | IFF_SLAVE_INACTIVE | IFF_BONDING | IFF_SLAVE_NEEDARP); @@ -2555,7 +2584,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) /* * This target is not on a VLAN */ - if (rt->u.dst.dev == bond->dev) { + if (rt->dst.dev == bond->dev) { ip_rt_put(rt); pr_debug("basa: rtdev == bond->dev: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], @@ -2566,7 +2595,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) vlan_id = 0; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); - if (vlan_dev == rt->u.dst.dev) { + if (vlan_dev == rt->dst.dev) { vlan_id = vlan->vlan_id; pr_debug("basa: vlan match on %s %d\n", vlan_dev->name, vlan_id); @@ -2584,7 +2613,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) if (net_ratelimit()) { pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n", bond->dev->name, &fl.fl4_dst, - rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); + rt->dst.dev ? rt->dst.dev->name : "NULL"); } ip_rt_put(rt); } @@ -3265,6 +3294,7 @@ static void bond_info_show_slave(struct seq_file *seq, else seq_puts(seq, "Aggregator ID: N/A\n"); } + seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id); } static int bond_info_seq_show(struct seq_file *seq, void *v) @@ -3774,20 +3804,21 @@ static int bond_close(struct net_device *bond_dev) return 0; } -static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) +static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct net_device_stats *stats = &bond_dev->stats; - struct net_device_stats local_stats; + struct rtnl_link_stats64 *stats = &bond_dev->stats64; + struct rtnl_link_stats64 local_stats; struct slave *slave; int i; - memset(&local_stats, 0, sizeof(struct net_device_stats)); + memset(&local_stats, 0, sizeof(local_stats)); read_lock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { - const struct net_device_stats *sstats = dev_get_stats(slave->dev); + const struct rtnl_link_stats64 *sstats = + dev_get_stats(slave->dev); local_stats.rx_packets += sstats->rx_packets; local_stats.rx_bytes += sstats->rx_bytes; @@ -4401,9 +4432,59 @@ static void bond_set_xmit_hash_policy(struct bonding *bond) } } +/* + * Lookup the slave that corresponds to a qid + */ +static inline int bond_slave_override(struct bonding *bond, + struct sk_buff *skb) +{ + int i, res = 1; + struct slave *slave = NULL; + struct slave *check_slave; + + read_lock(&bond->lock); + + if (!BOND_IS_OK(bond) || !skb->queue_mapping) + goto out; + + /* Find out if any slaves have the same mapping as this skb. */ + bond_for_each_slave(bond, check_slave, i) { + if (check_slave->queue_id == skb->queue_mapping) { + slave = check_slave; + break; + } + } + + /* If the slave isn't UP, use default transmit policy. */ + if (slave && slave->queue_id && IS_UP(slave->dev) && + (slave->link == BOND_LINK_UP)) { + res = bond_dev_queue_xmit(bond, skb, slave->dev); + } + +out: + read_unlock(&bond->lock); + return res; +} + +static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + /* + * This helper function exists to help dev_pick_tx get the correct + * destination queue. Using a helper function skips the a call to + * skb_tx_hash and will put the skbs in the queue we expect on their + * way down to the bonding driver. + */ + return skb->queue_mapping; +} + static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) { - const struct bonding *bond = netdev_priv(dev); + struct bonding *bond = netdev_priv(dev); + + if (TX_QUEUE_OVERRIDE(bond->params.mode)) { + if (!bond_slave_override(bond, skb)) + return NETDEV_TX_OK; + } switch (bond->params.mode) { case BOND_MODE_ROUNDROBIN: @@ -4488,7 +4569,8 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_open = bond_open, .ndo_stop = bond_close, .ndo_start_xmit = bond_start_xmit, - .ndo_get_stats = bond_get_stats, + .ndo_select_queue = bond_select_queue, + .ndo_get_stats64 = bond_get_stats, .ndo_do_ioctl = bond_do_ioctl, .ndo_set_multicast_list = bond_set_multicast_list, .ndo_change_mtu = bond_change_mtu, @@ -4756,6 +4838,20 @@ static int bond_check_params(struct bond_params *params) } } + if (tx_queues < 1 || tx_queues > 255) { + pr_warning("Warning: tx_queues (%d) should be between " + "1 and 255, resetting to %d\n", + tx_queues, BOND_DEFAULT_TX_QUEUES); + tx_queues = BOND_DEFAULT_TX_QUEUES; + } + + if ((all_slaves_active != 0) && (all_slaves_active != 1)) { + pr_warning("Warning: all_slaves_active module parameter (%d), " + "not of valid value (0/1), so it was set to " + "0\n", all_slaves_active); + all_slaves_active = 0; + } + /* reset values for TLB/ALB */ if ((bond_mode == BOND_MODE_TLB) || (bond_mode == BOND_MODE_ALB)) { @@ -4926,6 +5022,8 @@ static int bond_check_params(struct bond_params *params) params->primary[0] = 0; params->primary_reselect = primary_reselect_value; params->fail_over_mac = fail_over_mac_value; + params->tx_queues = tx_queues; + params->all_slaves_active = all_slaves_active; if (primary) { strncpy(params->primary, primary, IFNAMSIZ); @@ -5012,8 +5110,8 @@ int bond_create(struct net *net, const char *name) rtnl_lock(); - bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", - bond_setup); + bond_dev = alloc_netdev_mq(sizeof(struct bonding), name ? name : "", + bond_setup, tx_queues); if (!bond_dev) { pr_err("%s: eek! can't alloc netdev!\n", name); rtnl_unlock(); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index b8bec086daa1..f9a034361a8e 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -211,7 +211,8 @@ static ssize_t bonding_show_slaves(struct device *d, /* * Set the slaves in the current bond. The bond interface must be * up for this to succeed. - * This function is largely the same flow as bonding_update_bonds(). + * This is supposed to be only thin wrapper for bond_enslave and bond_release. + * All hard work should be done there. */ static ssize_t bonding_store_slaves(struct device *d, struct device_attribute *attr, @@ -219,10 +220,8 @@ static ssize_t bonding_store_slaves(struct device *d, { char command[IFNAMSIZ + 1] = { 0, }; char *ifname; - int i, res, found, ret = count; - u32 original_mtu; - struct slave *slave; - struct net_device *dev = NULL; + int res, ret = count; + struct net_device *dev; struct bonding *bond = to_bond(d); /* Quick sanity check -- is the bond interface up? */ @@ -231,8 +230,6 @@ static ssize_t bonding_store_slaves(struct device *d, bond->dev->name); } - /* Note: We can't hold bond->lock here, as bond_create grabs it. */ - if (!rtnl_trylock()) return restart_syscall(); @@ -242,91 +239,33 @@ static ssize_t bonding_store_slaves(struct device *d, !dev_valid_name(ifname)) goto err_no_cmd; - if (command[0] == '+') { - - /* Got a slave name in ifname. Is it already in the list? */ - found = 0; - - dev = __dev_get_by_name(dev_net(bond->dev), ifname); - if (!dev) { - pr_info("%s: Interface %s does not exist!\n", - bond->dev->name, ifname); - ret = -ENODEV; - goto out; - } - - if (dev->flags & IFF_UP) { - pr_err("%s: Error: Unable to enslave %s because it is already up.\n", - bond->dev->name, dev->name); - ret = -EPERM; - goto out; - } - - read_lock(&bond->lock); - bond_for_each_slave(bond, slave, i) - if (slave->dev == dev) { - pr_err("%s: Interface %s is already enslaved!\n", - bond->dev->name, ifname); - ret = -EPERM; - read_unlock(&bond->lock); - goto out; - } - read_unlock(&bond->lock); - - pr_info("%s: Adding slave %s.\n", bond->dev->name, ifname); - - /* If this is the first slave, then we need to set - the master's hardware address to be the same as the - slave's. */ - if (is_zero_ether_addr(bond->dev->dev_addr)) - memcpy(bond->dev->dev_addr, dev->dev_addr, - dev->addr_len); - - /* Set the slave's MTU to match the bond */ - original_mtu = dev->mtu; - res = dev_set_mtu(dev, bond->dev->mtu); - if (res) { - ret = res; - goto out; - } + dev = __dev_get_by_name(dev_net(bond->dev), ifname); + if (!dev) { + pr_info("%s: Interface %s does not exist!\n", + bond->dev->name, ifname); + ret = -ENODEV; + goto out; + } + switch (command[0]) { + case '+': + pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name); res = bond_enslave(bond->dev, dev); - bond_for_each_slave(bond, slave, i) - if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) - slave->original_mtu = original_mtu; - if (res) - ret = res; + break; - goto out; - } + case '-': + pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name); + res = bond_release(bond->dev, dev); + break; - if (command[0] == '-') { - dev = NULL; - original_mtu = 0; - bond_for_each_slave(bond, slave, i) - if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { - dev = slave->dev; - original_mtu = slave->original_mtu; - break; - } - if (dev) { - pr_info("%s: Removing slave %s\n", - bond->dev->name, dev->name); - res = bond_release(bond->dev, dev); - if (res) { - ret = res; - goto out; - } - /* set the slave MTU to the default */ - dev_set_mtu(dev, original_mtu); - } else { - pr_err("unable to remove non-existent slave %s for bond %s.\n", - ifname, bond->dev->name); - ret = -ENODEV; - } - goto out; + default: + goto err_no_cmd; } + if (res) + ret = res; + goto out; + err_no_cmd: pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name); @@ -1472,7 +1411,173 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d, } static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); +/* + * Show the queue_ids of the slaves in the current bond. + */ +static ssize_t bonding_show_queue_id(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct slave *slave; + int i, res = 0; + struct bonding *bond = to_bond(d); + + if (!rtnl_trylock()) + return restart_syscall(); + read_lock(&bond->lock); + bond_for_each_slave(bond, slave, i) { + if (res > (PAGE_SIZE - 6)) { + /* not enough space for another interface name */ + if ((PAGE_SIZE - res) > 10) + res = PAGE_SIZE - 10; + res += sprintf(buf + res, "++more++ "); + break; + } + res += sprintf(buf + res, "%s:%d ", + slave->dev->name, slave->queue_id); + } + read_unlock(&bond->lock); + if (res) + buf[res-1] = '\n'; /* eat the leftover space */ + rtnl_unlock(); + return res; +} + +/* + * Set the queue_ids of the slaves in the current bond. The bond + * interface must be enslaved for this to work. + */ +static ssize_t bonding_store_queue_id(struct device *d, + struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct slave *slave, *update_slave; + struct bonding *bond = to_bond(d); + u16 qid; + int i, ret = count; + char *delim; + struct net_device *sdev = NULL; + + if (!rtnl_trylock()) + return restart_syscall(); + + /* delim will point to queue id if successful */ + delim = strchr(buffer, ':'); + if (!delim) + goto err_no_cmd; + + /* + * Terminate string that points to device name and bump it + * up one, so we can read the queue id there. + */ + *delim = '\0'; + if (sscanf(++delim, "%hd\n", &qid) != 1) + goto err_no_cmd; + + /* Check buffer length, valid ifname and queue id */ + if (strlen(buffer) > IFNAMSIZ || + !dev_valid_name(buffer) || + qid > bond->params.tx_queues) + goto err_no_cmd; + + /* Get the pointer to that interface if it exists */ + sdev = __dev_get_by_name(dev_net(bond->dev), buffer); + if (!sdev) + goto err_no_cmd; + + read_lock(&bond->lock); + + /* Search for thes slave and check for duplicate qids */ + update_slave = NULL; + bond_for_each_slave(bond, slave, i) { + if (sdev == slave->dev) + /* + * We don't need to check the matching + * slave for dups, since we're overwriting it + */ + update_slave = slave; + else if (qid && qid == slave->queue_id) { + goto err_no_cmd_unlock; + } + } + + if (!update_slave) + goto err_no_cmd_unlock; + + /* Actually set the qids for the slave */ + update_slave->queue_id = qid; + + read_unlock(&bond->lock); +out: + rtnl_unlock(); + return ret; + +err_no_cmd_unlock: + read_unlock(&bond->lock); +err_no_cmd: + pr_info("invalid input for queue_id set for %s.\n", + bond->dev->name); + ret = -EPERM; + goto out; +} + +static DEVICE_ATTR(queue_id, S_IRUGO | S_IWUSR, bonding_show_queue_id, + bonding_store_queue_id); + + +/* + * Show and set the all_slaves_active flag. + */ +static ssize_t bonding_show_slaves_active(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct bonding *bond = to_bond(d); + + return sprintf(buf, "%d\n", bond->params.all_slaves_active); +} + +static ssize_t bonding_store_slaves_active(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int i, new_value, ret = count; + struct bonding *bond = to_bond(d); + struct slave *slave; + + if (sscanf(buf, "%d", &new_value) != 1) { + pr_err("%s: no all_slaves_active value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + + if (new_value == bond->params.all_slaves_active) + goto out; + + if ((new_value == 0) || (new_value == 1)) { + bond->params.all_slaves_active = new_value; + } else { + pr_info("%s: Ignoring invalid all_slaves_active value %d.\n", + bond->dev->name, new_value); + ret = -EINVAL; + goto out; + } + + bond_for_each_slave(bond, slave, i) { + if (slave->state == BOND_STATE_BACKUP) { + if (new_value) + slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; + else + slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; + } + } +out: + return count; +} +static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR, + bonding_show_slaves_active, bonding_store_slaves_active); static struct attribute *per_bond_attrs[] = { &dev_attr_slaves.attr, @@ -1499,6 +1604,8 @@ static struct attribute *per_bond_attrs[] = { &dev_attr_ad_actor_key.attr, &dev_attr_ad_partner_key.attr, &dev_attr_ad_partner_mac.attr, + &dev_attr_queue_id.attr, + &dev_attr_all_slaves_active.attr, NULL, }; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 2aa336720591..c6fdd851579a 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -23,8 +23,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.6.0" -#define DRV_RELDATE "September 26, 2009" +#define DRV_VERSION "3.7.0" +#define DRV_RELDATE "June 2, 2010" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -60,6 +60,9 @@ ((mode) == BOND_MODE_TLB) || \ ((mode) == BOND_MODE_ALB)) +#define TX_QUEUE_OVERRIDE(mode) \ + (((mode) == BOND_MODE_ACTIVEBACKUP) || \ + ((mode) == BOND_MODE_ROUNDROBIN)) /* * Less bad way to call ioctl from within the kernel; this needs to be * done some other way to get the call out of interrupt context. @@ -131,6 +134,8 @@ struct bond_params { char primary[IFNAMSIZ]; int primary_reselect; __be32 arp_targets[BOND_MAX_ARP_TARGETS]; + int tx_queues; + int all_slaves_active; }; struct bond_parm_tbl { @@ -159,12 +164,12 @@ struct slave { s8 link; /* one of BOND_LINK_XXXX */ s8 new_link; s8 state; /* one of BOND_STATE_XXXX */ - u32 original_flags; u32 original_mtu; u32 link_failure_count; u8 perm_hwaddr[ETH_ALEN]; u16 speed; u8 duplex; + u16 queue_id; struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */ struct tlb_slave_info tlb_info; }; @@ -291,7 +296,8 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave) struct bonding *bond = netdev_priv(slave->dev->master); if (!bond_is_lb(bond)) slave->state = BOND_STATE_BACKUP; - slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; + if (!bond->params.all_slaves_active) + slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; if (slave_do_arp_validate(bond, slave)) slave->dev->priv_flags |= IFF_SLAVE_NEEDARP; } diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 09257ca8f563..3df0c0f8b8bf 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -174,6 +174,7 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data, struct ser_device *ser; int ret; u8 *p; + ser = tty->disc_data; /* @@ -221,6 +222,7 @@ static int handle_tx(struct ser_device *ser) struct tty_struct *tty; struct sk_buff *skb; int tty_wr, len, room; + tty = ser->tty; ser->tx_started = true; @@ -281,6 +283,7 @@ error: static int caif_xmit(struct sk_buff *skb, struct net_device *dev) { struct ser_device *ser; + BUG_ON(dev == NULL); ser = netdev_priv(dev); @@ -299,6 +302,7 @@ static int caif_xmit(struct sk_buff *skb, struct net_device *dev) static void ldisc_tx_wakeup(struct tty_struct *tty) { struct ser_device *ser; + ser = tty->disc_data; BUG_ON(ser == NULL); BUG_ON(ser->tty != tty); @@ -348,6 +352,7 @@ static void ldisc_close(struct tty_struct *tty) struct ser_device *ser = tty->disc_data; /* Remove may be called inside or outside of rtnl_lock */ int islocked = rtnl_is_locked(); + if (!islocked) rtnl_lock(); /* device is freed automagically by net-sysfs */ @@ -374,6 +379,7 @@ static struct tty_ldisc_ops caif_ldisc = { static int register_ldisc(void) { int result; + result = tty_register_ldisc(N_CAIF, &caif_ldisc); if (result < 0) { pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF, @@ -391,12 +397,12 @@ static const struct net_device_ops netdev_ops = { static void caifdev_setup(struct net_device *dev) { struct ser_device *serdev = netdev_priv(dev); + dev->features = 0; dev->netdev_ops = &netdev_ops; dev->type = ARPHRD_CAIF; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = CAIF_MAX_MTU; - dev->hard_header_len = CAIF_NEEDED_HEADROOM; dev->tx_queue_len = 0; dev->destructor = free_netdev; skb_queue_head_init(&serdev->head); @@ -410,8 +416,6 @@ static void caifdev_setup(struct net_device *dev) static int caif_net_open(struct net_device *dev) { - struct ser_device *ser; - ser = netdev_priv(dev); netif_wake_queue(dev); return 0; } @@ -425,6 +429,7 @@ static int caif_net_close(struct net_device *dev) static int __init caif_ser_init(void) { int ret; + ret = register_ldisc(); debugfsdir = debugfs_create_dir("caif_serial", NULL); return ret; @@ -435,6 +440,7 @@ static void __exit caif_ser_exit(void) struct ser_device *ser = NULL; struct list_head *node; struct list_head *_tmp; + list_for_each_safe(node, _tmp, &ser_list) { ser = list_entry(node, struct ser_device, node); dev_close(ser->dev); diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index 4ff966473bc9..b43e9f5d3268 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h @@ -227,7 +227,7 @@ struct mscan_regs { u16 time; /* + 0x7c 0x3e */ } tx; _MSCAN_RESERVED_(32, 2); /* + 0x7e */ -} __attribute__ ((packed)); +} __packed; #undef _MSCAN_RESERVED_ #define MSCAN_REGION sizeof(struct mscan) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 1fc0871d2ef7..e75f1a876972 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -197,7 +197,7 @@ struct cpc_can_err_counter { }; /* Main message type used between library and application */ -struct __attribute__ ((packed)) ems_cpc_msg { +struct __packed ems_cpc_msg { u8 type; /* type of message */ u8 length; /* length of data within union 'msg' */ u8 msgid; /* confirmation handle */ diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 036b2dfb1d40..092f31a126e6 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -286,7 +286,6 @@ struct board_info { unsigned int clock_mc3; unsigned int clock_mc4; unsigned int espi_nports; - unsigned int clock_cspi; unsigned int clock_elmer0; unsigned char mdio_mdien; unsigned char mdio_mdiinv; diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 53bde15fc94d..599d178df62d 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -185,9 +185,6 @@ static int t1_pci_intr_handler(adapter_t *adapter) return 0; } -#ifdef CONFIG_CHELSIO_T1_COUGAR -#include "cspi.h" -#endif #ifdef CONFIG_CHELSIO_T1_1G #include "fpga_defs.h" @@ -280,7 +277,7 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi) t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val); } -#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) +#if defined(CONFIG_CHELSIO_T1_1G) /* * Elmer MI1 MDIO read/write operations. */ @@ -317,7 +314,7 @@ static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr, return 0; } -#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) +#if defined(CONFIG_CHELSIO_T1_1G) static const struct mdio_ops mi1_mdio_ops = { .init = mi1_mdio_init, .read = mi1_mdio_read, @@ -752,31 +749,6 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) mod_detect ? "removed" : "inserted"); } break; -#ifdef CONFIG_CHELSIO_T1_COUGAR - case CHBT_BOARD_COUGAR: - if (adapter->params.nports == 1) { - if (cause & ELMER0_GP_BIT1) { /* Vitesse MAC */ - struct cmac *mac = adapter->port[0].mac; - mac->ops->interrupt_handler(mac); - } - if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */ - } - } else { - int i, port_bit; - - for_each_port(adapter, i) { - port_bit = i ? i + 1 : 0; - if (!(cause & (1 << port_bit))) - continue; - - phy = adapter->port[i].phy; - phy_cause = phy->ops->interrupt_handler(phy); - if (phy_cause & cphy_cause_link_change) - t1_link_changed(adapter, i); - } - } - break; -#endif } t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); return 0; @@ -955,7 +927,6 @@ static int board_init(adapter_t *adapter, const struct board_info *bi) case CHBT_BOARD_N110: case CHBT_BOARD_N210: case CHBT_BOARD_CHT210: - case CHBT_BOARD_COUGAR: t1_tpi_par(adapter, 0xf); t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); break; @@ -1004,10 +975,6 @@ int t1_init_hw_modules(adapter_t *adapter) adapter->regs + A_MC5_CONFIG); } -#ifdef CONFIG_CHELSIO_T1_COUGAR - if (adapter->cspi && t1_cspi_init(adapter->cspi)) - goto out_err; -#endif if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac, bi->espi_nports)) goto out_err; @@ -1061,10 +1028,6 @@ void t1_free_sw_modules(adapter_t *adapter) t1_tp_destroy(adapter->tp); if (adapter->espi) t1_espi_destroy(adapter->espi); -#ifdef CONFIG_CHELSIO_T1_COUGAR - if (adapter->cspi) - t1_cspi_destroy(adapter->cspi); -#endif } static void __devinit init_link_config(struct link_config *lc, @@ -1084,14 +1047,6 @@ static void __devinit init_link_config(struct link_config *lc, } } -#ifdef CONFIG_CHELSIO_T1_COUGAR - if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) { - pr_err("%s: CSPI initialization failed\n", - adapter->name); - goto error; - } -#endif - /* * Allocate and initialize the data structures that hold the SW state of * the Terminator HW modules. diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 80471269977a..04e299f46455 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2824,7 +2824,7 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr, err = ip_route_output_key(&init_net, &rt, &fl); if (!err) - *dst = &rt->u.dst; + *dst = &rt->dst; return err; #else return -ENETUNREACH; @@ -2996,7 +2996,7 @@ err_out: static int cnic_cm_abort(struct cnic_sock *csk) { struct cnic_local *cp = csk->dev->cnic_priv; - u32 opcode; + u32 opcode = L4_KCQE_OPCODE_VALUE_RESET_COMP; if (!cnic_in_use(csk)) return -EINVAL; @@ -3008,12 +3008,9 @@ static int cnic_cm_abort(struct cnic_sock *csk) * connect was not successful. */ - csk->state = L4_KCQE_OPCODE_VALUE_RESET_COMP; - if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) - opcode = csk->state; - else - opcode = L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD; cp->close_conn(csk, opcode); + if (csk->state != opcode) + return -EALREADY; return 0; } @@ -3026,6 +3023,8 @@ static int cnic_cm_close(struct cnic_sock *csk) if (cnic_close_prep(csk)) { csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP; return cnic_cm_close_req(csk); + } else { + return -EALREADY; } return 0; } @@ -3141,12 +3140,6 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) break; case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED: - if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) { - cnic_cm_upcall(cp, csk, opcode); - break; - } else if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) - csk->state = opcode; - /* fall through */ case L4_KCQE_OPCODE_VALUE_CLOSE_COMP: case L4_KCQE_OPCODE_VALUE_RESET_COMP: case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE: @@ -3202,19 +3195,22 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev) static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode) { - if ((opcode == csk->state) || - (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED && - csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)) { - if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) - return 1; + if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) { + /* Unsolicited RESET_COMP or RESET_RECEIVED */ + opcode = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED; + csk->state = opcode; } - /* 57710+ only workaround to handle unsolicited RESET_COMP - * which will be treated like a RESET RCVD notification - * which triggers the clean up procedure + + /* 1. If event opcode matches the expected event in csk->state + * 2. If the expected event is CLOSE_COMP, we accept any event + * 3. If the expected event is 0, meaning the connection was never + * never established, we accept the opcode from cm_abort. */ - else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_COMP) { + if (opcode == csk->state || csk->state == 0 || + csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) { if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) { - csk->state = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED; + if (csk->state == 0) + csk->state = opcode; return 1; } } @@ -3226,8 +3222,14 @@ static void cnic_close_bnx2_conn(struct cnic_sock *csk, u32 opcode) struct cnic_dev *dev = csk->dev; struct cnic_local *cp = dev->cnic_priv; + if (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED) { + cnic_cm_upcall(cp, csk, opcode); + return; + } + clear_bit(SK_F_CONNECT_START, &csk->flags); cnic_close_conn(csk); + csk->state = opcode; cnic_cm_upcall(cp, csk, opcode); } @@ -3257,8 +3259,12 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode) case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED: case L4_KCQE_OPCODE_VALUE_CLOSE_COMP: case L4_KCQE_OPCODE_VALUE_RESET_COMP: - if (cnic_ready_to_close(csk, opcode)) - cmd = L5CM_RAMROD_CMD_ID_SEARCHER_DELETE; + if (cnic_ready_to_close(csk, opcode)) { + if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) + cmd = L5CM_RAMROD_CMD_ID_SEARCHER_DELETE; + else + close_complete = 1; + } break; case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE: cmd = L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD; diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index e3f1b8566495..066fd5b09fda 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2311,15 +2311,9 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) if (copy_from_user(&t, useraddr, sizeof(t))) return -EFAULT; /* Check t.len sanity ? */ - fw_data = kmalloc(t.len, GFP_KERNEL); - if (!fw_data) - return -ENOMEM; - - if (copy_from_user - (fw_data, useraddr + sizeof(t), t.len)) { - kfree(fw_data); - return -EFAULT; - } + fw_data = memdup_user(useraddr + sizeof(t), t.len); + if (IS_ERR(fw_data)) + return PTR_ERR(fw_data); ret = t3_load_fw(adapter, fw_data, t.len); kfree(fw_data); diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h index dd1770e075e6..62804bb4022d 100644 --- a/drivers/net/cxgb4/cxgb4.h +++ b/drivers/net/cxgb4/cxgb4.h @@ -219,6 +219,10 @@ struct adapter_params { struct vpd_params vpd; struct pci_params pci; + unsigned int sf_size; /* serial flash size in bytes */ + unsigned int sf_nsec; /* # of flash sectors */ + unsigned int sf_fw_start; /* start of FW image in flash */ + unsigned int fw_vers; unsigned int tp_vers; u8 api_vers[7]; @@ -305,7 +309,6 @@ enum { /* adapter flags */ FULL_INIT_DONE = (1 << 0), USING_MSI = (1 << 1), USING_MSIX = (1 << 2), - QUEUES_BOUND = (1 << 3), FW_OK = (1 << 4), }; @@ -646,6 +649,7 @@ void t4_intr_disable(struct adapter *adapter); void t4_intr_clear(struct adapter *adapter); int t4_slow_intr_handler(struct adapter *adapter); +int t4_wait_dev_ready(struct adapter *adap); int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc); int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port); diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 58045b00cf40..27f65b501a0a 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -216,7 +216,7 @@ void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat) void t4_os_portmod_changed(const struct adapter *adap, int port_id) { static const char *mod_str[] = { - NULL, "LR", "SR", "ER", "passive DA", "active DA" + NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" }; const struct net_device *dev = adap->port[port_id]; @@ -224,7 +224,7 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) netdev_info(dev, "port module unplugged\n"); - else + else if (pi->mod_type < ARRAY_SIZE(mod_str)) netdev_info(dev, "%s module inserted\n", mod_str[pi->mod_type]); } @@ -1234,7 +1234,8 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps) { unsigned int v = 0; - if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XAUI) { + if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XFI || + type == FW_PORT_TYPE_BT_XAUI) { v |= SUPPORTED_TP; if (caps & FW_PORT_CAP_SPEED_100M) v |= SUPPORTED_100baseT_Full; @@ -1250,7 +1251,10 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps) v |= SUPPORTED_10000baseKX4_Full; } else if (type == FW_PORT_TYPE_KR) v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full; - else if (type == FW_PORT_TYPE_FIBER) + else if (type == FW_PORT_TYPE_BP_AP) + v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC; + else if (type == FW_PORT_TYPE_FIBER_XFI || + type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) v |= SUPPORTED_FIBRE; if (caps & FW_PORT_CAP_ANEG) @@ -1276,13 +1280,19 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) const struct port_info *p = netdev_priv(dev); if (p->port_type == FW_PORT_TYPE_BT_SGMII || + p->port_type == FW_PORT_TYPE_BT_XFI || p->port_type == FW_PORT_TYPE_BT_XAUI) cmd->port = PORT_TP; - else if (p->port_type == FW_PORT_TYPE_FIBER) + else if (p->port_type == FW_PORT_TYPE_FIBER_XFI || + p->port_type == FW_PORT_TYPE_FIBER_XAUI) cmd->port = PORT_FIBRE; - else if (p->port_type == FW_PORT_TYPE_TWINAX) - cmd->port = PORT_DA; - else + else if (p->port_type == FW_PORT_TYPE_SFP) { + if (p->mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE || + p->mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE) + cmd->port = PORT_DA; + else + cmd->port = PORT_FIBRE; + } else cmd->port = PORT_OTHER; if (p->mdio_addr >= 0) { @@ -2483,6 +2493,7 @@ static void cxgb_down(struct adapter *adapter) t4_intr_disable(adapter); cancel_work_sync(&adapter->tid_release_task); adapter->tid_release_task_busy = false; + adapter->tid_release_head = NULL; if (adapter->flags & USING_MSIX) { free_msix_queue_irqs(adapter); @@ -2511,9 +2522,10 @@ static int cxgb_open(struct net_device *dev) } dev->real_num_tx_queues = pi->nqsets; - link_start(dev); - netif_tx_start_all_queues(dev); - return 0; + err = link_start(dev); + if (!err) + netif_tx_start_all_queues(dev); + return err; } static int cxgb_close(struct net_device *dev) @@ -2526,12 +2538,12 @@ static int cxgb_close(struct net_device *dev) return t4_enable_vi(adapter, 0, pi->viid, false, false); } -static struct net_device_stats *cxgb_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev) { struct port_stats stats; struct port_info *p = netdev_priv(dev); struct adapter *adapter = p->adapter; - struct net_device_stats *ns = &dev->stats; + struct rtnl_link_stats64 *ns = &dev->stats64; spin_lock(&adapter->stats_lock); t4_get_port_stats(adapter, p->tx_chan, &stats); @@ -2674,7 +2686,7 @@ static const struct net_device_ops cxgb4_netdev_ops = { .ndo_open = cxgb_open, .ndo_stop = cxgb_close, .ndo_start_xmit = t4_eth_xmit, - .ndo_get_stats = cxgb_get_stats, + .ndo_get_stats64 = cxgb_get_stats, .ndo_set_rx_mode = cxgb_set_rxmode, .ndo_set_mac_address = cxgb_set_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -2709,6 +2721,65 @@ static void setup_memwin(struct adapter *adap) WINDOW(ilog2(MEMWIN2_APERTURE) - 10)); } +static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) +{ + u32 v; + int ret; + + /* get device capabilities */ + memset(c, 0, sizeof(*c)); + c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST | FW_CMD_READ); + c->retval_len16 = htonl(FW_LEN16(*c)); + ret = t4_wr_mbox(adap, 0, c, sizeof(*c), c); + if (ret < 0) + return ret; + + /* select capabilities we'll be using */ + if (c->niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { + if (!vf_acls) + c->niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); + else + c->niccaps = htons(FW_CAPS_CONFIG_NIC_VM); + } else if (vf_acls) { + dev_err(adap->pdev_dev, "virtualization ACLs not supported"); + return ret; + } + c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST | FW_CMD_WRITE); + ret = t4_wr_mbox(adap, 0, c, sizeof(*c), NULL); + if (ret < 0) + return ret; + + ret = t4_config_glbl_rss(adap, 0, + FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL, + FW_RSS_GLB_CONFIG_CMD_TNLMAPEN | + FW_RSS_GLB_CONFIG_CMD_TNLALLLKP); + if (ret < 0) + return ret; + + ret = t4_cfg_pfvf(adap, 0, 0, 0, MAX_EGRQ, 64, MAX_INGQ, 0, 0, 4, + 0xf, 0xf, 16, FW_CMD_CAP_PF, FW_CMD_CAP_PF); + if (ret < 0) + return ret; + + t4_sge_init(adap); + + /* get basic stuff going */ + ret = t4_early_init(adap, 0); + if (ret < 0) + return ret; + + /* tweak some settings */ + t4_write_reg(adap, TP_SHIFT_CNT, 0x64f8849); + t4_write_reg(adap, ULP_RX_TDDP_PSZ, HPZ0(PAGE_SHIFT - 12)); + t4_write_reg(adap, TP_PIO_ADDR, TP_INGRESS_CONFIG); + v = t4_read_reg(adap, TP_PIO_DATA); + t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); + setup_memwin(adap); + return 0; +} + /* * Max # of ATIDs. The absolute HW max is 16K but we keep it lower. */ @@ -2746,43 +2817,6 @@ static int adap_init0(struct adapter *adap) if (ret < 0) goto bye; - /* get device capabilities */ - memset(&c, 0, sizeof(c)); - c.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); - c.retval_len16 = htonl(FW_LEN16(c)); - ret = t4_wr_mbox(adap, 0, &c, sizeof(c), &c); - if (ret < 0) - goto bye; - - /* select capabilities we'll be using */ - if (c.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { - if (!vf_acls) - c.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); - else - c.niccaps = htons(FW_CAPS_CONFIG_NIC_VM); - } else if (vf_acls) { - dev_err(adap->pdev_dev, "virtualization ACLs not supported"); - goto bye; - } - c.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); - ret = t4_wr_mbox(adap, 0, &c, sizeof(c), NULL); - if (ret < 0) - goto bye; - - ret = t4_config_glbl_rss(adap, 0, - FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL, - FW_RSS_GLB_CONFIG_CMD_TNLMAPEN | - FW_RSS_GLB_CONFIG_CMD_TNLALLLKP); - if (ret < 0) - goto bye; - - ret = t4_cfg_pfvf(adap, 0, 0, 0, 64, 64, 64, 0, 0, 4, 0xf, 0xf, 16, - FW_CMD_CAP_PF, FW_CMD_CAP_PF); - if (ret < 0) - goto bye; - for (v = 0; v < SGE_NTIMERS - 1; v++) adap->sge.timer_val[v] = min(intr_holdoff[v], MAX_SGE_TIMERVAL); adap->sge.timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL; @@ -2790,16 +2824,19 @@ static int adap_init0(struct adapter *adap) for (v = 1; v < SGE_NCOUNTERS; v++) adap->sge.counter_val[v] = min(intr_cnt[v - 1], THRESHOLD_3_MASK); - t4_sge_init(adap); +#define FW_PARAM_DEV(param) \ + (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ + FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) - /* get basic stuff going */ - ret = t4_early_init(adap, 0); + params[0] = FW_PARAM_DEV(CCLK); + ret = t4_query_params(adap, 0, 0, 0, 1, params, val); if (ret < 0) goto bye; + adap->params.vpd.cclk = val[0]; -#define FW_PARAM_DEV(param) \ - (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) + ret = adap_init1(adap, &c); + if (ret < 0) + goto bye; #define FW_PARAM_PFVF(param) \ (FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ @@ -2853,6 +2890,18 @@ static int adap_init0(struct adapter *adap) adap->vres.rq.size = val[3] - val[2] + 1; adap->vres.pbl.start = val[4]; adap->vres.pbl.size = val[5] - val[4] + 1; + + params[0] = FW_PARAM_PFVF(SQRQ_START); + params[1] = FW_PARAM_PFVF(SQRQ_END); + params[2] = FW_PARAM_PFVF(CQ_START); + params[3] = FW_PARAM_PFVF(CQ_END); + ret = t4_query_params(adap, 0, 0, 0, 4, params, val); + if (ret < 0) + goto bye; + adap->vres.qp.start = val[0]; + adap->vres.qp.size = val[1] - val[0] + 1; + adap->vres.cq.start = val[2]; + adap->vres.cq.size = val[3] - val[2] + 1; } if (c.iscsicaps) { params[0] = FW_PARAM_PFVF(ISCSI_START); @@ -2876,14 +2925,6 @@ static int adap_init0(struct adapter *adap) t4_read_mtu_tbl(adap, adap->params.mtus, NULL); t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, adap->params.b_wnd); - - /* tweak some settings */ - t4_write_reg(adap, TP_SHIFT_CNT, 0x64f8849); - t4_write_reg(adap, ULP_RX_TDDP_PSZ, HPZ0(PAGE_SHIFT - 12)); - t4_write_reg(adap, TP_PIO_ADDR, TP_INGRESS_CONFIG); - v = t4_read_reg(adap, TP_PIO_DATA); - t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); - setup_memwin(adap); return 0; /* @@ -2896,6 +2937,108 @@ bye: if (ret != -ETIMEDOUT && ret != -EIO) return ret; } +/* EEH callbacks */ + +static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + int i; + struct adapter *adap = pci_get_drvdata(pdev); + + if (!adap) + goto out; + + rtnl_lock(); + adap->flags &= ~FW_OK; + notify_ulds(adap, CXGB4_STATE_START_RECOVERY); + for_each_port(adap, i) { + struct net_device *dev = adap->port[i]; + + netif_device_detach(dev); + netif_carrier_off(dev); + } + if (adap->flags & FULL_INIT_DONE) + cxgb_down(adap); + rtnl_unlock(); + pci_disable_device(pdev); +out: return state == pci_channel_io_perm_failure ? + PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev) +{ + int i, ret; + struct fw_caps_config_cmd c; + struct adapter *adap = pci_get_drvdata(pdev); + + if (!adap) { + pci_restore_state(pdev); + pci_save_state(pdev); + return PCI_ERS_RESULT_RECOVERED; + } + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, "cannot reenable PCI device after reset\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + pci_cleanup_aer_uncorrect_error_status(pdev); + + if (t4_wait_dev_ready(adap) < 0) + return PCI_ERS_RESULT_DISCONNECT; + if (t4_fw_hello(adap, 0, 0, MASTER_MUST, NULL)) + return PCI_ERS_RESULT_DISCONNECT; + adap->flags |= FW_OK; + if (adap_init1(adap, &c)) + return PCI_ERS_RESULT_DISCONNECT; + + for_each_port(adap, i) { + struct port_info *p = adap2pinfo(adap, i); + + ret = t4_alloc_vi(adap, 0, p->tx_chan, 0, 0, 1, NULL, NULL); + if (ret < 0) + return PCI_ERS_RESULT_DISCONNECT; + p->viid = ret; + p->xact_addr_filt = -1; + } + + t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, + adap->params.b_wnd); + if (cxgb_up(adap)) + return PCI_ERS_RESULT_DISCONNECT; + return PCI_ERS_RESULT_RECOVERED; +} + +static void eeh_resume(struct pci_dev *pdev) +{ + int i; + struct adapter *adap = pci_get_drvdata(pdev); + + if (!adap) + return; + + rtnl_lock(); + for_each_port(adap, i) { + struct net_device *dev = adap->port[i]; + + if (netif_running(dev)) { + link_start(dev); + cxgb_set_rxmode(dev); + } + netif_device_attach(dev); + } + rtnl_unlock(); +} + +static struct pci_error_handlers cxgb4_eeh = { + .error_detected = eeh_err_detected, + .slot_reset = eeh_slot_reset, + .resume = eeh_resume, +}; + static inline bool is_10g_port(const struct link_config *lc) { return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0; @@ -3079,7 +3222,8 @@ static int __devinit enable_msix(struct adapter *adap) static void __devinit print_port_info(struct adapter *adap) { static const char *base[] = { - "R", "KX4", "T", "KX", "T", "KR", "CX4" + "R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4", + "KX", "KR", "KR SFP+", "KR FEC" }; int i; @@ -3143,8 +3287,10 @@ static int __devinit init_one(struct pci_dev *pdev, /* We control everything through PF 0 */ func = PCI_FUNC(pdev->devfn); - if (func > 0) + if (func > 0) { + pci_save_state(pdev); /* to restore SR-IOV later */ goto sriov; + } err = pci_enable_device(pdev); if (err) { @@ -3385,6 +3531,7 @@ static struct pci_driver cxgb4_driver = { .id_table = cxgb4_pci_tbl, .probe = init_one, .remove = __devexit_p(remove_one), + .err_handler = &cxgb4_eeh, }; static int __init cxgb4_init_module(void) diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h index 5b98546ac92d..0dc0866df1bf 100644 --- a/drivers/net/cxgb4/cxgb4_uld.h +++ b/drivers/net/cxgb4/cxgb4_uld.h @@ -185,6 +185,8 @@ struct cxgb4_virt_res { /* virtualized HW resources */ struct cxgb4_range stag; struct cxgb4_range rq; struct cxgb4_range pbl; + struct cxgb4_range qp; + struct cxgb4_range cq; }; /* diff --git a/drivers/net/cxgb4/l2t.c b/drivers/net/cxgb4/l2t.c index 9f96724a133a..5b990d24cca9 100644 --- a/drivers/net/cxgb4/l2t.c +++ b/drivers/net/cxgb4/l2t.c @@ -310,6 +310,13 @@ static void t4_l2e_free(struct l2t_entry *e) neigh_release(e->neigh); e->neigh = NULL; } + while (e->arpq_head) { + struct sk_buff *skb = e->arpq_head; + + e->arpq_head = skb->next; + kfree(skb); + } + e->arpq_tail = NULL; } spin_unlock_bh(&e->lock); diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c index da272a98fdbc..d92129b6c140 100644 --- a/drivers/net/cxgb4/t4_hw.c +++ b/drivers/net/cxgb4/t4_hw.c @@ -221,6 +221,13 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, if ((size & 15) || size > MBOX_LEN) return -EINVAL; + /* + * If the device is off-line, as in EEH, commands will time out. + * Fail them early so we don't waste time waiting. + */ + if (adap->pdev->error_state != pci_channel_io_normal) + return -EIO; + v = MBOWNER_GET(t4_read_reg(adap, ctl_reg)); for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++) v = MBOWNER_GET(t4_read_reg(adap, ctl_reg)); @@ -449,12 +456,10 @@ enum { SF_RD_STATUS = 5, /* read status register */ SF_WR_ENABLE = 6, /* enable writes */ SF_RD_DATA_FAST = 0xb, /* read flash */ + SF_RD_ID = 0x9f, /* read ID */ SF_ERASE_SECTOR = 0xd8, /* erase sector */ - FW_START_SEC = 8, /* first flash sector for FW */ - FW_END_SEC = 15, /* last flash sector for FW */ - FW_IMG_START = FW_START_SEC * SF_SEC_SIZE, - FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE, + FW_MAX_SIZE = 512 * 1024, }; /** @@ -558,7 +563,7 @@ static int t4_read_flash(struct adapter *adapter, unsigned int addr, { int ret; - if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) + if (addr + nwords * sizeof(u32) > adapter->params.sf_size || (addr & 3)) return -EINVAL; addr = swab32(addr) | SF_RD_DATA_FAST; @@ -596,7 +601,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, u32 buf[64]; unsigned int i, c, left, val, offset = addr & 0xff; - if (addr >= SF_SIZE || offset + n > SF_PAGE_SIZE) + if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE) return -EINVAL; val = swab32(addr) | SF_PROG_PAGE; @@ -614,7 +619,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, if (ret) goto unlock; } - ret = flash_wait_op(adapter, 5, 1); + ret = flash_wait_op(adapter, 8, 1); if (ret) goto unlock; @@ -647,9 +652,8 @@ unlock: */ static int get_fw_version(struct adapter *adapter, u32 *vers) { - return t4_read_flash(adapter, - FW_IMG_START + offsetof(struct fw_hdr, fw_ver), 1, - vers, 0); + return t4_read_flash(adapter, adapter->params.sf_fw_start + + offsetof(struct fw_hdr, fw_ver), 1, vers, 0); } /** @@ -661,8 +665,8 @@ static int get_fw_version(struct adapter *adapter, u32 *vers) */ static int get_tp_version(struct adapter *adapter, u32 *vers) { - return t4_read_flash(adapter, FW_IMG_START + offsetof(struct fw_hdr, - tp_microcode_ver), + return t4_read_flash(adapter, adapter->params.sf_fw_start + + offsetof(struct fw_hdr, tp_microcode_ver), 1, vers, 0); } @@ -684,9 +688,9 @@ int t4_check_fw_version(struct adapter *adapter) if (!ret) ret = get_tp_version(adapter, &adapter->params.tp_vers); if (!ret) - ret = t4_read_flash(adapter, - FW_IMG_START + offsetof(struct fw_hdr, intfver_nic), - 2, api_vers, 1); + ret = t4_read_flash(adapter, adapter->params.sf_fw_start + + offsetof(struct fw_hdr, intfver_nic), + 2, api_vers, 1); if (ret) return ret; @@ -726,7 +730,7 @@ static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end) if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 || (ret = sf1_write(adapter, 4, 0, 1, SF_ERASE_SECTOR | (start << 8))) != 0 || - (ret = flash_wait_op(adapter, 5, 500)) != 0) { + (ret = flash_wait_op(adapter, 14, 500)) != 0) { dev_err(adapter->pdev_dev, "erase of flash sector %d failed, error %d\n", start, ret); @@ -754,6 +758,9 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) u8 first_page[SF_PAGE_SIZE]; const u32 *p = (const u32 *)fw_data; const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data; + unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec; + unsigned int fw_img_start = adap->params.sf_fw_start; + unsigned int fw_start_sec = fw_img_start / sf_sec_size; if (!size) { dev_err(adap->pdev_dev, "FW image has no data\n"); @@ -784,8 +791,8 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) return -EINVAL; } - i = DIV_ROUND_UP(size, SF_SEC_SIZE); /* # of sectors spanned */ - ret = t4_flash_erase_sectors(adap, FW_START_SEC, FW_START_SEC + i - 1); + i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */ + ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1); if (ret) goto out; @@ -796,11 +803,11 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) */ memcpy(first_page, fw_data, SF_PAGE_SIZE); ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff); - ret = t4_write_flash(adap, FW_IMG_START, SF_PAGE_SIZE, first_page); + ret = t4_write_flash(adap, fw_img_start, SF_PAGE_SIZE, first_page); if (ret) goto out; - addr = FW_IMG_START; + addr = fw_img_start; for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { addr += SF_PAGE_SIZE; fw_data += SF_PAGE_SIZE; @@ -810,7 +817,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) } ret = t4_write_flash(adap, - FW_IMG_START + offsetof(struct fw_hdr, fw_ver), + fw_img_start + offsetof(struct fw_hdr, fw_ver), sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); out: if (ret) @@ -1128,6 +1135,7 @@ static void cim_intr_handler(struct adapter *adapter) static void ulprx_intr_handler(struct adapter *adapter) { static struct intr_info ulprx_intr_info[] = { + { 0x1800000, "ULPRX context error", -1, 1 }, { 0x7fffff, "ULPRX parity error", -1, 1 }, { 0 } }; @@ -2572,7 +2580,7 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, } if (rss_size) *rss_size = FW_VI_CMD_RSSSIZE_GET(ntohs(c.rsssize_pkd)); - return ntohs(c.viid_pkd); + return FW_VI_CMD_VIID_GET(ntohs(c.type_viid)); } /** @@ -2595,7 +2603,7 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, FW_CMD_EXEC | FW_VI_CMD_PFN(pf) | FW_VI_CMD_VFN(vf)); c.alloc_to_len16 = htonl(FW_VI_CMD_FREE | FW_LEN16(c)); - c.viid_pkd = htons(FW_VI_CMD_VIID(viid)); + c.type_viid = htons(FW_VI_CMD_VIID(viid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); } @@ -3045,7 +3053,7 @@ static void __devinit init_link_config(struct link_config *lc, } } -static int __devinit wait_dev_ready(struct adapter *adap) +int t4_wait_dev_ready(struct adapter *adap) { if (t4_read_reg(adap, PL_WHOAMI) != 0xffffffff) return 0; @@ -3053,6 +3061,33 @@ static int __devinit wait_dev_ready(struct adapter *adap) return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO; } +static int __devinit get_flash_params(struct adapter *adap) +{ + int ret; + u32 info; + + ret = sf1_write(adap, 1, 1, 0, SF_RD_ID); + if (!ret) + ret = sf1_read(adap, 3, 0, 1, &info); + t4_write_reg(adap, SF_OP, 0); /* unlock SF */ + if (ret) + return ret; + + if ((info & 0xff) != 0x20) /* not a Numonix flash */ + return -EINVAL; + info >>= 16; /* log2 of size */ + if (info >= 0x14 && info < 0x18) + adap->params.sf_nsec = 1 << (info - 16); + else if (info == 0x18) + adap->params.sf_nsec = 64; + else + return -EINVAL; + adap->params.sf_size = 1 << info; + adap->params.sf_fw_start = + t4_read_reg(adap, CIM_BOOT_CFG) & BOOTADDR_MASK; + return 0; +} + /** * t4_prep_adapter - prepare SW and HW for operation * @adapter: the adapter @@ -3066,13 +3101,19 @@ int __devinit t4_prep_adapter(struct adapter *adapter) { int ret; - ret = wait_dev_ready(adapter); + ret = t4_wait_dev_ready(adapter); if (ret < 0) return ret; get_pci_mode(adapter, &adapter->params.pci); adapter->params.rev = t4_read_reg(adapter, PL_REV); + ret = get_flash_params(adapter); + if (ret < 0) { + dev_err(adapter->pdev_dev, "error %d identifying flash\n", ret); + return ret; + } + ret = get_vpd_params(adapter, &adapter->params.vpd); if (ret < 0) return ret; @@ -3122,12 +3163,13 @@ int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf) p->rss_size = rss_size; memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN); memcpy(adap->port[i]->perm_addr, addr, ETH_ALEN); + adap->port[i]->dev_id = j; ret = ntohl(c.u.info.lstatus_to_modtype); p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP) ? FW_PORT_CMD_MDIOADDR_GET(ret) : -1; p->port_type = FW_PORT_CMD_PTYPE_GET(ret); - p->mod_type = FW_PORT_CMD_MODTYPE_GET(ret); + p->mod_type = FW_PORT_MOD_TYPE_NA; init_link_config(&p->link_cfg, ntohs(c.u.info.pcap)); j++; diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h index 025623285c93..f886677b93ec 100644 --- a/drivers/net/cxgb4/t4_hw.h +++ b/drivers/net/cxgb4/t4_hw.h @@ -57,8 +57,6 @@ enum { enum { SF_PAGE_SIZE = 256, /* serial flash page size */ - SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ - SF_SIZE = SF_SEC_SIZE * 16, /* serial flash size */ }; enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */ diff --git a/drivers/net/cxgb4/t4_regs.h b/drivers/net/cxgb4/t4_regs.h index 5ed56483cbc2..8fed46df886c 100644 --- a/drivers/net/cxgb4/t4_regs.h +++ b/drivers/net/cxgb4/t4_regs.h @@ -326,6 +326,9 @@ #define EDC_1_BASE_ADDR 0x7980 +#define CIM_BOOT_CFG 0x7b00 +#define BOOTADDR_MASK 0xffffff00U + #define CIM_PF_MAILBOX_DATA 0x240 #define CIM_PF_MAILBOX_CTRL 0x280 #define MBMSGVALID 0x00000008U diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/cxgb4/t4fw_api.h index 63991d68950e..111c2a5763e4 100644 --- a/drivers/net/cxgb4/t4fw_api.h +++ b/drivers/net/cxgb4/t4fw_api.h @@ -475,7 +475,13 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_PBL_END = 0x12, FW_PARAMS_PARAM_PFVF_L2T_START = 0x13, FW_PARAMS_PARAM_PFVF_L2T_END = 0x14, + FW_PARAMS_PARAM_PFVF_SQRQ_START = 0x15, + FW_PARAMS_PARAM_PFVF_SQRQ_END = 0x16, + FW_PARAMS_PARAM_PFVF_CQ_START = 0x17, + FW_PARAMS_PARAM_PFVF_CQ_END = 0x18, FW_PARAMS_PARAM_PFVF_SCHEDCLASS_ETH = 0x20, + FW_PARAMS_PARAM_PFVF_VIID = 0x24, + FW_PARAMS_PARAM_PFVF_CPMASK = 0x25, }; /* @@ -804,16 +810,16 @@ struct fw_eq_ofld_cmd { struct fw_vi_cmd { __be32 op_to_vfn; __be32 alloc_to_len16; - __be16 viid_pkd; + __be16 type_viid; u8 mac[6]; u8 portid_pkd; u8 nmac; u8 nmac0[6]; __be16 rsssize_pkd; u8 nmac1[6]; - __be16 r7; + __be16 idsiiq_pkd; u8 nmac2[6]; - __be16 r8; + __be16 idseiq_pkd; u8 nmac3[6]; __be64 r9; __be64 r10; @@ -824,6 +830,7 @@ struct fw_vi_cmd { #define FW_VI_CMD_ALLOC (1U << 31) #define FW_VI_CMD_FREE (1U << 30) #define FW_VI_CMD_VIID(x) ((x) << 0) +#define FW_VI_CMD_VIID_GET(x) ((x) & 0xfff) #define FW_VI_CMD_PORTID(x) ((x) << 4) #define FW_VI_CMD_RSSSIZE_GET(x) (((x) >> 0) & 0x7ff) @@ -1136,6 +1143,11 @@ struct fw_port_cmd { __be32 lstatus_to_modtype; __be16 pcap; __be16 acap; + __be16 mtu; + __u8 cbllen; + __u8 r9; + __be32 r10; + __be64 r11; } info; struct fw_port_ppp { __be32 pppen_to_ncsich; @@ -1196,14 +1208,17 @@ struct fw_port_cmd { #define FW_PORT_CMD_NCSICH(x) ((x) << 4) enum fw_port_type { - FW_PORT_TYPE_FIBER, - FW_PORT_TYPE_KX4, + FW_PORT_TYPE_FIBER_XFI, + FW_PORT_TYPE_FIBER_XAUI, FW_PORT_TYPE_BT_SGMII, - FW_PORT_TYPE_KX, + FW_PORT_TYPE_BT_XFI, FW_PORT_TYPE_BT_XAUI, - FW_PORT_TYPE_KR, + FW_PORT_TYPE_KX4, FW_PORT_TYPE_CX4, - FW_PORT_TYPE_TWINAX, + FW_PORT_TYPE_KX, + FW_PORT_TYPE_KR, + FW_PORT_TYPE_SFP, + FW_PORT_TYPE_BP_AP, FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK }; @@ -1213,6 +1228,9 @@ enum fw_port_module_type { FW_PORT_MOD_TYPE_LR, FW_PORT_MOD_TYPE_SR, FW_PORT_MOD_TYPE_ER, + FW_PORT_MOD_TYPE_TWINAX_PASSIVE, + FW_PORT_MOD_TYPE_TWINAX_ACTIVE, + FW_PORT_MOD_TYPE_LRM, FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK }; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index abcc838e18af..4fd6b2b4554b 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -961,7 +961,7 @@ struct dm9000_rxhdr { u8 RxPktReady; u8 RxStatus; __le16 RxLen; -} __attribute__((__packed__)); +} __packed; /* * Received a packet and pass to upper layer diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index f654db9121de..a4a0d2b6eb1c 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 4dc02c71ffd6..307a72f483ee 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -359,6 +359,7 @@ #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 #define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 +#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 @@ -714,6 +715,7 @@ #define BME1000_E_PHY_ID_R2 0x01410CB1 #define I82577_E_PHY_ID 0x01540050 #define I82578_E_PHY_ID 0x004DD040 +#define I82579_E_PHY_ID 0x01540090 /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index c0b3db40bd73..9ee133f5034e 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -164,6 +164,7 @@ enum e1000_boards { board_ich9lan, board_ich10lan, board_pchlan, + board_pch2lan, }; struct e1000_queue_stats { @@ -421,6 +422,8 @@ struct e1000_info { #define FLAG2_HAS_PHY_WAKEUP (1 << 1) #define FLAG2_IS_DISCARDING (1 << 2) #define FLAG2_DISABLE_ASPM_L1 (1 << 3) +#define FLAG2_HAS_PHY_STATS (1 << 4) +#define FLAG2_HAS_EEE (1 << 5) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) @@ -458,7 +461,6 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); extern void e1000e_update_stats(struct e1000_adapter *adapter); -extern bool e1000e_has_link(struct e1000_adapter *adapter); extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); @@ -476,6 +478,7 @@ extern struct e1000_info e1000_ich8_info; extern struct e1000_info e1000_ich9_info; extern struct e1000_info e1000_ich10_info; extern struct e1000_info e1000_pch_info; +extern struct e1000_info e1000_pch2_info; extern struct e1000_info e1000_es2_info; extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); @@ -494,6 +497,8 @@ extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); +extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); +extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index 38d79a669059..45aebb4a6fe1 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 2c521218102b..77c5829ab945 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -118,7 +118,6 @@ static int e1000_get_settings(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 status; if (hw->phy.media_type == e1000_media_type_copper) { @@ -156,22 +155,29 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; } - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - if (status & E1000_STATUS_SPEED_1000) - ecmd->speed = 1000; - else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = 100; - else - ecmd->speed = 10; + ecmd->speed = -1; + ecmd->duplex = -1; - if (status & E1000_STATUS_FD) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; + if (netif_running(netdev)) { + if (netif_carrier_ok(netdev)) { + ecmd->speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex - 1; + } } else { - ecmd->speed = -1; - ecmd->duplex = -1; + u32 status = er32(STATUS); + if (status & E1000_STATUS_LU) { + if (status & E1000_STATUS_SPEED_1000) + ecmd->speed = 1000; + else if (status & E1000_STATUS_SPEED_100) + ecmd->speed = 100; + else + ecmd->speed = 10; + + if (status & E1000_STATUS_FD) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } } ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || @@ -179,7 +185,7 @@ static int e1000_get_settings(struct net_device *netdev, /* MDI-X => 2; MDI =>1; Invalid =>0 */ if ((hw->phy.media_type == e1000_media_type_copper) && - !hw->mac.get_link_status) + netif_carrier_ok(netdev)) ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; else @@ -191,19 +197,15 @@ static int e1000_get_settings(struct net_device *netdev, static u32 e1000_get_link(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_hw *hw = &adapter->hw; /* - * If the link is not reported up to netdev, interrupts are disabled, - * and so the physical link state may have changed since we last - * looked. Set get_link_status to make sure that the true link - * state is interrogated, rather than pulling a cached and possibly - * stale link state from the driver. + * Avoid touching hardware registers when possible, otherwise + * link negotiation can get messed up when user-level scripts + * are rapidly polling the driver to see if link is up. */ - if (!netif_carrier_ok(netdev)) - mac->get_link_status = 1; - - return e1000e_has_link(adapter); + return netif_running(netdev) ? netif_carrier_ok(netdev) : + !!(er32(STATUS) & E1000_STATUS_LU); } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) @@ -880,6 +882,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) switch (mac->type) { case e1000_ich10lan: case e1000_pchlan: + case e1000_pch2lan: mask |= (1 << 18); break; default: @@ -1263,33 +1266,36 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) hw->mac.autoneg = 0; - /* Workaround: K1 must be disabled for stable 1Gbps operation */ - if (hw->mac.type == e1000_pchlan) - e1000_configure_k1_ich8lan(hw, false); - - if (hw->phy.type == e1000_phy_m88) { - /* Auto-MDI/MDIX Off */ - e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1e_wphy(hw, PHY_CONTROL, 0x9140); - /* autoneg off */ - e1e_wphy(hw, PHY_CONTROL, 0x8140); - } else if (hw->phy.type == e1000_phy_gg82563) - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); - - ctrl_reg = er32(CTRL); - - switch (hw->phy.type) { - case e1000_phy_ife: + if (hw->phy.type == e1000_phy_ife) { /* force 100, set loopback */ e1e_wphy(hw, PHY_CONTROL, 0x6100); /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ E1000_CTRL_SPD_100 |/* Force Speed to 100 */ E1000_CTRL_FD); /* Force Duplex to FULL */ + + ew32(CTRL, ctrl_reg); + udelay(500); + + return 0; + } + + /* Specific PHY configuration for loopback */ + switch (hw->phy.type) { + case e1000_phy_m88: + /* Auto-MDI/MDIX Off */ + e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); + /* reset to update Auto-MDI/MDIX */ + e1e_wphy(hw, PHY_CONTROL, 0x9140); + /* autoneg off */ + e1e_wphy(hw, PHY_CONTROL, 0x8140); + break; + case e1000_phy_gg82563: + e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); break; case e1000_phy_bm: /* Set Default MAC Interface speed to 1GB */ @@ -1312,23 +1318,41 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) /* Set Early Link Enable */ e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); - /* fall through */ + break; + case e1000_phy_82577: + case e1000_phy_82578: + /* Workaround: K1 must be disabled for stable 1Gbps operation */ + e1000_configure_k1_ich8lan(hw, false); + break; + case e1000_phy_82579: + /* Disable PHY energy detect power down */ + e1e_rphy(hw, PHY_REG(0, 21), &phy_reg); + e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3)); + /* Disable full chip energy detect */ + e1e_rphy(hw, PHY_REG(776, 18), &phy_reg); + e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); + /* Enable loopback on the PHY */ +#define I82577_PHY_LBK_CTRL 19 + e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); + break; default: - /* force 1000, set loopback */ - e1e_wphy(hw, PHY_CONTROL, 0x4140); - mdelay(250); + break; + } - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ + /* force 1000, set loopback */ + e1e_wphy(hw, PHY_CONTROL, 0x4140); + mdelay(250); - if (adapter->flags & FLAG_IS_ICH) - ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ - } + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); + ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ + ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + + if (adapter->flags & FLAG_IS_ICH) + ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ if (hw->phy.media_type == e1000_media_type_copper && hw->phy.type == e1000_phy_m88) { @@ -1868,6 +1892,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) if ((hw->phy.type == e1000_phy_ife) || (hw->mac.type == e1000_pchlan) || + (hw->mac.type == e1000_pch2lan) || (hw->mac.type == e1000_82583) || (hw->mac.type == e1000_82574)) { INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 5d1220d188d4..0cd569a57f6d 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -217,7 +217,10 @@ enum e1e_registers { E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ - E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ + E1000_FFLT_DBG = 0x05F04, /* Debug Register */ + E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */ +#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4)) +#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE E1000_HICR = 0x08F00, /* Host Interface Control */ }; @@ -303,13 +306,14 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 #define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 #define E1000_KMRNCTRLSTA_REN 0x00200000 +#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E -#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 +#define E1000_KMRNCTRLSTA_HD_CTRL 0x0002 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ @@ -387,6 +391,8 @@ enum e1e_registers { #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 +#define E1000_DEV_ID_PCH2_LV_LM 0x1502 +#define E1000_DEV_ID_PCH2_LV_V 0x1503 #define E1000_REVISION_4 4 @@ -406,6 +412,7 @@ enum e1000_mac_type { e1000_ich9lan, e1000_ich10lan, e1000_pchlan, + e1000_pch2lan, }; enum e1000_media_type { @@ -442,6 +449,7 @@ enum e1000_phy_type { e1000_phy_bm, e1000_phy_82578, e1000_phy_82577, + e1000_phy_82579, }; enum e1000_bus_width { @@ -929,6 +937,7 @@ struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; bool nvm_k1_enabled; + bool eee_disable; }; struct e1000_hw { diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index b2507d93de99..6b5e108bb51f 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -52,6 +52,8 @@ * 82577LC Gigabit Network Connection * 82578DM Gigabit Network Connection * 82578DC Gigabit Network Connection + * 82579LM Gigabit Network Connection + * 82579V Gigabit Network Connection */ #include "e1000.h" @@ -126,6 +128,13 @@ #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 +/* PHY Power Management Control */ +#define HV_PM_CTRL PHY_REG(770, 17) + +/* PHY Low Power Idle Control */ +#define I82579_LPI_CTRL PHY_REG(772, 20) +#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 + /* Strapping Option Register - RO */ #define E1000_STRAP 0x0000C #define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 @@ -226,6 +235,8 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); +static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); +static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -277,13 +288,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* + * The MAC-PHY interconnect may still be in SMBus mode + * after Sx->S0. If the manageability engine (ME) is + * disabled, then toggle the LANPHYPC Value bit to force + * the interconnect to PCIe mode. + */ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* - * The MAC-PHY interconnect may still be in SMBus mode - * after Sx->S0. Toggle the LANPHYPC Value bit to force - * the interconnect to PCIe mode, but only if there is no - * firmware present otherwise firmware will have done it. - */ ctrl = er32(CTRL); ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; @@ -324,6 +335,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) switch (phy->type) { case e1000_phy_82577: + case e1000_phy_82579: phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577; @@ -515,6 +527,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) case e1000_ich8lan: case e1000_ich9lan: case e1000_ich10lan: + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; /* ID LED init */ mac->ops.id_led_init = e1000e_id_led_init; /* setup LED */ @@ -526,6 +540,9 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) mac->ops.led_off = e1000_led_off_ich8lan; break; case e1000_pchlan: + case e1000_pch2lan: + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_pchlan; /* setup LED */ @@ -544,10 +561,47 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); + /* Disable PHY configuration by hardware, config by software */ + if (mac->type == e1000_pch2lan) { + u32 extcnf_ctrl = er32(EXTCNF_CTRL); + + extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; + ew32(EXTCNF_CTRL, extcnf_ctrl); + } + return 0; } /** + * e1000_set_eee_pchlan - Enable/disable EEE support + * @hw: pointer to the HW structure + * + * Enable/disable EEE based on setting in dev_spec structure. The bits in + * the LPI Control register will remain set only if/when link is up. + **/ +static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 phy_reg; + + if (hw->phy.type != e1000_phy_82579) + goto out; + + ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); + if (ret_val) + goto out; + + if (hw->dev_spec.ich8lan.eee_disable) + phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK; + else + phy_reg |= I82579_LPI_CTRL_ENABLE_MASK; + + ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); +out: + return ret_val; +} + +/** * e1000_check_for_copper_link_ich8lan - Check for link (Copper) * @hw: pointer to the HW structure * @@ -604,6 +658,11 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ e1000e_check_downshift(hw); + /* Enable/Disable EEE after link up */ + ret_val = e1000_set_eee_pchlan(hw); + if (ret_val) + goto out; + /* * If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. @@ -647,10 +706,19 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) if (rc) return rc; - if (hw->mac.type == e1000_pchlan) - rc = e1000_init_phy_params_pchlan(hw); - else + switch (hw->mac.type) { + case e1000_ich8lan: + case e1000_ich9lan: + case e1000_ich10lan: rc = e1000_init_phy_params_ich8lan(hw); + break; + case e1000_pchlan: + case e1000_pch2lan: + rc = e1000_init_phy_params_pchlan(hw); + break; + default: + break; + } if (rc) return rc; @@ -774,7 +842,7 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) * e1000_check_mng_mode_ich8lan - Checks management mode * @hw: pointer to the HW structure * - * This checks if the adapter has manageability enabled. + * This checks if the adapter has any manageability enabled. * This is a function pointer entry point only called by read/write * routines for the PHY and NVM parts. **/ @@ -783,9 +851,26 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) u32 fwsm; fwsm = er32(FWSM); + return (fwsm & E1000_ICH_FWSM_FW_VALID) && + ((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); +} + +/** + * e1000_check_mng_mode_pchlan - Checks management mode + * @hw: pointer to the HW structure + * + * This checks if the adapter has iAMT enabled. + * This is a function pointer entry point only called by read/write + * routines for the PHY and NVM parts. + **/ +static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) +{ + u32 fwsm; - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); + fwsm = er32(FWSM); + return (fwsm & E1000_ICH_FWSM_FW_VALID) && + (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); } /** @@ -820,14 +905,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) s32 ret_val = 0; u16 word_addr, reg_data, reg_addr, phy_page = 0; - if (!(hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) && - !(hw->mac.type == e1000_pchlan)) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - /* * Initialize the PHY from the NVM on ICH platforms. This * is needed due to an issue where the NVM configuration is @@ -835,12 +912,27 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) * Therefore, after each PHY reset, we will load the * configuration data out of the NVM manually. */ - if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || - (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) || - (hw->mac.type == e1000_pchlan)) + switch (hw->mac.type) { + case e1000_ich8lan: + if (phy->type != e1000_phy_igp_3) + return ret_val; + + if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) { + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + break; + } + /* Fall-thru */ + case e1000_pchlan: + case e1000_pch2lan: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - else - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + break; + default: + return ret_val; + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; data = er32(FEXTNVM); if (!(data & sw_cfg_mask)) @@ -851,8 +943,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) * extended configuration before SW configuration */ data = er32(EXTCNF_CTRL); - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - goto out; + if (!(hw->mac.type == e1000_pch2lan)) { + if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) + goto out; + } cnf_size = er32(EXTCNF_SIZE); cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; @@ -864,7 +958,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - (hw->mac.type == e1000_pchlan)) { + ((hw->mac.type == e1000_pchlan) || + (hw->mac.type == e1000_pch2lan))) { /* * HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. @@ -1071,16 +1166,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) u32 mac_reg; u16 oem_reg; - if (hw->mac.type != e1000_pchlan) + if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan)) return ret_val; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; - mac_reg = er32(EXTCNF_CTRL); - if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto out; + if (!(hw->mac.type == e1000_pch2lan)) { + mac_reg = er32(EXTCNF_CTRL); + if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) + goto out; + } mac_reg = er32(FEXTNVM); if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) @@ -1221,6 +1318,243 @@ out: } /** + * e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY + * @hw: pointer to the HW structure + **/ +void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) +{ + u32 mac_reg; + u16 i; + + /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ + for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { + mac_reg = er32(RAL(i)); + e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); + e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); + mac_reg = er32(RAH(i)); + e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); + e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000)); + } +} + +static u32 e1000_calc_rx_da_crc(u8 mac[]) +{ + u32 poly = 0xEDB88320; /* Polynomial for 802.3 CRC calculation */ + u32 i, j, mask, crc; + + crc = 0xffffffff; + for (i = 0; i < 6; i++) { + crc = crc ^ mac[i]; + for (j = 8; j > 0; j--) { + mask = (crc & 1) * (-1); + crc = (crc >> 1) ^ (poly & mask); + } + } + return ~crc; +} + +/** + * e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation + * with 82579 PHY + * @hw: pointer to the HW structure + * @enable: flag to enable/disable workaround when enabling/disabling jumbos + **/ +s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) +{ + s32 ret_val = 0; + u16 phy_reg, data; + u32 mac_reg; + u16 i; + + if (hw->mac.type != e1000_pch2lan) + goto out; + + /* disable Rx path while enabling/disabling workaround */ + e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); + ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); + if (ret_val) + goto out; + + if (enable) { + /* + * Write Rx addresses (rar_entry_count for RAL/H, +4 for + * SHRAL/H) and initial CRC values to the MAC + */ + for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { + u8 mac_addr[ETH_ALEN] = {0}; + u32 addr_high, addr_low; + + addr_high = er32(RAH(i)); + if (!(addr_high & E1000_RAH_AV)) + continue; + addr_low = er32(RAL(i)); + mac_addr[0] = (addr_low & 0xFF); + mac_addr[1] = ((addr_low >> 8) & 0xFF); + mac_addr[2] = ((addr_low >> 16) & 0xFF); + mac_addr[3] = ((addr_low >> 24) & 0xFF); + mac_addr[4] = (addr_high & 0xFF); + mac_addr[5] = ((addr_high >> 8) & 0xFF); + + ew32(PCH_RAICC(i), + e1000_calc_rx_da_crc(mac_addr)); + } + + /* Write Rx addresses to the PHY */ + e1000_copy_rx_addrs_to_phy_ich8lan(hw); + + /* Enable jumbo frame workaround in the MAC */ + mac_reg = er32(FFLT_DBG); + mac_reg &= ~(1 << 14); + mac_reg |= (7 << 15); + ew32(FFLT_DBG, mac_reg); + + mac_reg = er32(RCTL); + mac_reg |= E1000_RCTL_SECRC; + ew32(RCTL, mac_reg); + + ret_val = e1000e_read_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + &data); + if (ret_val) + goto out; + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + data | (1 << 0)); + if (ret_val) + goto out; + ret_val = e1000e_read_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + &data); + if (ret_val) + goto out; + data &= ~(0xF << 8); + data |= (0xB << 8); + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + data); + if (ret_val) + goto out; + + /* Enable jumbo frame workaround in the PHY */ + e1e_rphy(hw, PHY_REG(769, 20), &data); + ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(769, 23), &data); + data &= ~(0x7F << 5); + data |= (0x37 << 5); + ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(769, 16), &data); + data &= ~(1 << 13); + data |= (1 << 12); + ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(776, 20), &data); + data &= ~(0x3FF << 2); + data |= (0x1A << 2); + ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); + if (ret_val) + goto out; + ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00); + if (ret_val) + goto out; + e1e_rphy(hw, HV_PM_CTRL, &data); + ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10)); + if (ret_val) + goto out; + } else { + /* Write MAC register values back to h/w defaults */ + mac_reg = er32(FFLT_DBG); + mac_reg &= ~(0xF << 14); + ew32(FFLT_DBG, mac_reg); + + mac_reg = er32(RCTL); + mac_reg &= ~E1000_RCTL_SECRC; + ew32(FFLT_DBG, mac_reg); + + ret_val = e1000e_read_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + &data); + if (ret_val) + goto out; + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + data & ~(1 << 0)); + if (ret_val) + goto out; + ret_val = e1000e_read_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + &data); + if (ret_val) + goto out; + data &= ~(0xF << 8); + data |= (0xB << 8); + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + data); + if (ret_val) + goto out; + + /* Write PHY register values back to h/w defaults */ + e1e_rphy(hw, PHY_REG(769, 20), &data); + ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(769, 23), &data); + data &= ~(0x7F << 5); + ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(769, 16), &data); + data &= ~(1 << 12); + data |= (1 << 13); + ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); + if (ret_val) + goto out; + e1e_rphy(hw, PHY_REG(776, 20), &data); + data &= ~(0x3FF << 2); + data |= (0x8 << 2); + ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); + if (ret_val) + goto out; + ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00); + if (ret_val) + goto out; + e1e_rphy(hw, HV_PM_CTRL, &data); + ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10)); + if (ret_val) + goto out; + } + + /* re-enable Rx path after enabling/disabling workaround */ + ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); + +out: + return ret_val; +} + +/** + * e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be + * done after every PHY reset. + **/ +static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = 0; + + if (hw->mac.type != e1000_pch2lan) + goto out; + + /* Set MDIO slow mode before any other MDIO access */ + ret_val = e1000_set_mdio_slow_mode_hv(hw); + +out: + return ret_val; +} + +/** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure * @@ -1271,12 +1605,17 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) if (ret_val) goto out; break; + case e1000_pch2lan: + ret_val = e1000_lv_phy_workarounds_ich8lan(hw); + if (ret_val) + goto out; + break; default: break; } /* Dummy read to clear the phy wakeup bit after lcd reset */ - if (hw->mac.type == e1000_pchlan) + if (hw->mac.type >= e1000_pchlan) e1e_rphy(hw, BM_WUC, ®); /* Configure the LCD with the extended configuration region in NVM */ @@ -2800,6 +3139,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) ew32(FCTTV, hw->fc.pause_time); if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_82577)) { ew32(FCRTV_PCH, hw->fc.refresh_time); @@ -2863,6 +3203,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) return ret_val; break; case e1000_phy_82577: + case e1000_phy_82579: ret_val = e1000_copper_link_setup_82577(hw); if (ret_val) return ret_val; @@ -3116,21 +3457,12 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - case e1000_pchlan: - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_GBE_DISABLE; - ew32(PHY_CTRL, phy_ctrl); + phy_ctrl = er32(PHY_CTRL); + phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; + ew32(PHY_CTRL, phy_ctrl); - if (hw->mac.type == e1000_pchlan) - e1000_phy_hw_reset_ich8lan(hw); - default: - break; - } + if (hw->mac.type >= e1000_pchlan) + e1000_phy_hw_reset_ich8lan(hw); } /** @@ -3370,6 +3702,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) /* Clear PHY statistics registers */ if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_82577)) { hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data); hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data); @@ -3390,7 +3723,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) static struct e1000_mac_operations ich8_mac_ops = { .id_led_init = e1000e_id_led_init, - .check_mng_mode = e1000_check_mng_mode_ich8lan, + /* check_mng_mode dependent on mac type */ .check_for_link = e1000_check_for_copper_link_ich8lan, /* cleanup_led dependent on mac type */ .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, @@ -3497,6 +3830,7 @@ struct e1000_info e1000_pch_info = { | FLAG_HAS_JUMBO_FRAMES | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ | FLAG_APME_IN_WUC, + .flags2 = FLAG2_HAS_PHY_STATS, .pba = 26, .max_hw_frame_size = 4096, .get_variants = e1000_get_variants_ich8lan, @@ -3504,3 +3838,23 @@ struct e1000_info e1000_pch_info = { .phy_ops = &ich8_phy_ops, .nvm_ops = &ich8_nvm_ops, }; + +struct e1000_info e1000_pch2_info = { + .mac = e1000_pch2lan, + .flags = FLAG_IS_ICH + | FLAG_HAS_WOL + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_FLASH + | FLAG_HAS_JUMBO_FRAMES + | FLAG_APME_IN_WUC, + .flags2 = FLAG2_HAS_PHY_STATS + | FLAG2_HAS_EEE, + .pba = 18, + .max_hw_frame_size = DEFAULT_JUMBO, + .get_variants = e1000_get_variants_ich8lan, + .mac_ops = &ich8_mac_ops, + .phy_ops = &ich8_phy_ops, + .nvm_ops = &ich8_nvm_ops, +}; diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index a968e3a416ac..df4a27922931 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 57a7e41da69e..71592ed2e686 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -52,7 +52,9 @@ #include "e1000.h" -#define DRV_VERSION "1.0.2-k4" +#define DRV_EXTRAVERSION "-k2" + +#define DRV_VERSION "1.2.7" DRV_EXTRAVERSION char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; @@ -67,6 +69,7 @@ static const struct e1000_info *e1000_info_tbl[] = { [board_ich9lan] = &e1000_ich9_info, [board_ich10lan] = &e1000_ich10_info, [board_pchlan] = &e1000_pch_info, + [board_pch2lan] = &e1000_pch2_info, }; struct e1000_reg_info { @@ -2723,6 +2726,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) e1e_wphy(hw, 22, phy_data); } + /* Workaround Si errata on 82579 - configure jumbo frame flow */ + if (hw->mac.type == e1000_pch2lan) { + s32 ret_val; + + if (rctl & E1000_RCTL_LPE) + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); + else + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); + } + /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -2759,7 +2772,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) * per packet. */ pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if (!(adapter->flags & FLAG_IS_ICH) && (pages <= 3) && + if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) adapter->rx_ps_pages = pages; else @@ -3118,7 +3131,27 @@ void e1000e_reset(struct e1000_adapter *adapter) * with ERT support assuming ERT set to E1000_ERT_2048), or * - the full Rx FIFO size minus one full frame */ - if (hw->mac.type == e1000_pchlan) { + if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) + fc->pause_time = 0xFFFF; + else + fc->pause_time = E1000_FC_PAUSE_TIME; + fc->send_xon = 1; + fc->current_mode = fc->requested_mode; + + switch (hw->mac.type) { + default: + if ((adapter->flags & FLAG_HAS_ERT) && + (adapter->netdev->mtu > ETH_DATA_LEN)) + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - (E1000_ERT_2048 << 3))); + else + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - adapter->max_frame_size)); + + fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ + fc->low_water = fc->high_water - 8; + break; + case e1000_pchlan: /* * Workaround PCH LOM adapter hangs with certain network * loads. If hangs persist, try disabling Tx flow control. @@ -3131,26 +3164,15 @@ void e1000e_reset(struct e1000_adapter *adapter) fc->low_water = 0x3000; } fc->refresh_time = 0x1000; - } else { - if ((adapter->flags & FLAG_HAS_ERT) && - (adapter->netdev->mtu > ETH_DATA_LEN)) - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - (E1000_ERT_2048 << 3))); - else - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - adapter->max_frame_size)); - - fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; + break; + case e1000_pch2lan: + fc->high_water = 0x05C20; + fc->low_water = 0x05048; + fc->pause_time = 0x0650; + fc->refresh_time = 0x0400; + break; } - if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) - fc->pause_time = 0xFFFF; - else - fc->pause_time = E1000_FC_PAUSE_TIME; - fc->send_xon = 1; - fc->current_mode = fc->requested_mode; - /* Allow time for pending master requests to run */ mac->ops.reset_hw(hw); @@ -3162,8 +3184,6 @@ void e1000e_reset(struct e1000_adapter *adapter) e1000_get_hw_control(adapter); ew32(WUC, 0); - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) - e1e_wphy(&adapter->hw, BM_WUC, 0); if (mac->ops.init_hw(hw)) e_err("Hardware Error\n"); @@ -3672,6 +3692,110 @@ static void e1000_update_phy_info(unsigned long data) } /** + * e1000e_update_phy_stats - Update the PHY statistics counters + * @adapter: board private structure + **/ +static void e1000e_update_phy_stats(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + s32 ret_val; + u16 phy_data; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; + + hw->phy.addr = 1; + +#define HV_PHY_STATS_PAGE 778 + /* + * A page set is expensive so check if already on desired page. + * If not, set to the page with the PHY status registers. + */ + ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + &phy_data); + if (ret_val) + goto release; + if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) { + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (HV_PHY_STATS_PAGE << + IGP_PAGE_SHIFT)); + if (ret_val) + goto release; + } + + /* Read/clear the upper 16-bit registers and read/accumulate lower */ + + /* Single Collision Count */ + e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_SCC_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.scc += phy_data; + + /* Excessive Collision Count */ + e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.ecol += phy_data; + + /* Multiple Collision Count */ + e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_MCC_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.mcc += phy_data; + + /* Late Collision Count */ + e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_LATECOL_LOWER & + MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.latecol += phy_data; + + /* Collision Count - also used for adaptive IFS */ + e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_COLC_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + hw->mac.collision_delta = phy_data; + + /* Defer Count */ + e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_DC_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.dc += phy_data; + + /* Transmit with no CRS */ + e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS, + &phy_data); + ret_val = e1000e_read_phy_reg_mdic(hw, + HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS, + &phy_data); + if (!ret_val) + adapter->stats.tncrs += phy_data; + +release: + hw->phy.ops.release(hw); +} + +/** * e1000e_update_stats - Update the board statistics counters * @adapter: board private structure **/ @@ -3680,7 +3804,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; - u16 phy_data; /* * Prevent stats update while adapter is being reset, or if the pci @@ -3700,34 +3823,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.roc += er32(ROC); adapter->stats.mpc += er32(MPC); - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82577)) { - e1e_rphy(hw, HV_SCC_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_SCC_LOWER, &phy_data)) - adapter->stats.scc += phy_data; - - e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_ECOL_LOWER, &phy_data)) - adapter->stats.ecol += phy_data; - - e1e_rphy(hw, HV_MCC_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_MCC_LOWER, &phy_data)) - adapter->stats.mcc += phy_data; - - e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data)) - adapter->stats.latecol += phy_data; - - e1e_rphy(hw, HV_DC_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_DC_LOWER, &phy_data)) - adapter->stats.dc += phy_data; - } else { - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); + + /* Half-duplex statistics */ + if (adapter->link_duplex == HALF_DUPLEX) { + if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { + e1000e_update_phy_stats(adapter); + } else { + adapter->stats.scc += er32(SCC); + adapter->stats.ecol += er32(ECOL); + adapter->stats.mcc += er32(MCC); + adapter->stats.latecol += er32(LATECOL); + adapter->stats.dc += er32(DC); + + hw->mac.collision_delta = er32(COLC); + + if ((hw->mac.type != e1000_82574) && + (hw->mac.type != e1000_82583)) + adapter->stats.tncrs += er32(TNCRS); + } + adapter->stats.colc += hw->mac.collision_delta; } + adapter->stats.xonrxc += er32(XONRXC); adapter->stats.xontxc += er32(XONTXC); adapter->stats.xoffrxc += er32(XOFFRXC); @@ -3745,28 +3861,9 @@ void e1000e_update_stats(struct e1000_adapter *adapter) hw->mac.tx_packet_delta = er32(TPT); adapter->stats.tpt += hw->mac.tx_packet_delta; - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82577)) { - e1e_rphy(hw, HV_COLC_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_COLC_LOWER, &phy_data)) - hw->mac.collision_delta = phy_data; - } else { - hw->mac.collision_delta = er32(COLC); - } - adapter->stats.colc += hw->mac.collision_delta; adapter->stats.algnerrc += er32(ALGNERRC); adapter->stats.rxerrc += er32(RXERRC); - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82577)) { - e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); - if (!e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data)) - adapter->stats.tncrs += phy_data; - } else { - if ((hw->mac.type != e1000_82574) && - (hw->mac.type != e1000_82583)) - adapter->stats.tncrs += er32(TNCRS); - } adapter->stats.cexterr += er32(CEXTERR); adapter->stats.tsctc += er32(TSCTC); adapter->stats.tsctfc += er32(TSCTFC); @@ -3865,7 +3962,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter) ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); } -bool e1000e_has_link(struct e1000_adapter *adapter) +static bool e1000e_has_link(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; bool link_active = 0; @@ -4841,14 +4938,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) int retval = 0; /* copy MAC RARs to PHY RARs */ - for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) { - mac_reg = er32(RAL(i)); - e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); - e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); - mac_reg = er32(RAH(i)); - e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); - e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF)); - } + e1000_copy_rx_addrs_to_phy_ich8lan(hw); /* copy MAC MTA to PHY MTA */ for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { @@ -5899,6 +5989,9 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan }, + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); @@ -5935,7 +6028,7 @@ static int __init e1000_init_module(void) int ret; pr_info("Intel(R) PRO/1000 Network Driver - %s\n", e1000e_driver_version); - pr_info("Copyright (c) 1999 - 2009 Intel Corporation.\n"); + pr_info("Copyright (c) 1999 - 2010 Intel Corporation.\n"); ret = pci_register_driver(&e1000_driver); return ret; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index a150e48a117f..593251c78c6f 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -161,6 +161,15 @@ E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lea E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ "the CRC"); +/* + * Enable/disable EEE (a.k.a. IEEE802.3az) + * + * Valid Range: 0, 1 + * + * Default Value: 1 + */ +E1000_PARAM(EEE, "Enable/disable on parts that support the feature"); + struct e1000_option { enum { enable_option, range_option, list_option } type; const char *name; @@ -477,4 +486,23 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } } + { /* EEE for parts supporting the feature */ + static const struct e1000_option opt = { + .type = enable_option, + .name = "EEE Support", + .err = "defaulting to Enabled", + .def = OPTION_ENABLED + }; + + if (adapter->flags2 & FLAG2_HAS_EEE) { + /* Currently only supported on 82579 */ + if (num_EEE > bd) { + unsigned int eee = EEE[bd]; + e1000_validate_option(&eee, &opt, adapter); + hw->dev_spec.ich8lan.eee_disable = !eee; + } else { + hw->dev_spec.ich8lan.eee_disable = !opt.def; + } + } + } } diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index b4ac82d51b20..3d3dc0c82355 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -2319,6 +2319,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) case I82577_E_PHY_ID: phy_type = e1000_phy_82577; break; + case I82579_E_PHY_ID: + phy_type = e1000_phy_82579; + break; default: phy_type = e1000_phy_unknown; break; diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 882c50c9c34f..f608a6c54af5 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -126,7 +126,7 @@ struct ehea_swqe { u8 immediate_data[SWQE2_MAX_IMM]; /* 0xd0 */ struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES-1]; - } immdata_desc __attribute__ ((packed)); + } immdata_desc __packed; /* Send WQE Format 3 */ struct { diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c index d769772998c6..0a35085004d0 100644 --- a/drivers/net/enic/vnic_vic.c +++ b/drivers/net/enic/vnic_vic.c @@ -25,9 +25,10 @@ struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type) { - struct vic_provinfo *vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags); + struct vic_provinfo *vp; - if (!vp || !oui) + vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags); + if (!vp) return NULL; memcpy(vp->oui, oui, sizeof(vp->oui)); diff --git a/drivers/net/enic/vnic_vic.h b/drivers/net/enic/vnic_vic.h index 085c2a274cb1..7e46e5e8600f 100644 --- a/drivers/net/enic/vnic_vic.h +++ b/drivers/net/enic/vnic_vic.h @@ -44,7 +44,7 @@ struct vic_provinfo { u16 length; u8 value[0]; } tlv[0]; -} __attribute__ ((packed)); +} __packed; #define VIC_PROVINFO_MAX_DATA 1385 #define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \ diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 6ed2df14ec84..37ce8aca2cc6 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -180,6 +180,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); * @dty_tx: last buffer actually sent * @num_rx: number of receive buffers * @cur_rx: current receive buffer + * @vma: pointer to array of virtual memory addresses for buffers * @netdev: pointer to network device structure * @napi: NAPI structure * @stats: network device statistics @@ -203,6 +204,8 @@ struct ethoc { unsigned int num_rx; unsigned int cur_rx; + void** vma; + struct net_device *netdev; struct napi_struct napi; struct net_device_stats stats; @@ -285,18 +288,22 @@ static inline void ethoc_disable_rx_and_tx(struct ethoc *dev) ethoc_write(dev, MODER, mode); } -static int ethoc_init_ring(struct ethoc *dev) +static int ethoc_init_ring(struct ethoc *dev, void* mem_start) { struct ethoc_bd bd; int i; + void* vma; dev->cur_tx = 0; dev->dty_tx = 0; dev->cur_rx = 0; + ethoc_write(dev, TX_BD_NUM, dev->num_tx); + /* setup transmission buffers */ - bd.addr = virt_to_phys(dev->membase); + bd.addr = mem_start; bd.stat = TX_BD_IRQ | TX_BD_CRC; + vma = dev->membase; for (i = 0; i < dev->num_tx; i++) { if (i == dev->num_tx - 1) @@ -304,6 +311,9 @@ static int ethoc_init_ring(struct ethoc *dev) ethoc_write_bd(dev, i, &bd); bd.addr += ETHOC_BUFSIZ; + + dev->vma[i] = vma; + vma += ETHOC_BUFSIZ; } bd.stat = RX_BD_EMPTY | RX_BD_IRQ; @@ -314,6 +324,9 @@ static int ethoc_init_ring(struct ethoc *dev) ethoc_write_bd(dev, dev->num_tx + i, &bd); bd.addr += ETHOC_BUFSIZ; + + dev->vma[dev->num_tx + i] = vma; + vma += ETHOC_BUFSIZ; } return 0; @@ -415,7 +428,7 @@ static int ethoc_rx(struct net_device *dev, int limit) skb = netdev_alloc_skb_ip_align(dev, size); if (likely(skb)) { - void *src = phys_to_virt(bd.addr); + void *src = priv->vma[entry]; memcpy_fromio(skb_put(skb, size), src, size); skb->protocol = eth_type_trans(skb, dev); priv->stats.rx_packets++; @@ -600,8 +613,11 @@ static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) while (time_before(jiffies, timeout)) { u32 stat = ethoc_read(priv, MIISTATUS); - if (!(stat & MIISTATUS_BUSY)) + if (!(stat & MIISTATUS_BUSY)) { + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); return 0; + } schedule(); } @@ -622,21 +638,12 @@ static int ethoc_mdio_probe(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); struct phy_device *phy; - int i; + int err; - for (i = 0; i < PHY_MAX_ADDR; i++) { - phy = priv->mdio->phy_map[i]; - if (phy) { - if (priv->phy_id != -1) { - /* attach to specified PHY */ - if (priv->phy_id == phy->addr) - break; - } else { - /* autoselect PHY if none was specified */ - if (phy->addr != 0) - break; - } - } + if (priv->phy_id != -1) { + phy = priv->mdio->phy_map[priv->phy_id]; + } else { + phy = phy_find_first(priv->mdio); } if (!phy) { @@ -644,11 +651,11 @@ static int ethoc_mdio_probe(struct net_device *dev) return -ENXIO; } - phy = phy_connect(dev, dev_name(&phy->dev), ethoc_mdio_poll, 0, + err = phy_connect_direct(dev, phy, ethoc_mdio_poll, 0, PHY_INTERFACE_MODE_GMII); - if (IS_ERR(phy)) { + if (err) { dev_err(&dev->dev, "could not attach to PHY\n"); - return PTR_ERR(phy); + return err; } priv->phy = phy; @@ -658,8 +665,6 @@ static int ethoc_mdio_probe(struct net_device *dev) static int ethoc_open(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); - unsigned int min_tx = 2; - unsigned int num_bd; int ret; ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED, @@ -667,14 +672,7 @@ static int ethoc_open(struct net_device *dev) if (ret) return ret; - /* calculate the number of TX/RX buffers, maximum 128 supported */ - num_bd = min_t(unsigned int, - 128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ); - priv->num_tx = max(min_tx, num_bd / 4); - priv->num_rx = num_bd - priv->num_tx; - ethoc_write(priv, TX_BD_NUM, priv->num_tx); - - ethoc_init_ring(priv); + ethoc_init_ring(priv, (void*)dev->mem_start); ethoc_reset(priv); if (netif_queue_stopped(dev)) { @@ -838,7 +836,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) else bd.stat &= ~TX_BD_PAD; - dest = phys_to_virt(bd.addr); + dest = priv->vma[entry]; memcpy_toio(dest, skb->data, skb->len); bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK); @@ -884,6 +882,7 @@ static int ethoc_probe(struct platform_device *pdev) struct resource *mem = NULL; struct ethoc *priv = NULL; unsigned int phy; + int num_bd; int ret = 0; /* allocate networking device */ @@ -965,7 +964,7 @@ static int ethoc_probe(struct platform_device *pdev) } } else { /* Allocate buffer memory */ - priv->membase = dma_alloc_coherent(NULL, + priv->membase = dmam_alloc_coherent(&pdev->dev, buffer_size, (void *)&netdev->mem_start, GFP_KERNEL); if (!priv->membase) { @@ -978,6 +977,18 @@ static int ethoc_probe(struct platform_device *pdev) priv->dma_alloc = buffer_size; } + /* calculate the number of TX/RX buffers, maximum 128 supported */ + num_bd = min_t(unsigned int, + 128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); + priv->num_tx = max(2, num_bd / 4); + priv->num_rx = num_bd - priv->num_tx; + + priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void*), GFP_KERNEL); + if (!priv->vma) { + ret = -ENOMEM; + goto error; + } + /* Allow the platform setup code to pass in a MAC address. */ if (pdev->dev.platform_data) { struct ethoc_platform_data *pdata = @@ -1063,21 +1074,6 @@ free_mdio: kfree(priv->mdio->irq); mdiobus_free(priv->mdio); free: - if (priv) { - if (priv->dma_alloc) - dma_free_coherent(NULL, priv->dma_alloc, priv->membase, - netdev->mem_start); - else if (priv->membase) - devm_iounmap(&pdev->dev, priv->membase); - if (priv->iobase) - devm_iounmap(&pdev->dev, priv->iobase); - } - if (mem) - devm_release_mem_region(&pdev->dev, mem->start, - mem->end - mem->start + 1); - if (mmio) - devm_release_mem_region(&pdev->dev, mmio->start, - mmio->end - mmio->start + 1); free_netdev(netdev); out: return ret; @@ -1104,17 +1100,6 @@ static int ethoc_remove(struct platform_device *pdev) kfree(priv->mdio->irq); mdiobus_free(priv->mdio); } - if (priv->dma_alloc) - dma_free_coherent(NULL, priv->dma_alloc, priv->membase, - netdev->mem_start); - else { - devm_iounmap(&pdev->dev, priv->membase); - devm_release_mem_region(&pdev->dev, netdev->mem_start, - netdev->mem_end - netdev->mem_start + 1); - } - devm_iounmap(&pdev->dev, priv->iobase); - devm_release_mem_region(&pdev->dev, netdev->base_addr, - priv->io_region_size); unregister_netdev(netdev); free_netdev(netdev); } diff --git a/drivers/net/fec.c b/drivers/net/fec.c index edfff92a6d8e..a3cae4ed6ac9 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -210,7 +210,7 @@ static void fec_stop(struct net_device *dev); /* Transmitter timeout */ #define TX_TIMEOUT (2 * HZ) -static int +static netdev_tx_t fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); @@ -679,30 +679,24 @@ static int fec_enet_mii_probe(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); struct phy_device *phy_dev = NULL; - int phy_addr; + int ret; fep->phy_dev = NULL; /* find the first phy */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (fep->mii_bus->phy_map[phy_addr]) { - phy_dev = fep->mii_bus->phy_map[phy_addr]; - break; - } - } - + phy_dev = phy_find_first(fep->mii_bus); if (!phy_dev) { printk(KERN_ERR "%s: no PHY found\n", dev->name); return -ENODEV; } /* attach the mac to the phy */ - phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), + ret = phy_connect_direct(dev, phy_dev, &fec_enet_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(phy_dev)) { + if (ret) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phy_dev); + return ret; } /* mask with MAC supported features */ @@ -1365,6 +1359,8 @@ fec_drv_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM + static int fec_suspend(struct platform_device *dev, pm_message_t state) { @@ -1395,15 +1391,31 @@ fec_resume(struct platform_device *dev) return 0; } +static const struct dev_pm_ops fec_pm_ops = { + .suspend = fec_suspend, + .resume = fec_resume, + .freeze = fec_suspend, + .thaw = fec_resume, + .poweroff = fec_suspend, + .restore = fec_resume, +}; + +#define FEC_PM_OPS (&fec_pm_ops) + +#else /* !CONFIG_PM */ + +#define FEC_PM_OPS NULL + +#endif /* !CONFIG_PM */ + static struct platform_driver fec_driver = { .driver = { .name = "fec", .owner = THIS_MODULE, + .pm = FEC_PM_OPS, }, .probe = fec_probe, .remove = __devexit_p(fec_drv_remove), - .suspend = fec_suspend, - .resume = fec_resume, }; static int __init diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index 006f64d9f96a..dbaf72cbb233 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -29,15 +29,14 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, int reg, u32 value) { struct mpc52xx_fec_mdio_priv *priv = bus->priv; - struct mpc52xx_fec __iomem *fec; + struct mpc52xx_fec __iomem *fec = priv->regs; int tries = 3; value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; - fec = priv->regs; out_be32(&fec->ievent, FEC_IEVENT_MII); - out_be32(&priv->regs->mii_data, value); + out_be32(&fec->mii_data, value); /* wait for it to finish, this takes about 23 us on lite5200b */ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) @@ -47,7 +46,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, return -ETIMEDOUT; return value & FEC_MII_DATA_OP_RD ? - in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0; + in_be32(&fec->mii_data) & FEC_MII_DATA_DATAMSK : 0; } static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) @@ -69,9 +68,8 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, struct device_node *np = of->dev.of_node; struct mii_bus *bus; struct mpc52xx_fec_mdio_priv *priv; - struct resource res = {}; + struct resource res; int err; - int i; bus = mdiobus_alloc(); if (bus == NULL) @@ -93,7 +91,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, err = of_address_to_resource(np, 0, &res); if (err) goto out_free; - priv->regs = ioremap(res.start, res.end - res.start + 1); + priv->regs = ioremap(res.start, resource_size(&res)); if (priv->regs == NULL) { err = -ENOMEM; goto out_free; @@ -118,10 +116,6 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, out_unmap: iounmap(priv->regs); out_free: - for (i=0; i<PHY_MAX_ADDR; i++) - if (bus->irq[i] != PHY_POLL) - irq_dispose_mapping(bus->irq[i]); - kfree(bus->irq); kfree(priv); mdiobus_free(bus); @@ -133,23 +127,16 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of) struct device *dev = &of->dev; struct mii_bus *bus = dev_get_drvdata(dev); struct mpc52xx_fec_mdio_priv *priv = bus->priv; - int i; mdiobus_unregister(bus); dev_set_drvdata(dev, NULL); - iounmap(priv->regs); - for (i=0; i<PHY_MAX_ADDR; i++) - if (bus->irq[i] != PHY_POLL) - irq_dispose_mapping(bus->irq[i]); kfree(priv); - kfree(bus->irq); mdiobus_free(bus); return 0; } - static struct of_device_id mpc52xx_fec_mdio_match[] = { { .compatible = "fsl,mpc5200b-mdio", }, { .compatible = "fsl,mpc5200-mdio", }, @@ -171,5 +158,4 @@ struct of_platform_driver mpc52xx_fec_mdio_driver = { /* let fec driver call it, since this has to be registered before it */ EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver); - MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/fsl_pq_mdio.h b/drivers/net/fsl_pq_mdio.h index 1f7d865cedb6..bd17a2a0139b 100644 --- a/drivers/net/fsl_pq_mdio.h +++ b/drivers/net/fsl_pq_mdio.h @@ -39,7 +39,7 @@ struct fsl_pq_mdio { u8 reserved[28]; /* Space holder */ u32 utbipar; /* TBI phy address reg (only on UCC) */ u8 res4[2728]; -} __attribute__ ((packed)); +} __packed; int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum); int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 28b53d1cd4f1..c52f3712ecd3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -685,8 +685,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) priv->rx_queue[i] = NULL; for (i = 0; i < priv->num_tx_queues; i++) { - priv->tx_queue[i] = (struct gfar_priv_tx_q *)kzalloc( - sizeof (struct gfar_priv_tx_q), GFP_KERNEL); + priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q), + GFP_KERNEL); if (!priv->tx_queue[i]) { err = -ENOMEM; goto tx_alloc_failed; @@ -698,8 +698,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) } for (i = 0; i < priv->num_rx_queues; i++) { - priv->rx_queue[i] = (struct gfar_priv_rx_q *)kzalloc( - sizeof (struct gfar_priv_rx_q), GFP_KERNEL); + priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q), + GFP_KERNEL); if (!priv->rx_queue[i]) { err = -ENOMEM; goto rx_alloc_failed; diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 3a029d02c2b4..4d09eab3548e 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1555,7 +1555,6 @@ static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_dev } /* setup NAPI */ - memset(&greth->napi, 0, sizeof(greth->napi)); netif_napi_add(dev, &greth->napi, greth_poll, 64); return 0; diff --git a/drivers/net/irda/donauboe.h b/drivers/net/irda/donauboe.h index 0dbd1932b72f..36c3060411d2 100644 --- a/drivers/net/irda/donauboe.h +++ b/drivers/net/irda/donauboe.h @@ -273,7 +273,7 @@ struct OboeSlot __u8 control; /*Slot control/status see below */ __u32 address; /*Slot buffer address */ } -__attribute__ ((packed)); +__packed; #define OBOE_NTASKS OBOE_TXRING_OFFSET_IN_SLOTS diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index ac0443d52e50..58ddb5214916 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h @@ -125,7 +125,7 @@ struct irda_class_desc { __u8 bmAdditionalBOFs; __u8 bIrdaRateSniff; __u8 bMaxUnicastList; -} __attribute__ ((packed)); +} __packed; /* class specific interface request to get the IrDA-USB class descriptor * (6.2.5, USB-IrDA class spec 1.0) */ diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index b54d3b48045e..1046014dd6c2 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -154,7 +154,7 @@ struct ks959_speedparams { __le32 baudrate; /* baud rate, little endian */ __u8 flags; __u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; #define KS_DATA_5_BITS 0x00 #define KS_DATA_6_BITS 0x01 diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 8d713ebac15b..9cc142fcc712 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -117,7 +117,7 @@ struct ksdazzle_speedparams { __le32 baudrate; /* baud rate, little endian */ __u8 flags; __u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; #define KS_DATA_5_BITS 0x00 #define KS_DATA_6_BITS 0x01 diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 3050d1a0cccf..3f24a1f33022 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -544,9 +544,9 @@ struct ring_descr_hw { struct { u8 addr_res[3]; volatile u8 status; /* descriptor status */ - } __attribute__((packed)) rd_s; - } __attribute((packed)) rd_u; -} __attribute__ ((packed)); + } __packed rd_s; + } __packed rd_u; +} __packed; #define rd_addr rd_u.addr #define rd_status rd_u.rd_s.status diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ffae480587ae..9e15eb93860e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -44,11 +44,9 @@ #include <linux/dca.h> #endif -#define PFX "ixgbe: " -#define DPRINTK(nlevel, klevel, fmt, args...) \ - ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ - __func__ , ## args))) +/* common prefix used by pr_<> macros */ +#undef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* TX/RX descriptor defines */ #define IXGBE_DEFAULT_TXD 512 @@ -112,7 +110,6 @@ struct vf_data_storage { u16 vlans_enabled; bool clear_to_send; bool pf_set_mac; - int rar; u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; }; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index a4e2901f2f08..976fd9e146c6 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -707,9 +707,8 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, out: if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL)) - netif_info(adapter, hw, adapter->netdev, "Smartspeed has" - " downgraded the link speed from the maximum" - " advertised\n"); + e_info("Smartspeed has downgraded the link speed from " + "the maximum advertised\n"); return status; } diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 3080afb12bdf..d5d3aae8524b 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -105,12 +105,26 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS) -#ifdef DEBUG -extern char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw); +extern struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw); #define hw_dbg(hw, format, arg...) \ - printk(KERN_DEBUG "%s: " format, ixgbe_get_hw_dev_name(hw), ##arg) -#else -#define hw_dbg(hw, format, arg...) do {} while (0) -#endif + netdev_dbg(ixgbe_get_hw_dev(hw), format, ##arg) +#define e_err(format, arg...) \ + netdev_err(adapter->netdev, format, ## arg) +#define e_info(format, arg...) \ + netdev_info(adapter->netdev, format, ## arg) +#define e_warn(format, arg...) \ + netdev_warn(adapter->netdev, format, ## arg) +#define e_notice(format, arg...) \ + netdev_notice(adapter->netdev, format, ## arg) +#define e_crit(format, arg...) \ + netdev_crit(adapter->netdev, format, ## arg) +#define e_dev_info(format, arg...) \ + dev_info(&adapter->pdev->dev, format, ## arg) +#define e_dev_warn(format, arg...) \ + dev_warn(&adapter->pdev->dev, format, ## arg) +#define e_dev_err(format, arg...) \ + dev_err(&adapter->pdev->dev, format, ## arg) +#define e_dev_notice(format, arg...) \ + dev_notice(&adapter->pdev->dev, format, ## arg) #endif /* IXGBE_COMMON */ diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 71da325dfa80..657623589d53 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -121,7 +121,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) goto out; if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { - DPRINTK(DRV, ERR, "Enable failed, needs MSI-X\n"); + e_err("Enable failed, needs MSI-X\n"); err = 1; goto out; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 3a93a81872b8..873b45efca40 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -294,8 +294,7 @@ static int ixgbe_set_settings(struct net_device *netdev, hw->mac.autotry_restart = true; err = hw->mac.ops.setup_link(hw, advertised, true, true); if (err) { - DPRINTK(PROBE, INFO, - "setup link failed with code %d\n", err); + e_info("setup link failed with code %d\n", err); hw->mac.ops.setup_link(hw, old, true, true); } } else { @@ -1188,9 +1187,9 @@ static struct ixgbe_reg_test reg_test_82598[] = { writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ val = readl(adapter->hw.hw_addr + R); \ if (val != (_test[pat] & W & M)) { \ - DPRINTK(DRV, ERR, "pattern test reg %04X failed: got "\ - "0x%08X expected 0x%08X\n", \ - R, val, (_test[pat] & W & M)); \ + e_err("pattern test reg %04X failed: got " \ + "0x%08X expected 0x%08X\n", \ + R, val, (_test[pat] & W & M)); \ *data = R; \ writel(before, adapter->hw.hw_addr + R); \ return 1; \ @@ -1206,8 +1205,8 @@ static struct ixgbe_reg_test reg_test_82598[] = { writel((W & M), (adapter->hw.hw_addr + R)); \ val = readl(adapter->hw.hw_addr + R); \ if ((W & M) != (val & M)) { \ - DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ - "expected 0x%08X\n", R, (val & M), (W & M)); \ + e_err("set/check reg %04X test failed: got 0x%08X " \ + "expected 0x%08X\n", R, (val & M), (W & M)); \ *data = R; \ writel(before, (adapter->hw.hw_addr + R)); \ return 1; \ @@ -1240,8 +1239,8 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, toggle); after = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle; if (value != after) { - DPRINTK(DRV, ERR, "failed STATUS register test got: " - "0x%08X expected: 0x%08X\n", after, value); + e_err("failed STATUS register test got: 0x%08X expected: " + "0x%08X\n", after, value); *data = 1; return 1; } @@ -1341,8 +1340,8 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) *data = 1; return -1; } - DPRINTK(HW, INFO, "testing %s interrupt\n", - (shared_int ? "shared" : "unshared")); + e_info("testing %s interrupt\n", shared_int ? + "shared" : "unshared"); /* Disable all the interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); @@ -1847,7 +1846,7 @@ static void ixgbe_diag_test(struct net_device *netdev, if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ - DPRINTK(HW, INFO, "offline testing starting\n"); + e_info("offline testing starting\n"); /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ @@ -1880,17 +1879,17 @@ static void ixgbe_diag_test(struct net_device *netdev, else ixgbe_reset(adapter); - DPRINTK(HW, INFO, "register testing starting\n"); + e_info("register testing starting\n"); if (ixgbe_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; ixgbe_reset(adapter); - DPRINTK(HW, INFO, "eeprom testing starting\n"); + e_info("eeprom testing starting\n"); if (ixgbe_eeprom_test(adapter, &data[1])) eth_test->flags |= ETH_TEST_FL_FAILED; ixgbe_reset(adapter); - DPRINTK(HW, INFO, "interrupt testing starting\n"); + e_info("interrupt testing starting\n"); if (ixgbe_intr_test(adapter, &data[2])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1898,14 +1897,13 @@ static void ixgbe_diag_test(struct net_device *netdev, * loopback diagnostic. */ if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { - DPRINTK(HW, INFO, "Skip MAC loopback diagnostic in VT " - "mode\n"); + e_info("Skip MAC loopback diagnostic in VT mode\n"); data[3] = 0; goto skip_loopback; } ixgbe_reset(adapter); - DPRINTK(HW, INFO, "loopback testing starting\n"); + e_info("loopback testing starting\n"); if (ixgbe_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1916,7 +1914,7 @@ skip_loopback: if (if_running) dev_open(netdev); } else { - DPRINTK(HW, INFO, "online testing starting\n"); + e_info("online testing starting\n"); /* Online tests */ if (ixgbe_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -2134,8 +2132,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; if (netdev->features & NETIF_F_LRO) { netdev->features &= ~NETIF_F_LRO; - DPRINTK(PROBE, INFO, "rx-usecs set to 0, " - "disabling LRO/RSC\n"); + e_info("rx-usecs set to 0, disabling RSC\n"); } need_reset = true; } @@ -2232,7 +2229,7 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data) } else if (!adapter->rx_itr_setting) { netdev->features &= ~ETH_FLAG_LRO; if (data & ETH_FLAG_LRO) - DPRINTK(PROBE, INFO, "rx-usecs set to 0, " + e_info("rx-usecs set to 0, " "LRO/RSC cannot be enabled.\n"); } } diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index 45182ab41d6b..84e1194e0833 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -25,7 +25,6 @@ *******************************************************************************/ - #include "ixgbe.h" #ifdef CONFIG_IXGBE_DCB #include "ixgbe_dcb_82599.h" @@ -165,20 +164,20 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, adapter = netdev_priv(netdev); if (xid >= IXGBE_FCOE_DDP_MAX) { - DPRINTK(DRV, WARNING, "xid=0x%x out-of-range\n", xid); + e_warn("xid=0x%x out-of-range\n", xid); return 0; } fcoe = &adapter->fcoe; if (!fcoe->pool) { - DPRINTK(DRV, WARNING, "xid=0x%x no ddp pool for fcoe\n", xid); + e_warn("xid=0x%x no ddp pool for fcoe\n", xid); return 0; } ddp = &fcoe->ddp[xid]; if (ddp->sgl) { - DPRINTK(DRV, ERR, "xid 0x%x w/ non-null sgl=%p nents=%d\n", - xid, ddp->sgl, ddp->sgc); + e_err("xid 0x%x w/ non-null sgl=%p nents=%d\n", + xid, ddp->sgl, ddp->sgc); return 0; } ixgbe_fcoe_clear_ddp(ddp); @@ -186,14 +185,14 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, /* setup dma from scsi command sgl */ dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE); if (dmacount == 0) { - DPRINTK(DRV, ERR, "xid 0x%x DMA map error\n", xid); + e_err("xid 0x%x DMA map error\n", xid); return 0; } /* alloc the udl from our ddp pool */ ddp->udl = pci_pool_alloc(fcoe->pool, GFP_KERNEL, &ddp->udp); if (!ddp->udl) { - DPRINTK(DRV, ERR, "failed allocated ddp context\n"); + e_err("failed allocated ddp context\n"); goto out_noddp_unmap; } ddp->sgl = sgl; @@ -206,10 +205,9 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, while (len) { /* max number of buffers allowed in one DDP context */ if (j >= IXGBE_BUFFCNT_MAX) { - netif_err(adapter, drv, adapter->netdev, - "xid=%x:%d,%d,%d:addr=%llx " - "not enough descriptors\n", - xid, i, j, dmacount, (u64)addr); + e_err("xid=%x:%d,%d,%d:addr=%llx " + "not enough descriptors\n", + xid, i, j, dmacount, (u64)addr); goto out_noddp_free; } @@ -387,8 +385,8 @@ int ixgbe_fso(struct ixgbe_adapter *adapter, struct fc_frame_header *fh; if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) { - DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n", - skb_shinfo(skb)->gso_type); + e_err("Wrong gso type %d:expecting SKB_GSO_FCOE\n", + skb_shinfo(skb)->gso_type); return -EINVAL; } @@ -414,7 +412,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter, fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF; break; default: - DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof); + e_warn("unknown sof = 0x%x\n", sof); return -EINVAL; } @@ -441,7 +439,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter, fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A; break; default: - DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof); + e_warn("unknown eof = 0x%x\n", eof); return -EINVAL; } @@ -517,8 +515,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) adapter->pdev, IXGBE_FCPTR_MAX, IXGBE_FCPTR_ALIGN, PAGE_SIZE); if (!fcoe->pool) - DPRINTK(DRV, ERR, - "failed to allocated FCoE DDP pool\n"); + e_err("failed to allocated FCoE DDP pool\n"); spin_lock_init(&fcoe->lock); } @@ -614,7 +611,7 @@ int ixgbe_fcoe_enable(struct net_device *netdev) if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) goto out_enable; - DPRINTK(DRV, INFO, "Enabling FCoE offload features.\n"); + e_info("Enabling FCoE offload features.\n"); if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); @@ -660,7 +657,7 @@ int ixgbe_fcoe_disable(struct net_device *netdev) if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) goto out_disable; - DPRINTK(DRV, INFO, "Disabling FCoE offload features.\n"); + e_info("Disabling FCoE offload features.\n"); if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ce30c62a97f7..ebc4b04fdef2 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -696,19 +696,19 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, /* detected Tx unit hang */ union ixgbe_adv_tx_desc *tx_desc; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); - DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" - " Tx Queue <%d>\n" - " TDH, TDT <%x>, <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "tx_buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " jiffies <%lx>\n", - tx_ring->queue_index, - IXGBE_READ_REG(hw, tx_ring->head), - IXGBE_READ_REG(hw, tx_ring->tail), - tx_ring->next_to_use, eop, - tx_ring->tx_buffer_info[eop].time_stamp, jiffies); + e_err("Detected Tx Unit Hang\n" + " Tx Queue <%d>\n" + " TDH, TDT <%x>, <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "tx_buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " jiffies <%lx>\n", + tx_ring->queue_index, + IXGBE_READ_REG(hw, tx_ring->head), + IXGBE_READ_REG(hw, tx_ring->tail), + tx_ring->next_to_use, eop, + tx_ring->tx_buffer_info[eop].time_stamp, jiffies); return true; } @@ -812,9 +812,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, if (adapter->detect_tx_hung) { if (ixgbe_check_tx_hang(adapter, tx_ring, i)) { /* schedule immediate reset if we believe we hung */ - DPRINTK(PROBE, INFO, - "tx hang %d detected, resetting adapter\n", - adapter->tx_timeout_count + 1); + e_info("tx hang %d detected, resetting adapter\n", + adapter->tx_timeout_count + 1); ixgbe_tx_timeout(adapter->netdev); } } @@ -1653,10 +1652,10 @@ static void ixgbe_check_overtemp_task(struct work_struct *work) return; break; } - DPRINTK(DRV, ERR, "Network adapter has been stopped because it " - "has over heated. Restart the computer. If the problem " - "persists, power off the system and replace the " - "adapter\n"); + e_crit("Network adapter has been stopped because it " + "has over heated. Restart the computer. If the problem " + "persists, power off the system and replace the " + "adapter\n"); /* write to clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0); } @@ -1668,7 +1667,7 @@ static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) && (eicr & IXGBE_EICR_GPI_SDP1)) { - DPRINTK(PROBE, CRIT, "Fan has stopped, replace the adapter\n"); + e_crit("Fan has stopped, replace the adapter\n"); /* write to clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); } @@ -2154,9 +2153,8 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) handler, 0, adapter->name[vector], adapter->q_vector[vector]); if (err) { - DPRINTK(PROBE, ERR, - "request_irq failed for MSIX interrupt " - "Error: %d\n", err); + e_err("request_irq failed for MSIX interrupt: " + "Error: %d\n", err); goto free_queue_irqs; } } @@ -2165,8 +2163,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) err = request_irq(adapter->msix_entries[vector].vector, ixgbe_msix_lsc, 0, adapter->name[vector], netdev); if (err) { - DPRINTK(PROBE, ERR, - "request_irq for msix_lsc failed: %d\n", err); + e_err("request_irq for msix_lsc failed: %d\n", err); goto free_queue_irqs; } @@ -2352,7 +2349,7 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter) } if (err) - DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err); + e_err("request_irq failed, Error %d\n", err); return err; } @@ -2423,7 +2420,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) map_vector_to_rxq(adapter, 0, 0); map_vector_to_txq(adapter, 0, 0); - DPRINTK(HW, INFO, "Legacy interrupt IVAR setup done\n"); + e_info("Legacy interrupt IVAR setup done\n"); } /** @@ -2995,6 +2992,48 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) } /** + * ixgbe_write_uc_addr_list - write unicast addresses to RAR table + * @netdev: network interface device structure + * + * Writes unicast address list to the RAR table. + * Returns: -ENOMEM on failure/insufficient address space + * 0 on no addresses written + * X on writing X addresses to the RAR table + **/ +static int ixgbe_write_uc_addr_list(struct net_device *netdev) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + unsigned int vfn = adapter->num_vfs; + unsigned int rar_entries = hw->mac.num_rar_entries - (vfn + 1); + int count = 0; + + /* return ENOMEM indicating insufficient memory for addresses */ + if (netdev_uc_count(netdev) > rar_entries) + return -ENOMEM; + + if (!netdev_uc_empty(netdev) && rar_entries) { + struct netdev_hw_addr *ha; + /* return error if we do not support writing to RAR table */ + if (!hw->mac.ops.set_rar) + return -ENOMEM; + + netdev_for_each_uc_addr(ha, netdev) { + if (!rar_entries) + break; + hw->mac.ops.set_rar(hw, rar_entries--, ha->addr, + vfn, IXGBE_RAH_AV); + count++; + } + } + /* write the addresses in reverse order to avoid write combining */ + for (; rar_entries > 0 ; rar_entries--) + hw->mac.ops.clear_rar(hw, rar_entries); + + return count; +} + +/** * ixgbe_set_rx_mode - Unicast, Multicast and Promiscuous mode set * @netdev: network interface device structure * @@ -3007,38 +3046,58 @@ void ixgbe_set_rx_mode(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - u32 fctrl; + u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE; + int count; /* Check for Promiscuous and All Multicast modes */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + /* clear the bits we are changing the status of */ + fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); + if (netdev->flags & IFF_PROMISC) { hw->addr_ctrl.user_set_promisc = true; fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); + vmolr |= (IXGBE_VMOLR_ROPE | IXGBE_VMOLR_MPE); /* don't hardware filter vlans in promisc mode */ ixgbe_vlan_filter_disable(adapter); } else { if (netdev->flags & IFF_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; - fctrl &= ~IXGBE_FCTRL_UPE; - } else if (!hw->addr_ctrl.uc_set_promisc) { - fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); + vmolr |= IXGBE_VMOLR_MPE; + } else { + /* + * Write addresses to the MTA, if the attempt fails + * then we should just turn on promiscous mode so + * that we can at least receive multicast traffic + */ + hw->mac.ops.update_mc_addr_list(hw, netdev); + vmolr |= IXGBE_VMOLR_ROMPE; } ixgbe_vlan_filter_enable(adapter); hw->addr_ctrl.user_set_promisc = false; + /* + * Write addresses to available RAR registers, if there is not + * sufficient space to store all the addresses then enable + * unicast promiscous mode + */ + count = ixgbe_write_uc_addr_list(netdev); + if (count < 0) { + fctrl |= IXGBE_FCTRL_UPE; + vmolr |= IXGBE_VMOLR_ROPE; + } } - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); - - /* reprogram secondary unicast list */ - hw->mac.ops.update_uc_addr_list(hw, netdev); - - /* reprogram multicast list */ - hw->mac.ops.update_mc_addr_list(hw, netdev); - - if (adapter->num_vfs) + if (adapter->num_vfs) { ixgbe_restore_vf_multicasts(adapter); + vmolr |= IXGBE_READ_REG(hw, IXGBE_VMOLR(adapter->num_vfs)) & + ~(IXGBE_VMOLR_MPE | IXGBE_VMOLR_ROMPE | + IXGBE_VMOLR_ROPE); + IXGBE_WRITE_REG(hw, IXGBE_VMOLR(adapter->num_vfs), vmolr); + } + + IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) @@ -3257,8 +3316,8 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, msleep(1); } if (k >= IXGBE_MAX_RX_DESC_POLL) { - DPRINTK(DRV, ERR, "RXDCTL.ENABLE on Rx queue %d " - "not set within the polling period\n", rxr); + e_err("RXDCTL.ENABLE on Rx queue %d not set within " + "the polling period\n", rxr); } ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr], (adapter->rx_ring[rxr]->count - 1)); @@ -3387,8 +3446,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE)); if (!wait_loop) - DPRINTK(DRV, ERR, "Could not enable " - "Tx Queue %d\n", j); + e_err("Could not enable Tx Queue %d\n", j); } } @@ -3436,8 +3494,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) - DPRINTK(DRV, CRIT, - "Fan has stopped, replace the adapter\n"); + e_crit("Fan has stopped, replace the adapter\n"); } /* @@ -3466,7 +3523,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) } else { err = ixgbe_non_sfp_link_config(hw); if (err) - DPRINTK(PROBE, ERR, "link_config FAILED %d\n", err); + e_err("link_config FAILED %d\n", err); } for (i = 0; i < adapter->num_tx_queues; i++) @@ -3527,19 +3584,19 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) case IXGBE_ERR_SFP_NOT_PRESENT: break; case IXGBE_ERR_MASTER_REQUESTS_PENDING: - dev_err(&adapter->pdev->dev, "master disable timed out\n"); + e_dev_err("master disable timed out\n"); break; case IXGBE_ERR_EEPROM_VERSION: /* We are running on a pre-production device, log a warning */ - dev_warn(&adapter->pdev->dev, "This device is a pre-production " - "adapter/LOM. Please be aware there may be issues " - "associated with your hardware. If you are " - "experiencing problems please contact your Intel or " - "hardware representative who provided you with this " - "hardware.\n"); + e_dev_warn("This device is a pre-production adapter/LOM. " + "Please be aware there may be issuesassociated with " + "your hardware. If you are experiencing problems " + "please contact your Intel or hardware " + "representative who provided you with this " + "hardware.\n"); break; default: - dev_err(&adapter->pdev->dev, "Hardware Error: %d\n", err); + e_dev_err("Hardware Error: %d\n", err); } /* reprogram the RAR[0] in case user changed it. */ @@ -3920,12 +3977,12 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) adapter->num_tx_queues = 1; #ifdef CONFIG_IXGBE_DCB if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - DPRINTK(PROBE, INFO, "FCoE enabled with DCB\n"); + e_info("FCoE enabled with DCB\n"); ixgbe_set_dcb_queues(adapter); } #endif if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - DPRINTK(PROBE, INFO, "FCoE enabled with RSS\n"); + e_info("FCoE enabled with RSS\n"); if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) ixgbe_set_fdir_queues(adapter); @@ -4038,7 +4095,8 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, * This just means we'll go with either a single MSI * vector or fall back to legacy interrupts. */ - DPRINTK(HW, DEBUG, "Unable to allocate MSI-X interrupts\n"); + netif_printk(adapter, hw, KERN_DEBUG, adapter->netdev, + "Unable to allocate MSI-X interrupts\n"); adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; kfree(adapter->msix_entries); adapter->msix_entries = NULL; @@ -4435,8 +4493,9 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) if (!err) { adapter->flags |= IXGBE_FLAG_MSI_ENABLED; } else { - DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, " - "falling back to legacy. Error: %d\n", err); + netif_printk(adapter, hw, KERN_DEBUG, adapter->netdev, + "Unable to allocate MSI interrupt, " + "falling back to legacy. Error: %d\n", err); /* reset err */ err = 0; } @@ -4557,27 +4616,25 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) err = ixgbe_set_interrupt_capability(adapter); if (err) { - DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n"); + e_dev_err("Unable to setup interrupt capabilities\n"); goto err_set_interrupt; } err = ixgbe_alloc_q_vectors(adapter); if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory for queue " - "vectors\n"); + e_dev_err("Unable to allocate memory for queue vectors\n"); goto err_alloc_q_vectors; } err = ixgbe_alloc_queues(adapter); if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + e_dev_err("Unable to allocate memory for queues\n"); goto err_alloc_queues; } - DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, " - "Tx Queue count = %u\n", - (adapter->num_rx_queues > 1) ? "Enabled" : - "Disabled", adapter->num_rx_queues, adapter->num_tx_queues); + e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u\n", + (adapter->num_rx_queues > 1) ? "Enabled" : "Disabled", + adapter->num_rx_queues, adapter->num_tx_queues); set_bit(__IXGBE_DOWN, &adapter->state); @@ -4648,15 +4705,13 @@ static void ixgbe_sfp_task(struct work_struct *work) goto reschedule; ret = hw->phy.ops.reset(hw); if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize " - "because an unsupported SFP+ module type " - "was detected.\n" - "Reload the driver after installing a " - "supported module.\n"); + e_dev_err("failed to initialize because an unsupported " + "SFP+ module type was detected.\n"); + e_dev_err("Reload the driver after installing a " + "supported module.\n"); unregister_netdev(adapter->netdev); } else { - DPRINTK(PROBE, INFO, "detected SFP+: %d\n", - hw->phy.sfp_type); + e_info("detected SFP+: %d\n", hw->phy.sfp_type); } /* don't need this routine any more */ clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); @@ -4783,7 +4838,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* initialize eeprom parameters */ if (ixgbe_init_eeprom_params_generic(hw)) { - dev_err(&pdev->dev, "EEPROM initialization failed\n"); + e_dev_err("EEPROM initialization failed\n"); return -EIO; } @@ -4836,8 +4891,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, err: vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; - DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit " - "descriptor ring\n"); + e_err("Unable to allocate memory for the Tx descriptor ring\n"); return -ENOMEM; } @@ -4859,7 +4913,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]); if (!err) continue; - DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); + e_err("Allocation for Tx Queue %u failed\n", i); break; } @@ -4884,8 +4938,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, if (!rx_ring->rx_buffer_info) rx_ring->rx_buffer_info = vmalloc(size); if (!rx_ring->rx_buffer_info) { - DPRINTK(PROBE, ERR, - "vmalloc allocation failed for the rx desc ring\n"); + e_err("vmalloc allocation failed for the Rx desc ring\n"); goto alloc_failed; } memset(rx_ring->rx_buffer_info, 0, size); @@ -4898,8 +4951,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) { - DPRINTK(PROBE, ERR, - "Memory allocation failed for the rx desc ring\n"); + e_err("Memory allocation failed for the Rx desc ring\n"); vfree(rx_ring->rx_buffer_info); goto alloc_failed; } @@ -4932,7 +4984,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]); if (!err) continue; - DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); + e_err("Allocation for Rx Queue %u failed\n", i); break; } @@ -5031,8 +5083,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) return -EINVAL; - DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n", - netdev->mtu, new_mtu); + e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); /* must set new MTU before calling down or up */ netdev->mtu = new_mtu; @@ -5145,8 +5196,7 @@ static int ixgbe_resume(struct pci_dev *pdev) err = pci_enable_device_mem(pdev); if (err) { - printk(KERN_ERR "ixgbe: Cannot enable PCI device from " - "suspend\n"); + e_dev_err("Cannot enable PCI device from suspend\n"); return err; } pci_set_master(pdev); @@ -5155,8 +5205,7 @@ static int ixgbe_resume(struct pci_dev *pdev) err = ixgbe_init_interrupt_scheme(adapter); if (err) { - printk(KERN_ERR "ixgbe: Cannot initialize interrupts for " - "device\n"); + e_dev_err("Cannot initialize interrupts for device\n"); return err; } @@ -5516,10 +5565,10 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) err = hw->phy.ops.identify_sfp(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize because " - "an unsupported SFP+ module type was detected.\n" - "Reload the driver after installing a supported " - "module.\n"); + e_dev_err("failed to initialize because an unsupported SFP+ " + "module type was detected.\n"); + e_dev_err("Reload the driver after installing a supported " + "module.\n"); unregister_netdev(adapter->netdev); return; } @@ -5548,8 +5597,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work) set_bit(__IXGBE_FDIR_INIT_DONE, &(adapter->tx_ring[i]->reinit_state)); } else { - DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, " - "ignored adding FDIR ATR filters\n"); + e_err("failed to finish FDIR re-initialization, " + "ignored adding FDIR ATR filters\n"); } /* Done FDIR Re-initialization, enable transmits */ netif_tx_start_all_queues(adapter->netdev); @@ -5620,16 +5669,14 @@ static void ixgbe_watchdog_task(struct work_struct *work) flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X); } - printk(KERN_INFO "ixgbe: %s NIC Link is Up %s, " - "Flow Control: %s\n", - netdev->name, + e_info("NIC Link is Up %s, Flow Control: %s\n", (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? - "10 Gbps" : - (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? - "1 Gbps" : "unknown speed")), + "10 Gbps" : + (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? + "1 Gbps" : "unknown speed")), ((flow_rx && flow_tx) ? "RX/TX" : - (flow_rx ? "RX" : - (flow_tx ? "TX" : "None")))); + (flow_rx ? "RX" : + (flow_tx ? "TX" : "None")))); netif_carrier_on(netdev); } else { @@ -5640,8 +5687,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) adapter->link_up = false; adapter->link_speed = 0; if (netif_carrier_ok(netdev)) { - printk(KERN_INFO "ixgbe: %s NIC Link is Down\n", - netdev->name); + e_info("NIC Link is Down\n"); netif_carrier_off(netdev); } } @@ -5817,9 +5863,8 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, break; default: if (unlikely(net_ratelimit())) { - DPRINTK(PROBE, WARNING, - "partial checksum but proto=%x!\n", - skb->protocol); + e_warn("partial checksum but " + "proto=%x!\n", skb->protocol); } break; } @@ -5930,7 +5975,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, return count; dma_error: - dev_err(&pdev->dev, "TX DMA map failed\n"); + e_dev_err("TX DMA map failed\n"); /* clear timestamp and dma mappings for failed tx_buffer_info map */ tx_buffer_info->dma = 0; @@ -6427,8 +6472,7 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED; err = pci_enable_sriov(adapter->pdev, adapter->num_vfs); if (err) { - DPRINTK(PROBE, ERR, - "Failed to enable PCI sriov: %d\n", err); + e_err("Failed to enable PCI sriov: %d\n", err); goto err_novfs; } /* If call to enable VFs succeeded then allocate memory @@ -6452,9 +6496,8 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, } /* Oh oh */ - DPRINTK(PROBE, ERR, - "Unable to allocate memory for VF " - "Data Storage - SRIOV disabled\n"); + e_err("Unable to allocate memory for VF Data Storage - SRIOV " + "disabled\n"); pci_disable_sriov(adapter->pdev); err_novfs: @@ -6502,8 +6545,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) { - dev_err(&pdev->dev, "No usable DMA " - "configuration, aborting\n"); + e_dev_err("No usable DMA configuration, " + "aborting\n"); goto err_dma; } } @@ -6513,8 +6556,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), ixgbe_driver_name); if (err) { - dev_err(&pdev->dev, - "pci_request_selected_regions failed 0x%x\n", err); + e_dev_err("pci_request_selected_regions failed 0x%x\n", err); goto err_pci_reg; } @@ -6625,8 +6667,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) - DPRINTK(PROBE, CRIT, - "Fan has stopped, replace the adapter\n"); + e_crit("Fan has stopped, replace the adapter\n"); } /* reset_hw fills in the perm_addr as well */ @@ -6645,19 +6686,19 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, round_jiffies(jiffies + (2 * HZ))); err = 0; } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize because " - "an unsupported SFP+ module type was detected.\n" - "Reload the driver after installing a supported " - "module.\n"); + e_dev_err("failed to initialize because an unsupported SFP+ " + "module type was detected.\n"); + e_dev_err("Reload the driver after installing a supported " + "module.\n"); goto err_sw_init; } else if (err) { - dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); + e_dev_err("HW Init failed: %d\n", err); goto err_sw_init; } ixgbe_probe_vf(adapter, ii); - netdev->features = NETIF_F_SG | + netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | @@ -6704,7 +6745,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* make sure the EEPROM is good */ if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) { - dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n"); + e_dev_err("The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; } @@ -6713,7 +6754,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len); if (ixgbe_validate_mac_addr(netdev->perm_addr)) { - dev_err(&pdev->dev, "invalid MAC address\n"); + e_dev_err("invalid MAC address\n"); err = -EIO; goto err_eeprom; } @@ -6748,7 +6789,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->mac.ops.get_bus_info(hw); /* print bus type/speed/width info */ - dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n", + e_dev_info("(PCI Express:%s:%s) %pM\n", ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s": (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"), ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" : @@ -6758,20 +6799,20 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->dev_addr); ixgbe_read_pba_num_generic(hw, &part_num); if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present) - dev_info(&pdev->dev, "MAC: %d, PHY: %d, SFP+: %d, PBA No: %06x-%03x\n", - hw->mac.type, hw->phy.type, hw->phy.sfp_type, - (part_num >> 8), (part_num & 0xff)); + e_dev_info("MAC: %d, PHY: %d, SFP+: %d, " + "PBA No: %06x-%03x\n", + hw->mac.type, hw->phy.type, hw->phy.sfp_type, + (part_num >> 8), (part_num & 0xff)); else - dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n", - hw->mac.type, hw->phy.type, - (part_num >> 8), (part_num & 0xff)); + e_dev_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n", + hw->mac.type, hw->phy.type, + (part_num >> 8), (part_num & 0xff)); if (hw->bus.width <= ixgbe_bus_width_pcie_x4) { - dev_warn(&pdev->dev, "PCI-Express bandwidth available for " - "this card is not sufficient for optimal " - "performance.\n"); - dev_warn(&pdev->dev, "For optimal performance a x8 " - "PCI-Express slot is required.\n"); + e_dev_warn("PCI-Express bandwidth available for this card is " + "not sufficient for optimal performance.\n"); + e_dev_warn("For optimal performance a x8 PCI-Express slot " + "is required.\n"); } /* save off EEPROM version number */ @@ -6782,12 +6823,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err == IXGBE_ERR_EEPROM_VERSION) { /* We are running on a pre-production device, log a warning */ - dev_warn(&pdev->dev, "This device is a pre-production " - "adapter/LOM. Please be aware there may be issues " - "associated with your hardware. If you are " - "experiencing problems please contact your Intel or " - "hardware representative who provided you with this " - "hardware.\n"); + e_dev_warn("This device is a pre-production adapter/LOM. " + "Please be aware there may be issues associated " + "with your hardware. If you are experiencing " + "problems please contact your Intel or hardware " + "representative who provided you with this " + "hardware.\n"); } strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); @@ -6810,8 +6851,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } #endif if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { - DPRINTK(PROBE, INFO, "IOV is enabled with %d VFs\n", - adapter->num_vfs); + e_info("IOV is enabled with %d VFs\n", adapter->num_vfs); for (i = 0; i < adapter->num_vfs; i++) ixgbe_vf_configuration(pdev, (i | 0x10000000)); } @@ -6819,7 +6859,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* add san mac addr to netdev */ ixgbe_add_sanmac_netdev(netdev); - dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n"); + e_dev_info("Intel(R) 10 Gigabit Network Connection\n"); cards_found++; return 0; @@ -6909,7 +6949,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); - DPRINTK(PROBE, INFO, "complete\n"); + e_dev_info("complete\n"); free_netdev(netdev); @@ -6959,8 +6999,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) int err; if (pci_enable_device_mem(pdev)) { - DPRINTK(PROBE, ERR, - "Cannot re-enable PCI device after reset.\n"); + e_err("Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; } else { pci_set_master(pdev); @@ -6976,8 +7015,8 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) err = pci_cleanup_aer_uncorrect_error_status(pdev); if (err) { - dev_err(&pdev->dev, - "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", err); + e_dev_err("pci_cleanup_aer_uncorrect_error_status " + "failed 0x%0x\n", err); /* non-fatal, continue */ } @@ -6998,7 +7037,7 @@ static void ixgbe_io_resume(struct pci_dev *pdev) if (netif_running(netdev)) { if (ixgbe_up(adapter)) { - DPRINTK(PROBE, INFO, "ixgbe_up failed after reset\n"); + e_info("ixgbe_up failed after reset\n"); return; } } @@ -7034,10 +7073,9 @@ static struct pci_driver ixgbe_driver = { static int __init ixgbe_init_module(void) { int ret; - printk(KERN_INFO "%s: %s - version %s\n", ixgbe_driver_name, - ixgbe_driver_string, ixgbe_driver_version); - - printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright); + pr_info("%s - version %s\n", ixgbe_driver_string, + ixgbe_driver_version); + pr_info("%s\n", ixgbe_copyright); #ifdef CONFIG_IXGBE_DCA dca_register_notify(&dca_notifier); @@ -7076,18 +7114,17 @@ static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event, } #endif /* CONFIG_IXGBE_DCA */ -#ifdef DEBUG + /** - * ixgbe_get_hw_dev_name - return device name string + * ixgbe_get_hw_dev return device * used by hardware layer to print debugging information **/ -char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw) +struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw) { struct ixgbe_adapter *adapter = hw->back; - return adapter->netdev->name; + return adapter->netdev; } -#endif module_exit(ixgbe_exit_module); /* ixgbe_main.c */ diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index f6cee94ec8e8..6e6dee04ff61 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -25,7 +25,6 @@ *******************************************************************************/ - #include <linux/types.h> #include <linux/module.h> #include <linux/pci.h> @@ -138,6 +137,7 @@ static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf) inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; + int rar_entry = hw->mac.num_rar_entries - (vf + 1); /* reset offloads to defaults */ if (adapter->vfinfo[vf].pf_vlan) { @@ -159,26 +159,17 @@ inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) /* Flush and reset the mta with the new values */ ixgbe_set_rx_mode(adapter->netdev); - if (adapter->vfinfo[vf].rar > 0) { - adapter->hw.mac.ops.clear_rar(&adapter->hw, - adapter->vfinfo[vf].rar); - adapter->vfinfo[vf].rar = -1; - } + hw->mac.ops.clear_rar(hw, rar_entry); } int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, int vf, unsigned char *mac_addr) { struct ixgbe_hw *hw = &adapter->hw; - - adapter->vfinfo[vf].rar = hw->mac.ops.set_rar(hw, vf + 1, mac_addr, - vf, IXGBE_RAH_AV); - if (adapter->vfinfo[vf].rar < 0) { - DPRINTK(DRV, ERR, "Could not set MAC Filter for VF %d\n", vf); - return -1; - } + int rar_entry = hw->mac.num_rar_entries - (vf + 1); memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, 6); + hw->mac.ops.set_rar(hw, rar_entry, mac_addr, vf, IXGBE_RAH_AV); return 0; } @@ -194,11 +185,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) if (enable) { random_ether_addr(vf_mac_addr); - DPRINTK(PROBE, INFO, "IOV: VF %d is enabled " - "mac %02X:%02X:%02X:%02X:%02X:%02X\n", - vfn, - vf_mac_addr[0], vf_mac_addr[1], vf_mac_addr[2], - vf_mac_addr[3], vf_mac_addr[4], vf_mac_addr[5]); + e_info("IOV: VF %d is enabled MAC %pM\n", vfn, vf_mac_addr); /* * Store away the VF "permananet" MAC address, it will ask * for it later. @@ -243,7 +230,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); if (retval) - printk(KERN_ERR "Error receiving message from VF\n"); + pr_err("Error receiving message from VF\n"); /* this is a message we already processed, do nothing */ if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK)) @@ -257,7 +244,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) if (msgbuf[0] == IXGBE_VF_RESET) { unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; u8 *addr = (u8 *)(&msgbuf[1]); - DPRINTK(PROBE, INFO, "VF Reset msg received from vf %d\n", vf); + e_info("VF Reset msg received from vf %d\n", vf); adapter->vfinfo[vf].clear_to_send = false; ixgbe_vf_reset_msg(adapter, vf); adapter->vfinfo[vf].clear_to_send = true; @@ -310,7 +297,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); break; default: - DPRINTK(DRV, ERR, "Unhandled Msg %8.8x\n", msgbuf[0]); + e_err("Unhandled Msg %8.8x\n", msgbuf[0]); retval = IXGBE_ERR_MBX; break; } diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index a16cff7e54a3..73f1e75f68d4 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -3411,6 +3411,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_IPV6_CSUM; netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; + netdev->features |= NETIF_F_GRO; netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_IP_CSUM; diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 7805bbf1d53a..62362b4a8c56 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -5718,7 +5718,7 @@ static void dev_set_promiscuous(struct net_device *dev, struct dev_priv *priv, * from the bridge. */ if ((hw->features & STP_SUPPORT) && !promiscuous && - dev->br_port) { + (dev->priv_flags & IFF_BRIDGE_PORT)) { struct ksz_switch *sw = hw->ksz_switch; int port = priv->port.first_port; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 72b7949c91b1..09334f8f148b 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -60,11 +60,51 @@ #include <net/net_namespace.h> struct pcpu_lstats { - unsigned long packets; - unsigned long bytes; + u64 packets; + u64 bytes; +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) + seqcount_t seq; +#endif unsigned long drops; }; +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) +static void inline lstats_update_begin(struct pcpu_lstats *lstats) +{ + write_seqcount_begin(&lstats->seq); +} +static void inline lstats_update_end(struct pcpu_lstats *lstats) +{ + write_seqcount_end(&lstats->seq); +} +static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats) +{ + u64 tpackets, tbytes; + unsigned int seq; + + do { + seq = read_seqcount_begin(&lstats->seq); + tpackets = lstats->packets; + tbytes = lstats->bytes; + } while (read_seqcount_retry(&lstats->seq, seq)); + + *packets += tpackets; + *bytes += tbytes; +} +#else +static void inline lstats_update_begin(struct pcpu_lstats *lstats) +{ +} +static void inline lstats_update_end(struct pcpu_lstats *lstats) +{ +} +static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats) +{ + *packets += lstats->packets; + *bytes += lstats->bytes; +} +#endif + /* * The higher levels take care of making this non-reentrant (it's * called with bh's disabled). @@ -86,21 +126,23 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, len = skb->len; if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { + lstats_update_begin(lb_stats); lb_stats->bytes += len; lb_stats->packets++; + lstats_update_end(lb_stats); } else lb_stats->drops++; return NETDEV_TX_OK; } -static struct net_device_stats *loopback_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev) { const struct pcpu_lstats __percpu *pcpu_lstats; - struct net_device_stats *stats = &dev->stats; - unsigned long bytes = 0; - unsigned long packets = 0; - unsigned long drops = 0; + struct rtnl_link_stats64 *stats = &dev->stats64; + u64 bytes = 0; + u64 packets = 0; + u64 drops = 0; int i; pcpu_lstats = (void __percpu __force *)dev->ml_priv; @@ -108,8 +150,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) const struct pcpu_lstats *lb_stats; lb_stats = per_cpu_ptr(pcpu_lstats, i); - bytes += lb_stats->bytes; - packets += lb_stats->packets; + lstats_fetch_and_add(&packets, &bytes, lb_stats); drops += lb_stats->drops; } stats->rx_packets = packets; @@ -158,7 +199,7 @@ static void loopback_dev_free(struct net_device *dev) static const struct net_device_ops loopback_ops = { .ndo_init = loopback_dev_init, .ndo_start_xmit= loopback_xmit, - .ndo_get_stats = loopback_get_stats, + .ndo_get_stats64 = loopback_get_stats64, }; /* diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 1136c9a22b67..3832fa4961dd 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -157,6 +157,8 @@ static void dayna_block_output(struct net_device *dev, int count, #define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c)) #define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c)) +#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c)) + /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); @@ -164,8 +166,8 @@ static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); -static void word_memcpy_tocard(void *tp, const void *fp, int count); -static void word_memcpy_fromcard(void *tp, const void *fp, int count); +static void word_memcpy_tocard(unsigned long tp, const void *fp, int count); +static void word_memcpy_fromcard(void *tp, unsigned long fp, int count); static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) { @@ -245,9 +247,9 @@ static enum mac8390_access __init mac8390_testio(volatile unsigned long membase) unsigned long outdata = 0xA5A0B5B0; unsigned long indata = 0x00000000; /* Try writing 32 bits */ - memcpy(membase, &outdata, 4); + memcpy_toio(membase, &outdata, 4); /* Now compare them */ - if (memcmp((char *)&outdata, (char *)membase, 4) == 0) + if (memcmp_withio(&outdata, membase, 4) == 0) return ACCESS_32; /* Write 16 bit output */ word_memcpy_tocard(membase, &outdata, 4); @@ -554,7 +556,7 @@ static int __init mac8390_initdev(struct net_device *dev, case MAC8390_APPLE: switch (mac8390_testio(dev->mem_start)) { case ACCESS_UNKNOWN: - pr_info("Don't know how to access card memory!\n"); + pr_err("Don't know how to access card memory!\n"); return -ENODEV; break; @@ -641,12 +643,13 @@ static int __init mac8390_initdev(struct net_device *dev, static int mac8390_open(struct net_device *dev) { + int err; + __ei_open(dev); - if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) { - pr_info("%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return -EAGAIN; - } - return 0; + err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev); + if (err) + pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq); + return err; } static int mac8390_close(struct net_device *dev) @@ -731,7 +734,7 @@ static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; - memcpy_fromio((void *)hdr, (char *)dev->mem_start + hdr_start, 4); + memcpy_fromio(hdr, dev->mem_start + hdr_start, 4); /* Fix endianness */ hdr->count = swab16(hdr->count); } @@ -745,14 +748,13 @@ static void sane_block_input(struct net_device *dev, int count, if (xfer_start + count > ei_status.rmem_end) { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; - memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, + memcpy_fromio(skb->data, dev->mem_start + xfer_base, semi_count); count -= semi_count; - memcpy_toio(skb->data + semi_count, - (char *)ei_status.rmem_start, count); - } else { - memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, + memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count); + } else { + memcpy_fromio(skb->data, dev->mem_start + xfer_base, count); } } @@ -761,7 +763,7 @@ static void sane_block_output(struct net_device *dev, int count, { long shmem = (start_page - WD_START_PG)<<8; - memcpy_toio((char *)dev->mem_start + shmem, buf, count); + memcpy_toio(dev->mem_start + shmem, buf, count); } /* dayna block input/output */ @@ -812,7 +814,7 @@ static void slow_sane_get_8390_hdr(struct net_device *dev, int ring_page) { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; - word_memcpy_fromcard(hdr, (char *)dev->mem_start + hdr_start, 4); + word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4); /* Register endianism - fix here rather than 8390.c */ hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8); } @@ -826,15 +828,14 @@ static void slow_sane_block_input(struct net_device *dev, int count, if (xfer_start + count > ei_status.rmem_end) { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; - word_memcpy_fromcard(skb->data, - (char *)dev->mem_start + xfer_base, + word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base, semi_count); count -= semi_count; word_memcpy_fromcard(skb->data + semi_count, - (char *)ei_status.rmem_start, count); + ei_status.rmem_start, count); } else { - word_memcpy_fromcard(skb->data, - (char *)dev->mem_start + xfer_base, count); + word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base, + count); } } @@ -843,12 +844,12 @@ static void slow_sane_block_output(struct net_device *dev, int count, { long shmem = (start_page - WD_START_PG)<<8; - word_memcpy_tocard((char *)dev->mem_start + shmem, buf, count); + word_memcpy_tocard(dev->mem_start + shmem, buf, count); } -static void word_memcpy_tocard(void *tp, const void *fp, int count) +static void word_memcpy_tocard(unsigned long tp, const void *fp, int count) { - volatile unsigned short *to = tp; + volatile unsigned short *to = (void *)tp; const unsigned short *from = fp; count++; @@ -858,10 +859,10 @@ static void word_memcpy_tocard(void *tp, const void *fp, int count) *to++ = *from++; } -static void word_memcpy_fromcard(void *tp, const void *fp, int count) +static void word_memcpy_fromcard(void *tp, unsigned long fp, int count) { unsigned short *to = tp; - const volatile unsigned short *from = fp; + const volatile unsigned short *from = (const void *)fp; count++; count /= 2; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 87e8d4cb4057..e096875aa055 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -37,8 +37,14 @@ struct macvlan_port { struct net_device *dev; struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; struct list_head vlans; + struct rcu_head rcu; }; +#define macvlan_port_get_rcu(dev) \ + ((struct macvlan_port *) rcu_dereference(dev->rx_handler_data)) +#define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data) +#define macvlan_port_exists(dev) (dev->priv_flags & IFF_MACVLAN_PORT) + static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, const unsigned char *addr) { @@ -145,15 +151,16 @@ static void macvlan_broadcast(struct sk_buff *skb, } /* called under rcu_read_lock() from netif_receive_skb */ -static struct sk_buff *macvlan_handle_frame(struct macvlan_port *port, - struct sk_buff *skb) +static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) { + struct macvlan_port *port; const struct ethhdr *eth = eth_hdr(skb); const struct macvlan_dev *vlan; const struct macvlan_dev *src; struct net_device *dev; unsigned int len; + port = macvlan_port_get_rcu(skb->dev); if (is_multicast_ether_addr(eth->h_dest)) { src = macvlan_hash_lookup(port, eth->h_source); if (!src) @@ -515,6 +522,7 @@ static int macvlan_port_create(struct net_device *dev) { struct macvlan_port *port; unsigned int i; + int err; if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) return -EINVAL; @@ -527,19 +535,32 @@ static int macvlan_port_create(struct net_device *dev) INIT_LIST_HEAD(&port->vlans); for (i = 0; i < MACVLAN_HASH_SIZE; i++) INIT_HLIST_HEAD(&port->vlan_hash[i]); - rcu_assign_pointer(dev->macvlan_port, port); - return 0; + + err = netdev_rx_handler_register(dev, macvlan_handle_frame, port); + if (err) + kfree(port); + + dev->priv_flags |= IFF_MACVLAN_PORT; + return err; } -static void macvlan_port_destroy(struct net_device *dev) +static void macvlan_port_rcu_free(struct rcu_head *head) { - struct macvlan_port *port = dev->macvlan_port; + struct macvlan_port *port; - rcu_assign_pointer(dev->macvlan_port, NULL); - synchronize_rcu(); + port = container_of(head, struct macvlan_port, rcu); kfree(port); } +static void macvlan_port_destroy(struct net_device *dev) +{ + struct macvlan_port *port = macvlan_port_get(dev); + + dev->priv_flags &= ~IFF_MACVLAN_PORT; + netdev_rx_handler_unregister(dev); + call_rcu(&port->rcu, macvlan_port_rcu_free); +} + static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) { if (tb[IFLA_ADDRESS]) { @@ -615,12 +636,12 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, if (!tb[IFLA_ADDRESS]) random_ether_addr(dev->dev_addr); - if (lowerdev->macvlan_port == NULL) { + if (!macvlan_port_exists(lowerdev)) { err = macvlan_port_create(lowerdev); if (err < 0) return err; } - port = lowerdev->macvlan_port; + port = macvlan_port_get(lowerdev); vlan->lowerdev = lowerdev; vlan->dev = dev; @@ -730,10 +751,11 @@ static int macvlan_device_event(struct notifier_block *unused, struct macvlan_dev *vlan, *next; struct macvlan_port *port; - port = dev->macvlan_port; - if (port == NULL) + if (!macvlan_port_exists(dev)) return NOTIFY_DONE; + port = macvlan_port_get(dev); + switch (event) { case NETDEV_CHANGE: list_for_each_entry(vlan, &port->vlans, list) @@ -767,14 +789,12 @@ static int __init macvlan_init_module(void) int err; register_netdevice_notifier(&macvlan_notifier_block); - macvlan_handle_frame_hook = macvlan_handle_frame; err = macvlan_link_register(&macvlan_link_ops); if (err < 0) goto err1; return 0; err1: - macvlan_handle_frame_hook = NULL; unregister_netdevice_notifier(&macvlan_notifier_block); return err; } @@ -782,7 +802,6 @@ err1: static void __exit macvlan_cleanup_module(void) { rtnl_link_unregister(&macvlan_link_ops); - macvlan_handle_frame_hook = NULL; unregister_netdevice_notifier(&macvlan_notifier_block); } diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 96180c0ec206..a0d8a26f5a02 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -961,6 +961,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, } SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev); + dev->dev_id = port - 1; /* * Initialize driver private data diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 423053482ed5..22d0b3b796b4 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -110,7 +110,7 @@ struct mlx4_eqe { u32 raw[6]; struct { __be32 cqn; - } __attribute__((packed)) comp; + } __packed comp; struct { u16 reserved1; __be16 token; @@ -118,27 +118,27 @@ struct mlx4_eqe { u8 reserved3[3]; u8 status; __be64 out_param; - } __attribute__((packed)) cmd; + } __packed cmd; struct { __be32 qpn; - } __attribute__((packed)) qp; + } __packed qp; struct { __be32 srqn; - } __attribute__((packed)) srq; + } __packed srq; struct { __be32 cqn; u32 reserved1; u8 reserved2[3]; u8 syndrome; - } __attribute__((packed)) cq_err; + } __packed cq_err; struct { u32 reserved1[2]; __be32 port; - } __attribute__((packed)) port_change; + } __packed port_change; } event; u8 reserved3[3]; u8 owner; -} __attribute__((packed)); +} __packed; static void eq_set_ci(struct mlx4_eq *eq, int req_not) { diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 3dc69be4949f..9c188bdd7f4f 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -58,7 +58,7 @@ struct mlx4_mpt_entry { __be32 mtt_sz; __be32 entity_size; __be32 first_byte_offset; -} __attribute__((packed)); +} __packed; #define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) #define MLX4_MPT_FLAG_FREE (0x3UL << 28) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 1b2c29150202..e7b4187da057 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -69,7 +69,6 @@ #define MPHDRLEN 6 /* multilink protocol header length */ #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ -#define MIN_FRAG_SIZE 64 /* * An instance of /dev/ppp can be associated with either a ppp @@ -539,14 +538,9 @@ static int get_filter(void __user *arg, struct sock_filter **p) } len = uprog.len * sizeof(struct sock_filter); - code = kmalloc(len, GFP_KERNEL); - if (code == NULL) - return -ENOMEM; - - if (copy_from_user(code, uprog.filter, len)) { - kfree(code); - return -EFAULT; - } + code = memdup_user(uprog.filter, len); + if (IS_ERR(code)) + return PTR_ERR(code); err = sk_chk_filter(code, uprog.len); if (err) { @@ -1933,9 +1927,9 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) /* If the queue is getting long, don't wait any longer for packets before the start of the queue. */ if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) { - struct sk_buff *skb = skb_peek(&ppp->mrq); - if (seq_before(ppp->minseq, skb->sequence)) - ppp->minseq = skb->sequence; + struct sk_buff *mskb = skb_peek(&ppp->mrq); + if (seq_before(ppp->minseq, mskb->sequence)) + ppp->minseq = mskb->sequence; } /* Pull completed packets off the queue and receive them. */ diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 805b64d1e893..344ef330e123 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -89,7 +89,6 @@ #define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS) #define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1) -static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb); static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); static const struct proto_ops pppoe_ops; @@ -949,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) abort: kfree_skb(skb); - return 1; + return 0; } /************************************************************************ diff --git a/drivers/net/ps3_gelic_wireless.h b/drivers/net/ps3_gelic_wireless.h index 0a88b535197a..f7e51b7d7049 100644 --- a/drivers/net/ps3_gelic_wireless.h +++ b/drivers/net/ps3_gelic_wireless.h @@ -74,7 +74,7 @@ struct gelic_eurus_common_cfg { u16 bss_type; /* infra or adhoc */ u16 auth_method; /* shared key or open */ u16 op_mode; /* B/G */ -} __attribute__((packed)); +} __packed; /* for GELIC_EURUS_CMD_WEP_CFG */ @@ -88,7 +88,7 @@ struct gelic_eurus_wep_cfg { /* all fields are big endian */ u16 security; u8 key[4][16]; -} __attribute__((packed)); +} __packed; /* for GELIC_EURUS_CMD_WPA_CFG */ enum gelic_eurus_wpa_security { @@ -120,7 +120,7 @@ struct gelic_eurus_wpa_cfg { u16 security; u16 psk_type; /* psk key encoding type */ u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; /* psk key; hex or passphrase */ -} __attribute__((packed)); +} __packed; /* for GELIC_EURUS_CMD_{START,GET}_SCAN */ enum gelic_eurus_scan_capability { @@ -171,7 +171,7 @@ struct gelic_eurus_scan_info { __be32 reserved3; __be32 reserved4; u8 elements[0]; /* ie */ -} __attribute__ ((packed)); +} __packed; /* the hypervisor returns bbs up to 16 */ #define GELIC_EURUS_MAX_SCAN (16) @@ -193,7 +193,7 @@ struct gelic_wl_scan_info { struct gelic_eurus_rssi_info { /* big endian */ __be16 rssi; -} __attribute__ ((packed)); +} __packed; /* for 'stat' member of gelic_wl_info */ diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 896d40df9a13..3675678bbf01 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -51,8 +51,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 2 -#define QLCNIC_LINUX_VERSIONID "5.0.2" +#define _QLCNIC_LINUX_SUBVERSION 6 +#define QLCNIC_LINUX_VERSIONID "5.0.6" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) @@ -68,6 +68,7 @@ #define QLCNIC_DECODE_VERSION(v) \ QLCNIC_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16)) +#define QLCNIC_MIN_FW_VERSION QLCNIC_VERSION_CODE(4, 4, 2) #define QLCNIC_NUM_FLASH_SECTORS (64) #define QLCNIC_FLASH_SECTOR_SIZE (64 * 1024) #define QLCNIC_FLASH_TOTAL_SIZE (QLCNIC_NUM_FLASH_SECTORS \ @@ -112,8 +113,10 @@ #define TX_UDPV6_PKT 0x0c /* Tx defines */ -#define MAX_BUFFERS_PER_CMD 32 -#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) +#define MAX_TSO_HEADER_DESC 2 +#define MGMT_CMD_DESC_RESV 4 +#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \ + + MGMT_CMD_DESC_RESV) #define QLCNIC_MAX_TX_TIMEOUTS 2 /* @@ -197,8 +200,7 @@ struct cmd_desc_type0 { __le64 addr_buffer4; - __le32 reserved2; - __le16 reserved; + u8 eth_addr[ETH_ALEN]; __le16 vlan_TCI; } __attribute__ ((aligned(64))); @@ -315,6 +317,8 @@ struct uni_data_desc{ #define QLCNIC_BRDTYPE_P3_10G_XFP 0x0032 #define QLCNIC_BRDTYPE_P3_10G_TP 0x0080 +#define QLCNIC_MSIX_TABLE_OFFSET 0x44 + /* Flash memory map */ #define QLCNIC_BRDCFG_START 0x4000 /* board config */ #define QLCNIC_BOOTLD_START 0x10000 /* bootld */ @@ -367,7 +371,7 @@ struct qlcnic_recv_crb { */ struct qlcnic_cmd_buffer { struct sk_buff *skb; - struct qlcnic_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; + struct qlcnic_skb_frag frag_array[MAX_SKB_FRAGS + 1]; u32 frag_count; }; @@ -377,7 +381,6 @@ struct qlcnic_rx_buffer { struct sk_buff *skb; u64 dma; u16 ref_handle; - u16 state; }; /* Board types */ @@ -419,7 +422,6 @@ struct qlcnic_adapter_stats { u64 xmit_on; u64 xmit_off; u64 skb_alloc_failure; - u64 null_skb; u64 null_rxbuf; u64 rx_dma_map_error; u64 tx_dma_map_error; @@ -542,7 +544,17 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_READ_PEXQ_PARAMETERS 0x0000001c #define QLCNIC_CDRP_CMD_GET_LIC_CAPABILITIES 0x0000001d #define QLCNIC_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e -#define QLCNIC_CDRP_CMD_MAX 0x0000001f +#define QLCNIC_CDRP_CMD_MAC_ADDRESS 0x0000001f + +#define QLCNIC_CDRP_CMD_GET_PCI_INFO 0x00000020 +#define QLCNIC_CDRP_CMD_GET_NIC_INFO 0x00000021 +#define QLCNIC_CDRP_CMD_SET_NIC_INFO 0x00000022 +#define QLCNIC_CDRP_CMD_RESET_NPAR 0x00000023 +#define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024 +#define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH 0x00000025 +#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 +#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 +#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 #define QLCNIC_RCODE_SUCCESS 0 #define QLCNIC_RCODE_TIMEOUT 17 @@ -556,12 +568,12 @@ struct qlcnic_recv_context { #define QLCNIC_CAP0_LSO (1 << 6) #define QLCNIC_CAP0_JUMBO_CONTIGUOUS (1 << 7) #define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) +#define QLCNIC_CAP0_VALIDOFF (1 << 11) /* * Context state */ -#define QLCHAL_VERSION 1 - +#define QLCNIC_HOST_CTX_STATE_FREED 0 #define QLCNIC_HOST_CTX_STATE_ACTIVE 2 /* @@ -592,9 +604,10 @@ struct qlcnic_hostrq_rx_ctx { __le32 sds_ring_offset; /* Offset to SDS config */ __le16 num_rds_rings; /* Count of RDS rings */ __le16 num_sds_rings; /* Count of SDS rings */ - __le16 rsvd1; /* Padding */ - __le16 rsvd2; /* Padding */ - u8 reserved[128]; /* reserve space for future expansion*/ + __le16 valid_field_offset; + u8 txrx_sds_binding; + u8 msix_handler; + u8 reserved[128]; /* reserve space for future expansion*/ /* MUST BE 64-bit aligned. The following is packed: - N hostrq_rds_rings @@ -881,12 +894,14 @@ struct qlcnic_mac_req { #define QLCNIC_LRO_ENABLED 0x08 #define QLCNIC_BRIDGE_ENABLED 0X10 #define QLCNIC_DIAG_ENABLED 0x20 +#define QLCNIC_ESWITCH_ENABLED 0x40 #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) #define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS #define QLCNIC_MSIX_TBL_SPACE 8192 #define QLCNIC_PCI_REG_MSIX_TBL 0x44 +#define QLCNIC_MSIX_TBL_PGSIZE 4096 #define QLCNIC_NETDEV_WEIGHT 128 #define QLCNIC_ADAPTER_UP_MAGIC 777 @@ -919,11 +934,11 @@ struct qlcnic_adapter { u8 rx_csum; u8 portnum; u8 physical_port; + u8 reset_context; u8 mc_enabled; u8 max_mc_count; u8 rss_supported; - u8 rsrvd1; u8 fw_wait_cnt; u8 fw_fail_cnt; u8 tx_timeo_cnt; @@ -940,6 +955,15 @@ struct qlcnic_adapter { u16 link_autoneg; u16 module_type; + u16 op_mode; + u16 switch_mode; + u16 max_tx_ques; + u16 max_rx_ques; + u16 min_tx_bw; + u16 max_tx_bw; + u16 max_mtu; + + u32 fw_hal_version; u32 capabilities; u32 flags; u32 irq; @@ -948,18 +972,22 @@ struct qlcnic_adapter { u32 int_vec_bit; u32 heartbit; + u8 max_mac_filters; u8 dev_state; u8 diag_test; u8 diag_cnt; u8 reset_ack_timeo; u8 dev_init_timeo; - u8 rsrd1; u16 msg_enable; u8 mac_addr[ETH_ALEN]; u64 dev_rst_time; + struct qlcnic_pci_info *npars; + struct qlcnic_eswitch *eswitch; + struct qlcnic_nic_template *nic_ops; + struct qlcnic_adapter_stats stats; struct qlcnic_recv_context recv_ctx; @@ -974,8 +1002,6 @@ struct qlcnic_adapter { struct delayed_work fw_work; - struct work_struct tx_timeout_task; - struct qlcnic_nic_intr_coalesce coal; unsigned long state; @@ -984,6 +1010,53 @@ struct qlcnic_adapter { const struct firmware *fw; }; +struct qlcnic_info { + __le16 pci_func; + __le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */ + __le16 phys_port; + __le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */ + + __le32 capabilities; + u8 max_mac_filters; + u8 reserved1; + __le16 max_mtu; + + __le16 max_tx_ques; + __le16 max_rx_ques; + __le16 min_tx_bw; + __le16 max_tx_bw; + u8 reserved2[104]; +}; + +struct qlcnic_pci_info { + __le16 id; /* pci function id */ + __le16 active; /* 1 = Enabled */ + __le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */ + __le16 default_port; /* default port number */ + + __le16 tx_min_bw; /* Multiple of 100mbpc */ + __le16 tx_max_bw; + __le16 reserved1[2]; + + u8 mac[ETH_ALEN]; + u8 reserved2[106]; +}; + +struct qlcnic_eswitch { + u8 port; + u8 active_vports; + u8 active_vlans; + u8 active_ucast_filters; + u8 max_ucast_filters; + u8 max_active_vlans; + + u32 flags; +#define QLCNIC_SWITCH_ENABLE BIT_1 +#define QLCNIC_SWITCH_VLAN_FILTERING BIT_2 +#define QLCNIC_SWITCH_PROMISC_MODE BIT_3 +#define QLCNIC_SWITCH_PORT_MIRRORING BIT_4 +}; + int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val); int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val); @@ -1031,13 +1104,13 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); /* Functions from qlcnic_init.c */ -int qlcnic_phantom_init(struct qlcnic_adapter *adapter); int qlcnic_load_firmware(struct qlcnic_adapter *adapter); int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter); void qlcnic_request_firmware(struct qlcnic_adapter *adapter); void qlcnic_release_firmware(struct qlcnic_adapter *adapter); int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter); int qlcnic_setup_idc_param(struct qlcnic_adapter *adapter); +int qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter); int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp); int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, @@ -1050,6 +1123,10 @@ void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32); int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter); void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter); +int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter); +void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter); + +void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter); void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter); void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); @@ -1070,13 +1147,14 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup); int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable); -int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable); +int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring); -int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac); +int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac); void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter); int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter); +void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *); /* Functions from qlcnic_main.c */ int qlcnic_reset_context(struct qlcnic_adapter *); @@ -1088,6 +1166,25 @@ int qlcnic_check_loopback_buff(unsigned char *data); netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); +/* Management functions */ +int qlcnic_set_mac_address(struct qlcnic_adapter *, u8*); +int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*); +int qlcnic_get_nic_info(struct qlcnic_adapter *, u8); +int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); +int qlcnic_get_pci_info(struct qlcnic_adapter *); +int qlcnic_reset_partition(struct qlcnic_adapter *, u8); + +/* eSwitch management functions */ +int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8, + struct qlcnic_eswitch *); +int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8, + struct qlcnic_eswitch *); +int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8); +int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8, + u8, u8, u16); +int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); +extern int qlcnic_config_tso; + /* * QLOGIC Board information */ @@ -1131,6 +1228,15 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) extern const struct ethtool_ops qlcnic_ethtool_ops; +struct qlcnic_nic_template { + int (*get_mac_addr) (struct qlcnic_adapter *, u8*); + int (*config_bridged_mode) (struct qlcnic_adapter *, u32); + int (*config_led) (struct qlcnic_adapter *, u32, u32); + int (*set_ilb_mode) (struct qlcnic_adapter *); + void (*clear_ilb_mode) (struct qlcnic_adapter *); + int (*start_firmware) (struct qlcnic_adapter *); +}; + #define QLCDB(adapter, lvl, _fmt, _args...) do { \ if (NETIF_MSG_##lvl & adapter->msg_enable) \ printk(KERN_INFO "%s: %s: " _fmt, \ diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index c2c1f5cc16c6..941cd0873f87 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -88,12 +88,12 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { if (qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, - QLCHAL_VERSION, - recv_ctx->context_id, - mtu, - 0, - QLCNIC_CDRP_CMD_SET_MTU)) { + adapter->ahw.pci_func, + adapter->fw_hal_version, + recv_ctx->context_id, + mtu, + 0, + QLCNIC_CDRP_CMD_SET_MTU)) { dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); return -EIO; @@ -121,7 +121,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) int i, nrds_rings, nsds_rings; size_t rq_size, rsp_size; - u32 cap, reg, val; + u32 cap, reg, val, reg2; int err; struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; @@ -152,9 +152,14 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr); - cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN); + cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN + | QLCNIC_CAP0_VALIDOFF); cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); + prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx, + msix_handler); + prq->txrx_sds_binding = nsds_rings - 1; + prq->capabilities[0] = cpu_to_le32(cap); prq->host_int_crb_mode = cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); @@ -175,6 +180,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) for (i = 0; i < nrds_rings; i++) { rds_ring = &recv_ctx->rds_rings[i]; + rds_ring->producer = 0; prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); @@ -188,6 +194,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) for (i = 0; i < nsds_rings; i++) { sds_ring = &recv_ctx->sds_rings[i]; + sds_ring->consumer = 0; + memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring)); prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); @@ -197,7 +205,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) phys_addr = hostrq_phys_addr; err = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, (u32)(phys_addr >> 32), (u32)(phys_addr & 0xffffffff), rq_size, @@ -216,8 +224,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) rds_ring = &recv_ctx->rds_rings[i]; reg = le32_to_cpu(prsp_rds[i].host_producer_crb); - rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter, + if (adapter->fw_hal_version == QLCNIC_FW_BASE) + rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter, QLCNIC_REG(reg - 0x200)); + else + rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 + + reg; } prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) @@ -227,12 +239,18 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) sds_ring = &recv_ctx->sds_rings[i]; reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); - sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter, - QLCNIC_REG(reg - 0x200)); + reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); - reg = le32_to_cpu(prsp_sds[i].interrupt_crb); - sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter, + if (adapter->fw_hal_version == QLCNIC_FW_BASE) { + sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter, QLCNIC_REG(reg - 0x200)); + sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter, + QLCNIC_REG(reg2 - 0x200)); + } else { + sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 + + reg; + sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2; + } } recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); @@ -253,7 +271,7 @@ qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) if (qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, recv_ctx->context_id, QLCNIC_DESTROY_CTX_RESET, 0, @@ -262,6 +280,8 @@ qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) dev_err(&adapter->pdev->dev, "Failed to destroy rx ctx in firmware\n"); } + + recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED; } static int @@ -278,6 +298,11 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) dma_addr_t rq_phys_addr, rsp_phys_addr; struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + /* reset host resources */ + tx_ring->producer = 0; + tx_ring->sw_consumer = 0; + *(tx_ring->hw_consumer) = 0; + rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); rq_addr = pci_alloc_consistent(adapter->pdev, rq_size, &rq_phys_addr); @@ -319,7 +344,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) phys_addr = rq_phys_addr; err = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, (u32)(phys_addr >> 32), ((u32)phys_addr & 0xffffffff), rq_size, @@ -327,8 +352,12 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) if (err == QLCNIC_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); - tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter, + if (adapter->fw_hal_version == QLCNIC_FW_BASE) + tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter, QLCNIC_REG(temp - 0x200)); + else + tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 + + temp; adapter->tx_context_id = le16_to_cpu(prsp->context_id); @@ -351,7 +380,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) { if (qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, adapter->tx_context_id, QLCNIC_DESTROY_CTX_RESET, 0, @@ -368,7 +397,7 @@ qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) if (qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, reg, 0, 0, @@ -385,7 +414,7 @@ qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) { return qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, + adapter->fw_hal_version, reg, val, 0, @@ -457,15 +486,6 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) sds_ring->desc_head = (struct status_desc *)addr; } - - err = qlcnic_fw_cmd_create_rx_ctx(adapter); - if (err) - goto err_out_free; - err = qlcnic_fw_cmd_create_tx_ctx(adapter); - if (err) - goto err_out_free; - - set_bit(__QLCNIC_FW_ATTACHED, &adapter->state); return 0; err_out_free: @@ -473,15 +493,27 @@ err_out_free: return err; } -void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) + +int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter) { - struct qlcnic_recv_context *recv_ctx; - struct qlcnic_host_rds_ring *rds_ring; - struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_host_tx_ring *tx_ring; - int ring; + int err; + err = qlcnic_fw_cmd_create_rx_ctx(adapter); + if (err) + return err; + err = qlcnic_fw_cmd_create_tx_ctx(adapter); + if (err) { + qlcnic_fw_cmd_destroy_rx_ctx(adapter); + return err; + } + + set_bit(__QLCNIC_FW_ATTACHED, &adapter->state); + return 0; +} + +void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) +{ if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { qlcnic_fw_cmd_destroy_rx_ctx(adapter); qlcnic_fw_cmd_destroy_tx_ctx(adapter); @@ -489,6 +521,15 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) /* Allow dma queues to drain after context reset */ msleep(20); } +} + +void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_host_tx_ring *tx_ring; + int ring; recv_ctx = &adapter->recv_ctx; @@ -533,3 +574,468 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) } } +/* Set MAC address of a NIC partition */ +int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac) +{ + int err = 0; + u32 arg1, arg2, arg3; + + arg1 = adapter->ahw.pci_func | BIT_9; + arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24); + arg3 = mac[4] | (mac[5] << 16); + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + arg2, + arg3, + QLCNIC_CDRP_CMD_MAC_ADDRESS); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to set mac address%d\n", err); + err = -EIO; + } + + return err; +} + +/* Get MAC address of a NIC partition */ +int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) +{ + int err; + u32 arg1; + + arg1 = adapter->ahw.pci_func | BIT_8; + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + 0, + 0, + QLCNIC_CDRP_CMD_MAC_ADDRESS); + + if (err == QLCNIC_RCODE_SUCCESS) + qlcnic_fetch_mac(adapter, QLCNIC_ARG1_CRB_OFFSET, + QLCNIC_ARG2_CRB_OFFSET, 0, mac); + else { + dev_err(&adapter->pdev->dev, + "Failed to get mac address%d\n", err); + err = -EIO; + } + + return err; +} + +/* Get info of a NIC partition */ +int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, u8 func_id) +{ + int err; + dma_addr_t nic_dma_t; + struct qlcnic_info *nic_info; + void *nic_info_addr; + size_t nic_size = sizeof(struct qlcnic_info); + + nic_info_addr = pci_alloc_consistent(adapter->pdev, + nic_size, &nic_dma_t); + if (!nic_info_addr) + return -ENOMEM; + memset(nic_info_addr, 0, nic_size); + + nic_info = (struct qlcnic_info *) nic_info_addr; + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + MSD(nic_dma_t), + LSD(nic_dma_t), + (func_id << 16 | nic_size), + QLCNIC_CDRP_CMD_GET_NIC_INFO); + + if (err == QLCNIC_RCODE_SUCCESS) { + adapter->physical_port = le16_to_cpu(nic_info->phys_port); + adapter->switch_mode = le16_to_cpu(nic_info->switch_mode); + adapter->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques); + adapter->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques); + adapter->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw); + adapter->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw); + adapter->max_mtu = le16_to_cpu(nic_info->max_mtu); + adapter->capabilities = le32_to_cpu(nic_info->capabilities); + adapter->max_mac_filters = nic_info->max_mac_filters; + + if (adapter->capabilities & BIT_6) + adapter->flags |= QLCNIC_ESWITCH_ENABLED; + else + adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; + + dev_info(&adapter->pdev->dev, + "phy port: %d switch_mode: %d,\n" + "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n" + "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n", + adapter->physical_port, adapter->switch_mode, + adapter->max_tx_ques, adapter->max_rx_ques, + adapter->min_tx_bw, adapter->max_tx_bw, + adapter->max_mtu, adapter->capabilities); + } else { + dev_err(&adapter->pdev->dev, + "Failed to get nic info%d\n", err); + err = -EIO; + } + + pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); + return err; +} + +/* Configure a NIC partition */ +int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) +{ + int err = -EIO; + u32 func_state; + dma_addr_t nic_dma_t; + void *nic_info_addr; + struct qlcnic_info *nic_info; + size_t nic_size = sizeof(struct qlcnic_info); + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + + if (qlcnic_api_lock(adapter)) + return err; + + func_state = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + if (QLC_DEV_CHECK_ACTIVE(func_state, nic->pci_func)) { + qlcnic_api_unlock(adapter); + return err; + } + + qlcnic_api_unlock(adapter); + + nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size, + &nic_dma_t); + if (!nic_info_addr) + return -ENOMEM; + + memset(nic_info_addr, 0, nic_size); + nic_info = (struct qlcnic_info *)nic_info_addr; + + nic_info->pci_func = cpu_to_le16(nic->pci_func); + nic_info->op_mode = cpu_to_le16(nic->op_mode); + nic_info->phys_port = cpu_to_le16(nic->phys_port); + nic_info->switch_mode = cpu_to_le16(nic->switch_mode); + nic_info->capabilities = cpu_to_le32(nic->capabilities); + nic_info->max_mac_filters = nic->max_mac_filters; + nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques); + nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques); + nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); + nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + MSD(nic_dma_t), + LSD(nic_dma_t), + nic_size, + QLCNIC_CDRP_CMD_SET_NIC_INFO); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to set nic info%d\n", err); + err = -EIO; + } + + pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); + return err; +} + +/* Get PCI Info of a partition */ +int qlcnic_get_pci_info(struct qlcnic_adapter *adapter) +{ + int err = 0, i; + dma_addr_t pci_info_dma_t; + struct qlcnic_pci_info *npar; + void *pci_info_addr; + size_t npar_size = sizeof(struct qlcnic_pci_info); + size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; + + pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size, + &pci_info_dma_t); + if (!pci_info_addr) + return -ENOMEM; + memset(pci_info_addr, 0, pci_size); + + if (!adapter->npars) + adapter->npars = kzalloc(pci_size, GFP_KERNEL); + if (!adapter->npars) { + err = -ENOMEM; + goto err_npar; + } + + if (!adapter->eswitch) + adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * + QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); + if (!adapter->eswitch) { + err = -ENOMEM; + goto err_eswitch; + } + + npar = (struct qlcnic_pci_info *) pci_info_addr; + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + MSD(pci_info_dma_t), + LSD(pci_info_dma_t), + pci_size, + QLCNIC_CDRP_CMD_GET_PCI_INFO); + + if (err == QLCNIC_RCODE_SUCCESS) { + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++) { + adapter->npars[i].id = le32_to_cpu(npar->id); + adapter->npars[i].active = le32_to_cpu(npar->active); + adapter->npars[i].type = le32_to_cpu(npar->type); + adapter->npars[i].default_port = + le32_to_cpu(npar->default_port); + adapter->npars[i].tx_min_bw = + le32_to_cpu(npar->tx_min_bw); + adapter->npars[i].tx_max_bw = + le32_to_cpu(npar->tx_max_bw); + memcpy(adapter->npars[i].mac, npar->mac, ETH_ALEN); + } + } else { + dev_err(&adapter->pdev->dev, + "Failed to get PCI Info%d\n", err); + kfree(adapter->npars); + err = -EIO; + } + goto err_npar; + +err_eswitch: + kfree(adapter->npars); + adapter->npars = NULL; + +err_npar: + pci_free_consistent(adapter->pdev, pci_size, pci_info_addr, + pci_info_dma_t); + return err; +} + +/* Reset a NIC partition */ + +int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no) +{ + int err = -EIO; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + func_no, + 0, + 0, + QLCNIC_CDRP_CMD_RESET_NPAR); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to issue reset partition%d\n", err); + err = -EIO; + } + + return err; +} + +/* Get eSwitch Capabilities */ +int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, + struct qlcnic_eswitch *eswitch) +{ + int err = -EIO; + u32 arg1, arg2; + + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) + return err; + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + port, + 0, + 0, + QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY); + + if (err == QLCNIC_RCODE_SUCCESS) { + arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); + arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); + + eswitch->port = arg1 & 0xf; + eswitch->active_vports = LSB(arg2); + eswitch->max_ucast_filters = MSB(arg2); + eswitch->max_active_vlans = LSB(MSW(arg2)); + if (arg1 & BIT_6) + eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; + if (arg1 & BIT_7) + eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE; + if (arg1 & BIT_8) + eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; + } else { + dev_err(&adapter->pdev->dev, + "Failed to get eswitch capabilities%d\n", err); + } + + return err; +} + +/* Get current status of eswitch */ +int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port, + struct qlcnic_eswitch *eswitch) +{ + int err = -EIO; + u32 arg1, arg2; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + port, + 0, + 0, + QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS); + + if (err == QLCNIC_RCODE_SUCCESS) { + arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); + arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); + + eswitch->port = arg1 & 0xf; + eswitch->active_vports = LSB(arg2); + eswitch->active_ucast_filters = MSB(arg2); + eswitch->active_vlans = LSB(MSW(arg2)); + if (arg1 & BIT_6) + eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; + if (arg1 & BIT_8) + eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; + + } else { + dev_err(&adapter->pdev->dev, + "Failed to get eswitch status%d\n", err); + } + + return err; +} + +/* Enable/Disable eSwitch */ +int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable) +{ + int err = -EIO; + u32 arg1, arg2; + struct qlcnic_eswitch *eswitch; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + + eswitch = &adapter->eswitch[id]; + if (!eswitch) + return err; + + arg1 = eswitch->port | (enable ? BIT_4 : 0); + arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) | + (eswitch->max_active_vlans << 16); + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + arg2, + 0, + QLCNIC_CDRP_CMD_TOGGLE_ESWITCH); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to enable eswitch%d\n", eswitch->port); + eswitch->flags &= ~QLCNIC_SWITCH_ENABLE; + err = -EIO; + } else { + eswitch->flags |= QLCNIC_SWITCH_ENABLE; + dev_info(&adapter->pdev->dev, + "Enabled eSwitch for port %d\n", eswitch->port); + } + + return err; +} + +/* Configure eSwitch for port mirroring */ +int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, + u8 enable_mirroring, u8 pci_func) +{ + int err = -EIO; + u32 arg1; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC || + !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) + return err; + + arg1 = id | (enable_mirroring ? BIT_4 : 0); + arg1 |= pci_func << 8; + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + 0, + 0, + QLCNIC_CDRP_CMD_SET_PORTMIRRORING); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to configure port mirroring%d on eswitch:%d\n", + pci_func, id); + } else { + dev_info(&adapter->pdev->dev, + "Configured eSwitch %d for port mirroring:%d\n", + id, pci_func); + } + + return err; +} + +/* Configure eSwitch port */ +int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, + int vlan_tagging, u8 discard_tagged, u8 promsc_mode, + u8 mac_learn, u8 pci_func, u16 vlan_id) +{ + int err = -EIO; + u32 arg1; + struct qlcnic_eswitch *eswitch; + + if (adapter->op_mode != QLCNIC_MGMT_FUNC) + return err; + + eswitch = &adapter->eswitch[id]; + if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE)) + return err; + + arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0); + arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0); + arg1 |= pci_func << 8; + if (vlan_tagging) + arg1 |= BIT_5 | (vlan_id << 16); + + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + adapter->fw_hal_version, + arg1, + 0, + 0, + QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to configure eswitch port%d\n", eswitch->port); + eswitch->flags |= QLCNIC_SWITCH_ENABLE; + } else { + eswitch->flags &= ~QLCNIC_SWITCH_ENABLE; + dev_info(&adapter->pdev->dev, + "Configured eSwitch for port %d\n", eswitch->port); + } + + return err; +} diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 3bd514ec7e8f..d4e803e2a977 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -69,8 +69,6 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), QLC_OFF(stats.skb_alloc_failure)}, - {"null skb", - QLC_SIZEOF(stats.null_skb), QLC_OFF(stats.null_skb)}, {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), @@ -350,7 +348,7 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) for (i = 0; diag_registers[i] != -1; i++) regs_buff[i] = QLCRD32(adapter, diag_registers[i]); - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) return; regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/ @@ -683,13 +681,13 @@ static int qlcnic_loopback_test(struct net_device *netdev) if (ret) goto clear_it; - ret = qlcnic_set_ilb_mode(adapter); + ret = adapter->nic_ops->set_ilb_mode(adapter); if (ret) goto done; ret = qlcnic_do_ilb_test(adapter); - qlcnic_clear_ilb_mode(adapter); + adapter->nic_ops->clear_ilb_mode(adapter); done: qlcnic_diag_free_res(netdev, max_sds_rings); @@ -715,7 +713,8 @@ static int qlcnic_irq_test(struct net_device *netdev) adapter->diag_cnt = 0; ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - QLCHAL_VERSION, adapter->portnum, 0, 0, 0x00000011); + adapter->fw_hal_version, adapter->portnum, + 0, 0, 0x00000011); if (ret) goto done; @@ -834,7 +833,10 @@ static int qlcnic_blink_led(struct net_device *dev, u32 val) struct qlcnic_adapter *adapter = netdev_priv(dev); int ret; - ret = qlcnic_config_led(adapter, 1, 0xf); + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) + return -EIO; + + ret = adapter->nic_ops->config_led(adapter, 1, 0xf); if (ret) { dev_err(&adapter->pdev->dev, "Failed to set LED blink state.\n"); @@ -843,7 +845,7 @@ static int qlcnic_blink_led(struct net_device *dev, u32 val) msleep_interruptible(val * 1000); - ret = qlcnic_config_led(adapter, 0, 0xf); + ret = adapter->nic_ops->config_led(adapter, 0, 0xf); if (ret) { dev_err(&adapter->pdev->dev, "Failed to reset LED blink state.\n"); @@ -905,7 +907,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev, { struct qlcnic_adapter *adapter = netdev_priv(netdev); - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) return -EINVAL; /* diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index ad9d167723c4..7b81cab27002 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -208,6 +208,39 @@ enum { QLCNIC_HW_PX_MAP_CRB_PGR0 }; +#define BIT_0 0x1 +#define BIT_1 0x2 +#define BIT_2 0x4 +#define BIT_3 0x8 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x100 +#define BIT_9 0x200 +#define BIT_10 0x400 +#define BIT_11 0x800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x10000 +#define BIT_17 0x20000 +#define BIT_18 0x40000 +#define BIT_19 0x80000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x1000000 +#define BIT_25 0x2000000 +#define BIT_26 0x4000000 +#define BIT_27 0x8000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + /* This field defines CRB adr [31:20] of the agents */ #define QLCNIC_HW_CRB_HUB_AGT_ADR_MN \ @@ -668,10 +701,11 @@ enum { #define QLCNIC_CRB_DEV_REF_COUNT (QLCNIC_CAM_RAM(0x138)) #define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140)) -#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144)) -#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148)) -#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c)) +#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144)) +#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148)) +#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c)) #define QLCNIC_CRB_DRV_IDC_VER (QLCNIC_CAM_RAM(0x174)) +#define QLCNIC_CRB_DEV_NPAR_STATE (QLCNIC_CAM_RAM(0x19c)) #define QLCNIC_ROM_DEV_INIT_TIMEOUT (0x3e885c) #define QLCNIC_ROM_DRV_RESET_TIMEOUT (0x3e8860) @@ -684,15 +718,26 @@ enum { #define QLCNIC_DEV_FAILED 0x6 #define QLCNIC_DEV_QUISCENT 0x7 +#define QLCNIC_DEV_NPAR_NOT_RDY 0 +#define QLCNIC_DEV_NPAR_RDY 1 + +#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4))) #define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4))) #define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4))) #define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4))) #define QLC_DEV_SET_QSCNT_RDY(VAL, FN) ((VAL) |= (2 << (FN * 4))) #define QLC_DEV_CLR_RST_QSCNT(VAL, FN) ((VAL) &= ~(3 << (FN * 4))) +#define QLC_DEV_GET_DRV(VAL, FN) (0xf & ((VAL) >> (FN * 4))) +#define QLC_DEV_SET_DRV(VAL, FN) ((VAL) << (FN * 4)) + +#define QLCNIC_TYPE_NIC 1 +#define QLCNIC_TYPE_FCOE 2 +#define QLCNIC_TYPE_ISCSI 3 + #define QLCNIC_RCODE_DRIVER_INFO 0x20000000 -#define QLCNIC_RCODE_DRIVER_CAN_RELOAD 0x40000000 -#define QLCNIC_RCODE_FATAL_ERROR 0x80000000 +#define QLCNIC_RCODE_DRIVER_CAN_RELOAD BIT_30 +#define QLCNIC_RCODE_FATAL_ERROR BIT_31 #define QLCNIC_FWERROR_PEGNUM(code) ((code) & 0xff) #define QLCNIC_FWERROR_CODE(code) ((code >> 8) & 0xfffff) @@ -721,6 +766,35 @@ struct qlcnic_legacy_intr_set { u32 pci_int_reg; }; +#define QLCNIC_FW_API 0x1b216c +#define QLCNIC_DRV_OP_MODE 0x1b2170 +#define QLCNIC_MSIX_BASE 0x132110 +#define QLCNIC_MAX_PCI_FUNC 8 + +/* PCI function operational mode */ +enum { + QLCNIC_MGMT_FUNC = 0, + QLCNIC_PRIV_FUNC = 1, + QLCNIC_NON_PRIV_FUNC = 2 +}; + +/* FW HAL api version */ +enum { + QLCNIC_FW_BASE = 1, + QLCNIC_FW_NPAR = 2 +}; + +#define QLC_DEV_DRV_DEFAULT 0x11111111 + +#define LSB(x) ((uint8_t)(x)) +#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8)) + +#define LSW(x) ((uint16_t)((uint32_t)(x))) +#define MSW(x) ((uint16_t)((uint32_t)(x) >> 16)) + +#define LSD(x) ((uint32_t)((uint64_t)(x))) +#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) + #define QLCNIC_LEGACY_INTR_CONFIG \ { \ { \ diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 0c2e1f08f459..e08c8b0556a4 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -327,7 +327,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, i = 0; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) return -EIO; tx_ring = adapter->tx_ring; @@ -338,9 +338,15 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, if (nr_desc >= qlcnic_tx_avail(tx_ring)) { netif_tx_stop_queue(tx_ring->txq); - __netif_tx_unlock_bh(tx_ring->txq); - adapter->stats.xmit_off++; - return -EBUSY; + smp_mb(); + if (qlcnic_tx_avail(tx_ring) > nr_desc) { + if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) + netif_tx_wake_queue(tx_ring->txq); + } else { + adapter->stats.xmit_off++; + __netif_tx_unlock_bh(tx_ring->txq); + return -EBUSY; + } } do { @@ -407,10 +413,15 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr) return -ENOMEM; } memcpy(cur->mac_addr, addr, ETH_ALEN); - list_add_tail(&cur->list, &adapter->mac_list); - return qlcnic_sre_macaddr_change(adapter, - cur->mac_addr, QLCNIC_MAC_ADD); + if (qlcnic_sre_macaddr_change(adapter, + cur->mac_addr, QLCNIC_MAC_ADD)) { + kfree(cur); + return -EIO; + } + + list_add_tail(&cur->list, &adapter->mac_list); + return 0; } void qlcnic_set_multi(struct net_device *netdev) @@ -420,7 +431,7 @@ void qlcnic_set_multi(struct net_device *netdev) u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) return; qlcnic_nic_add_mac(adapter, adapter->mac_addr); @@ -538,7 +549,7 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) return rv; } -int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable) +int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) { struct qlcnic_nic_req req; u64 word; @@ -704,21 +715,15 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu) return rc; } -int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac) +int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac) { - u32 crbaddr, mac_hi, mac_lo; + u32 crbaddr; int pci_func = adapter->ahw.pci_func; crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); - mac_lo = QLCRD32(adapter, crbaddr); - mac_hi = QLCRD32(adapter, crbaddr+4); - - if (pci_func & 1) - *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); - else - *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32)); + qlcnic_fetch_mac(adapter, crbaddr, crbaddr+4, pci_func & 1, mac); return 0; } @@ -766,7 +771,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, * Out: 'off' is 2M pci map addr * side effect: lock crb window */ -static void +static int qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) { u32 window; @@ -775,6 +780,10 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) off -= QLCNIC_PCI_CRBSPACE; window = CRB_HI(off); + if (window == 0) { + dev_err(&adapter->pdev->dev, "Invalid offset 0x%lx\n", off); + return -EIO; + } writel(window, addr); if (readl(addr) != window) { @@ -782,7 +791,9 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) dev_warn(&adapter->pdev->dev, "failed to set CRB window to %d off 0x%lx\n", window, off); + return -EIO; } + return 0; } int @@ -803,11 +814,12 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) /* indirect access */ write_lock_irqsave(&adapter->ahw.crb_lock, flags); crb_win_lock(adapter); - qlcnic_pci_set_crbwindow_2M(adapter, off); - writel(data, addr); + rv = qlcnic_pci_set_crbwindow_2M(adapter, off); + if (!rv) + writel(data, addr); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); - return 0; + return rv; } dev_err(&adapter->pdev->dev, @@ -821,7 +833,7 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) { unsigned long flags; int rv; - u32 data; + u32 data = -1; void __iomem *addr = NULL; rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr); @@ -833,8 +845,8 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) /* indirect access */ write_lock_irqsave(&adapter->ahw.crb_lock, flags); crb_win_lock(adapter); - qlcnic_pci_set_crbwindow_2M(adapter, off); - data = readl(addr); + if (!qlcnic_pci_set_crbwindow_2M(adapter, off)) + data = readl(addr); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); return data; diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 71a4e664ad76..6678127ed4f2 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -112,15 +112,42 @@ void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter) rds_ring = &recv_ctx->rds_rings[ring]; for (i = 0; i < rds_ring->num_desc; ++i) { rx_buf = &(rds_ring->rx_buf_arr[i]); - if (rx_buf->state == QLCNIC_BUFFER_FREE) + if (rx_buf->skb == NULL) continue; + pci_unmap_single(adapter->pdev, rx_buf->dma, rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (rx_buf->skb != NULL) - dev_kfree_skb_any(rx_buf->skb); + + dev_kfree_skb_any(rx_buf->skb); + } + } +} + +void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_rx_buffer *rx_buf; + int i, ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + + spin_lock(&rds_ring->lock); + + INIT_LIST_HEAD(&rds_ring->free_list); + + rx_buf = rds_ring->rx_buf_arr; + for (i = 0; i < rds_ring->num_desc; i++) { + list_add_tail(&rx_buf->list, + &rds_ring->free_list); + rx_buf++; } + + spin_unlock(&rds_ring->lock); } } @@ -181,7 +208,9 @@ skip_rds: tx_ring = adapter->tx_ring; vfree(tx_ring->cmd_buf_arr); + tx_ring->cmd_buf_arr = NULL; kfree(adapter->tx_ring); + adapter->tx_ring = NULL; } int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) @@ -264,7 +293,6 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) list_add_tail(&rx_buf->list, &rds_ring->free_list); rx_buf->ref_handle = i; - rx_buf->state = QLCNIC_BUFFER_FREE; rx_buf++; } spin_lock_init(&rds_ring->lock); @@ -413,7 +441,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) /* resetall */ qlcnic_rom_lock(adapter); - QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xffffffff); + QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff); qlcnic_rom_unlock(adapter); if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) || @@ -520,17 +548,16 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { int timeo; u32 val; - val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO); - val = (val >> (adapter->portnum * 4)) & 0xf; - - if ((val & 0x3) != 1) { - dev_err(&adapter->pdev->dev, "Not an Ethernet NIC func=%u\n", - val); - return -EIO; + if (adapter->fw_hal_version == QLCNIC_FW_BASE) { + val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO); + val = QLC_DEV_GET_DRV(val, adapter->portnum); + if ((val & 0x3) != QLCNIC_TYPE_NIC) { + dev_err(&adapter->pdev->dev, + "Not an Ethernet NIC func=%u\n", val); + return -EIO; + } + adapter->physical_port = (val >> 2); } - - adapter->physical_port = (val >> 2); - if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo)) timeo = 30; @@ -544,16 +571,34 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { return 0; } +int +qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter) +{ + u32 ver = -1, min_ver; + + qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET, (int *)&ver); + + ver = QLCNIC_DECODE_VERSION(ver); + min_ver = QLCNIC_MIN_FW_VERSION; + + if (ver < min_ver) { + dev_err(&adapter->pdev->dev, + "firmware version %d.%d.%d unsupported." + "Min supported version %d.%d.%d\n", + _major(ver), _minor(ver), _build(ver), + _major(min_ver), _minor(min_ver), _build(min_ver)); + return -EINVAL; + } + + return 0; +} + static int qlcnic_has_mn(struct qlcnic_adapter *adapter) { - u32 capability, flashed_ver; + u32 capability; capability = 0; - qlcnic_rom_fast_read(adapter, - QLCNIC_FW_VERSION_OFFSET, (int *)&flashed_ver); - flashed_ver = QLCNIC_DECODE_VERSION(flashed_ver); - capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY); if (capability & QLCNIC_PEG_TUNE_MN_PRESENT) return 1; @@ -1007,7 +1052,7 @@ static int qlcnic_validate_firmware(struct qlcnic_adapter *adapter) { __le32 val; - u32 ver, min_ver, bios, min_size; + u32 ver, bios, min_size; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; u8 fw_type = adapter->fw_type; @@ -1029,12 +1074,9 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) return -EINVAL; val = qlcnic_get_fw_version(adapter); - - min_ver = QLCNIC_VERSION_CODE(4, 0, 216); - ver = QLCNIC_DECODE_VERSION(val); - if ((_major(ver) > _QLCNIC_LINUX_MAJOR) || (ver < min_ver)) { + if (ver < QLCNIC_MIN_FW_VERSION) { dev_err(&pdev->dev, "%s: firmware version %d.%d.%d unsupported\n", fw_name[fw_type], _major(ver), _minor(ver), _build(ver)); @@ -1122,7 +1164,7 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter) adapter->fw = NULL; } -int qlcnic_phantom_init(struct qlcnic_adapter *adapter) +static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter) { u32 val; int retries = 60; @@ -1147,7 +1189,8 @@ int qlcnic_phantom_init(struct qlcnic_adapter *adapter) QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); out_err: - dev_err(&adapter->pdev->dev, "firmware init failed\n"); + dev_err(&adapter->pdev->dev, "Command Peg initialization not " + "complete, state: 0x%x.\n", val); return -EIO; } @@ -1180,6 +1223,10 @@ int qlcnic_init_firmware(struct qlcnic_adapter *adapter) { int err; + err = qlcnic_cmd_peg_ready(adapter); + if (err) + return err; + err = qlcnic_receive_peg_ready(adapter); if (err) return err; @@ -1265,14 +1312,12 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, dma_addr_t dma; struct pci_dev *pdev = adapter->pdev; - buffer->skb = dev_alloc_skb(rds_ring->skb_size); - if (!buffer->skb) { + skb = dev_alloc_skb(rds_ring->skb_size); + if (!skb) { adapter->stats.skb_alloc_failure++; return -ENOMEM; } - skb = buffer->skb; - skb_reserve(skb, 2); dma = pci_map_single(pdev, skb->data, @@ -1281,13 +1326,11 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, if (pci_dma_mapping_error(pdev, dma)) { adapter->stats.rx_dma_map_error++; dev_kfree_skb_any(skb); - buffer->skb = NULL; return -ENOMEM; } buffer->skb = skb; buffer->dma = dma; - buffer->state = QLCNIC_BUFFER_BUSY; return 0; } @@ -1300,14 +1343,15 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, buffer = &rds_ring->rx_buf_arr[index]; + if (unlikely(buffer->skb == NULL)) { + WARN_ON(1); + return NULL; + } + pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, PCI_DMA_FROMDEVICE); skb = buffer->skb; - if (!skb) { - adapter->stats.null_skb++; - goto no_skb; - } if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) { adapter->stats.csummed++; @@ -1319,8 +1363,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, skb->dev = adapter->netdev; buffer->skb = NULL; -no_skb: - buffer->state = QLCNIC_BUFFER_FREE; + return skb; } @@ -1495,7 +1538,7 @@ qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) WARN_ON(desc_cnt > 1); - if (rxbuf) + if (likely(rxbuf)) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); else adapter->stats.null_rxbuf++; @@ -1701,3 +1744,24 @@ qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) sds_ring->consumer = consumer; writel(consumer, sds_ring->crb_sts_consumer); } + +void +qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2, + u8 alt_mac, u8 *mac) +{ + u32 mac_low, mac_high; + int i; + + mac_low = QLCRD32(adapter, off1); + mac_high = QLCRD32(adapter, off2); + + if (alt_mac) { + mac_low |= (mac_low >> 16) | (mac_high << 16); + mac_high >>= 16; + } + + for (i = 0; i < 2; i++) + mac[i] = (u8)(mac_high >> ((1 - i) * 8)); + for (i = 2; i < 6; i++) + mac[i] = (u8)(mac_low >> ((5 - i) * 8)); +} diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 23ea9caa5261..3b71dfcd6d44 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -35,14 +35,14 @@ #include <linux/inetdevice.h> #include <linux/sysfs.h> -MODULE_DESCRIPTION("QLogic 10 GbE Converged Ethernet Driver"); +MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(QLCNIC_LINUX_VERSIONID); MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME); char qlcnic_driver_name[] = "qlcnic"; -static const char qlcnic_driver_string[] = "QLogic Converged Ethernet Driver v" - QLCNIC_LINUX_VERSIONID; +static const char qlcnic_driver_string[] = "QLogic 1/10 GbE " + "Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID; static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG; @@ -65,13 +65,16 @@ static int load_fw_file; module_param(load_fw_file, int, 0644); MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); +static int qlcnic_config_npars; +module_param(qlcnic_config_npars, int, 0644); +MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled"); + static int __devinit qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void __devexit qlcnic_remove(struct pci_dev *pdev); static int qlcnic_open(struct net_device *netdev); static int qlcnic_close(struct net_device *netdev); static void qlcnic_tx_timeout(struct net_device *netdev); -static void qlcnic_tx_timeout_task(struct work_struct *work); static void qlcnic_attach_work(struct work_struct *work); static void qlcnic_fwinit_work(struct work_struct *work); static void qlcnic_fw_poll_work(struct work_struct *work); @@ -79,6 +82,7 @@ static void qlcnic_schedule_work(struct qlcnic_adapter *adapter, work_func_t func, int delay); static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter); static int qlcnic_poll(struct napi_struct *napi, int budget); +static int qlcnic_rx_poll(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev); #endif @@ -99,7 +103,14 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data); static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev); static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long); - +static int qlcnic_start_firmware(struct qlcnic_adapter *); + +static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); +static void qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *); +static int qlcnicvf_set_ilb_mode(struct qlcnic_adapter *); +static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); +static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); +static int qlcnicvf_start_firmware(struct qlcnic_adapter *); /* PCI Device ID Table */ #define ENTRY(device) \ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ @@ -120,12 +131,6 @@ qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring) { writel(tx_ring->producer, tx_ring->crb_cmd_producer); - - if (qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH) { - netif_stop_queue(adapter->netdev); - smp_mb(); - adapter->stats.xmit_off++; - } } static const u32 msi_tgt_status[8] = { @@ -184,8 +189,13 @@ qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - netif_napi_add(netdev, &sds_ring->napi, - qlcnic_poll, QLCNIC_NETDEV_WEIGHT); + + if (ring == adapter->max_sds_rings - 1) + netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, + QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings); + else + netif_napi_add(netdev, &sds_ring->napi, + qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2); } return 0; @@ -307,19 +317,14 @@ static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count) static int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) { - int i; - unsigned char *p; - u64 mac_addr; + u8 mac_addr[ETH_ALEN]; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - if (qlcnic_get_mac_addr(adapter, &mac_addr) != 0) + if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0) return -EIO; - p = (unsigned char *)&mac_addr; - for (i = 0; i < 6; i++) - netdev->dev_addr[i] = *(p + 5 - i); - + memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); @@ -340,7 +345,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; - if (netif_running(netdev)) { + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { netif_device_detach(netdev); qlcnic_napi_disable(adapter); } @@ -349,7 +354,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); qlcnic_set_multi(adapter->netdev); - if (netif_running(netdev)) { + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { netif_device_attach(netdev); qlcnic_napi_enable(adapter); } @@ -371,6 +376,33 @@ static const struct net_device_ops qlcnic_netdev_ops = { #endif }; +static struct qlcnic_nic_template qlcnic_ops = { + .get_mac_addr = qlcnic_get_mac_addr, + .config_bridged_mode = qlcnic_config_bridged_mode, + .config_led = qlcnic_config_led, + .set_ilb_mode = qlcnic_set_ilb_mode, + .clear_ilb_mode = qlcnic_clear_ilb_mode, + .start_firmware = qlcnic_start_firmware +}; + +static struct qlcnic_nic_template qlcnic_pf_ops = { + .get_mac_addr = qlcnic_get_mac_address, + .config_bridged_mode = qlcnic_config_bridged_mode, + .config_led = qlcnic_config_led, + .set_ilb_mode = qlcnic_set_ilb_mode, + .clear_ilb_mode = qlcnic_clear_ilb_mode, + .start_firmware = qlcnic_start_firmware +}; + +static struct qlcnic_nic_template qlcnic_vf_ops = { + .get_mac_addr = qlcnic_get_mac_address, + .config_bridged_mode = qlcnicvf_config_bridged_mode, + .config_led = qlcnicvf_config_led, + .set_ilb_mode = qlcnicvf_set_ilb_mode, + .clear_ilb_mode = qlcnicvf_clear_ilb_mode, + .start_firmware = qlcnicvf_start_firmware +}; + static void qlcnic_setup_intr(struct qlcnic_adapter *adapter) { @@ -453,6 +485,121 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) } static int +qlcnic_set_function_modes(struct qlcnic_adapter *adapter) +{ + u8 id; + u32 ref_count; + int i, ret = 1; + u32 data = QLCNIC_MGMT_FUNC; + void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + + /* If other drivers are not in use set their privilege level */ + ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + ret = qlcnic_api_lock(adapter); + if (ret) + goto err_lock; + if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func)) + goto err_npar; + + if (qlcnic_config_npars) { + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + id = adapter->npars[i].id; + if (adapter->npars[i].type != QLCNIC_TYPE_NIC || + id == adapter->ahw.pci_func) + continue; + data |= (qlcnic_config_npars & + QLC_DEV_SET_DRV(0xf, id)); + } + } else { + data = readl(priv_op); + data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw.pci_func)) | + (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, + adapter->ahw.pci_func)); + } + writel(data, priv_op); +err_npar: + qlcnic_api_unlock(adapter); +err_lock: + return ret; +} + +static u32 +qlcnic_get_driver_mode(struct qlcnic_adapter *adapter) +{ + void __iomem *msix_base_addr; + void __iomem *priv_op; + u32 func; + u32 msix_base; + u32 op_mode, priv_level; + + /* Determine FW API version */ + adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API); + if (adapter->fw_hal_version == ~0) { + adapter->nic_ops = &qlcnic_ops; + adapter->fw_hal_version = QLCNIC_FW_BASE; + adapter->ahw.pci_func = PCI_FUNC(adapter->pdev->devfn); + adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1); + dev_info(&adapter->pdev->dev, + "FW does not support nic partion\n"); + return adapter->fw_hal_version; + } + + /* Find PCI function number */ + pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func); + msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE; + msix_base = readl(msix_base_addr); + func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE; + adapter->ahw.pci_func = func; + + qlcnic_get_nic_info(adapter, adapter->ahw.pci_func); + + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { + adapter->nic_ops = &qlcnic_ops; + return adapter->fw_hal_version; + } + + /* Determine function privilege level */ + priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + op_mode = readl(priv_op); + if (op_mode == QLC_DEV_DRV_DEFAULT) + priv_level = QLCNIC_MGMT_FUNC; + else + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + + switch (priv_level) { + case QLCNIC_MGMT_FUNC: + adapter->op_mode = QLCNIC_MGMT_FUNC; + adapter->nic_ops = &qlcnic_pf_ops; + qlcnic_get_pci_info(adapter); + /* Set privilege level for other functions */ + qlcnic_set_function_modes(adapter); + dev_info(&adapter->pdev->dev, + "HAL Version: %d, Management function\n", + adapter->fw_hal_version); + break; + case QLCNIC_PRIV_FUNC: + adapter->op_mode = QLCNIC_PRIV_FUNC; + dev_info(&adapter->pdev->dev, + "HAL Version: %d, Privileged function\n", + adapter->fw_hal_version); + adapter->nic_ops = &qlcnic_pf_ops; + break; + case QLCNIC_NON_PRIV_FUNC: + adapter->op_mode = QLCNIC_NON_PRIV_FUNC; + dev_info(&adapter->pdev->dev, + "HAL Version: %d Non Privileged function\n", + adapter->fw_hal_version); + adapter->nic_ops = &qlcnic_vf_ops; + break; + default: + dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n", + priv_level); + return 0; + } + return adapter->fw_hal_version; +} + +static int qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) { void __iomem *mem_ptr0 = NULL; @@ -460,7 +607,6 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) unsigned long mem_len, pci_len0 = 0; struct pci_dev *pdev = adapter->pdev; - int pci_func = adapter->ahw.pci_func; /* remap phys address */ mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ @@ -483,8 +629,13 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) adapter->ahw.pci_base0 = mem_ptr0; adapter->ahw.pci_len0 = pci_len0; + if (!qlcnic_get_driver_mode(adapter)) { + iounmap(adapter->ahw.pci_base0); + return -EIO; + } + adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func))); + QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func))); return 0; } @@ -509,7 +660,7 @@ static void get_brd_name(struct qlcnic_adapter *adapter, char *name) } if (!found) - name = "Unknown"; + sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr); } static void @@ -553,8 +704,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) dev_info(&pdev->dev, "firmware v%d.%d.%d\n", fw_major, fw_minor, fw_build); - adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1); - adapter->flags &= ~QLCNIC_LRO_ENABLED; if (adapter->ahw.port_type == QLCNIC_XGBE) { @@ -565,6 +714,8 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; } + qlcnic_get_nic_info(adapter, adapter->ahw.pci_func); + adapter->msix_supported = !!use_msi_x; adapter->rss_supported = !!use_msi_x; @@ -591,8 +742,12 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) if (load_fw_file) qlcnic_request_firmware(adapter); - else + else { + if (qlcnic_check_flash_fw_ver(adapter)) + goto err_out; + adapter->fw_type = QLCNIC_FLASH_ROMIMAGE; + } err = qlcnic_need_fw_reset(adapter); if (err < 0) @@ -602,6 +757,7 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) if (first_boot != 0x55555555) { QLCWR32(adapter, CRB_CMDPEG_STATE, 0); + QLCWR32(adapter, CRB_RCVPEG_STATE, 0); qlcnic_pinit_from_rom(adapter); msleep(1); } @@ -624,7 +780,7 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) wait_init: /* Handshake with the card before we register the devices. */ - err = qlcnic_phantom_init(adapter); + err = qlcnic_init_firmware(adapter); if (err) goto err_out; @@ -633,6 +789,10 @@ wait_init: qlcnic_check_options(adapter); + if (adapter->flags & QLCNIC_ESWITCH_ENABLED && + adapter->op_mode != QLCNIC_NON_PRIV_FUNC) + qlcnic_dev_set_npar_ready(adapter); + adapter->need_fw_reset = 0; qlcnic_release_firmware(adapter); @@ -716,9 +876,23 @@ qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter) static int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) { + int ring; + struct qlcnic_host_rds_ring *rds_ring; + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) return -EIO; + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) + return 0; + + if (qlcnic_fw_create_ctx(adapter)) + return -EIO; + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx.rds_rings[ring]; + qlcnic_post_rx_buffers(adapter, ring, rds_ring); + } + qlcnic_set_multi(netdev); qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu); @@ -736,6 +910,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_linkevent_request(adapter, 1); + adapter->reset_context = 0; set_bit(__QLCNIC_DEV_UP, &adapter->state); return 0; } @@ -775,6 +950,9 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_napi_disable(adapter); + qlcnic_fw_destroy_ctx(adapter); + + qlcnic_reset_rx_buffers_list(adapter); qlcnic_release_tx_buffers(adapter); spin_unlock(&adapter->tx_clean_lock); } @@ -796,16 +974,11 @@ qlcnic_attach(struct qlcnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - int err, ring; - struct qlcnic_host_rds_ring *rds_ring; + int err; if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) return 0; - err = qlcnic_init_firmware(adapter); - if (err) - return err; - err = qlcnic_napi_add(adapter, netdev); if (err) return err; @@ -813,7 +986,7 @@ qlcnic_attach(struct qlcnic_adapter *adapter) err = qlcnic_alloc_sw_resources(adapter); if (err) { dev_err(&pdev->dev, "Error in setting sw resources\n"); - return err; + goto err_out_napi_del; } err = qlcnic_alloc_hw_resources(adapter); @@ -822,16 +995,10 @@ qlcnic_attach(struct qlcnic_adapter *adapter) goto err_out_free_sw; } - - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &adapter->recv_ctx.rds_rings[ring]; - qlcnic_post_rx_buffers(adapter, ring, rds_ring); - } - err = qlcnic_request_irq(adapter); if (err) { dev_err(&pdev->dev, "failed to setup interrupt\n"); - goto err_out_free_rxbuf; + goto err_out_free_hw; } qlcnic_init_coalesce_defaults(adapter); @@ -841,11 +1008,12 @@ qlcnic_attach(struct qlcnic_adapter *adapter) adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC; return 0; -err_out_free_rxbuf: - qlcnic_release_rx_buffers(adapter); +err_out_free_hw: qlcnic_free_hw_resources(adapter); err_out_free_sw: qlcnic_free_sw_resources(adapter); +err_out_napi_del: + qlcnic_napi_del(adapter); return err; } @@ -880,6 +1048,8 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) } } + qlcnic_fw_destroy_ctx(adapter); + qlcnic_detach(adapter); adapter->diag_test = 0; @@ -898,6 +1068,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) { struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_host_rds_ring *rds_ring; int ring; int ret; @@ -917,6 +1088,17 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) return ret; } + ret = qlcnic_fw_create_ctx(adapter); + if (ret) { + qlcnic_detach(adapter); + return ret; + } + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx.rds_rings[ring]; + qlcnic_post_rx_buffers(adapter, ring, rds_ring); + } + if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &adapter->recv_ctx.sds_rings[ring]; @@ -928,6 +1110,27 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) return 0; } +/* Reset context in hardware only */ +static int +qlcnic_reset_hw_context(struct qlcnic_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EBUSY; + + netif_device_detach(netdev); + + qlcnic_down(adapter, netdev); + + qlcnic_up(adapter, netdev); + + netif_device_attach(netdev); + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return 0; +} + int qlcnic_reset_context(struct qlcnic_adapter *adapter) { @@ -971,18 +1174,17 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, adapter->max_mc_count = 38; netdev->netdev_ops = &qlcnic_netdev_ops; - netdev->watchdog_timeo = 2*HZ; + netdev->watchdog_timeo = 5*HZ; qlcnic_change_mtu(netdev, netdev->mtu); SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); - netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - netdev->features |= (NETIF_F_GRO); - netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6); - netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6); if (pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; @@ -997,8 +1199,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->irq = adapter->msix_entries[0].vector; - INIT_WORK(&adapter->tx_timeout_task, qlcnic_tx_timeout_task); - if (qlcnic_read_mac_addr(adapter)) dev_warn(&pdev->dev, "failed to read mac addr\n"); @@ -1036,7 +1236,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *netdev = NULL; struct qlcnic_adapter *adapter = NULL; int err; - int pci_func_id = PCI_FUNC(pdev->devfn); uint8_t revision_id; uint8_t pci_using_dac; @@ -1072,7 +1271,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->netdev = netdev; adapter->pdev = pdev; adapter->dev_rst_time = jiffies; - adapter->ahw.pci_func = pci_func_id; revision_id = pdev->revision; adapter->ahw.revision_id = revision_id; @@ -1088,7 +1286,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_netdev; /* This will be reset for mezz cards */ - adapter->portnum = pci_func_id; + adapter->portnum = adapter->ahw.pci_func; err = qlcnic_get_board_info(adapter); if (err) { @@ -1102,7 +1300,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (qlcnic_setup_idc_param(adapter)) goto err_out_iounmap; - err = qlcnic_start_firmware(adapter); + err = adapter->nic_ops->start_firmware(adapter); if (err) { dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"); goto err_out_decr_ref; @@ -1171,10 +1369,13 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) unregister_netdev(netdev); - cancel_work_sync(&adapter->tx_timeout_task); - qlcnic_detach(adapter); + if (adapter->npars != NULL) + kfree(adapter->npars); + if (adapter->eswitch != NULL) + kfree(adapter->eswitch); + qlcnic_clr_all_drv_state(adapter); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1206,10 +1407,6 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) if (netif_running(netdev)) qlcnic_down(adapter, netdev); - cancel_work_sync(&adapter->tx_timeout_task); - - qlcnic_detach(adapter); - qlcnic_clr_all_drv_state(adapter); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1263,35 +1460,23 @@ qlcnic_resume(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - err = qlcnic_start_firmware(adapter); + err = adapter->nic_ops->start_firmware(adapter); if (err) { dev_err(&pdev->dev, "failed to start firmware\n"); return err; } if (netif_running(netdev)) { - err = qlcnic_attach(adapter); - if (err) - goto err_out; - err = qlcnic_up(adapter, netdev); if (err) - goto err_out_detach; - + goto done; qlcnic_config_indev_addr(netdev, NETDEV_UP); } - +done: netif_device_attach(netdev); qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); return 0; - -err_out_detach: - qlcnic_detach(adapter); -err_out: - qlcnic_clr_all_drv_state(adapter); - netif_device_attach(netdev); - return err; } #endif @@ -1340,11 +1525,11 @@ qlcnic_tso_check(struct net_device *netdev, u8 opcode = TX_ETHER_PKT; __be16 protocol = skb->protocol; u16 flags = 0, vid = 0; - u32 producer; int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; struct cmd_desc_type0 *hwdesc; struct vlan_ethhdr *vh; struct qlcnic_adapter *adapter = netdev_priv(netdev); + u32 producer = tx_ring->producer; if (protocol == cpu_to_be16(ETH_P_8021Q)) { @@ -1360,6 +1545,11 @@ qlcnic_tso_check(struct net_device *netdev, vlan_oob = 1; } + if (*(skb->data) & BIT_0) { + flags |= BIT_0; + memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN); + } + if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { @@ -1409,7 +1599,6 @@ qlcnic_tso_check(struct net_device *netdev, /* For LSO, we need to copy the MAC/IP/TCP headers into * the descriptor ring */ - producer = tx_ring->producer; copied = 0; offset = 2; @@ -1537,10 +1726,15 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* 4 fragments per cmd des */ no_of_desc = (frag_count + 3) >> 2; - if (unlikely(no_of_desc + 2 > qlcnic_tx_avail(tx_ring))) { + if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { netif_stop_queue(netdev); - adapter->stats.xmit_off++; - return NETDEV_TX_BUSY; + smp_mb(); + if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) + netif_start_queue(netdev); + else { + adapter->stats.xmit_off++; + return NETDEV_TX_BUSY; + } } producer = tx_ring->producer; @@ -1675,35 +1869,11 @@ static void qlcnic_tx_timeout(struct net_device *netdev) return; dev_err(&netdev->dev, "transmit timeout, resetting.\n"); - schedule_work(&adapter->tx_timeout_task); -} - -static void qlcnic_tx_timeout_task(struct work_struct *work) -{ - struct qlcnic_adapter *adapter = - container_of(work, struct qlcnic_adapter, tx_timeout_task); - - if (!netif_running(adapter->netdev)) - return; - - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) - return; if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) - goto request_reset; - - clear_bit(__QLCNIC_RESETTING, &adapter->state); - if (!qlcnic_reset_context(adapter)) { - adapter->netdev->trans_start = jiffies; - return; - - /* context reset failed, fall through for fw reset */ - } - -request_reset: - adapter->need_fw_reset = 1; - clear_bit(__QLCNIC_RESETTING, &adapter->state); - QLCDB(adapter, DRV, "Resetting adapter\n"); + adapter->need_fw_reset = 1; + else + adapter->reset_context = 1; } static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) @@ -1846,14 +2016,12 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) smp_mb(); if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { - __netif_tx_lock(tx_ring->txq, smp_processor_id()); if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { netif_wake_queue(netdev); - adapter->tx_timeo_cnt = 0; adapter->stats.xmit_on++; } - __netif_tx_unlock(tx_ring->txq); } + adapter->tx_timeo_cnt = 0; } /* * If everything is freed up to consumer then check if the ring is full @@ -1898,6 +2066,25 @@ static int qlcnic_poll(struct napi_struct *napi, int budget) return work_done; } +static int qlcnic_rx_poll(struct napi_struct *napi, int budget) +{ + struct qlcnic_host_sds_ring *sds_ring = + container_of(napi, struct qlcnic_host_sds_ring, napi); + + struct qlcnic_adapter *adapter = sds_ring->adapter; + int work_done; + + work_done = qlcnic_process_rcv_ring(sds_ring, budget); + + if (work_done < budget) { + napi_complete(&sds_ring->napi); + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) + qlcnic_enable_int(sds_ring); + } + + return work_done; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev) { @@ -2109,7 +2296,7 @@ qlcnic_fwinit_work(struct work_struct *work) { struct qlcnic_adapter *adapter = container_of(work, struct qlcnic_adapter, fw_work.work); - u32 dev_state = 0xf; + u32 dev_state = 0xf, npar_state; if (qlcnic_api_lock(adapter)) goto err_ret; @@ -2122,6 +2309,19 @@ qlcnic_fwinit_work(struct work_struct *work) return; } + if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { + npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + if (npar_state == QLCNIC_DEV_NPAR_RDY) { + qlcnic_api_unlock(adapter); + goto wait_npar; + } else { + qlcnic_schedule_work(adapter, qlcnic_fwinit_work, + FW_POLL_DELAY); + qlcnic_api_unlock(adapter); + return; + } + } + if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) { dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n", adapter->reset_ack_timeo); @@ -2154,7 +2354,7 @@ skip_ack_check: qlcnic_api_unlock(adapter); - if (!qlcnic_start_firmware(adapter)) { + if (!adapter->nic_ops->start_firmware(adapter)) { qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); return; } @@ -2163,6 +2363,7 @@ skip_ack_check: qlcnic_api_unlock(adapter); +wait_npar: dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state); @@ -2177,7 +2378,7 @@ skip_ack_check: break; default: - if (!qlcnic_start_firmware(adapter)) { + if (!adapter->nic_ops->start_firmware(adapter)) { qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); return; } @@ -2202,10 +2403,6 @@ qlcnic_detach_work(struct work_struct *work) qlcnic_down(adapter, netdev); - rtnl_lock(); - qlcnic_detach(adapter); - rtnl_unlock(); - status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); if (status & QLCNIC_RCODE_FATAL_ERROR) @@ -2251,6 +2448,26 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) qlcnic_api_unlock(adapter); } +/* Transit to NPAR READY state from NPAR NOT READY state */ +static void +qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter) +{ + u32 state; + + if (qlcnic_api_lock(adapter)) + return; + + state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); + + if (state != QLCNIC_DEV_NPAR_RDY) { + QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, + QLCNIC_DEV_NPAR_RDY); + QLCDB(adapter, DRV, "NPAR READY state set\n"); + } + + qlcnic_api_unlock(adapter); +} + static void qlcnic_schedule_work(struct qlcnic_adapter *adapter, work_func_t func, int delay) @@ -2274,18 +2491,10 @@ qlcnic_attach_work(struct work_struct *work) struct qlcnic_adapter *adapter = container_of(work, struct qlcnic_adapter, fw_work.work); struct net_device *netdev = adapter->netdev; - int err; if (netif_running(netdev)) { - err = qlcnic_attach(adapter); - if (err) - goto done; - - err = qlcnic_up(adapter, netdev); - if (err) { - qlcnic_detach(adapter); + if (qlcnic_up(adapter, netdev)) goto done; - } qlcnic_config_indev_addr(netdev, NETDEV_UP); } @@ -2322,6 +2531,12 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) adapter->fw_fail_cnt = 0; if (adapter->need_fw_reset) goto detach; + + if (adapter->reset_context) { + qlcnic_reset_hw_context(adapter); + adapter->netdev->trans_start = jiffies; + } + return 0; } @@ -2365,6 +2580,46 @@ reschedule: qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); } +static int +qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) +{ + int err; + + err = qlcnic_can_start_firmware(adapter); + if (err) + return err; + + qlcnic_check_options(adapter); + + adapter->need_fw_reset = 0; + + return err; +} + +static int +qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) +{ + return -EOPNOTSUPP; +} + +static int +qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) +{ + return -EOPNOTSUPP; +} + +static int +qlcnicvf_set_ilb_mode(struct qlcnic_adapter *adapter) +{ + return -EOPNOTSUPP; +} + +static void +qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *adapter) +{ + return; +} + static ssize_t qlcnic_store_bridged_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -2376,13 +2631,13 @@ qlcnic_store_bridged_mode(struct device *dev, if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)) goto err_out; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) goto err_out; if (strict_strtoul(buf, 2, &new)) goto err_out; - if (!qlcnic_config_bridged_mode(adapter, !!new)) + if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) ret = len; err_out: @@ -2684,7 +2939,7 @@ recheck: if (!adapter) goto done; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) goto done; qlcnic_config_indev_addr(dev, event); @@ -2720,7 +2975,7 @@ recheck: if (!adapter) goto done; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) goto done; switch (event) { diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 20624ba44a37..bfb8b327f2fd 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1062,7 +1062,7 @@ struct tx_buf_desc { #define TX_DESC_LEN_MASK 0x000fffff #define TX_DESC_C 0x40000000 #define TX_DESC_E 0x80000000 -} __attribute((packed)); +} __packed; /* * IOCB Definitions... @@ -1095,7 +1095,7 @@ struct ob_mac_iocb_req { __le16 vlan_tci; __le16 reserved4; struct tx_buf_desc tbd[TX_DESC_PER_IOCB]; -} __attribute((packed)); +} __packed; struct ob_mac_iocb_rsp { u8 opcode; /* */ @@ -1112,7 +1112,7 @@ struct ob_mac_iocb_rsp { u32 tid; u32 txq_idx; __le32 reserved[13]; -} __attribute((packed)); +} __packed; struct ob_mac_tso_iocb_req { u8 opcode; @@ -1140,7 +1140,7 @@ struct ob_mac_tso_iocb_req { __le16 vlan_tci; __le16 mss; struct tx_buf_desc tbd[TX_DESC_PER_IOCB]; -} __attribute((packed)); +} __packed; struct ob_mac_tso_iocb_rsp { u8 opcode; @@ -1157,7 +1157,7 @@ struct ob_mac_tso_iocb_rsp { u32 tid; u32 txq_idx; __le32 reserved2[13]; -} __attribute((packed)); +} __packed; struct ib_mac_iocb_rsp { u8 opcode; /* 0x20 */ @@ -1216,7 +1216,7 @@ struct ib_mac_iocb_rsp { #define IB_MAC_IOCB_RSP_HL 0x80 __le32 hdr_len; /* */ __le64 hdr_addr; /* */ -} __attribute((packed)); +} __packed; struct ib_ae_iocb_rsp { u8 opcode; @@ -1237,7 +1237,7 @@ struct ib_ae_iocb_rsp { #define PCI_ERR_ANON_BUF_RD 0x40 u8 q_id; __le32 reserved[15]; -} __attribute((packed)); +} __packed; /* * These three structures are for generic @@ -1249,7 +1249,7 @@ struct ql_net_rsp_iocb { __le16 length; __le32 tid; __le32 reserved[14]; -} __attribute((packed)); +} __packed; struct net_req_iocb { u8 opcode; @@ -1257,7 +1257,7 @@ struct net_req_iocb { __le16 flags1; __le32 tid; __le32 reserved1[30]; -} __attribute((packed)); +} __packed; /* * tx ring initialization control block for chip. @@ -1283,7 +1283,7 @@ struct wqicb { __le16 rid; __le64 addr; __le64 cnsmr_idx_addr; -} __attribute((packed)); +} __packed; /* * rx ring initialization control block for chip. @@ -1317,7 +1317,7 @@ struct cqicb { __le64 sbq_addr; __le16 sbq_buf_size; __le16 sbq_len; /* entry count */ -} __attribute((packed)); +} __packed; struct ricb { u8 base_cq; @@ -1335,7 +1335,7 @@ struct ricb { u8 hash_cq_id[1024]; __le32 ipv6_hash_key[10]; __le32 ipv4_hash_key[4]; -} __attribute((packed)); +} __packed; /* SOFTWARE/DRIVER DATA STRUCTURES. */ diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 9a251acf5ab8..7d482a2316ac 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -44,12 +44,13 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/uaccess.h> +#include <linux/phy.h> #include <asm/processor.h> #define DRV_NAME "r6040" -#define DRV_VERSION "0.25" -#define DRV_RELDATE "20Aug2009" +#define DRV_VERSION "0.26" +#define DRV_RELDATE "30May2010" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ @@ -179,7 +180,6 @@ struct r6040_descriptor { struct r6040_private { spinlock_t lock; /* driver lock */ - struct timer_list timer; struct pci_dev *pdev; struct r6040_descriptor *rx_insert_ptr; struct r6040_descriptor *rx_remove_ptr; @@ -189,13 +189,15 @@ struct r6040_private { struct r6040_descriptor *tx_ring; dma_addr_t rx_ring_dma; dma_addr_t tx_ring_dma; - u16 tx_free_desc, phy_addr, phy_mode; + u16 tx_free_desc, phy_addr; u16 mcr0, mcr1; - u16 switch_sig; struct net_device *dev; - struct mii_if_info mii_if; + struct mii_bus *mii_bus; struct napi_struct napi; void __iomem *base; + struct phy_device *phydev; + int old_link; + int old_duplex; }; static char version[] __devinitdata = KERN_INFO DRV_NAME @@ -238,20 +240,30 @@ static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val } } -static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg) +static int r6040_mdiobus_read(struct mii_bus *bus, int phy_addr, int reg) { + struct net_device *dev = bus->priv; struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - return (r6040_phy_read(ioaddr, lp->phy_addr, reg)); + return r6040_phy_read(ioaddr, phy_addr, reg); } -static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static int r6040_mdiobus_write(struct mii_bus *bus, int phy_addr, + int reg, u16 value) { + struct net_device *dev = bus->priv; struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - r6040_phy_write(ioaddr, lp->phy_addr, reg, val); + r6040_phy_write(ioaddr, phy_addr, reg, value); + + return 0; +} + +static int r6040_mdiobus_reset(struct mii_bus *bus) +{ + return 0; } static void r6040_free_txbufs(struct net_device *dev) @@ -408,10 +420,9 @@ static void r6040_tx_timeout(struct net_device *dev) void __iomem *ioaddr = priv->base; netdev_warn(dev, "transmit timed out, int enable %4.4x " - "status %4.4x, PHY status %4.4x\n", + "status %4.4x\n", ioread16(ioaddr + MIER), - ioread16(ioaddr + MISR), - r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR)); + ioread16(ioaddr + MISR)); dev->stats.tx_errors++; @@ -463,9 +474,6 @@ static int r6040_close(struct net_device *dev) struct r6040_private *lp = netdev_priv(dev); struct pci_dev *pdev = lp->pdev; - /* deleted timer */ - del_timer_sync(&lp->timer); - spin_lock_irq(&lp->lock); napi_disable(&lp->napi); netif_stop_queue(dev); @@ -495,64 +503,14 @@ static int r6040_close(struct net_device *dev) return 0; } -/* Status of PHY CHIP */ -static int r6040_phy_mode_chk(struct net_device *dev) -{ - struct r6040_private *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - int phy_dat; - - /* PHY Link Status Check */ - phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1); - if (!(phy_dat & 0x4)) - phy_dat = 0x8000; /* Link Failed, full duplex */ - - /* PHY Chip Auto-Negotiation Status */ - phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1); - if (phy_dat & 0x0020) { - /* Auto Negotiation Mode */ - phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5); - phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4); - if (phy_dat & 0x140) - /* Force full duplex */ - phy_dat = 0x8000; - else - phy_dat = 0; - } else { - /* Force Mode */ - phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0); - if (phy_dat & 0x100) - phy_dat = 0x8000; - else - phy_dat = 0x0000; - } - - return phy_dat; -}; - -static void r6040_set_carrier(struct mii_if_info *mii) -{ - if (r6040_phy_mode_chk(mii->dev)) { - /* autoneg is off: Link is always assumed to be up */ - if (!netif_carrier_ok(mii->dev)) - netif_carrier_on(mii->dev); - } else - r6040_phy_mode_chk(mii->dev); -} - static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct r6040_private *lp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(rq); - int rc; - if (!netif_running(dev)) + if (!lp->phydev) return -EINVAL; - spin_lock_irq(&lp->lock); - rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL); - spin_unlock_irq(&lp->lock); - r6040_set_carrier(&lp->mii_if); - return rc; + + return phy_mii_ioctl(lp->phydev, if_mii(rq), cmd); } static int r6040_rx(struct net_device *dev, int limit) @@ -751,26 +709,6 @@ static int r6040_up(struct net_device *dev) if (ret) return ret; - /* Read the PHY ID */ - lp->switch_sig = r6040_phy_read(ioaddr, 0, 2); - - if (lp->switch_sig == ICPLUS_PHY_ID) { - r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */ - lp->phy_mode = 0x8000; - } else { - /* PHY Mode Check */ - r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP); - r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE); - - if (PHY_MODE == 0x3100) - lp->phy_mode = r6040_phy_mode_chk(dev); - else - lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; - } - - /* Set duplex mode */ - lp->mcr0 |= lp->phy_mode; - /* improve performance (by RDC guys) */ r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000)); r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000)); @@ -783,35 +721,6 @@ static int r6040_up(struct net_device *dev) return 0; } -/* - A periodic timer routine - Polling PHY Chip Link Status -*/ -static void r6040_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct r6040_private *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - u16 phy_mode; - - /* Polling PHY Chip Status */ - if (PHY_MODE == 0x3100) - phy_mode = r6040_phy_mode_chk(dev); - else - phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; - - if (phy_mode != lp->phy_mode) { - lp->phy_mode = phy_mode; - lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode; - iowrite16(lp->mcr0, ioaddr); - } - - /* Timer active again */ - mod_timer(&lp->timer, round_jiffies(jiffies + HZ)); - - /* Check media */ - mii_check_media(&lp->mii_if, 1, 1); -} /* Read/set MAC address routines */ static void r6040_mac_address(struct net_device *dev) @@ -873,10 +782,6 @@ static int r6040_open(struct net_device *dev) napi_enable(&lp->napi); netif_start_queue(dev); - /* set and active a timer process */ - setup_timer(&lp->timer, r6040_timer, (unsigned long) dev); - if (lp->switch_sig != ICPLUS_PHY_ID) - mod_timer(&lp->timer, jiffies + HZ); return 0; } @@ -1015,40 +920,22 @@ static void netdev_get_drvinfo(struct net_device *dev, static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct r6040_private *rp = netdev_priv(dev); - int rc; - - spin_lock_irq(&rp->lock); - rc = mii_ethtool_gset(&rp->mii_if, cmd); - spin_unlock_irq(&rp->lock); - return rc; + return phy_ethtool_gset(rp->phydev, cmd); } static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct r6040_private *rp = netdev_priv(dev); - int rc; - - spin_lock_irq(&rp->lock); - rc = mii_ethtool_sset(&rp->mii_if, cmd); - spin_unlock_irq(&rp->lock); - r6040_set_carrier(&rp->mii_if); - - return rc; -} - -static u32 netdev_get_link(struct net_device *dev) -{ - struct r6040_private *rp = netdev_priv(dev); - return mii_link_ok(&rp->mii_if); + return phy_ethtool_sset(rp->phydev, cmd); } static const struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, .get_settings = netdev_get_settings, .set_settings = netdev_set_settings, - .get_link = netdev_get_link, + .get_link = ethtool_op_get_link, }; static const struct net_device_ops r6040_netdev_ops = { @@ -1067,6 +954,79 @@ static const struct net_device_ops r6040_netdev_ops = { #endif }; +static void r6040_adjust_link(struct net_device *dev) +{ + struct r6040_private *lp = netdev_priv(dev); + struct phy_device *phydev = lp->phydev; + int status_changed = 0; + void __iomem *ioaddr = lp->base; + + BUG_ON(!phydev); + + if (lp->old_link != phydev->link) { + status_changed = 1; + lp->old_link = phydev->link; + } + + /* reflect duplex change */ + if (phydev->link && (lp->old_duplex != phydev->duplex)) { + lp->mcr0 |= (phydev->duplex == DUPLEX_FULL ? 0x8000 : 0); + iowrite16(lp->mcr0, ioaddr); + + status_changed = 1; + lp->old_duplex = phydev->duplex; + } + + if (status_changed) { + pr_info("%s: link %s", dev->name, phydev->link ? + "UP" : "DOWN"); + if (phydev->link) + pr_cont(" - %d/%s", phydev->speed, + DUPLEX_FULL == phydev->duplex ? "full" : "half"); + pr_cont("\n"); + } +} + +static int r6040_mii_probe(struct net_device *dev) +{ + struct r6040_private *lp = netdev_priv(dev); + struct phy_device *phydev = NULL; + + phydev = phy_find_first(lp->mii_bus); + if (!phydev) { + dev_err(&lp->pdev->dev, "no PHY found\n"); + return -ENODEV; + } + + phydev = phy_connect(dev, dev_name(&phydev->dev), &r6040_adjust_link, + 0, PHY_INTERFACE_MODE_MII); + + if (IS_ERR(phydev)) { + dev_err(&lp->pdev->dev, "could not attach to PHY\n"); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + phydev->supported &= (SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_Autoneg + | SUPPORTED_MII + | SUPPORTED_TP); + + phydev->advertising = phydev->supported; + lp->phydev = phydev; + lp->old_link = 0; + lp->old_duplex = -1; + + dev_info(&lp->pdev->dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s)\n", + phydev->drv->name, dev_name(&phydev->dev)); + + return 0; +} + static int __devinit r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1077,6 +1037,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, static int card_idx = -1; int bar = 0; u16 *adrp; + int i; printk("%s\n", version); @@ -1163,7 +1124,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, /* Init RDC private data */ lp->mcr0 = 0x1002; lp->phy_addr = phy_table[card_idx]; - lp->switch_sig = 0; /* The RDC-specific entries in the device structure. */ dev->netdev_ops = &r6040_netdev_ops; @@ -1171,28 +1131,54 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, &lp->napi, r6040_poll, 64); - lp->mii_if.dev = dev; - lp->mii_if.mdio_read = r6040_mdio_read; - lp->mii_if.mdio_write = r6040_mdio_write; - lp->mii_if.phy_id = lp->phy_addr; - lp->mii_if.phy_id_mask = 0x1f; - lp->mii_if.reg_num_mask = 0x1f; - - /* Check the vendor ID on the PHY, if 0xffff assume none attached */ - if (r6040_phy_read(ioaddr, lp->phy_addr, 2) == 0xffff) { - dev_err(&pdev->dev, "Failed to detect an attached PHY\n"); - err = -ENODEV; + + lp->mii_bus = mdiobus_alloc(); + if (!lp->mii_bus) { + dev_err(&pdev->dev, "mdiobus_alloc() failed\n"); goto err_out_unmap; } + lp->mii_bus->priv = dev; + lp->mii_bus->read = r6040_mdiobus_read; + lp->mii_bus->write = r6040_mdiobus_write; + lp->mii_bus->reset = r6040_mdiobus_reset; + lp->mii_bus->name = "r6040_eth_mii"; + snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", card_idx); + lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + if (!lp->mii_bus->irq) { + dev_err(&pdev->dev, "mii_bus irq allocation failed\n"); + goto err_out_mdio; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + lp->mii_bus->irq[i] = PHY_POLL; + + err = mdiobus_register(lp->mii_bus); + if (err) { + dev_err(&pdev->dev, "failed to register MII bus\n"); + goto err_out_mdio_irq; + } + + err = r6040_mii_probe(dev); + if (err) { + dev_err(&pdev->dev, "failed to probe MII bus\n"); + goto err_out_mdio_unregister; + } + /* Register net device. After this dev->name assign */ err = register_netdev(dev); if (err) { dev_err(&pdev->dev, "Failed to register net device\n"); - goto err_out_unmap; + goto err_out_mdio_unregister; } return 0; +err_out_mdio_unregister: + mdiobus_unregister(lp->mii_bus); +err_out_mdio_irq: + kfree(lp->mii_bus->irq); +err_out_mdio: + mdiobus_free(lp->mii_bus); err_out_unmap: pci_iounmap(pdev, ioaddr); err_out_free_res: @@ -1206,8 +1192,12 @@ err_out: static void __devexit r6040_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct r6040_private *lp = netdev_priv(dev); unregister_netdev(dev); + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); pci_release_regions(pdev); free_netdev(dev); pci_disable_device(pdev); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 96b6cfbf0a3a..239d7efdd450 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -88,7 +88,7 @@ static const int multicast_filter_limit = 32; #define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) #define RTL_R8(reg) readb (ioaddr + (reg)) #define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) +#define RTL_R32(reg) readl (ioaddr + (reg)) enum mac_version { RTL_GIGA_MAC_NONE = 0x00, diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 156460527231..8ad476a19d95 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -27,6 +27,7 @@ #include "nic.h" #include "mcdi.h" +#include "workarounds.h" /************************************************************************** * @@ -92,13 +93,6 @@ const char *efx_reset_type_names[] = { #define EFX_MAX_MTU (9 * 1024) -/* RX slow fill workqueue. If memory allocation fails in the fast path, - * a work item is pushed onto this work queue to retry the allocation later, - * to avoid the NIC being starved of RX buffers. Since this is a per cpu - * workqueue, there is nothing to be gained in making it per NIC - */ -static struct workqueue_struct *refill_workqueue; - /* Reset workqueue. If any NIC has a hardware failure then a reset will be * queued onto this work queue. This is not a per-nic work queue, because * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised. @@ -475,7 +469,8 @@ static void efx_init_channels(struct efx_nic *efx) efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + efx->type->rx_buffer_padding); - efx->rx_buffer_order = get_order(efx->rx_buffer_len); + efx->rx_buffer_order = get_order(efx->rx_buffer_len + + sizeof(struct efx_rx_page_state)); /* Initialise the channels */ efx_for_each_channel(channel, efx) { @@ -515,11 +510,11 @@ static void efx_start_channel(struct efx_channel *channel) channel->enabled = true; smp_wmb(); - napi_enable(&channel->napi_str); - - /* Load up RX descriptors */ + /* Fill the queues before enabling NAPI */ efx_for_each_channel_rx_queue(rx_queue, channel) efx_fast_push_rx_descriptors(rx_queue); + + napi_enable(&channel->napi_str); } /* This disables event queue processing and packet transmission. @@ -528,8 +523,6 @@ static void efx_start_channel(struct efx_channel *channel) */ static void efx_stop_channel(struct efx_channel *channel) { - struct efx_rx_queue *rx_queue; - if (!channel->enabled) return; @@ -537,12 +530,6 @@ static void efx_stop_channel(struct efx_channel *channel) channel->enabled = false; napi_disable(&channel->napi_str); - - /* Ensure that any worker threads have exited or will be no-ops */ - efx_for_each_channel_rx_queue(rx_queue, channel) { - spin_lock_bh(&rx_queue->add_lock); - spin_unlock_bh(&rx_queue->add_lock); - } } static void efx_fini_channels(struct efx_nic *efx) @@ -556,10 +543,18 @@ static void efx_fini_channels(struct efx_nic *efx) BUG_ON(efx->port_enabled); rc = efx_nic_flush_queues(efx); - if (rc) + if (rc && EFX_WORKAROUND_7803(efx)) { + /* Schedule a reset to recover from the flush failure. The + * descriptor caches reference memory we're about to free, + * but falcon_reconfigure_mac_wrapper() won't reconnect + * the MACs because of the pending reset. */ + EFX_ERR(efx, "Resetting to recover from flush failure\n"); + efx_schedule_reset(efx, RESET_TYPE_ALL); + } else if (rc) { EFX_ERR(efx, "failed to flush queues\n"); - else + } else { EFX_LOG(efx, "successfully flushed all queues\n"); + } efx_for_each_channel(channel, efx) { EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); @@ -586,9 +581,9 @@ static void efx_remove_channel(struct efx_channel *channel) efx_remove_eventq(channel); } -void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay) +void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue) { - queue_delayed_work(refill_workqueue, &rx_queue->work, delay); + mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100)); } /************************************************************************** @@ -1233,15 +1228,8 @@ static void efx_start_all(struct efx_nic *efx) * since we're holding the rtnl_lock at this point. */ static void efx_flush_all(struct efx_nic *efx) { - struct efx_rx_queue *rx_queue; - /* Make sure the hardware monitor is stopped */ cancel_delayed_work_sync(&efx->monitor_work); - - /* Ensure that all RX slow refills are complete. */ - efx_for_each_rx_queue(rx_queue, efx) - cancel_delayed_work_sync(&rx_queue->work); - /* Stop scheduled port reconfigurations */ cancel_work_sync(&efx->mac_work); } @@ -1504,11 +1492,11 @@ static int efx_net_stop(struct net_device *net_dev) } /* Context: process, dev_base_lock or RTNL held, non-blocking. */ -static struct net_device_stats *efx_net_stats(struct net_device *net_dev) +static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct net_device_stats *stats = &net_dev->stats; + struct rtnl_link_stats64 *stats = &net_dev->stats64; spin_lock_bh(&efx->stats_lock); efx->type->update_stats(efx); @@ -1530,11 +1518,8 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) stats->tx_window_errors = mac_stats->tx_late_collision; stats->rx_errors = (stats->rx_length_errors + - stats->rx_over_errors + stats->rx_crc_errors + stats->rx_frame_errors + - stats->rx_fifo_errors + - stats->rx_missed_errors + mac_stats->rx_symbol_error); stats->tx_errors = (stats->tx_window_errors + mac_stats->tx_bad); @@ -1645,7 +1630,7 @@ static void efx_set_multicast_list(struct net_device *net_dev) static const struct net_device_ops efx_netdev_ops = { .ndo_open = efx_net_open, .ndo_stop = efx_net_stop, - .ndo_get_stats = efx_net_stats, + .ndo_get_stats64 = efx_net_stats, .ndo_tx_timeout = efx_watchdog, .ndo_start_xmit = efx_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, @@ -1886,6 +1871,9 @@ static void efx_reset_work(struct work_struct *data) { struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); + if (efx->reset_pending == RESET_TYPE_NONE) + return; + /* If we're not RUNNING then don't reset. Leave the reset_pending * flag set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { @@ -2052,8 +2040,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, rx_queue->queue = i; rx_queue->channel = &efx->channel[0]; /* for safety */ rx_queue->buffer = NULL; - spin_lock_init(&rx_queue->add_lock); - INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work); + setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill, + (unsigned long)rx_queue); } efx->type = type; @@ -2332,6 +2320,9 @@ static int efx_pm_thaw(struct device *dev) efx->type->resume_wol(efx); + /* Reschedule any quenched resets scheduled during efx_pm_freeze() */ + queue_work(reset_workqueue, &efx->reset_work); + return 0; } @@ -2421,11 +2412,6 @@ static int __init efx_init_module(void) if (rc) goto err_notifier; - refill_workqueue = create_workqueue("sfc_refill"); - if (!refill_workqueue) { - rc = -ENOMEM; - goto err_refill; - } reset_workqueue = create_singlethread_workqueue("sfc_reset"); if (!reset_workqueue) { rc = -ENOMEM; @@ -2441,8 +2427,6 @@ static int __init efx_init_module(void) err_pci: destroy_workqueue(reset_workqueue); err_reset: - destroy_workqueue(refill_workqueue); - err_refill: unregister_netdevice_notifier(&efx_netdev_notifier); err_notifier: return rc; @@ -2454,7 +2438,6 @@ static void __exit efx_exit_module(void) pci_unregister_driver(&efx_pci_driver); destroy_workqueue(reset_workqueue); - destroy_workqueue(refill_workqueue); unregister_netdevice_notifier(&efx_netdev_notifier); } diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index ffd708c5304a..e1e448887dfc 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -47,12 +47,12 @@ extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue); extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue); extern void efx_rx_strategy(struct efx_channel *channel); extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue); -extern void efx_rx_work(struct work_struct *data); +extern void efx_rx_slow_fill(unsigned long context); extern void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, bool checksummed); extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, unsigned int len, bool checksummed, bool discard); -extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay); +extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_RXQ_SIZE 1024 #define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 655b697b45b2..8558865ff380 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -548,7 +548,9 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) { struct efx_link_state *link_state = &efx->link_state; efx_oword_t reg; - int link_speed; + int link_speed, isolate; + + isolate = (efx->reset_pending != RESET_TYPE_NONE); switch (link_state->speed) { case 10000: link_speed = 3; break; @@ -570,7 +572,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) * discarded. */ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) { EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, - !link_state->up); + !link_state->up || isolate); } efx_writeo(efx, ®, FR_AB_MAC_CTRL); @@ -584,7 +586,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1); /* Unisolate the MAC -> RX */ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) - EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1); + EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate); efx_writeo(efx, ®, FR_AZ_RX_CFG); } diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 6032c0e1f1f8..86e43b1f7689 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -20,7 +20,7 @@ #include "nic.h" #include "selftest.h" -struct efx_mcdi_phy_cfg { +struct efx_mcdi_phy_data { u32 flags; u32 type; u32 supported_cap; @@ -35,7 +35,7 @@ struct efx_mcdi_phy_cfg { }; static int -efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg) +efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg) { u8 outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; size_t outlen; @@ -259,7 +259,7 @@ static u32 ethtool_to_mcdi_cap(u32 cap) static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; enum efx_phy_mode mode, supported; u32 flags; @@ -307,7 +307,7 @@ static u32 mcdi_to_ethtool_media(u32 media) static int efx_mcdi_phy_probe(struct efx_nic *efx) { - struct efx_mcdi_phy_cfg *phy_data; + struct efx_mcdi_phy_data *phy_data; u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; u32 caps; int rc; @@ -395,6 +395,7 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx) efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) efx->wanted_fc |= EFX_FC_AUTO; + efx_link_set_wanted_fc(efx, efx->wanted_fc); return 0; @@ -405,7 +406,7 @@ fail: int efx_mcdi_phy_reconfigure(struct efx_nic *efx) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u32 caps = (efx->link_advertising ? ethtool_to_mcdi_cap(efx->link_advertising) : phy_cfg->forced_cap); @@ -446,7 +447,7 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx, */ void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u32 rmtadv; /* The link partner capabilities are only relevent if the @@ -505,7 +506,7 @@ static void efx_mcdi_phy_remove(struct efx_nic *efx) static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; int rc; @@ -535,7 +536,7 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u32 caps; int rc; @@ -674,7 +675,7 @@ out: static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, unsigned flags) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u32 mode; int rc; @@ -712,7 +713,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index) { - struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data; + struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) { if (index == 0) diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 4762c91cb587..ba636e086fc3 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -18,6 +18,7 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if_vlan.h> +#include <linux/timer.h> #include <linux/mdio.h> #include <linux/list.h> #include <linux/pci.h> @@ -221,7 +222,6 @@ struct efx_tx_queue { * If both this and skb are %NULL, the buffer slot is currently free. * @data: Pointer to ethernet header * @len: Buffer length, in bytes. - * @unmap_addr: DMA address to unmap */ struct efx_rx_buffer { dma_addr_t dma_addr; @@ -229,7 +229,24 @@ struct efx_rx_buffer { struct page *page; char *data; unsigned int len; - dma_addr_t unmap_addr; +}; + +/** + * struct efx_rx_page_state - Page-based rx buffer state + * + * Inserted at the start of every page allocated for receive buffers. + * Used to facilitate sharing dma mappings between recycled rx buffers + * and those passed up to the kernel. + * + * @refcnt: Number of struct efx_rx_buffer's referencing this page. + * When refcnt falls to zero, the page is unmapped for dma + * @dma_addr: The dma address of this page. + */ +struct efx_rx_page_state { + unsigned refcnt; + dma_addr_t dma_addr; + + unsigned int __pad[0] ____cacheline_aligned; }; /** @@ -242,10 +259,6 @@ struct efx_rx_buffer { * @added_count: Number of buffers added to the receive queue. * @notified_count: Number of buffers given to NIC (<= @added_count). * @removed_count: Number of buffers removed from the receive queue. - * @add_lock: Receive queue descriptor add spin lock. - * This lock must be held in order to add buffers to the RX - * descriptor ring (rxd and buffer) and to update added_count (but - * not removed_count). * @max_fill: RX descriptor maximum fill level (<= ring size) * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill * (<= @max_fill) @@ -259,12 +272,7 @@ struct efx_rx_buffer { * overflow was observed. It should never be set. * @alloc_page_count: RX allocation strategy counter. * @alloc_skb_count: RX allocation strategy counter. - * @work: Descriptor push work thread - * @buf_page: Page for next RX buffer. - * We can use a single page for multiple RX buffers. This tracks - * the remaining space in the allocation. - * @buf_dma_addr: Page's DMA address. - * @buf_data: Page's host address. + * @slow_fill: Timer used to defer efx_nic_generate_fill_event(). * @flushed: Use when handling queue flushing */ struct efx_rx_queue { @@ -277,7 +285,6 @@ struct efx_rx_queue { int added_count; int notified_count; int removed_count; - spinlock_t add_lock; unsigned int max_fill; unsigned int fast_fill_trigger; unsigned int fast_fill_limit; @@ -285,12 +292,9 @@ struct efx_rx_queue { unsigned int min_overfill; unsigned int alloc_page_count; unsigned int alloc_skb_count; - struct delayed_work work; + struct timer_list slow_fill; unsigned int slow_fill_count; - struct page *buf_page; - dma_addr_t buf_dma_addr; - char *buf_data; enum efx_flush_state flushed; }; @@ -336,7 +340,7 @@ enum efx_rx_alloc_method { * @eventq: Event queue buffer * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. - * @eventq_magic: Event queue magic value for driver-generated test events + * @magic_count: Event queue test event count * @irq_count: Number of IRQs since last adaptive moderation decision * @irq_mod_score: IRQ moderation score * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors @@ -367,7 +371,7 @@ struct efx_channel { struct efx_special_buffer eventq; unsigned int eventq_read_ptr; unsigned int last_eventq_read_ptr; - unsigned int eventq_magic; + unsigned int magic_count; unsigned int irq_count; unsigned int irq_mod_score; @@ -645,6 +649,7 @@ union efx_multicast_hash { * struct efx_nic - an Efx NIC * @name: Device name (net device name or bus id before net device registered) * @pci_dev: The PCI device + * @port_num: Index of this host port within the controller * @type: Controller type attributes * @legacy_irq: IRQ number * @workqueue: Workqueue for port reconfigures and the HW monitor. @@ -728,6 +733,7 @@ union efx_multicast_hash { struct efx_nic { char name[IFNAMSIZ]; struct pci_dev *pci_dev; + unsigned port_num; const struct efx_nic_type *type; int legacy_irq; struct workqueue_struct *workqueue; diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 5d3aaec58556..0ee6fd367e6f 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -79,6 +79,14 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); /* Depth of RX flush request fifo */ #define EFX_RX_FLUSH_COUNT 4 +/* Generated event code for efx_generate_test_event() */ +#define EFX_CHANNEL_MAGIC_TEST(_channel) \ + (0x00010100 + (_channel)->channel) + +/* Generated event code for efx_generate_fill_event() */ +#define EFX_CHANNEL_MAGIC_FILL(_channel) \ + (0x00010200 + (_channel)->channel) + /************************************************************************** * * Solarstorm hardware access @@ -850,6 +858,26 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) checksummed, discard); } +static void +efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event) +{ + struct efx_nic *efx = channel->efx; + unsigned code; + + code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC); + if (code == EFX_CHANNEL_MAGIC_TEST(channel)) + ++channel->magic_count; + else if (code == EFX_CHANNEL_MAGIC_FILL(channel)) + /* The queue must be empty, so we won't receive any rx + * events, so efx_process_channel() won't refill the + * queue. Refill it here */ + efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]); + else + EFX_LOG(efx, "channel %d received generated " + "event "EFX_QWORD_FMT"\n", channel->channel, + EFX_QWORD_VAL(*event)); +} + /* Global events are basically PHY events */ static void efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event) @@ -993,11 +1021,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget) } break; case FSE_AZ_EV_CODE_DRV_GEN_EV: - channel->eventq_magic = EFX_QWORD_FIELD( - event, FSF_AZ_DRV_GEN_EV_MAGIC); - EFX_LOG(channel->efx, "channel %d received generated " - "event "EFX_QWORD_FMT"\n", channel->channel, - EFX_QWORD_VAL(event)); + efx_handle_generated_event(channel, &event); break; case FSE_AZ_EV_CODE_GLOBAL_EV: efx_handle_global_event(channel, &event); @@ -1088,12 +1112,20 @@ void efx_nic_remove_eventq(struct efx_channel *channel) } -/* Generates a test event on the event queue. A subsequent call to - * process_eventq() should pick up the event and place the value of - * "magic" into channel->eventq_magic; - */ -void efx_nic_generate_test_event(struct efx_channel *channel, unsigned int magic) +void efx_nic_generate_test_event(struct efx_channel *channel) { + unsigned int magic = EFX_CHANNEL_MAGIC_TEST(channel); + efx_qword_t test_event; + + EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE, + FSE_AZ_EV_CODE_DRV_GEN_EV, + FSF_AZ_DRV_GEN_EV_MAGIC, magic); + efx_generate_event(channel, &test_event); +} + +void efx_nic_generate_fill_event(struct efx_channel *channel) +{ + unsigned int magic = EFX_CHANNEL_MAGIC_FILL(channel); efx_qword_t test_event; EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE, @@ -1219,9 +1251,6 @@ int efx_nic_flush_queues(struct efx_nic *efx) rx_queue->flushed = FLUSH_DONE; } - if (EFX_WORKAROUND_7803(efx)) - return 0; - return -ETIMEDOUT; } diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index bbc2c0c2f843..95770e15115d 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -190,8 +190,8 @@ extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh; /* Interrupts and test events */ extern int efx_nic_init_interrupt(struct efx_nic *efx); extern void efx_nic_enable_interrupts(struct efx_nic *efx); -extern void efx_nic_generate_test_event(struct efx_channel *channel, - unsigned int magic); +extern void efx_nic_generate_test_event(struct efx_channel *channel); +extern void efx_nic_generate_fill_event(struct efx_channel *channel); extern void efx_nic_generate_interrupt(struct efx_nic *efx); extern void efx_nic_disable_interrupts(struct efx_nic *efx); extern void efx_nic_fini_interrupt(struct efx_nic *efx); diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index e308818b9f55..9fb698e3519d 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -25,6 +25,9 @@ /* Number of RX descriptors pushed at once. */ #define EFX_RX_BATCH 8 +/* Maximum size of a buffer sharing a page */ +#define EFX_RX_HALF_PAGE ((PAGE_SIZE >> 1) - sizeof(struct efx_rx_page_state)) + /* Size of buffer allocated for skb header area. */ #define EFX_SKB_HEADERS 64u @@ -98,155 +101,138 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) return PAGE_SIZE << efx->rx_buffer_order; } - /** - * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation + * efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers * * @rx_queue: Efx RX queue - * @rx_buf: RX buffer structure to populate * - * This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. Return a negative error code or 0 on success. + * This allocates EFX_RX_BATCH skbs, maps them for DMA, and populates a + * struct efx_rx_buffer for each one. Return a negative error code or 0 + * on success. May fail having only inserted fewer than EFX_RX_BATCH + * buffers. */ -static int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf) +static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue) { struct efx_nic *efx = rx_queue->efx; struct net_device *net_dev = efx->net_dev; + struct efx_rx_buffer *rx_buf; int skb_len = efx->rx_buffer_len; + unsigned index, count; - rx_buf->skb = netdev_alloc_skb(net_dev, skb_len); - if (unlikely(!rx_buf->skb)) - return -ENOMEM; + for (count = 0; count < EFX_RX_BATCH; ++count) { + index = rx_queue->added_count & EFX_RXQ_MASK; + rx_buf = efx_rx_buffer(rx_queue, index); - /* Adjust the SKB for padding and checksum */ - skb_reserve(rx_buf->skb, NET_IP_ALIGN); - rx_buf->len = skb_len - NET_IP_ALIGN; - rx_buf->data = (char *)rx_buf->skb->data; - rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY; + rx_buf->skb = netdev_alloc_skb(net_dev, skb_len); + if (unlikely(!rx_buf->skb)) + return -ENOMEM; + rx_buf->page = NULL; - rx_buf->dma_addr = pci_map_single(efx->pci_dev, - rx_buf->data, rx_buf->len, - PCI_DMA_FROMDEVICE); + /* Adjust the SKB for padding and checksum */ + skb_reserve(rx_buf->skb, NET_IP_ALIGN); + rx_buf->len = skb_len - NET_IP_ALIGN; + rx_buf->data = (char *)rx_buf->skb->data; + rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY; + + rx_buf->dma_addr = pci_map_single(efx->pci_dev, + rx_buf->data, rx_buf->len, + PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(efx->pci_dev, + rx_buf->dma_addr))) { + dev_kfree_skb_any(rx_buf->skb); + rx_buf->skb = NULL; + return -EIO; + } - if (unlikely(pci_dma_mapping_error(efx->pci_dev, rx_buf->dma_addr))) { - dev_kfree_skb_any(rx_buf->skb); - rx_buf->skb = NULL; - return -EIO; + ++rx_queue->added_count; + ++rx_queue->alloc_skb_count; } return 0; } /** - * efx_init_rx_buffer_page - create new RX buffer using page-based allocation + * efx_init_rx_buffers_page - create EFX_RX_BATCH page-based RX buffers * * @rx_queue: Efx RX queue - * @rx_buf: RX buffer structure to populate * - * This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. Return a negative error code or 0 on success. + * This allocates memory for EFX_RX_BATCH receive buffers, maps them for DMA, + * and populates struct efx_rx_buffers for each one. Return a negative error + * code or 0 on success. If a single page can be split between two buffers, + * then the page will either be inserted fully, or not at at all. */ -static int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf) +static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) { struct efx_nic *efx = rx_queue->efx; - int bytes, space, offset; - - bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; - - /* If there is space left in the previously allocated page, - * then use it. Otherwise allocate a new one */ - rx_buf->page = rx_queue->buf_page; - if (rx_buf->page == NULL) { - dma_addr_t dma_addr; - - rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC, - efx->rx_buffer_order); - if (unlikely(rx_buf->page == NULL)) + struct efx_rx_buffer *rx_buf; + struct page *page; + void *page_addr; + struct efx_rx_page_state *state; + dma_addr_t dma_addr; + unsigned index, count; + + /* We can split a page between two buffers */ + BUILD_BUG_ON(EFX_RX_BATCH & 1); + + for (count = 0; count < EFX_RX_BATCH; ++count) { + page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC, + efx->rx_buffer_order); + if (unlikely(page == NULL)) return -ENOMEM; - - dma_addr = pci_map_page(efx->pci_dev, rx_buf->page, - 0, efx_rx_buf_size(efx), + dma_addr = pci_map_page(efx->pci_dev, page, 0, + efx_rx_buf_size(efx), PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(efx->pci_dev, dma_addr))) { - __free_pages(rx_buf->page, efx->rx_buffer_order); - rx_buf->page = NULL; + __free_pages(page, efx->rx_buffer_order); return -EIO; } - - rx_queue->buf_page = rx_buf->page; - rx_queue->buf_dma_addr = dma_addr; - rx_queue->buf_data = (page_address(rx_buf->page) + - EFX_PAGE_IP_ALIGN); - } - - rx_buf->len = bytes; - rx_buf->data = rx_queue->buf_data; - offset = efx_rx_buf_offset(rx_buf); - rx_buf->dma_addr = rx_queue->buf_dma_addr + offset; - - /* Try to pack multiple buffers per page */ - if (efx->rx_buffer_order == 0) { - /* The next buffer starts on the next 512 byte boundary */ - rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff); - offset += ((bytes + 0x1ff) & ~0x1ff); - - space = efx_rx_buf_size(efx) - offset; - if (space >= bytes) { - /* Refs dropped on kernel releasing each skb */ - get_page(rx_queue->buf_page); - goto out; + page_addr = page_address(page); + state = page_addr; + state->refcnt = 0; + state->dma_addr = dma_addr; + + page_addr += sizeof(struct efx_rx_page_state); + dma_addr += sizeof(struct efx_rx_page_state); + + split: + index = rx_queue->added_count & EFX_RXQ_MASK; + rx_buf = efx_rx_buffer(rx_queue, index); + rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; + rx_buf->skb = NULL; + rx_buf->page = page; + rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN; + rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; + ++rx_queue->added_count; + ++rx_queue->alloc_page_count; + ++state->refcnt; + + if ((~count & 1) && (efx->rx_buffer_len <= EFX_RX_HALF_PAGE)) { + /* Use the second half of the page */ + get_page(page); + dma_addr += (PAGE_SIZE >> 1); + page_addr += (PAGE_SIZE >> 1); + ++count; + goto split; } } - /* This is the final RX buffer for this page, so mark it for - * unmapping */ - rx_queue->buf_page = NULL; - rx_buf->unmap_addr = rx_queue->buf_dma_addr; - - out: return 0; } -/* This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. - */ -static int efx_init_rx_buffer(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *new_rx_buf) -{ - int rc = 0; - - if (rx_queue->channel->rx_alloc_push_pages) { - new_rx_buf->skb = NULL; - rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf); - rx_queue->alloc_page_count++; - } else { - new_rx_buf->page = NULL; - rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf); - rx_queue->alloc_skb_count++; - } - - if (unlikely(rc < 0)) - EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__, - rx_queue->queue, rc); - return rc; -} - static void efx_unmap_rx_buffer(struct efx_nic *efx, struct efx_rx_buffer *rx_buf) { if (rx_buf->page) { + struct efx_rx_page_state *state; + EFX_BUG_ON_PARANOID(rx_buf->skb); - if (rx_buf->unmap_addr) { - pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr, + + state = page_address(rx_buf->page); + if (--state->refcnt == 0) { + pci_unmap_page(efx->pci_dev, + state->dma_addr, efx_rx_buf_size(efx), PCI_DMA_FROMDEVICE); - rx_buf->unmap_addr = 0; } } else if (likely(rx_buf->skb)) { pci_unmap_single(efx->pci_dev, rx_buf->dma_addr, @@ -273,31 +259,84 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, efx_free_rx_buffer(rx_queue->efx, rx_buf); } +/* Attempt to resurrect the other receive buffer that used to share this page, + * which had previously been passed up to the kernel and freed. */ +static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, + struct efx_rx_buffer *rx_buf) +{ + struct efx_rx_page_state *state = page_address(rx_buf->page); + struct efx_rx_buffer *new_buf; + unsigned fill_level, index; + + /* +1 because efx_rx_packet() incremented removed_count. +1 because + * we'd like to insert an additional descriptor whilst leaving + * EFX_RXD_HEAD_ROOM for the non-recycle path */ + fill_level = (rx_queue->added_count - rx_queue->removed_count + 2); + if (unlikely(fill_level >= EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM)) { + /* We could place "state" on a list, and drain the list in + * efx_fast_push_rx_descriptors(). For now, this will do. */ + return; + } + + ++state->refcnt; + get_page(rx_buf->page); + + index = rx_queue->added_count & EFX_RXQ_MASK; + new_buf = efx_rx_buffer(rx_queue, index); + new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1); + new_buf->skb = NULL; + new_buf->page = rx_buf->page; + new_buf->data = (void *) + ((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1)); + new_buf->len = rx_buf->len; + ++rx_queue->added_count; +} + +/* Recycle the given rx buffer directly back into the rx_queue. There is + * always room to add this buffer, because we've just popped a buffer. */ +static void efx_recycle_rx_buffer(struct efx_channel *channel, + struct efx_rx_buffer *rx_buf) +{ + struct efx_nic *efx = channel->efx; + struct efx_rx_queue *rx_queue = &efx->rx_queue[channel->channel]; + struct efx_rx_buffer *new_buf; + unsigned index; + + if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE && + page_count(rx_buf->page) == 1) + efx_resurrect_rx_buffer(rx_queue, rx_buf); + + index = rx_queue->added_count & EFX_RXQ_MASK; + new_buf = efx_rx_buffer(rx_queue, index); + + memcpy(new_buf, rx_buf, sizeof(*new_buf)); + rx_buf->page = NULL; + rx_buf->skb = NULL; + ++rx_queue->added_count; +} + /** * efx_fast_push_rx_descriptors - push new RX descriptors quickly * @rx_queue: RX descriptor queue - * @retry: Recheck the fill level * This will aim to fill the RX descriptor queue up to * @rx_queue->@fast_fill_limit. If there is insufficient atomic - * memory to do so, the caller should retry. + * memory to do so, a slow fill will be scheduled. + * + * The caller must provide serialisation (none is used here). In practise, + * this means this function must run from the NAPI handler, or be called + * when NAPI is disabled. */ -static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, - int retry) +void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue) { - struct efx_rx_buffer *rx_buf; - unsigned fill_level, index; - int i, space, rc = 0; + struct efx_channel *channel = rx_queue->channel; + unsigned fill_level; + int space, rc = 0; - /* Calculate current fill level. Do this outside the lock, - * because most of the time we'll end up not wanting to do the - * fill anyway. - */ + /* Calculate current fill level, and exit if we don't need to fill */ fill_level = (rx_queue->added_count - rx_queue->removed_count); EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE); - - /* Don't fill if we don't need to */ if (fill_level >= rx_queue->fast_fill_trigger) - return 0; + goto out; /* Record minimum fill level */ if (unlikely(fill_level < rx_queue->min_fill)) { @@ -305,34 +344,25 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, rx_queue->min_fill = fill_level; } - /* Acquire RX add lock. If this lock is contended, then a fast - * fill must already be in progress (e.g. in the refill - * tasklet), so we don't need to do anything - */ - if (!spin_trylock_bh(&rx_queue->add_lock)) - return -1; - - retry: - /* Recalculate current fill level now that we have the lock */ - fill_level = (rx_queue->added_count - rx_queue->removed_count); - EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE); space = rx_queue->fast_fill_limit - fill_level; if (space < EFX_RX_BATCH) - goto out_unlock; + goto out; EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from" " level %d to level %d using %s allocation\n", rx_queue->queue, fill_level, rx_queue->fast_fill_limit, - rx_queue->channel->rx_alloc_push_pages ? "page" : "skb"); + channel->rx_alloc_push_pages ? "page" : "skb"); do { - for (i = 0; i < EFX_RX_BATCH; ++i) { - index = rx_queue->added_count & EFX_RXQ_MASK; - rx_buf = efx_rx_buffer(rx_queue, index); - rc = efx_init_rx_buffer(rx_queue, rx_buf); - if (unlikely(rc)) - goto out; - ++rx_queue->added_count; + if (channel->rx_alloc_push_pages) + rc = efx_init_rx_buffers_page(rx_queue); + else + rc = efx_init_rx_buffers_skb(rx_queue); + if (unlikely(rc)) { + /* Ensure that we don't leave the rx queue empty */ + if (rx_queue->added_count == rx_queue->removed_count) + efx_schedule_slow_fill(rx_queue); + goto out; } } while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH); @@ -341,63 +371,18 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, rx_queue->added_count - rx_queue->removed_count); out: - /* Send write pointer to card. */ - efx_nic_notify_rx_desc(rx_queue); - - /* If the fast fill is running inside from the refill tasklet, then - * for SMP systems it may be running on a different CPU to - * RX event processing, which means that the fill level may now be - * out of date. */ - if (unlikely(retry && (rc == 0))) - goto retry; - - out_unlock: - spin_unlock_bh(&rx_queue->add_lock); - - return rc; -} - -/** - * efx_fast_push_rx_descriptors - push new RX descriptors quickly - * @rx_queue: RX descriptor queue - * - * This will aim to fill the RX descriptor queue up to - * @rx_queue->@fast_fill_limit. If there is insufficient memory to do so, - * it will schedule a work item to immediately continue the fast fill - */ -void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue) -{ - int rc; - - rc = __efx_fast_push_rx_descriptors(rx_queue, 0); - if (unlikely(rc)) { - /* Schedule the work item to run immediately. The hope is - * that work is immediately pending to free some memory - * (e.g. an RX event or TX completion) - */ - efx_schedule_slow_fill(rx_queue, 0); - } + if (rx_queue->notified_count != rx_queue->added_count) + efx_nic_notify_rx_desc(rx_queue); } -void efx_rx_work(struct work_struct *data) +void efx_rx_slow_fill(unsigned long context) { - struct efx_rx_queue *rx_queue; - int rc; - - rx_queue = container_of(data, struct efx_rx_queue, work.work); - - if (unlikely(!rx_queue->channel->enabled)) - return; - - EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU " - "%d\n", rx_queue->queue, raw_smp_processor_id()); + struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context; + struct efx_channel *channel = rx_queue->channel; + /* Post an event to cause NAPI to run and refill the queue */ + efx_nic_generate_fill_event(channel); ++rx_queue->slow_fill_count; - /* Push new RX descriptors, allowing at least 1 jiffy for - * the kernel to free some more memory. */ - rc = __efx_fast_push_rx_descriptors(rx_queue, 1); - if (rc) - efx_schedule_slow_fill(rx_queue, 1); } static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, @@ -498,6 +483,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, unsigned int len, bool checksummed, bool discard) { struct efx_nic *efx = rx_queue->efx; + struct efx_channel *channel = rx_queue->channel; struct efx_rx_buffer *rx_buf; bool leak_packet = false; @@ -525,12 +511,13 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, /* Discard packet, if instructed to do so */ if (unlikely(discard)) { if (unlikely(leak_packet)) - rx_queue->channel->n_skbuff_leaks++; + channel->n_skbuff_leaks++; else - /* We haven't called efx_unmap_rx_buffer yet, - * so fini the entire rx_buffer here */ - efx_fini_rx_buffer(rx_queue, rx_buf); - return; + efx_recycle_rx_buffer(channel, rx_buf); + + /* Don't hold off the previous receive */ + rx_buf = NULL; + goto out; } /* Release card resources - assumes all RX buffers consumed in-order @@ -547,6 +534,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, * prefetched into cache. */ rx_buf->len = len; +out: if (rx_queue->channel->rx_pkt) __efx_rx_packet(rx_queue->channel, rx_queue->channel->rx_pkt, @@ -682,6 +670,7 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue); + del_timer_sync(&rx_queue->slow_fill); efx_nic_fini_rx(rx_queue); /* Release RX buffers NB start at index 0 not current HW ptr */ @@ -691,16 +680,6 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) efx_fini_rx_buffer(rx_queue, rx_buf); } } - - /* For a page that is part-way through splitting into RX buffers */ - if (rx_queue->buf_page != NULL) { - pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr, - efx_rx_buf_size(rx_queue->efx), - PCI_DMA_FROMDEVICE); - __free_pages(rx_queue->buf_page, - rx_queue->efx->rx_buffer_order); - rx_queue->buf_page = NULL; - } } void efx_remove_rx_queue(struct efx_rx_queue *rx_queue) diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 371e86cc090f..1f83404af63b 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -38,7 +38,7 @@ struct efx_loopback_payload { struct udphdr udp; __be16 iteration; const char msg[64]; -} __attribute__ ((packed)); +} __packed; /* Loopback test source MAC address */ static const unsigned char payload_source[ETH_ALEN] = { @@ -161,23 +161,17 @@ static int efx_test_interrupts(struct efx_nic *efx, static int efx_test_eventq_irq(struct efx_channel *channel, struct efx_self_tests *tests) { - unsigned int magic, count; - - /* Channel specific code, limited to 20 bits */ - magic = (0x00010150 + channel->channel); - EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n", - channel->channel, magic); + unsigned int magic_count, count; tests->eventq_dma[channel->channel] = -1; tests->eventq_int[channel->channel] = -1; tests->eventq_poll[channel->channel] = -1; - /* Reset flag and zero magic word */ + magic_count = channel->magic_count; channel->efx->last_irq_cpu = -1; - channel->eventq_magic = 0; smp_wmb(); - efx_nic_generate_test_event(channel, magic); + efx_nic_generate_test_event(channel); /* Wait for arrival of interrupt */ count = 0; @@ -187,7 +181,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, if (channel->work_pending) efx_process_channel_now(channel); - if (channel->eventq_magic == magic) + if (channel->magic_count != magic_count) goto eventq_ok; } while (++count < 2); @@ -204,7 +198,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, /* Check to see if event was received even if interrupt wasn't */ efx_process_channel_now(channel); - if (channel->eventq_magic == magic) { + if (channel->magic_count != magic_count) { EFX_ERR(channel->efx, "channel %d event was generated, but " "failed to trigger an interrupt\n", channel->channel); tests->eventq_dma[channel->channel] = 1; @@ -545,7 +539,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, static int efx_wait_for_link(struct efx_nic *efx) { struct efx_link_state *link_state = &efx->link_state; - int count; + int count, link_up_count = 0; bool link_up; for (count = 0; count < 40; count++) { @@ -567,8 +561,12 @@ static int efx_wait_for_link(struct efx_nic *efx) link_up = !efx->mac_op->check_fault(efx); mutex_unlock(&efx->mac_lock); - if (link_up) - return 0; + if (link_up) { + if (++link_up_count == 2) + return 0; + } else { + link_up_count = 0; + } } return -ETIMEDOUT; diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index 518f7fc91473..782e45a613d6 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -54,7 +54,7 @@ /* Increase filter depth to avoid RX_RESET */ #define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A /* Flushes may never complete */ -#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A +#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_AB /* Leak overlength packets rather than free */ #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 084eff21b67a..61891a6cacc2 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -2161,21 +2161,21 @@ struct sky2_tx_le { __le16 length; /* also vlan tag or checksum start */ u8 ctrl; u8 opcode; -} __attribute((packed)); +} __packed; struct sky2_rx_le { __le32 addr; __le16 length; u8 ctrl; u8 opcode; -} __attribute((packed)); +} __packed; struct sky2_status_le { __le32 status; /* also checksum */ __le16 length; /* also vlan tag */ u8 css; u8 opcode; -} __attribute((packed)); +} __packed; struct tx_ring_info { struct sk_buff *skb; diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index cff98d07cba8..67e3b71bf705 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -334,7 +334,7 @@ struct txd_desc { u32 va_lo; u32 va_hi; struct pbl pbl[0]; /* Fragments */ -} __attribute__ ((packed)); +} __packed; /* Register region size */ #define BDX_REGS_SIZE 0x1000 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 573054ae7b58..289cdc5fde92 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #include "tg3.h" #define DRV_MODULE_NAME "tg3" -#define DRV_MODULE_VERSION "3.110" -#define DRV_MODULE_RELDATE "April 9, 2010" +#define DRV_MODULE_VERSION "3.111" +#define DRV_MODULE_RELDATE "June 5, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -145,8 +145,6 @@ #define TG3_RX_JMB_BUFF_RING_SIZE \ (sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE) -#define TG3_RSS_MIN_NUM_MSIX_VECS 2 - /* Due to a hardware bug, the 5701 can only DMA to memory addresses * that are at least dword aligned when used in PCIX mode. The driver * works around this bug by double copying the packet. This workaround @@ -272,6 +270,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, @@ -585,18 +584,23 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) static void tg3_ape_lock_init(struct tg3 *tp) { int i; + u32 regbase; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + regbase = TG3_APE_LOCK_GRANT; + else + regbase = TG3_APE_PER_LOCK_GRANT; /* Make sure the driver hasn't any stale locks. */ for (i = 0; i < 8; i++) - tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i, - APE_LOCK_GRANT_DRIVER); + tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER); } static int tg3_ape_lock(struct tg3 *tp, int locknum) { int i, off; int ret = 0; - u32 status; + u32 status, req, gnt; if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return 0; @@ -609,13 +613,21 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) return -EINVAL; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + req = TG3_APE_LOCK_REQ; + gnt = TG3_APE_LOCK_GRANT; + } else { + req = TG3_APE_PER_LOCK_REQ; + gnt = TG3_APE_PER_LOCK_GRANT; + } + off = 4 * locknum; - tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER); + tg3_ape_write32(tp, req + off, APE_LOCK_REQ_DRIVER); /* Wait for up to 1 millisecond to acquire lock. */ for (i = 0; i < 100; i++) { - status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off); + status = tg3_ape_read32(tp, gnt + off); if (status == APE_LOCK_GRANT_DRIVER) break; udelay(10); @@ -623,7 +635,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) if (status != APE_LOCK_GRANT_DRIVER) { /* Revoke the lock request. */ - tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, + tg3_ape_write32(tp, gnt + off, APE_LOCK_GRANT_DRIVER); ret = -EBUSY; @@ -634,7 +646,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) static void tg3_ape_unlock(struct tg3 *tp, int locknum) { - int off; + u32 gnt; if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return; @@ -647,8 +659,12 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) return; } - off = 4 * locknum; - tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + gnt = TG3_APE_LOCK_GRANT; + else + gnt = TG3_APE_PER_LOCK_GRANT; + + tg3_ape_write32(tp, gnt + 4 * locknum, APE_LOCK_GRANT_DRIVER); } static void tg3_disable_ints(struct tg3 *tp) @@ -1069,14 +1085,11 @@ static int tg3_mdio_init(struct tg3 *tp) u32 reg; struct phy_device *phydev; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - u32 funcnum, is_serdes; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + u32 is_serdes; - funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC; - if (funcnum) - tp->phy_addr = 2; - else - tp->phy_addr = 1; + tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1; if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; @@ -1589,7 +1602,8 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) u32 reg; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; @@ -1964,7 +1978,8 @@ static int tg3_phy_reset(struct tg3 *tp) } } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) return 0; @@ -2049,6 +2064,7 @@ static void tg3_frob_aux_power(struct tg3 *tp) /* The GPIOs do something completely different on 57765. */ if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) return; @@ -4191,6 +4207,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) current_duplex = DUPLEX_FULL; else current_duplex = DUPLEX_HALF; + } else if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + /* Link is up via parallel detect */ } else { current_link_up = 0; } @@ -6212,6 +6230,8 @@ static void tg3_free_rings(struct tg3 *tp) for (j = 0; j < tp->irq_cnt; j++) { struct tg3_napi *tnapi = &tp->napi[j]; + tg3_rx_prodring_free(tp, &tp->prodring[j]); + if (!tnapi->tx_buffers) continue; @@ -6247,8 +6267,6 @@ static void tg3_free_rings(struct tg3 *tp) dev_kfree_skb_any(skb); } - - tg3_rx_prodring_free(tp, &tp->prodring[j]); } } @@ -6782,7 +6800,8 @@ static void tg3_restore_pci_state(struct tg3 *tp) /* Allow reads and writes to the APE register and memory space. */ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) val |= PCISTATE_ALLOW_APE_CTLSPC_WR | - PCISTATE_ALLOW_APE_SHMEM_WR; + PCISTATE_ALLOW_APE_SHMEM_WR | + PCISTATE_ALLOW_APE_PSPACE_WR; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); @@ -7069,6 +7088,7 @@ static int tg3_chip_reset(struct tg3 *tp) tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { val = tr32(0x7c00); @@ -7504,7 +7524,8 @@ static void tg3_rings_reset(struct tg3 *tp) /* Disable all receive return rings but the first. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; @@ -7720,7 +7741,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) */ val = tr32(TG3PCI_PCISTATE); val |= PCISTATE_ALLOW_APE_CTLSPC_WR | - PCISTATE_ALLOW_APE_SHMEM_WR; + PCISTATE_ALLOW_APE_SHMEM_WR | + PCISTATE_ALLOW_APE_PSPACE_WR; tw32(TG3PCI_PCISTATE, val); } @@ -7741,6 +7763,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return err; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { val = tr32(TG3PCI_DMA_RW_CTRL) & ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; @@ -7869,7 +7892,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_std_mapping & 0xffffffff)); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); @@ -7894,7 +7918,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) | BDINFO_FLAGS_USE_EXT_RECV); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + if (!(tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_JUMBO_BUFFER_DESC); } else { @@ -7903,6 +7928,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) | (TG3_RX_STD_DMA_SZ << 2); @@ -7921,6 +7947,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { tw32(STD_REPLENISH_LWM, 32); tw32(JMB_REPLENISH_LWM, 16); @@ -7956,7 +7983,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || @@ -8195,6 +8223,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } tp->tx_mode = TX_MODE_ENABLE; + if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX; tw32_f(MAC_TX_MODE, tp->tx_mode); udelay(100); @@ -8206,7 +8237,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) { int idx = i % sizeof(val); - ent[idx] = i % (tp->irq_cnt - 1); + ent[idx] = (i % (tp->irq_cnt - 1)) + 1; if (idx == sizeof(val) - 1) { tw32(reg, val); reg += 4; @@ -8511,8 +8542,10 @@ static void tg3_timer(unsigned long __opaque) } tg3_setup_phy(tp, 0); } - } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + } else if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && + !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { tg3_serdes_parallel_detect(tp); + } tp->timer_counter = tp->timer_multiplier; } @@ -8606,6 +8639,7 @@ static int tg3_test_interrupt(struct tg3 *tp) * observable way to know whether the interrupt was delivered. */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE; @@ -8650,6 +8684,7 @@ static int tg3_test_interrupt(struct tg3 *tp) if (intr_ok) { /* Reenable MSI one shot mode. */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE; @@ -8775,9 +8810,9 @@ static bool tg3_enable_msix(struct tg3 *tp) } rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt); - if (rc != 0) { - if (rc < TG3_RSS_MIN_NUM_MSIX_VECS) - return false; + if (rc < 0) { + return false; + } else if (rc != 0) { if (pci_enable_msix(tp->pdev, msix_ent, rc)) return false; netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", @@ -8785,16 +8820,19 @@ static bool tg3_enable_msix(struct tg3 *tp) tp->irq_cnt = rc; } - tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; - for (i = 0; i < tp->irq_max; i++) tp->napi[i].irq_vec = msix_ent[i].vector; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS; - tp->dev->real_num_tx_queues = tp->irq_cnt - 1; - } else - tp->dev->real_num_tx_queues = 1; + tp->dev->real_num_tx_queues = 1; + if (tp->irq_cnt > 1) { + tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS; + tp->dev->real_num_tx_queues = tp->irq_cnt - 1; + } + } return true; } @@ -8943,6 +8981,7 @@ static int tg3_open(struct net_device *dev) } if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 && (tp->tg3_flags2 & TG3_FLG2_USING_MSI) && (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) { @@ -10554,7 +10593,8 @@ static int tg3_test_memory(struct tg3 *tp) int err = 0; int i; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) mem_tbl = mem_tbl_5717; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) mem_tbl = mem_tbl_57765; @@ -11634,7 +11674,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_get_57780_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) tg3_get_5717_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -12070,11 +12111,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { - if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) - tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; - else + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + else + tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; } if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) @@ -12804,7 +12844,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724) + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719) pci_read_config_dword(tp->pdev, TG3PCI_GEN2_PRODID_ASICREV, &prod_id_asic_rev); @@ -12970,6 +13011,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags3 |= TG3_FLG3_5755_PLUS; @@ -12999,6 +13041,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Determine TSO capabilities */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3; else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || @@ -13036,6 +13079,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX; tp->irq_max = TG3_IRQ_MAX_VECS; @@ -13043,6 +13087,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG; else if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) { @@ -13051,6 +13096,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; @@ -13242,7 +13288,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * APE register and memory space. */ pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR | - PCISTATE_ALLOW_APE_SHMEM_WR; + PCISTATE_ALLOW_APE_SHMEM_WR | + PCISTATE_ALLOW_APE_PSPACE_WR; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg); } @@ -13252,6 +13299,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; @@ -13332,6 +13380,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || @@ -13580,9 +13629,12 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) tw32_f(NVRAM_CMD, NVRAM_CMD_RESET); else tg3_nvram_unlock(tp); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - if (tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC) + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + if (PCI_FUNC(tp->pdev->devfn) & 1) mac_offset = 0xcc; + if (PCI_FUNC(tp->pdev->devfn) > 1) + mac_offset += 0x18c; } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mac_offset = 0x10; @@ -13668,6 +13720,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) #endif if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT; goto out; @@ -13880,6 +13933,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) goto out; @@ -14079,6 +14133,7 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; @@ -14156,6 +14211,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case TG3_PHY_ID_BCM5718C: return "5718C"; case TG3_PHY_ID_BCM5718S: return "5718S"; case TG3_PHY_ID_BCM57765: return "57765"; + case TG3_PHY_ID_BCM5719C: return "5719C"; case TG3_PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; @@ -14404,7 +14460,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) && - tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) + tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) dev->netdev_ops = &tg3_netdev_ops; else dev->netdev_ops = &tg3_netdev_ops_dma_bug; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ce9c4918c318..6b6af7698b38 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -53,6 +53,7 @@ #define TG3PCI_DEVICE_TIGON3_57765 0x16b4 #define TG3PCI_DEVICE_TIGON3_57791 0x16b2 #define TG3PCI_DEVICE_TIGON3_57795 0x16b6 +#define TG3PCI_DEVICE_TIGON3_5719 0x1657 /* 0x04 --> 0x2c unused */ #define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM #define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644 @@ -160,6 +161,7 @@ #define ASIC_REV_57780 0x57780 #define ASIC_REV_5717 0x5717 #define ASIC_REV_57765 0x57785 +#define ASIC_REV_5719 0x5719 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -231,6 +233,7 @@ #define PCISTATE_RETRY_SAME_DMA 0x00002000 #define PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000 #define PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000 +#define PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000 #define TG3PCI_CLOCK_CTRL 0x00000074 #define CLOCK_CTRL_CORECLK_DISABLE 0x00000200 #define CLOCK_CTRL_RXCLK_DISABLE 0x00000400 @@ -468,6 +471,7 @@ #define TX_MODE_FLOW_CTRL_ENABLE 0x00000010 #define TX_MODE_BIG_BCKOFF_ENABLE 0x00000020 #define TX_MODE_LONG_PAUSE_ENABLE 0x00000040 +#define TX_MODE_MBUF_LOCKUP_FIX 0x00000100 #define MAC_TX_STATUS 0x00000460 #define TX_STATUS_XOFFED 0x00000001 #define TX_STATUS_SENT_XOFF 0x00000002 @@ -1071,10 +1075,8 @@ #define TG3_CPMU_HST_ACC 0x0000361c #define CPMU_HST_ACC_MACCLK_MASK 0x001f0000 #define CPMU_HST_ACC_MACCLK_6_25 0x00130000 -/* 0x3620 --> 0x362c unused */ +/* 0x3620 --> 0x3630 unused */ -#define TG3_CPMU_STATUS 0x0000362c -#define TG3_CPMU_STATUS_PCIE_FUNC 0x20000000 #define TG3_CPMU_CLCK_STAT 0x00003630 #define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 #define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 @@ -2209,6 +2211,11 @@ #define APE_EVENT_STATUS_STATE_SUSPEND 0x00040000 #define APE_EVENT_STATUS_EVENT_PENDING 0x80000000 +#define TG3_APE_PER_LOCK_REQ 0x8400 +#define APE_LOCK_PER_REQ_DRIVER 0x00001000 +#define TG3_APE_PER_LOCK_GRANT 0x8420 +#define APE_PER_LOCK_GRANT_DRIVER 0x00001000 + /* APE convenience enumerations. */ #define TG3_APE_LOCK_GRC 1 #define TG3_APE_LOCK_MEM 4 @@ -2942,6 +2949,7 @@ struct tg3 { #define TG3_PHY_ID_BCM5718C 0x5c0d8a00 #define TG3_PHY_ID_BCM5718S 0xbc050ff0 #define TG3_PHY_ID_BCM57765 0x5c0d8a40 +#define TG3_PHY_ID_BCM5719C 0x5c0d8a20 #define TG3_PHY_ID_BCM5906 0xdc00ac40 #define TG3_PHY_ID_BCM8002 0x60010140 #define TG3_PHY_ID_INVALID 0xffffffff @@ -2965,7 +2973,8 @@ struct tg3 { (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \ (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \ (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \ - (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM8002) + (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM5719C || \ + (X) == TG3_PHY_ID_BCM8002) u32 led_ctrl; u32 phy_otp; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index c0e70006374e..960962660079 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -262,13 +262,13 @@ struct de_srom_media_block { u16 csr13; u16 csr14; u16 csr15; -} __attribute__((packed)); +} __packed; struct de_srom_info_leaf { u16 default_media; u8 n_blocks; u8 unused; -} __attribute__((packed)); +} __packed; struct de_desc { __le32 opts1; diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 6002e651b9ea..3031ed9c4a1a 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -120,8 +120,8 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) 0x00, 0x06 /* ttm bit map */ }; - tp->mtable = (struct mediatable *) - kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL); + tp->mtable = kmalloc(sizeof(struct mediatable) + + sizeof(struct medialeaf), GFP_KERNEL); if (tp->mtable == NULL) return; /* Horrible, impossible failure. */ @@ -227,9 +227,9 @@ subsequent_board: return; } - mtable = (struct mediatable *) - kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf), - GFP_KERNEL); + mtable = kmalloc(sizeof(struct mediatable) + + count * sizeof(struct medialeaf), + GFP_KERNEL); if (mtable == NULL) return; /* Horrible, impossible failure. */ last_mediatable = tp->mtable = mtable; diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 0afa2d4f9472..e525875ed67d 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -20,6 +20,7 @@ #include <linux/types.h> #include <linux/spinlock.h> #include <linux/netdevice.h> +#include <linux/ethtool.h> #include <linux/timer.h> #include <linux/delay.h> #include <linux/pci.h> @@ -51,22 +52,23 @@ struct tulip_chip_table { enum tbl_flag { - HAS_MII = 0x0001, - HAS_MEDIA_TABLE = 0x0002, - CSR12_IN_SROM = 0x0004, - ALWAYS_CHECK_MII = 0x0008, - HAS_ACPI = 0x0010, - MC_HASH_ONLY = 0x0020, /* Hash-only multicast filter. */ - HAS_PNICNWAY = 0x0080, - HAS_NWAY = 0x0040, /* Uses internal NWay xcvr. */ - HAS_INTR_MITIGATION = 0x0100, - IS_ASIX = 0x0200, - HAS_8023X = 0x0400, - COMET_MAC_ADDR = 0x0800, - HAS_PCI_MWI = 0x1000, - HAS_PHY_IRQ = 0x2000, - HAS_SWAPPED_SEEPROM = 0x4000, - NEEDS_FAKE_MEDIA_TABLE = 0x8000, + HAS_MII = 0x00001, + HAS_MEDIA_TABLE = 0x00002, + CSR12_IN_SROM = 0x00004, + ALWAYS_CHECK_MII = 0x00008, + HAS_ACPI = 0x00010, + MC_HASH_ONLY = 0x00020, /* Hash-only multicast filter. */ + HAS_PNICNWAY = 0x00080, + HAS_NWAY = 0x00040, /* Uses internal NWay xcvr. */ + HAS_INTR_MITIGATION = 0x00100, + IS_ASIX = 0x00200, + HAS_8023X = 0x00400, + COMET_MAC_ADDR = 0x00800, + HAS_PCI_MWI = 0x01000, + HAS_PHY_IRQ = 0x02000, + HAS_SWAPPED_SEEPROM = 0x04000, + NEEDS_FAKE_MEDIA_TABLE = 0x08000, + COMET_PM = 0x10000, }; @@ -120,6 +122,11 @@ enum tulip_offsets { CSR13 = 0x68, CSR14 = 0x70, CSR15 = 0x78, + CSR18 = 0x88, + CSR19 = 0x8c, + CSR20 = 0x90, + CSR27 = 0xAC, + CSR28 = 0xB0, }; /* register offset and bits for CFDD PCI config reg */ @@ -289,6 +296,30 @@ enum t21143_csr6_bits { csr6_mask_100bt = (csr6_scr | csr6_pcs | csr6_hbd), }; +enum tulip_comet_csr13_bits { +/* The LINKOFFE and LINKONE work in conjunction with LSCE, i.e. they + * determine which link status transition wakes up if LSCE is + * enabled */ + comet_csr13_linkoffe = (1 << 17), + comet_csr13_linkone = (1 << 16), + comet_csr13_wfre = (1 << 10), + comet_csr13_mpre = (1 << 9), + comet_csr13_lsce = (1 << 8), + comet_csr13_wfr = (1 << 2), + comet_csr13_mpr = (1 << 1), + comet_csr13_lsc = (1 << 0), +}; + +enum tulip_comet_csr18_bits { + comet_csr18_pmes_sticky = (1 << 24), + comet_csr18_pm_mode = (1 << 19), + comet_csr18_apm_mode = (1 << 18), + comet_csr18_d3a = (1 << 7) +}; + +enum tulip_comet_csr20_bits { + comet_csr20_pmes = (1 << 15), +}; /* Keep the ring sizes a power of two for efficiency. Making the Tx ring too large decreases the effectiveness of channel @@ -411,6 +442,7 @@ struct tulip_private { unsigned int csr6; /* Current CSR6 control settings. */ unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ void (*link_change) (struct net_device * dev, int csr5); + struct ethtool_wolinfo wolinfo; /* WOL settings */ u16 sym_advertise, mii_advertise; /* NWay capabilities advertised. */ u16 lpar; /* 21143 Link partner ability. */ u16 advertising[4]; diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 254643ed945e..03e96b928c04 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -30,7 +30,6 @@ #include <linux/etherdevice.h> #include <linux/delay.h> #include <linux/mii.h> -#include <linux/ethtool.h> #include <linux/crc32.h> #include <asm/unaligned.h> #include <asm/uaccess.h> @@ -272,6 +271,7 @@ static void tulip_down(struct net_device *dev); static struct net_device_stats *tulip_get_stats(struct net_device *dev); static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); +static void tulip_set_wolopts(struct pci_dev *pdev, u32 wolopts); #ifdef CONFIG_NET_POLL_CONTROLLER static void poll_tulip(struct net_device *dev); #endif @@ -309,6 +309,11 @@ static void tulip_up(struct net_device *dev) /* Wake the chip from sleep/snooze mode. */ tulip_set_power_state (tp, 0, 0); + /* Disable all WOL events */ + pci_enable_wake(tp->pdev, PCI_D3hot, 0); + pci_enable_wake(tp->pdev, PCI_D3cold, 0); + tulip_set_wolopts(tp->pdev, 0); + /* On some chip revs we must set the MII/SYM port before the reset!? */ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) iowrite32(0x00040000, ioaddr + CSR6); @@ -345,8 +350,8 @@ static void tulip_up(struct net_device *dev) } else if (tp->flags & COMET_MAC_ADDR) { iowrite32(addr_low, ioaddr + 0xA4); iowrite32(addr_high, ioaddr + 0xA8); - iowrite32(0, ioaddr + 0xAC); - iowrite32(0, ioaddr + 0xB0); + iowrite32(0, ioaddr + CSR27); + iowrite32(0, ioaddr + CSR28); } } else { /* This is set_rx_mode(), but without starting the transmitter. */ @@ -876,8 +881,35 @@ static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in strcpy(info->bus_info, pci_name(np->pdev)); } + +static int tulip_ethtool_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wolinfo) +{ + struct tulip_private *tp = netdev_priv(dev); + + if (wolinfo->wolopts & (~tp->wolinfo.supported)) + return -EOPNOTSUPP; + + tp->wolinfo.wolopts = wolinfo->wolopts; + device_set_wakeup_enable(&tp->pdev->dev, tp->wolinfo.wolopts); + return 0; +} + +static void tulip_ethtool_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wolinfo) +{ + struct tulip_private *tp = netdev_priv(dev); + + wolinfo->supported = tp->wolinfo.supported; + wolinfo->wolopts = tp->wolinfo.wolopts; + return; +} + + static const struct ethtool_ops ops = { - .get_drvinfo = tulip_get_drvinfo + .get_drvinfo = tulip_get_drvinfo, + .set_wol = tulip_ethtool_set_wol, + .get_wol = tulip_ethtool_get_wol, }; /* Provide ioctl() calls to examine the MII xcvr state. */ @@ -1093,8 +1125,8 @@ static void set_rx_mode(struct net_device *dev) iowrite32(3, ioaddr + CSR13); iowrite32(mc_filter[1], ioaddr + CSR14); } else if (tp->flags & COMET_MAC_ADDR) { - iowrite32(mc_filter[0], ioaddr + 0xAC); - iowrite32(mc_filter[1], ioaddr + 0xB0); + iowrite32(mc_filter[0], ioaddr + CSR27); + iowrite32(mc_filter[1], ioaddr + CSR28); } tp->mc_filter[0] = mc_filter[0]; tp->mc_filter[1] = mc_filter[1]; @@ -1381,6 +1413,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, return i; } + /* The chip will fail to enter a low-power state later unless + * first explicitly commanded into D0 */ + if (pci_set_power_state(pdev, PCI_D0)) { + printk (KERN_NOTICE PFX + "Failed to set power state to D0\n"); + } + irq = pdev->irq; /* alloc_etherdev ensures aligned and zeroed private structures */ @@ -1427,6 +1466,19 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->chip_id = chip_idx; tp->flags = tulip_tbl[chip_idx].flags; + + tp->wolinfo.supported = 0; + tp->wolinfo.wolopts = 0; + /* COMET: Enable power management only for AN983B */ + if (chip_idx == COMET ) { + u32 sig; + pci_read_config_dword (pdev, 0x80, &sig); + if (sig == 0x09811317) { + tp->flags |= COMET_PM; + tp->wolinfo.supported = WAKE_PHY | WAKE_MAGIC; + printk(KERN_INFO "tulip_init_one: Enabled WOL support for AN983B\n"); + } + } tp->pdev = pdev; tp->base_addr = ioaddr; tp->revision = pdev->revision; @@ -1759,11 +1811,43 @@ err_out_free_netdev: } +/* set the registers according to the given wolopts */ +static void tulip_set_wolopts (struct pci_dev *pdev, u32 wolopts) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + if (tp->flags & COMET_PM) { + + unsigned int tmp; + + tmp = ioread32(ioaddr + CSR18); + tmp &= ~(comet_csr18_pmes_sticky | comet_csr18_apm_mode | comet_csr18_d3a); + tmp |= comet_csr18_pm_mode; + iowrite32(tmp, ioaddr + CSR18); + + /* Set the Wake-up Control/Status Register to the given WOL options*/ + tmp = ioread32(ioaddr + CSR13); + tmp &= ~(comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_wfre | comet_csr13_lsce | comet_csr13_mpre); + if (wolopts & WAKE_MAGIC) + tmp |= comet_csr13_mpre; + if (wolopts & WAKE_PHY) + tmp |= comet_csr13_linkoffe | comet_csr13_linkone | comet_csr13_lsce; + /* Clear the event flags */ + tmp |= comet_csr13_wfr | comet_csr13_mpr | comet_csr13_lsc; + iowrite32(tmp, ioaddr + CSR13); + } +} + #ifdef CONFIG_PM + static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) { + pci_power_t pstate; struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); if (!dev) return -EINVAL; @@ -1779,7 +1863,16 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) save_state: pci_save_state(pdev); pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pstate = pci_choose_state(pdev, state); + if (state.event == PM_EVENT_SUSPEND && pstate != PCI_D0) { + int rc; + + tulip_set_wolopts(pdev, tp->wolinfo.wolopts); + rc = pci_enable_wake(pdev, pstate, tp->wolinfo.wolopts); + if (rc) + printk("tulip: pci_enable_wake failed (%d)\n", rc); + } + pci_set_power_state(pdev, pstate); return 0; } @@ -1788,7 +1881,10 @@ save_state: static int tulip_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; int retval; + unsigned int tmp; if (!dev) return -EINVAL; @@ -1809,6 +1905,18 @@ static int tulip_resume(struct pci_dev *pdev) return retval; } + if (tp->flags & COMET_PM) { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + /* Clear the PMES flag */ + tmp = ioread32(ioaddr + CSR20); + tmp |= comet_csr20_pmes; + iowrite32(tmp, ioaddr + CSR20); + + /* Disable all wake-up events */ + tulip_set_wolopts(pdev, 0); + } netif_device_attach(dev); if (netif_running(dev)) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 22bde49262c0..2e50077ff450 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -255,7 +255,7 @@ struct typhoon_shared { struct rx_free rxBuff[RXFREE_ENTRIES] __3xp_aligned; u32 zeroWord; struct tx_desc txHi[TXHI_ENTRIES]; -} __attribute__ ((packed)); +} __packed; struct rxbuff_ent { struct sk_buff *skb; diff --git a/drivers/net/typhoon.h b/drivers/net/typhoon.h index 673fd5125914..88187fc84aa3 100644 --- a/drivers/net/typhoon.h +++ b/drivers/net/typhoon.h @@ -77,7 +77,7 @@ struct typhoon_indexes { volatile __le32 cmdCleared; volatile __le32 respReady; volatile __le32 rxHiReady; -} __attribute__ ((packed)); +} __packed; /* The host<->Typhoon interface * Our means of communicating where things are @@ -125,7 +125,7 @@ struct typhoon_interface { __le32 rxHiAddr; __le32 rxHiAddrHi; __le32 rxHiSize; -} __attribute__ ((packed)); +} __packed; /* The Typhoon transmit/fragment descriptor * @@ -187,7 +187,7 @@ struct tx_desc { #define TYPHOON_TX_PF_VLAN_MASK cpu_to_le32(0x0ffff000) #define TYPHOON_TX_PF_INTERNAL cpu_to_le32(0xf0000000) #define TYPHOON_TX_PF_VLAN_TAG_SHIFT 12 -} __attribute__ ((packed)); +} __packed; /* The TCP Segmentation offload option descriptor * @@ -208,7 +208,7 @@ struct tcpopt_desc { __le32 respAddrLo; __le32 bytesTx; __le32 status; -} __attribute__ ((packed)); +} __packed; /* The IPSEC Offload descriptor * @@ -227,7 +227,7 @@ struct ipsec_desc { __le32 sa1; __le32 sa2; __le32 reserved; -} __attribute__ ((packed)); +} __packed; /* The Typhoon receive descriptor (Updated by NIC) * @@ -284,7 +284,7 @@ struct rx_desc { #define TYPHOON_RX_UNKNOWN_SA cpu_to_le16(0x0100) #define TYPHOON_RX_ESP_FORMAT_ERR cpu_to_le16(0x0200) __be32 vlanTag; -} __attribute__ ((packed)); +} __packed; /* The Typhoon free buffer descriptor, used to give a buffer to the NIC * @@ -301,7 +301,7 @@ struct rx_free { __le32 physAddrHi; u32 virtAddr; u32 virtAddrHi; -} __attribute__ ((packed)); +} __packed; /* The Typhoon command descriptor, used for commands and responses * @@ -347,7 +347,7 @@ struct cmd_desc { __le16 parm1; __le32 parm2; __le32 parm3; -} __attribute__ ((packed)); +} __packed; /* The Typhoon response descriptor, see command descriptor for details */ @@ -359,7 +359,7 @@ struct resp_desc { __le16 parm1; __le32 parm2; __le32 parm3; -} __attribute__ ((packed)); +} __packed; #define INIT_COMMAND_NO_RESPONSE(x, command) \ do { struct cmd_desc *_ptr = (x); \ @@ -427,7 +427,7 @@ struct stats_resp { #define TYPHOON_LINK_HALF_DUPLEX cpu_to_le32(0x00000000) __le32 unused2; __le32 unused3; -} __attribute__ ((packed)); +} __packed; /* TYPHOON_CMD_XCVR_SELECT xcvr values (resp.parm1) */ @@ -488,7 +488,7 @@ struct sa_descriptor { u32 index; u32 unused; u32 unused2; -} __attribute__ ((packed)); +} __packed; /* TYPHOON_CMD_SET_OFFLOAD_TASKS bits (cmd.parm2 (Tx) & cmd.parm3 (Rx)) * This is all for IPv4. @@ -518,14 +518,14 @@ struct typhoon_file_header { __le32 numSections; __le32 startAddr; __le32 hmacDigest[5]; -} __attribute__ ((packed)); +} __packed; struct typhoon_section_header { __le32 len; u16 checksum; u16 reserved; __le32 startAddr; -} __attribute__ ((packed)); +} __packed; /* The Typhoon Register offsets */ diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 807470e156af..dc32a62e611c 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3704,6 +3704,19 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_MII; } +static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct ucc_geth_private *ugeth = netdev_priv(dev); + + if (!netif_running(dev)) + return -EINVAL; + + if (!ugeth->phydev) + return -ENODEV; + + return phy_mii_ioctl(ugeth->phydev, if_mii(rq), cmd); +} + static const struct net_device_ops ucc_geth_netdev_ops = { .ndo_open = ucc_geth_open, .ndo_stop = ucc_geth_close, @@ -3713,6 +3726,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { .ndo_change_mtu = eth_change_mtu, .ndo_set_multicast_list = ucc_geth_set_multi, .ndo_tx_timeout = ucc_geth_timeout, + .ndo_do_ioctl = ucc_geth_ioctl, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ucc_netpoll, #endif diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index ef1fbeb11c6e..05a95586f3c5 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -106,7 +106,7 @@ struct ucc_geth { u32 scar; /* Statistics carry register */ u32 scam; /* Statistics caryy mask register */ u8 res5[0x200 - 0x1c4]; -} __attribute__ ((packed)); +} __packed; /* UCC GETH TEMODR Register */ #define TEMODER_TX_RMON_STATISTICS_ENABLE 0x0100 /* enable Tx statistics @@ -420,11 +420,11 @@ struct ucc_geth { struct ucc_geth_thread_data_tx { u8 res0[104]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_thread_data_rx { u8 res0[40]; -} __attribute__ ((packed)); +} __packed; /* Send Queue Queue-Descriptor */ struct ucc_geth_send_queue_qd { @@ -432,19 +432,19 @@ struct ucc_geth_send_queue_qd { u8 res0[0x8]; u32 last_bd_completed_address;/* initialize to last entry in BD ring */ u8 res1[0x30]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_send_queue_mem_region { struct ucc_geth_send_queue_qd sqqd[NUM_TX_QUEUES]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_thread_tx_pram { u8 res0[64]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_thread_rx_pram { u8 res0[128]; -} __attribute__ ((packed)); +} __packed; #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING 64 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8 64 @@ -484,7 +484,7 @@ struct ucc_geth_scheduler { /**< weight factor for queues */ u32 minw; /* temporary variable handled by QE */ u8 res1[0x70 - 0x64]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_tx_firmware_statistics_pram { u32 sicoltx; /* single collision */ @@ -506,7 +506,7 @@ struct ucc_geth_tx_firmware_statistics_pram { and 1518 octets */ u32 txpktsjumbo; /* total packets (including bad) between 1024 and MAXLength octets */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_firmware_statistics_pram { u32 frrxfcser; /* frames with crc error */ @@ -540,7 +540,7 @@ struct ucc_geth_rx_firmware_statistics_pram { replaced */ u32 insertvlan; /* total frames that had their VLAN tag inserted */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_interrupt_coalescing_entry { u32 interruptcoalescingmaxvalue; /* interrupt coalescing max @@ -548,23 +548,23 @@ struct ucc_geth_rx_interrupt_coalescing_entry { u32 interruptcoalescingcounter; /* interrupt coalescing counter, initialize to interruptcoalescingmaxvalue */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_interrupt_coalescing_table { struct ucc_geth_rx_interrupt_coalescing_entry coalescingentry[NUM_RX_QUEUES]; /**< interrupt coalescing entry */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_prefetched_bds { struct qe_bd bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_bd_queues_entry { u32 bdbaseptr; /* BD base pointer */ u32 bdptr; /* BD pointer */ u32 externalbdbaseptr; /* external BD base pointer */ u32 externalbdptr; /* external BD pointer */ -} __attribute__ ((packed)); +} __packed; struct ucc_geth_tx_global_pram { u16 temoder; @@ -580,13 +580,13 @@ struct ucc_geth_tx_global_pram { u32 tqptr; /* a base pointer to the Tx Queues Memory Region */ u8 res2[0x80 - 0x74]; -} __attribute__ ((packed)); +} __packed; /* structure representing Extended Filtering Global Parameters in PRAM */ struct ucc_geth_exf_global_pram { u32 l2pcdptr; /* individual address filter, high */ u8 res0[0x10 - 0x04]; -} __attribute__ ((packed)); +} __packed; struct ucc_geth_rx_global_pram { u32 remoder; /* ethernet mode reg. */ @@ -620,7 +620,7 @@ struct ucc_geth_rx_global_pram { u32 exfGlobalParam; /* base address for extended filtering global parameters */ u8 res6[0x100 - 0xC4]; /* Initialize to zero */ -} __attribute__ ((packed)); +} __packed; #define GRACEFUL_STOP_ACKNOWLEDGE_RX 0x01 @@ -639,7 +639,7 @@ struct ucc_geth_init_pram { u32 txglobal; /* tx global */ u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX]; /* tx threads */ u8 res3[0x1]; -} __attribute__ ((packed)); +} __packed; #define ENET_INIT_PARAM_RGF_SHIFT (32 - 4) #define ENET_INIT_PARAM_TGF_SHIFT (32 - 8) @@ -661,7 +661,7 @@ struct ucc_geth_82xx_enet_address { u16 h; /* address (MSB) */ u16 m; /* address */ u16 l; /* address (LSB) */ -} __attribute__ ((packed)); +} __packed; /* structure representing 82xx Address Filtering PRAM */ struct ucc_geth_82xx_address_filtering_pram { @@ -672,7 +672,7 @@ struct ucc_geth_82xx_address_filtering_pram { struct ucc_geth_82xx_enet_address __iomem taddr; struct ucc_geth_82xx_enet_address __iomem paddr[NUM_OF_PADDRS]; u8 res0[0x40 - 0x38]; -} __attribute__ ((packed)); +} __packed; /* GETH Tx firmware statistics structure, used when calling UCC_GETH_GetStatistics. */ @@ -696,7 +696,7 @@ struct ucc_geth_tx_firmware_statistics { and 1518 octets */ u32 txpktsjumbo; /* total packets (including bad) between 1024 and MAXLength octets */ -} __attribute__ ((packed)); +} __packed; /* GETH Rx firmware statistics structure, used when calling UCC_GETH_GetStatistics. */ @@ -732,7 +732,7 @@ struct ucc_geth_rx_firmware_statistics { replaced */ u32 insertvlan; /* total frames that had their VLAN tag inserted */ -} __attribute__ ((packed)); +} __packed; /* GETH hardware statistics structure, used when calling UCC_GETH_GetStatistics. */ @@ -781,7 +781,7 @@ struct ucc_geth_hardware_statistics { u32 rbca; /* Total number of frames received successfully that had destination address equal to the broadcast address */ -} __attribute__ ((packed)); +} __packed; /* UCC GETH Tx errors returned via TxConf callback */ #define TX_ERRORS_DEF 0x0200 diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 9516f382a6ba..aea4645be7f6 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -179,7 +179,7 @@ struct ax88172_int_data { __le16 res2; u8 status; __le16 res3; -} __attribute__ ((packed)); +} __packed; static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 4dd23513c5af..39422f71e1d0 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -211,7 +211,7 @@ struct hso_serial_state_notification { u16 wIndex; u16 wLength; u16 UART_state_bitmap; -} __attribute__((packed)); +} __packed; struct hso_tiocmget { struct mutex mutex; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index d6078b8c4273..2b7b39cad1ce 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -207,7 +207,7 @@ struct kaweth_ethernet_configuration __le16 segment_size; __u16 max_multicast_filters; __u8 reserved3; -} __attribute__ ((packed)); +} __packed; /**************************************************************** * kaweth_device diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 961a8ed38d8f..ba72a7281cb0 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -64,13 +64,13 @@ struct nc_header { // packed: // all else is optional, and must start with: // __le16 vendorId; // from usb-if // __le16 productId; -} __attribute__((__packed__)); +} __packed; #define PAD_BYTE ((unsigned char)0xAC) struct nc_trailer { __le16 packet_id; -} __attribute__((__packed__)); +} __packed; // packets may use FLAG_FRAMING_NC and optional pad #define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \ diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index f1942d69a0d5..ee85c8b9a858 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -165,7 +165,7 @@ struct lsi_umts { u8 gw_addr_len; /* NW-supplied GW address len */ u8 gw_addr[16]; /* NW-supplied GW address (bigendian) */ u8 reserved[8]; -} __attribute__ ((packed)); +} __packed; #define SIERRA_NET_LSI_COMMON_LEN 4 #define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts)) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index a95c73de5824..44115eea57f9 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -643,7 +643,7 @@ int usbnet_stop (struct net_device *net) netif_stop_queue (net); netif_info(dev, ifdown, dev->net, - "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", + "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n", net->stats.rx_packets, net->stats.tx_packets, net->stats.rx_errors, net->stats.tx_errors); diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index c38191179fae..f7b33ae7a703 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -193,7 +193,7 @@ struct rx_desc { __le32 pa_low; /* Low 32 bit PCI address */ __le16 pa_high; /* Next 16 bit PCI address (48 total) */ __le16 size; /* bits 0--14 - frame size, bit 15 - enable int. */ -} __attribute__ ((__packed__)); +} __packed; /* * Transmit descriptor @@ -208,7 +208,7 @@ struct tdesc1 { __le16 vlan; u8 TCR; u8 cmd; /* bits 0--1 - TCPLS, bits 4--7 - CMDZ */ -} __attribute__ ((__packed__)); +} __packed; enum { TD_QUEUE = cpu_to_le16(0x8000) @@ -218,7 +218,7 @@ struct td_buf { __le32 pa_low; __le16 pa_high; __le16 size; /* bits 0--13 - size, bit 15 - queue */ -} __attribute__ ((__packed__)); +} __packed; struct tx_desc { struct tdesc0 tdesc0; @@ -1096,7 +1096,7 @@ struct mac_regs { volatile __le16 PatternCRC[8]; /* 0xB0 */ volatile __le32 ByteMask[4][4]; /* 0xC0 */ -} __attribute__ ((__packed__)); +} __packed; enum hw_mib { @@ -1216,7 +1216,7 @@ struct arp_packet { u8 ar_sip[4]; u8 ar_tha[ETH_ALEN]; u8 ar_tip[4]; -} __attribute__ ((__packed__)); +} __packed; struct _magic_packet { u8 dest_mac[6]; @@ -1224,7 +1224,7 @@ struct _magic_packet { __be16 type; u8 MAC[16][6]; u8 password[6]; -} __attribute__ ((__packed__)); +} __packed; /* * Store for chip context when saving and restoring status. Not diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index b504bd561362..45c5dc225631 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -4012,7 +4012,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) int high_dma = 0; u64 vpath_mask = 0; struct vxgedev *vdev; - struct vxge_config ll_config; + struct vxge_config *ll_config = NULL; struct vxge_hw_device_config *device_config = NULL; struct vxge_hw_device_attr attr; int i, j, no_of_vpath = 0, max_vpath_supported = 0; @@ -4071,17 +4071,24 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit0; } - memset(&ll_config, 0, sizeof(struct vxge_config)); - ll_config.tx_steering_type = TX_MULTIQ_STEERING; - ll_config.intr_type = MSI_X; - ll_config.napi_weight = NEW_NAPI_WEIGHT; - ll_config.rth_steering = RTH_STEERING; + ll_config = kzalloc(sizeof(*ll_config), GFP_KERNEL); + if (!ll_config) { + ret = -ENOMEM; + vxge_debug_init(VXGE_ERR, + "ll_config : malloc failed %s %d", + __FILE__, __LINE__); + goto _exit0; + } + ll_config->tx_steering_type = TX_MULTIQ_STEERING; + ll_config->intr_type = MSI_X; + ll_config->napi_weight = NEW_NAPI_WEIGHT; + ll_config->rth_steering = RTH_STEERING; /* get the default configuration parameters */ vxge_hw_device_config_default_get(device_config); /* initialize configuration parameters */ - vxge_device_config_init(device_config, &ll_config.intr_type); + vxge_device_config_init(device_config, &ll_config->intr_type); ret = pci_enable_device(pdev); if (ret) { @@ -4134,7 +4141,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) (unsigned long long)pci_resource_start(pdev, 0)); status = vxge_hw_device_hw_info_get(attr.bar0, - &ll_config.device_hw_info); + &ll_config->device_hw_info); if (status != VXGE_HW_OK) { vxge_debug_init(VXGE_ERR, "%s: Reading of hardware info failed." @@ -4143,7 +4150,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit3; } - if (ll_config.device_hw_info.fw_version.major != + if (ll_config->device_hw_info.fw_version.major != VXGE_DRIVER_FW_VERSION_MAJOR) { vxge_debug_init(VXGE_ERR, "%s: Incorrect firmware version." @@ -4153,7 +4160,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit3; } - vpath_mask = ll_config.device_hw_info.vpath_mask; + vpath_mask = ll_config->device_hw_info.vpath_mask; if (vpath_mask == 0) { vxge_debug_ll_config(VXGE_TRACE, "%s: No vpaths available in device", VXGE_DRIVER_NAME); @@ -4165,10 +4172,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) "%s:%d Vpath mask = %llx", __func__, __LINE__, (unsigned long long)vpath_mask); - function_mode = ll_config.device_hw_info.function_mode; - host_type = ll_config.device_hw_info.host_type; + function_mode = ll_config->device_hw_info.function_mode; + host_type = ll_config->device_hw_info.host_type; is_privileged = __vxge_hw_device_is_privilaged(host_type, - ll_config.device_hw_info.func_id); + ll_config->device_hw_info.func_id); /* Check how many vpaths are available */ for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { @@ -4182,7 +4189,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) /* Enable SRIOV mode, if firmware has SRIOV support and if it is a PF */ if (is_sriov(function_mode) && (max_config_dev > 1) && - (ll_config.intr_type != INTA) && + (ll_config->intr_type != INTA) && (is_privileged == VXGE_HW_OK)) { ret = pci_enable_sriov(pdev, ((max_config_dev - 1) < num_vfs) ? (max_config_dev - 1) : num_vfs); @@ -4195,7 +4202,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) * Configure vpaths and get driver configured number of vpaths * which is less than or equal to the maximum vpaths per function. */ - no_of_vpath = vxge_config_vpaths(device_config, vpath_mask, &ll_config); + no_of_vpath = vxge_config_vpaths(device_config, vpath_mask, ll_config); if (!no_of_vpath) { vxge_debug_ll_config(VXGE_ERR, "%s: No more vpaths to configure", VXGE_DRIVER_NAME); @@ -4230,21 +4237,21 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) /* set private device info */ pci_set_drvdata(pdev, hldev); - ll_config.gro_enable = VXGE_GRO_ALWAYS_AGGREGATE; - ll_config.fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; - ll_config.addr_learn_en = addr_learn_en; - ll_config.rth_algorithm = RTH_ALG_JENKINS; - ll_config.rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4; - ll_config.rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config.rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config.rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config.rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config.rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; - ll_config.rth_bkt_sz = RTH_BUCKET_SIZE; - ll_config.tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; - ll_config.rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; - - if (vxge_device_register(hldev, &ll_config, high_dma, no_of_vpath, + ll_config->gro_enable = VXGE_GRO_ALWAYS_AGGREGATE; + ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; + ll_config->addr_learn_en = addr_learn_en; + ll_config->rth_algorithm = RTH_ALG_JENKINS; + ll_config->rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4; + ll_config->rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; + ll_config->rth_bkt_sz = RTH_BUCKET_SIZE; + ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; + ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; + + if (vxge_device_register(hldev, ll_config, high_dma, no_of_vpath, &vdev)) { ret = -EINVAL; goto _exit4; @@ -4275,7 +4282,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) vdev->vpaths[j].vdev = vdev; vdev->vpaths[j].max_mac_addr_cnt = max_mac_vpath; memcpy((u8 *)vdev->vpaths[j].macaddr, - (u8 *)ll_config.device_hw_info.mac_addrs[i], + ll_config->device_hw_info.mac_addrs[i], ETH_ALEN); /* Initialize the mac address list header */ @@ -4296,18 +4303,18 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) macaddr = (u8 *)vdev->vpaths[0].macaddr; - ll_config.device_hw_info.serial_number[VXGE_HW_INFO_LEN - 1] = '\0'; - ll_config.device_hw_info.product_desc[VXGE_HW_INFO_LEN - 1] = '\0'; - ll_config.device_hw_info.part_number[VXGE_HW_INFO_LEN - 1] = '\0'; + ll_config->device_hw_info.serial_number[VXGE_HW_INFO_LEN - 1] = '\0'; + ll_config->device_hw_info.product_desc[VXGE_HW_INFO_LEN - 1] = '\0'; + ll_config->device_hw_info.part_number[VXGE_HW_INFO_LEN - 1] = '\0'; vxge_debug_init(VXGE_TRACE, "%s: SERIAL NUMBER: %s", - vdev->ndev->name, ll_config.device_hw_info.serial_number); + vdev->ndev->name, ll_config->device_hw_info.serial_number); vxge_debug_init(VXGE_TRACE, "%s: PART NUMBER: %s", - vdev->ndev->name, ll_config.device_hw_info.part_number); + vdev->ndev->name, ll_config->device_hw_info.part_number); vxge_debug_init(VXGE_TRACE, "%s: Neterion %s Server Adapter", - vdev->ndev->name, ll_config.device_hw_info.product_desc); + vdev->ndev->name, ll_config->device_hw_info.product_desc); vxge_debug_init(VXGE_TRACE, "%s: MAC ADDR: %pM", vdev->ndev->name, macaddr); @@ -4317,11 +4324,11 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) vxge_debug_init(VXGE_TRACE, "%s: Firmware version : %s Date : %s", vdev->ndev->name, - ll_config.device_hw_info.fw_version.version, - ll_config.device_hw_info.fw_date.date); + ll_config->device_hw_info.fw_version.version, + ll_config->device_hw_info.fw_date.date); if (new_device) { - switch (ll_config.device_hw_info.function_mode) { + switch (ll_config->device_hw_info.function_mode) { case VXGE_HW_FUNCTION_MODE_SINGLE_FUNCTION: vxge_debug_init(VXGE_TRACE, "%s: Single Function Mode Enabled", vdev->ndev->name); @@ -4344,7 +4351,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) vxge_print_parm(vdev, vpath_mask); /* Store the fw version for ethttool option */ - strcpy(vdev->fw_version, ll_config.device_hw_info.fw_version.version); + strcpy(vdev->fw_version, ll_config->device_hw_info.fw_version.version); memcpy(vdev->ndev->dev_addr, (u8 *)vdev->vpaths[0].macaddr, ETH_ALEN); memcpy(vdev->ndev->perm_addr, vdev->ndev->dev_addr, ETH_ALEN); @@ -4383,7 +4390,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) * present to prevent such a failure. */ - if (ll_config.device_hw_info.function_mode == + if (ll_config->device_hw_info.function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) if (vdev->config.intr_type == INTA) vxge_hw_device_unmask_all(hldev); @@ -4395,6 +4402,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) VXGE_COPY_DEBUG_INFO_TO_LL(vdev, vxge_hw_device_error_level_get(hldev), vxge_hw_device_trace_level_get(hldev)); + kfree(ll_config); return 0; _exit5: @@ -4412,6 +4420,7 @@ _exit2: _exit1: pci_disable_device(pdev); _exit0: + kfree(ll_config); kfree(device_config); driver_config->config_dev_cnt--; pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index e087b9a6daaa..43b77271532b 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2038,16 +2038,10 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Now copy the data to the card. */ - buf = kmalloc(wrthdr.size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, - ifr->ifr_data + sizeof (struct fstioc_write), - wrthdr.size)) { - kfree(buf); - return -EFAULT; - } + buf = memdup_user(ifr->ifr_data + sizeof(struct fstioc_write), + wrthdr.size); + if (IS_ERR(buf)) + return PTR_ERR(buf); memcpy_toio(card->mem + wrthdr.offset, buf, wrthdr.size); kfree(buf); diff --git a/drivers/net/wan/hd64570.h b/drivers/net/wan/hd64570.h index 3839662ff201..e4f539ad071b 100644 --- a/drivers/net/wan/hd64570.h +++ b/drivers/net/wan/hd64570.h @@ -153,7 +153,7 @@ typedef struct { u16 len; /* Data Length */ u8 stat; /* Status */ u8 unused; /* pads to 2-byte boundary */ -}__attribute__ ((packed)) pkt_desc; +}__packed pkt_desc; /* Packet Descriptor Status bits */ diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index ee7083fbea50..b38ffa149aba 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -36,7 +36,7 @@ struct hdlc_header { u8 address; u8 control; __be16 protocol; -}__attribute__ ((packed)); +}__packed; struct cisco_packet { @@ -45,7 +45,7 @@ struct cisco_packet { __be32 par2; __be16 rel; /* reliability */ __be32 time; -}__attribute__ ((packed)); +}__packed; #define CISCO_PACKET_LEN 18 #define CISCO_BIG_PACKET_LEN 20 diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 0e52993e2079..0edb535bb2b5 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -112,7 +112,7 @@ typedef struct { unsigned de: 1; unsigned ea2: 1; #endif -}__attribute__ ((packed)) fr_hdr; +}__packed fr_hdr; typedef struct pvc_device_struct { diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 43ae6f440bfb..f4125da2762f 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -330,7 +330,7 @@ struct _dlci_stat { short dlci; char flags; -} __attribute__((packed)); +} __packed; struct _frad_stat { @@ -1211,14 +1211,9 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r } else { - temp = kmalloc(mem.len, GFP_KERNEL); - if (!temp) - return(-ENOMEM); - if(copy_from_user(temp, mem.data, mem.len)) - { - kfree(temp); - return -EFAULT; - } + temp = memdup_user(mem.data, mem.len); + if (IS_ERR(temp)) + return PTR_ERR(temp); sdla_write(dev, mem.addr, temp, mem.len); kfree(temp); } diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index d86e8f31e7fc..2f725d0cc762 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -848,7 +848,7 @@ struct i2400m_cmd_enter_power_save { struct i2400m_l3l4_hdr hdr; struct i2400m_tlv_hdr tlv; __le32 val; -} __attribute__((packed)); +} __packed; /* diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 11491354e5b5..8b55a5b14152 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -651,7 +651,7 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, struct { struct i2400m_bootrom_header cmd; u8 cmd_payload[chunk_len]; - } __attribute__((packed)) *buf; + } __packed *buf; struct i2400m_bootrom_header ack; d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx " @@ -794,7 +794,7 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, struct { struct i2400m_bootrom_header cmd; u8 cmd_pl[0]; - } __attribute__((packed)) *cmd_buf; + } __packed *cmd_buf; size_t signature_block_offset, signature_block_size; d_fnstart(3, dev, "offset %zu\n", offset); @@ -1029,7 +1029,7 @@ int i2400m_read_mac_addr(struct i2400m *i2400m) struct { struct i2400m_bootrom_header ack; u8 ack_pl[16]; - } __attribute__((packed)) ack_buf; + } __packed ack_buf; d_fnstart(5, dev, "(i2400m %p)\n", i2400m); cmd = i2400m->bm_cmd_buf; @@ -1115,7 +1115,7 @@ int i2400m_dnload_init_signed(struct i2400m *i2400m, struct { struct i2400m_bootrom_header cmd; struct i2400m_bcf_hdr cmd_pl; - } __attribute__((packed)) *cmd_buf; + } __packed *cmd_buf; struct i2400m_bootrom_header ack; d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr); diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index 035e4cf3e6ed..9e02b90b0080 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -91,7 +91,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, struct { struct i2400m_l3l4_hdr hdr; struct i2400m_tlv_rf_operation sw_rf; - } __attribute__((packed)) *cmd; + } __packed *cmd; char strerr[32]; d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state); diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h index b07e4d3a6b4d..bbc10b1cde87 100644 --- a/drivers/net/wireless/adm8211.h +++ b/drivers/net/wireless/adm8211.h @@ -80,7 +80,7 @@ struct adm8211_csr { __le32 FEMR; /* 0x104 */ __le32 FPSR; /* 0x108 */ __le32 FFER; /* 0x10C */ -} __attribute__ ((packed)); +} __packed; /* CSR0 - PAR (PCI Address Register) */ #define ADM8211_PAR_MWIE (1 << 24) @@ -484,7 +484,7 @@ struct adm8211_tx_hdr { u8 entry_control; // huh?? u16 reserved_1; u32 reserved_2; -} __attribute__ ((packed)); +} __packed; #define RX_COPY_BREAK 128 @@ -531,7 +531,7 @@ struct adm8211_eeprom { u8 lnags_threshold[14]; /* 0x70 */ __le16 checksum; /* 0x7E */ u8 cis_data[0]; /* 0x80, 384 bytes */ -} __attribute__ ((packed)); +} __packed; struct adm8211_priv { struct pci_dev *pdev; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 3b7ab20a5c54..6b605df8a923 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -506,20 +506,20 @@ struct WepKeyRid { u8 mac[ETH_ALEN]; __le16 klen; u8 key[16]; -} __attribute__ ((packed)); +} __packed; /* These structures are from the Aironet's PC4500 Developers Manual */ typedef struct Ssid Ssid; struct Ssid { __le16 len; u8 ssid[32]; -} __attribute__ ((packed)); +} __packed; typedef struct SsidRid SsidRid; struct SsidRid { __le16 len; Ssid ssids[3]; -} __attribute__ ((packed)); +} __packed; typedef struct ModulationRid ModulationRid; struct ModulationRid { @@ -528,7 +528,7 @@ struct ModulationRid { #define MOD_DEFAULT cpu_to_le16(0) #define MOD_CCK cpu_to_le16(1) #define MOD_MOK cpu_to_le16(2) -} __attribute__ ((packed)); +} __packed; typedef struct ConfigRid ConfigRid; struct ConfigRid { @@ -652,7 +652,7 @@ struct ConfigRid { #define MAGIC_STAY_IN_CAM (1<<10) u8 magicControl; __le16 autoWake; -} __attribute__ ((packed)); +} __packed; typedef struct StatusRid StatusRid; struct StatusRid { @@ -711,20 +711,20 @@ struct StatusRid { #define STAT_LEAPFAILED 91 #define STAT_LEAPTIMEDOUT 92 #define STAT_LEAPCOMPLETE 93 -} __attribute__ ((packed)); +} __packed; typedef struct StatsRid StatsRid; struct StatsRid { __le16 len; __le16 spacer; __le32 vals[100]; -} __attribute__ ((packed)); +} __packed; typedef struct APListRid APListRid; struct APListRid { __le16 len; u8 ap[4][ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; typedef struct CapabilityRid CapabilityRid; struct CapabilityRid { @@ -754,7 +754,7 @@ struct CapabilityRid { __le16 bootBlockVer; __le16 requiredHard; __le16 extSoftCap; -} __attribute__ ((packed)); +} __packed; /* Only present on firmware >= 5.30.17 */ typedef struct BSSListRidExtra BSSListRidExtra; @@ -762,7 +762,7 @@ struct BSSListRidExtra { __le16 unknown[4]; u8 fixed[12]; /* WLAN management frame */ u8 iep[624]; -} __attribute__ ((packed)); +} __packed; typedef struct BSSListRid BSSListRid; struct BSSListRid { @@ -796,7 +796,7 @@ struct BSSListRid { /* Only present on firmware >= 5.30.17 */ BSSListRidExtra extra; -} __attribute__ ((packed)); +} __packed; typedef struct { BSSListRid bss; @@ -807,13 +807,13 @@ typedef struct tdsRssiEntry tdsRssiEntry; struct tdsRssiEntry { u8 rssipct; u8 rssidBm; -} __attribute__ ((packed)); +} __packed; typedef struct tdsRssiRid tdsRssiRid; struct tdsRssiRid { u16 len; tdsRssiEntry x[256]; -} __attribute__ ((packed)); +} __packed; typedef struct MICRid MICRid; struct MICRid { @@ -823,7 +823,7 @@ struct MICRid { u8 multicast[16]; __le16 unicastValid; u8 unicast[16]; -} __attribute__ ((packed)); +} __packed; typedef struct MICBuffer MICBuffer; struct MICBuffer { @@ -841,7 +841,7 @@ struct MICBuffer { } u; __be32 mic; __be32 seq; -} __attribute__ ((packed)); +} __packed; typedef struct { u8 da[ETH_ALEN]; @@ -996,7 +996,7 @@ struct rx_hdr { u8 rate; u8 freq; __le16 tmp[4]; -} __attribute__ ((packed)); +} __packed; typedef struct { unsigned int ctl: 15; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 8a2d4afc74f8..429b281d40d1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -305,7 +305,7 @@ struct dfu_status { unsigned char poll_timeout[3]; unsigned char state; unsigned char string; -} __attribute__((packed)); +} __packed; static inline int at76_is_intersil(enum board_type board) { diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h index 1ec5ccffdbc0..972ea0fc1a0b 100644 --- a/drivers/net/wireless/at76c50x-usb.h +++ b/drivers/net/wireless/at76c50x-usb.h @@ -99,7 +99,7 @@ struct hwcfg_r505 { u8 reserved2[14]; u8 cr15_values[14]; u8 reserved3[3]; -} __attribute__((packed)); +} __packed; struct hwcfg_rfmd { u8 cr20_values[14]; @@ -111,7 +111,7 @@ struct hwcfg_rfmd { u8 low_power_values[14]; u8 normal_power_values[14]; u8 reserved1[3]; -} __attribute__((packed)); +} __packed; struct hwcfg_intersil { u8 mac_addr[ETH_ALEN]; @@ -120,7 +120,7 @@ struct hwcfg_intersil { u8 pidvid[4]; u8 regulatory_domain; u8 reserved[1]; -} __attribute__((packed)); +} __packed; union at76_hwcfg { struct hwcfg_intersil i; @@ -149,14 +149,14 @@ struct at76_card_config { u8 ssid_len; u8 short_preamble; __le16 beacon_period; -} __attribute__((packed)); +} __packed; struct at76_command { u8 cmd; u8 reserved; __le16 size; u8 data[0]; -} __attribute__((packed)); +} __packed; /* Length of Atmel-specific Rx header before 802.11 frame */ #define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet) @@ -171,7 +171,7 @@ struct at76_rx_buffer { u8 noise_level; __le32 rx_time; u8 packet[IEEE80211_MAX_FRAG_THRESHOLD]; -} __attribute__((packed)); +} __packed; /* Length of Atmel-specific Tx header before 802.11 frame */ #define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet) @@ -182,7 +182,7 @@ struct at76_tx_buffer { u8 padding; u8 reserved[4]; u8 packet[IEEE80211_MAX_FRAG_THRESHOLD]; -} __attribute__((packed)); +} __packed; /* defines for scan_type below */ #define SCAN_TYPE_ACTIVE 0 @@ -198,7 +198,7 @@ struct at76_req_scan { __le16 max_channel_time; u8 essid_size; u8 international_scan; -} __attribute__((packed)); +} __packed; struct at76_req_ibss { u8 bssid[ETH_ALEN]; @@ -207,7 +207,7 @@ struct at76_req_ibss { u8 channel; u8 essid_size; u8 reserved[3]; -} __attribute__((packed)); +} __packed; struct at76_req_join { u8 bssid[ETH_ALEN]; @@ -217,7 +217,7 @@ struct at76_req_join { __le16 timeout; u8 essid_size; u8 reserved; -} __attribute__((packed)); +} __packed; struct set_mib_buffer { u8 type; @@ -229,7 +229,7 @@ struct set_mib_buffer { __le16 word; u8 addr[ETH_ALEN]; } data; -} __attribute__((packed)); +} __packed; struct mib_local { u16 reserved0; @@ -241,14 +241,14 @@ struct mib_local { u16 reserved2; u8 preamble_type; u16 reserved3; -} __attribute__((packed)); +} __packed; struct mib_mac_addr { u8 mac_addr[ETH_ALEN]; u8 res[2]; /* ??? */ u8 group_addr[4][ETH_ALEN]; u8 group_addr_status[4]; -} __attribute__((packed)); +} __packed; struct mib_mac { __le32 max_tx_msdu_lifetime; @@ -269,7 +269,7 @@ struct mib_mac { u8 desired_bssid[ETH_ALEN]; u8 desired_bsstype; /* ad-hoc or infrastructure */ u8 reserved2; -} __attribute__((packed)); +} __packed; struct mib_mac_mgmt { __le16 beacon_period; @@ -292,7 +292,7 @@ struct mib_mac_mgmt { u8 multi_domain_capability_enabled; u8 country_string[3]; u8 reserved[3]; -} __attribute__((packed)); +} __packed; struct mib_mac_wep { u8 privacy_invoked; /* 0 disable encr., 1 enable encr */ @@ -303,7 +303,7 @@ struct mib_mac_wep { __le32 wep_excluded_count; u8 wep_default_keyvalue[WEP_KEYS][WEP_LARGE_KEY_LEN]; u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */ -} __attribute__((packed)); +} __packed; struct mib_phy { __le32 ed_threshold; @@ -320,19 +320,19 @@ struct mib_phy { u8 current_cca_mode; u8 phy_type; u8 current_reg_domain; -} __attribute__((packed)); +} __packed; struct mib_fw_version { u8 major; u8 minor; u8 patch; u8 build; -} __attribute__((packed)); +} __packed; struct mib_mdomain { u8 tx_powerlevel[14]; u8 channel_list[14]; /* 0 for invalid channels */ -} __attribute__((packed)); +} __packed; struct at76_fw_header { __le32 crc; /* CRC32 of the whole image */ @@ -346,7 +346,7 @@ struct at76_fw_header { __le32 int_fw_len; /* internal firmware image length */ __le32 ext_fw_offset; /* external firmware image offset */ __le32 ext_fw_len; /* external firmware image length */ -} __attribute__((packed)); +} __packed; /* a description of a regulatory domain and the allowed channels */ struct reg_domain { diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index cc09595b781a..2242a140e4fe 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -13,5 +13,6 @@ ath5k-y += base.o ath5k-y += led.o ath5k-y += rfkill.o ath5k-y += ani.o +ath5k-y += sysfs.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index f2311ab35504..26dbe65fedb0 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -74,8 +74,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) const s8 fr[] = { -78, -80 }; #endif if (level < 0 || level >= ARRAY_SIZE(sz)) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, - "level out of range %d", level); + ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", + level); return; } @@ -106,8 +106,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) if (level < 0 || level >= ARRAY_SIZE(val) || level > ah->ah_sc->ani_state.max_spur_level) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, - "level out of range %d", level); + ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range", + level); return; } @@ -130,8 +130,7 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) const int val[] = { 0, 4, 8 }; if (level < 0 || level >= ARRAY_SIZE(val)) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, - "level out of range %d", level); + ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); return; } @@ -481,14 +480,15 @@ ath5k_ani_calibration(struct ath5k_hw *ah) struct ath5k_ani_state *as = &ah->ah_sc->ani_state; int listen, ofdm_high, ofdm_low, cck_high, cck_low; - if (as->ani_mode != ATH5K_ANI_MODE_AUTO) - return; - /* get listen time since last call and add it to the counter because we - * might not have restarted the "ani period" last time */ + * might not have restarted the "ani period" last time. + * always do this to calculate the busy time also in manual mode */ listen = ath5k_hw_ani_get_listen_time(ah, as); as->listen_time += listen; + if (as->ani_mode != ATH5K_ANI_MODE_AUTO) + return; + ath5k_ani_save_and_clear_phy_errors(ah, as); ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 2785946f659a..ea6362a8988d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -204,6 +204,7 @@ #define AR5K_TUNE_TPC_TXPOWER false #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ +#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ #define AR5K_INIT_CARR_SENSE_EN 1 @@ -565,7 +566,7 @@ enum ath5k_pkt_type { ) /* - * DMA size definitions (2^n+2) + * DMA size definitions (2^(n+2)) */ enum ath5k_dmasize { AR5K_DMASIZE_4B = 0, @@ -1118,6 +1119,7 @@ struct ath5k_hw { /* Calibration timestamp */ unsigned long ah_cal_next_full; unsigned long ah_cal_next_ani; + unsigned long ah_cal_next_nf; /* Calibration mask */ u8 ah_cal_mask; @@ -1125,15 +1127,10 @@ struct ath5k_hw { /* * Function pointers */ - int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags); int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); - int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int); int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, struct ath5k_tx_status *); int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, @@ -1148,6 +1145,9 @@ struct ath5k_hw { int ath5k_hw_attach(struct ath5k_softc *sc); void ath5k_hw_detach(struct ath5k_hw *ah); +int ath5k_sysfs_register(struct ath5k_softc *sc); +void ath5k_sysfs_unregister(struct ath5k_softc *sc); + /* LED functions */ int ath5k_init_leds(struct ath5k_softc *sc); void ath5k_led_enable(struct ath5k_softc *sc); @@ -1231,6 +1231,11 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); /* Hardware Descriptor Functions */ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); +int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + u32 size, unsigned int flags); +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); @@ -1270,6 +1275,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); +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); @@ -1280,6 +1286,7 @@ 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); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 31c008042bfe..b32e28caeee2 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -352,8 +352,6 @@ err_free: */ void ath5k_hw_detach(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); - __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); if (ah->ah_rf_banks != NULL) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 648972df369d..20328bdd138b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -311,7 +311,8 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, struct ath5k_txq *txq, int padsize); -static inline void ath5k_txbuf_free(struct ath5k_softc *sc, + +static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) { BUG_ON(!bf); @@ -321,9 +322,11 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, PCI_DMA_TODEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; } -static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, +static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) { struct ath5k_hw *ah = sc->ah; @@ -336,6 +339,8 @@ static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; } @@ -352,7 +357,6 @@ static void ath5k_txq_release(struct ath5k_softc *sc); static int ath5k_rx_start(struct ath5k_softc *sc); static void ath5k_rx_stop(struct ath5k_softc *sc); static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, - struct ath5k_desc *ds, struct sk_buff *skb, struct ath5k_rx_status *rs); static void ath5k_tasklet_rx(unsigned long data); @@ -578,7 +582,7 @@ ath5k_pci_probe(struct pci_dev *pdev, spin_lock_init(&sc->block); /* Set private data */ - pci_set_drvdata(pdev, hw); + pci_set_drvdata(pdev, sc); /* Setup interrupt handler */ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); @@ -694,25 +698,23 @@ err: static void __devexit ath5k_pci_remove(struct pci_dev *pdev) { - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; + struct ath5k_softc *sc = pci_get_drvdata(pdev); ath5k_debug_finish_device(sc); - ath5k_detach(pdev, hw); + 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(hw); + ieee80211_free_hw(sc->hw); } #ifdef CONFIG_PM_SLEEP static int ath5k_pci_suspend(struct device *dev) { - struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); - struct ath5k_softc *sc = hw->priv; + struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); ath5k_led_off(sc); return 0; @@ -721,8 +723,7 @@ static int ath5k_pci_suspend(struct device *dev) static int ath5k_pci_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; + struct ath5k_softc *sc = pci_get_drvdata(pdev); /* * Suspend/Resume resets the PCI configuration space, so we have to @@ -768,7 +769,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) * return false w/o doing anything. MAC's that do * support it will return true w/o doing anything. */ - ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + if (ret < 0) goto err; if (ret > 0) @@ -864,6 +866,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) ath5k_init_leds(sc); + ath5k_sysfs_register(sc); + return 0; err_queues: ath5k_txq_release(sc); @@ -899,6 +903,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); ath5k_unregister_leds(sc); + ath5k_sysfs_unregister(sc); /* * NB: can't reclaim these until after ieee80211_ifdetach * returns because we'll get called back to reclaim node @@ -1111,8 +1116,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) static int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", - sc->curchan->center_freq, chan->center_freq); + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "channel set, resetting (%u -> %u MHz)\n", + sc->curchan->center_freq, chan->center_freq); /* * To switch channels clear any pending DMA operations; @@ -1228,21 +1234,23 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) * not get overrun under high load (as can happen with a * 5212 when ANI processing enables PHY error frames). * - * To insure the last descriptor is self-linked we create + * To ensure the last descriptor is self-linked we create * each descriptor as self-linked and add it to the end. As * each additional descriptor is added the previous self-linked - * entry is ``fixed'' naturally. This should be safe even + * entry is "fixed" naturally. This should be safe even * if DMA is happening. When processing RX interrupts we * never remove/process the last, self-linked, entry on the - * descriptor list. This insures the hardware always has + * descriptor list. This ensures the hardware always has * someplace to write a new frame. */ ds = bf->desc; ds->ds_link = bf->daddr; /* link to self */ ds->ds_data = bf->skbaddr; - ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); - if (ret) + ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); + if (ret) { + ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__); return ret; + } if (sc->rxlink != NULL) *sc->rxlink = bf->daddr; @@ -1347,7 +1355,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, mrr_tries[i] = info->control.rates[i + 1].count; } - ah->ah_setup_mrr_tx_desc(ah, ds, + ath5k_hw_setup_mrr_tx_desc(ah, ds, mrr_rate[0], mrr_tries[0], mrr_rate[1], mrr_tries[1], mrr_rate[2], mrr_tries[2]); @@ -1443,17 +1451,20 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) { struct ath5k_buf *bf; - ath5k_txbuf_free(sc, sc->bbuf); + ath5k_txbuf_free_skb(sc, sc->bbuf); list_for_each_entry(bf, &sc->txbuf, list) - ath5k_txbuf_free(sc, bf); + ath5k_txbuf_free_skb(sc, bf); list_for_each_entry(bf, &sc->rxbuf, list) - ath5k_rxbuf_free(sc, bf); + ath5k_rxbuf_free_skb(sc, bf); /* Free memory associated with all descriptors */ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + sc->desc = NULL; + sc->desc_daddr = 0; kfree(sc->bufptr); sc->bufptr = NULL; + sc->bbuf = NULL; } @@ -1602,7 +1613,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) list_for_each_entry_safe(bf, bf0, &txq->q, list) { ath5k_debug_printtxbuf(sc, bf); - ath5k_txbuf_free(sc, bf); + ath5k_txbuf_free_skb(sc, bf); spin_lock_bh(&sc->txbuflock); list_move_tail(&bf->list, &sc->txbuf); @@ -1721,8 +1732,8 @@ ath5k_rx_stop(struct ath5k_softc *sc) } static unsigned int -ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, - struct sk_buff *skb, struct ath5k_rx_status *rs) +ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb, + struct ath5k_rx_status *rs) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -1889,9 +1900,138 @@ static int ath5k_remove_padding(struct sk_buff *skb) } static void -ath5k_tasklet_rx(unsigned long data) +ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, + struct ath5k_rx_status *rs) { struct ieee80211_rx_status *rxs; + + /* The MAC header is padded to have 32-bit boundary if the + * packet payload is non-zero. The general calculation for + * padsize would take into account odd header lengths: + * padsize = (4 - hdrlen % 4) % 4; However, since only + * even-length headers are used, padding can only be 0 or 2 + * bytes and we can optimize this a bit. In addition, we must + * not try to remove padding from short control frames that do + * not have payload. */ + ath5k_remove_padding(skb); + + rxs = IEEE80211_SKB_RXCB(skb); + + rxs->flag = 0; + if (unlikely(rs->rs_status & AR5K_RXERR_MIC)) + rxs->flag |= RX_FLAG_MMIC_ERROR; + + /* + * always extend the mac timestamp, since this information is + * also needed for proper IBSS merging. + * + * XXX: it might be too late to do it here, since rs_tstamp is + * 15bit only. that means TSF extension has to be done within + * 32768usec (about 32ms). it might be necessary to move this to + * the interrupt handler, like it is done in madwifi. + * + * Unfortunately we don't know when the hardware takes the rx + * timestamp (beginning of phy frame, data frame, end of rx?). + * The only thing we know is that it is hardware specific... + * On AR5213 it seems the rx timestamp is at the end of the + * frame, but i'm not sure. + * + * NOTE: mac80211 defines mactime at the beginning of the first + * data symbol. Since we don't have any time references it's + * impossible to comply to that. This affects IBSS merge only + * right now, so it's not too bad... + */ + rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); + rxs->flag |= RX_FLAG_TSFT; + + rxs->freq = sc->curchan->center_freq; + rxs->band = sc->curband->band; + + rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; + + rxs->antenna = rs->rs_antenna; + + if (rs->rs_antenna > 0 && rs->rs_antenna < 5) + sc->stats.antenna_rx[rs->rs_antenna]++; + else + sc->stats.antenna_rx[0]++; /* invalid */ + + rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate); + rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); + + if (rxs->rate_idx >= 0 && rs->rs_rate == + sc->curband->bitrates[rxs->rate_idx].hw_value_short) + rxs->flag |= RX_FLAG_SHORTPRE; + + ath5k_debug_dump_skb(sc, skb, "RX ", 0); + + ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); + + /* check beacons in IBSS mode */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) + ath5k_check_ibss_tsf(sc, skb, rxs); + + ieee80211_rx(sc->hw, skb); +} + +/** ath5k_frame_receive_ok() - Do we want to receive this frame or not? + * + * Check if we want to further process this frame or not. Also update + * statistics. Return true if we want this frame, false if not. + */ +static bool +ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) +{ + sc->stats.rx_all_count++; + + if (unlikely(rs->rs_status)) { + if (rs->rs_status & AR5K_RXERR_CRC) + sc->stats.rxerr_crc++; + if (rs->rs_status & AR5K_RXERR_FIFO) + sc->stats.rxerr_fifo++; + if (rs->rs_status & AR5K_RXERR_PHY) { + sc->stats.rxerr_phy++; + if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32) + sc->stats.rxerr_phy_code[rs->rs_phyerr]++; + return false; + } + if (rs->rs_status & AR5K_RXERR_DECRYPT) { + /* + * Decrypt error. If the error occurred + * because there was no hardware key, then + * let the frame through so the upper layers + * can process it. This is necessary for 5210 + * parts which have no way to setup a ``clear'' + * key cache entry. + * + * XXX do key cache faulting + */ + sc->stats.rxerr_decrypt++; + if (rs->rs_keyix == AR5K_RXKEYIX_INVALID && + !(rs->rs_status & AR5K_RXERR_CRC)) + return true; + } + if (rs->rs_status & AR5K_RXERR_MIC) { + sc->stats.rxerr_mic++; + return true; + } + + /* let crypto-error packets fall through in MNTR */ + if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || + sc->opmode != NL80211_IFTYPE_MONITOR) + return false; + } + + if (unlikely(rs->rs_more)) { + sc->stats.rxerr_jumbo++; + return false; + } + return true; +} + +static void +ath5k_tasklet_rx(unsigned long data) +{ struct ath5k_rx_status rs = {}; struct sk_buff *skb, *next_skb; dma_addr_t next_skb_addr; @@ -1901,7 +2041,6 @@ ath5k_tasklet_rx(unsigned long data) struct ath5k_buf *bf; struct ath5k_desc *ds; int ret; - int rx_flag; spin_lock(&sc->rxbuflock); if (list_empty(&sc->rxbuf)) { @@ -1909,8 +2048,6 @@ ath5k_tasklet_rx(unsigned long data) goto unlock; } do { - rx_flag = 0; - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); BUG_ON(bf->skb == NULL); skb = bf->skb; @@ -1926,137 +2063,30 @@ ath5k_tasklet_rx(unsigned long data) else if (unlikely(ret)) { ATH5K_ERR(sc, "error in processing rx descriptor\n"); sc->stats.rxerr_proc++; - spin_unlock(&sc->rxbuflock); - return; + break; } - sc->stats.rx_all_count++; - - if (unlikely(rs.rs_status)) { - if (rs.rs_status & AR5K_RXERR_CRC) - sc->stats.rxerr_crc++; - if (rs.rs_status & AR5K_RXERR_FIFO) - sc->stats.rxerr_fifo++; - if (rs.rs_status & AR5K_RXERR_PHY) { - sc->stats.rxerr_phy++; - if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) - sc->stats.rxerr_phy_code[rs.rs_phyerr]++; - goto next; - } - if (rs.rs_status & AR5K_RXERR_DECRYPT) { - /* - * Decrypt error. If the error occurred - * because there was no hardware key, then - * let the frame through so the upper layers - * can process it. This is necessary for 5210 - * parts which have no way to setup a ``clear'' - * key cache entry. - * - * XXX do key cache faulting - */ - sc->stats.rxerr_decrypt++; - if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && - !(rs.rs_status & AR5K_RXERR_CRC)) - goto accept; - } - if (rs.rs_status & AR5K_RXERR_MIC) { - rx_flag |= RX_FLAG_MMIC_ERROR; - sc->stats.rxerr_mic++; - goto accept; - } + if (ath5k_receive_frame_ok(sc, &rs)) { + next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); - /* let crypto-error packets fall through in MNTR */ - if ((rs.rs_status & - ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || - sc->opmode != NL80211_IFTYPE_MONITOR) + /* + * If we can't replace bf->skb with a new skb under + * memory pressure, just skip this packet + */ + if (!next_skb) goto next; - } - - if (unlikely(rs.rs_more)) { - sc->stats.rxerr_jumbo++; - goto next; - - } -accept: - next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); - - /* - * If we can't replace bf->skb with a new skb under memory - * pressure, just skip this packet - */ - if (!next_skb) - goto next; - - pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); - skb_put(skb, rs.rs_datalen); - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - ath5k_remove_padding(skb); - - rxs = IEEE80211_SKB_RXCB(skb); - - /* - * always extend the mac timestamp, since this information is - * also needed for proper IBSS merging. - * - * XXX: it might be too late to do it here, since rs_tstamp is - * 15bit only. that means TSF extension has to be done within - * 32768usec (about 32ms). it might be necessary to move this to - * the interrupt handler, like it is done in madwifi. - * - * Unfortunately we don't know when the hardware takes the rx - * timestamp (beginning of phy frame, data frame, end of rx?). - * The only thing we know is that it is hardware specific... - * On AR5213 it seems the rx timestamp is at the end of the - * frame, but i'm not sure. - * - * NOTE: mac80211 defines mactime at the beginning of the first - * data symbol. Since we don't have any time references it's - * impossible to comply to that. This affects IBSS merge only - * right now, so it's not too bad... - */ - rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); - rxs->flag = rx_flag | RX_FLAG_TSFT; - - rxs->freq = sc->curchan->center_freq; - rxs->band = sc->curband->band; - - rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi; - - rxs->antenna = rs.rs_antenna; - - if (rs.rs_antenna > 0 && rs.rs_antenna < 5) - sc->stats.antenna_rx[rs.rs_antenna]++; - else - sc->stats.antenna_rx[0]++; /* invalid */ - - rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); - rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); - - if (rxs->rate_idx >= 0 && rs.rs_rate == - sc->curband->bitrates[rxs->rate_idx].hw_value_short) - rxs->flag |= RX_FLAG_SHORTPRE; - ath5k_debug_dump_skb(sc, skb, "RX ", 0); + pci_unmap_single(sc->pdev, bf->skbaddr, + common->rx_bufsize, + PCI_DMA_FROMDEVICE); - ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); + skb_put(skb, rs.rs_datalen); - /* check beacons in IBSS mode */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_check_ibss_tsf(sc, skb, rxs); + ath5k_receive_frame(sc, skb, &rs); - ieee80211_rx(sc->hw, skb); - - bf->skb = next_skb; - bf->skbaddr = next_skb_addr; + bf->skb = next_skb; + bf->skbaddr = next_skb_addr; + } next: list_move_tail(&bf->list, &sc->rxbuf); } while (ath5k_rxbuf_setup(sc, bf) == 0); @@ -2065,8 +2095,6 @@ unlock: } - - /*************\ * TX Handling * \*************/ @@ -2298,6 +2326,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", sc->bmisscount); + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "stuck beacon, resetting\n"); tasklet_schedule(&sc->restq); } return; @@ -2647,7 +2677,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "putting device to sleep\n"); } - ath5k_txbuf_free(sc, sc->bbuf); + ath5k_txbuf_free_skb(sc, sc->bbuf); mmiowb(); mutex_unlock(&sc->lock); @@ -2705,6 +2735,8 @@ ath5k_intr(int irq, void *dev_id) * Fatal errors are unrecoverable. * Typically these are caused by DMA errors. */ + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "fatal int, resetting\n"); tasklet_schedule(&sc->restq); } else if (unlikely(status & AR5K_INT_RXORN)) { /* @@ -2717,8 +2749,11 @@ ath5k_intr(int irq, void *dev_id) * this guess is copied from the HAL. */ sc->stats.rxorn_intr++; - if (ah->ah_mac_srev < AR5K_SREV_AR5212) + if (ah->ah_mac_srev < AR5K_SREV_AR5212) { + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "rx overrun, resetting\n"); tasklet_schedule(&sc->restq); + } else tasklet_schedule(&sc->rxtq); } else { @@ -2785,10 +2820,6 @@ ath5k_tasklet_calibrate(unsigned long data) /* Only full calibration for now */ ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; - /* Stop queues so that calibration - * doesn't interfere with tx */ - ieee80211_stop_queues(sc->hw); - ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", ieee80211_frequency_to_channel(sc->curchan->center_freq), sc->curchan->hw_value); @@ -2806,8 +2837,16 @@ ath5k_tasklet_calibrate(unsigned long data) ieee80211_frequency_to_channel( sc->curchan->center_freq)); - /* Wake queues */ - ieee80211_wake_queues(sc->hw); + /* Noise floor calibration interrupts rx/tx path while I/Q calibration + * doesn't. We stop the queues so that calibration doesn't interfere + * with TX and don't run it as often */ + if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { + ah->ah_cal_next_nf = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); + ieee80211_stop_queues(sc->hw); + ath5k_hw_update_noise_floor(ah); + ieee80211_wake_queues(sc->hw); + } ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; } @@ -2926,6 +2965,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); + ah->ah_cal_next_full = jiffies; + ah->ah_cal_next_ani = jiffies; + ah->ah_cal_next_nf = jiffies; + /* * Change channels and update the h/w rate map if we're switching; * e.g. 11a to 11b/g. @@ -3360,7 +3403,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ath5k_debug_dump_skb(sc, skb, "BC ", 1); - ath5k_txbuf_free(sc, sc->bbuf); + ath5k_txbuf_free_skb(sc, sc->bbuf); sc->bbuf->skb = skb; ret = ath5k_beacon_setup(sc, sc->bbuf); if (ret) diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 74f007126f41..beae519aa735 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -34,7 +34,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) { u16 ee_header; - ATH5K_TRACE(ah->ah_sc); /* Capabilities stored in the EEPROM */ ee_header = ah->ah_capabilities.cap_eeprom.ee_header; @@ -123,8 +122,6 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result) { - ATH5K_TRACE(ah->ah_sc); - switch (cap_type) { case AR5K_CAP_NUM_TXQUEUES: if (result) { @@ -173,8 +170,6 @@ yes: int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id) { - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version == AR5K_AR5210) { AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); @@ -186,8 +181,6 @@ int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version == AR5K_AR5210) { AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 6fb5c5ffa5b1..8c638865c712 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -278,6 +278,7 @@ static ssize_t write_file_reset(struct file *file, size_t count, loff_t *ppos) { struct ath5k_softc *sc = file->private_data; + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); tasklet_schedule(&sc->restq); return count; } @@ -307,7 +308,6 @@ 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_TRACE, "trace", "trace function calls" }, { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, }; @@ -426,6 +426,13 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf, "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); + v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0); + len += snprintf(buf+len, sizeof(buf)-len, + "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v); + v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1); + len += snprintf(buf+len, sizeof(buf)-len, + "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -729,6 +736,66 @@ static const struct file_operations fops_ani = { }; +/* debugfs: queues etc */ + +static ssize_t read_file_queue(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + + struct ath5k_txq *txq; + struct ath5k_buf *bf, *bf0; + int i, n = 0; + + len += snprintf(buf+len, sizeof(buf)-len, + "available txbuffers: %d\n", sc->txbuf_len); + + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { + txq = &sc->txqs[i]; + + len += snprintf(buf+len, sizeof(buf)-len, + "%02d: %ssetup\n", i, txq->setup ? "" : "not "); + + if (!txq->setup) + continue; + + list_for_each_entry_safe(bf, bf0, &txq->q, list) + n++; + len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_queue(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "start", 5) == 0) + ieee80211_wake_queues(sc->hw); + else if (strncmp(buf, "stop", 4) == 0) + ieee80211_stop_queues(sc->hw); + + return count; +} + + +static const struct file_operations fops_queue = { + .read = read_file_queue, + .write = write_file_queue, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -772,6 +839,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc) S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_ani); + + sc->debug.debugfs_queue = debugfs_create_file("queue", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_queue); } void @@ -790,6 +862,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) debugfs_remove(sc->debug.debugfs_antenna); debugfs_remove(sc->debug.debugfs_frameerrors); debugfs_remove(sc->debug.debugfs_ani); + debugfs_remove(sc->debug.debugfs_queue); debugfs_remove(sc->debug.debugfs_phydir); } @@ -852,7 +925,7 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, ds, (unsigned long long)bf->daddr, ds->ds_link, ds->ds_data, rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, - rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, + rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1, !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); } @@ -867,7 +940,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; - printk(KERN_DEBUG "rx queue %x, link %p\n", + printk(KERN_DEBUG "rxdp %x, rxlink %p\n", ath5k_hw_get_rxdp(ah), sc->rxlink); spin_lock_bh(&sc->rxbuflock); diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index ddd5b3a99e8d..606ae94a9157 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -77,6 +77,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_antenna; struct dentry *debugfs_frameerrors; struct dentry *debugfs_ani; + struct dentry *debugfs_queue; }; /** @@ -115,18 +116,12 @@ enum ath5k_debug_level { ATH5K_DEBUG_DUMP_RX = 0x00000100, ATH5K_DEBUG_DUMP_TX = 0x00000200, ATH5K_DEBUG_DUMPBANDS = 0x00000400, - ATH5K_DEBUG_TRACE = 0x00001000, ATH5K_DEBUG_ANI = 0x00002000, ATH5K_DEBUG_ANY = 0xffffffff }; #ifdef CONFIG_ATH5K_DEBUG -#define ATH5K_TRACE(_sc) do { \ - if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ - printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ - } while (0) - #define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ @@ -168,8 +163,6 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); #include <linux/compiler.h> -#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) - static inline void __attribute__ ((format (printf, 3, 4))) ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 7d7b646ab65a..43244382f213 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -91,14 +91,13 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; /* - * Verify and set header length - * XXX: I only found that on 5210 code, does it work on 5211 ? + * Verify and set header length (only 5210) */ if (ah->ah_version == AR5K_AR5210) { - if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) + if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210) return -EINVAL; tx_ctl->tx_control_0 |= - AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); + AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210); } /*Differences between 5210-5211*/ @@ -110,11 +109,11 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, case AR5K_PKT_TYPE_PIFS: frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; default: - frame_type = type /*<< 2 ?*/; + frame_type = type; } tx_ctl->tx_control_0 |= - AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | + AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210) | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); } else { @@ -123,21 +122,30 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); tx_ctl->tx_control_1 |= - AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); + AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211); } + #define _TX_FLAGS(_c, _flag) \ if (flags & AR5K_TXDESC_##_flag) { \ tx_ctl->tx_control_##_c |= \ AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ } - +#define _TX_FLAGS_5211(_c, _flag) \ + if (flags & AR5K_TXDESC_##_flag) { \ + tx_ctl->tx_control_##_c |= \ + AR5K_2W_TX_DESC_CTL##_c##_##_flag##_5211; \ + } _TX_FLAGS(0, CLRDMASK); - _TX_FLAGS(0, VEOL); _TX_FLAGS(0, INTREQ); _TX_FLAGS(0, RTSENA); - _TX_FLAGS(1, NOACK); + + if (ah->ah_version == AR5K_AR5211) { + _TX_FLAGS_5211(0, VEOL); + _TX_FLAGS_5211(1, NOACK); + } #undef _TX_FLAGS +#undef _TX_FLAGS_5211 /* * WEP crap @@ -147,7 +155,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); + AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX); } /* @@ -156,7 +164,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, if ((ah->ah_version == AR5K_AR5210) && (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) tx_ctl->tx_control_1 |= rtscts_duration & - AR5K_2W_TX_DESC_CTL1_RTS_DURATION; + AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210; return 0; } @@ -176,7 +184,6 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; - ATH5K_TRACE(ah->ah_sc); tx_ctl = &desc->ud.ds_tx5212.tx_ctl; /* @@ -256,7 +263,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (key_index != AR5K_TXKEYIX_INVALID) { tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, - AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); + AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); } /* @@ -278,13 +285,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* * Initialize a 4-word multi rate retry tx control descriptor on 5212 */ -static int +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) { struct ath5k_hw_4w_tx_ctl *tx_ctl; + /* no mrr support for cards older than 5212 */ + if (ah->ah_version < AR5K_AR5212) + return 0; + /* * Rates can be 0 as long as the retry count is 0 too. * A zero rate and nonzero retry count will put the HW into a mode where @@ -324,15 +335,6 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, return 0; } -/* no mrr support for cards older than 5212 */ -static int -ath5k_hw_setup_no_mrr(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) -{ - return 0; -} - /* * Proccess the tx status descriptor on 5210/5211 */ @@ -342,8 +344,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - ATH5K_TRACE(ah->ah_sc); - tx_ctl = &desc->ud.ds_tx5210.tx_ctl; tx_status = &desc->ud.ds_tx5210.tx_stat; @@ -396,8 +396,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - ATH5K_TRACE(ah->ah_sc); - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; tx_status = &desc->ud.ds_tx5212.tx_stat; @@ -419,11 +417,11 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); ts->ts_antenna = (tx_status->tx_status_1 & - AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; + AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; ts->ts_status = 0; ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); + AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); /* The longretry counter has the number of un-acked retries * for the final rate. To get the total number of retries @@ -485,12 +483,11 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, /* * Initialize an rx control descriptor */ -static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags) +int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + u32 size, unsigned int flags) { struct ath5k_hw_rx_ctl *rx_ctl; - ATH5K_TRACE(ah->ah_sc); rx_ctl = &desc->ud.ds_rx.rx_ctl; /* @@ -502,10 +499,11 @@ static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, */ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); + if (unlikely(size & ~AR5K_DESC_RX_CTL1_BUF_LEN)) + return -EINVAL; + /* Setup descriptor */ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; - if (unlikely(rx_ctl->rx_control_1 != size)) - return -EINVAL; if (flags & AR5K_RXDESC_INTREQ) rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; @@ -521,13 +519,15 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, { struct ath5k_hw_rx_status *rx_status; - rx_status = &desc->ud.ds_rx.u.rx_stat; + rx_status = &desc->ud.ds_rx.rx_stat; /* No frame received / not ready */ if (unlikely(!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_DONE))) + AR5K_5210_RX_DESC_STATUS1_DONE))) return -EINPROGRESS; + memset(rs, 0, sizeof(struct ath5k_rx_status)); + /* * Frame receive status */ @@ -537,15 +537,23 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); rs->rs_more = !!(rx_status->rx_status_0 & AR5K_5210_RX_DESC_STATUS0_MORE); - /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ + /* TODO: this timestamp is 13 bit, later on we assume 15 bit! + * also the HAL code for 5210 says the timestamp is bits [10..22] of the + * TSF, and extends the timestamp here to 15 bit. + * we need to check on 5210... + */ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; + + if (ah->ah_version == AR5K_AR5211) + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211); + else + rs->rs_antenna = (rx_status->rx_status_0 & + AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210) + ? 2 : 1; /* * Key table status @@ -560,19 +568,21 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, * Receive/descriptor errors */ if (!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) rs->rs_status |= AR5K_RXERR_CRC; - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) + /* only on 5210 */ + if ((ah->ah_version == AR5K_AR5210) && + (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210)) rs->rs_status |= AR5K_RXERR_FIFO; if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); } @@ -588,22 +598,20 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, * Proccess the rx status descriptor on 5212 */ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_rx_status *rs) + struct ath5k_desc *desc, + struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; - struct ath5k_hw_rx_error *rx_err; - ATH5K_TRACE(ah->ah_sc); - rx_status = &desc->ud.ds_rx.u.rx_stat; - - /* Overlay on error */ - rx_err = &desc->ud.ds_rx.u.rx_err; + rx_status = &desc->ud.ds_rx.rx_stat; /* No frame received / not ready */ if (unlikely(!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DONE))) + AR5K_5212_RX_DESC_STATUS1_DONE))) return -EINPROGRESS; + memset(rs, 0, sizeof(struct ath5k_rx_status)); + /* * Frame receive status */ @@ -619,15 +627,13 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, AR5K_5212_RX_DESC_STATUS0_MORE); rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; /* * Key table status */ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); + AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); else rs->rs_keyix = AR5K_RXKEYIX_INVALID; @@ -635,7 +641,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, * Receive/descriptor errors */ if (!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) rs->rs_status |= AR5K_RXERR_CRC; @@ -643,9 +649,10 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, - AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); - ath5k_ani_phy_error_report(ah, rs->rs_phyerr); + rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); + if (!ah->ah_capabilities.cap_has_phyerr_counters) + ath5k_ani_phy_error_report(ah, rs->rs_phyerr); } if (rx_status->rx_status_1 & @@ -656,7 +663,6 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) rs->rs_status |= AR5K_RXERR_MIC; } - return 0; } @@ -665,29 +671,15 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, */ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) { - - if (ah->ah_version != AR5K_AR5210 && - ah->ah_version != AR5K_AR5211 && - ah->ah_version != AR5K_AR5212) - return -ENOTSUPP; - if (ah->ah_version == AR5K_AR5212) { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; - } else { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; + ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; + } else if (ah->ah_version <= AR5K_AR5211) { ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; - } - - if (ah->ah_version == AR5K_AR5212) - ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; - else if (ah->ah_version <= AR5K_AR5211) ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; - + } else + return -ENOTSUPP; return 0; } - diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 64538fbe4167..b2adb2a281c2 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -17,28 +17,24 @@ */ /* - * Internal RX/TX descriptor structures - * (rX: reserved fields possibily used by future versions of the ar5k chipset) + * RX/TX descriptor structures */ /* - * common hardware RX control descriptor + * Common hardware RX control descriptor */ struct ath5k_hw_rx_ctl { u32 rx_control_0; /* RX control word 0 */ u32 rx_control_1; /* RX control word 1 */ } __packed; -/* RX control word 0 field/sflags */ -#define AR5K_DESC_RX_CTL0 0x00000000 - /* RX control word 1 fields/flags */ -#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff -#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 +#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ +#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ /* - * common hardware RX status descriptor - * 5210/11 and 5212 differ only in the flags defined below + * Common hardware RX status descriptor + * 5210, 5211 and 5212 differ only in the fields and flags defined below */ struct ath5k_hw_rx_status { u32 rx_status_0; /* RX status word 0 */ @@ -47,81 +43,69 @@ struct ath5k_hw_rx_status { /* 5210/5211 */ /* RX status word 0 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 +#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ +#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210 0x00004000 /* [5210] receive on ant 1 */ +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 /* reception rate */ #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 /* rssi */ #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211 0x38000000 /* [5211] receive antenna */ +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211_S 27 /* RX status word 1 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 -#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 -#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 +#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ +#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* reception success */ +#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ +#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 0x00000008 /* [5210] FIFO overrun */ +#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decyption CRC failure */ +#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 /* PHY error */ #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decyption key index */ #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 +#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 /* 13 bit of TSF */ #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 -#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 +#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 /* key cache miss */ /* 5212 */ /* RX status word 0 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 +#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ +#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ +#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 /* decompression CRC error */ +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 /* reception rate */ #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 /* rssi */ #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 /* receive antenna */ #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 /* RX status word 1 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 -#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 -#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 +#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ +#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* frame reception success */ +#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ +#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 /* decryption CRC failure */ +#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 /* PHY error */ +#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 /* MIC decrypt error */ +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 /* decryption key index */ #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 +#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 /* first 15bit of the TSF */ #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 -#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 - -/* - * common hardware RX error descriptor - */ -struct ath5k_hw_rx_error { - u32 rx_error_0; /* RX status word 0 */ - u32 rx_error_1; /* RX status word 1 */ -} __packed; - -/* RX error word 0 fields/flags */ -#define AR5K_RX_DESC_ERROR0 0x00000000 - -/* RX error word 1 fields/flags */ -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 +#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 /* key cache miss */ +#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE 0x0000ff00 /* phy error code overlays key index and valid fields */ +#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE_S 8 /** * enum ath5k_phy_error_code - PHY Error codes */ enum ath5k_phy_error_code { - AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ + AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ - AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ + AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ /* these are specific to the 5212 */ @@ -148,112 +132,111 @@ struct ath5k_hw_2w_tx_ctl { } __packed; /* TX control word 0 fields/flags */ -#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 -#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 +#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ +#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210 0x0003f000 /* [5210] header length */ +#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210_S 12 +#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 /* tx rate */ #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 -#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 - +#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ +#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET_5210 0x00800000 /* [5210] long packet */ +#define AR5K_2W_TX_DESC_CTL0_VEOL_5211 0x00800000 /* [5211] virtual end-of-list */ +#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 /* [5210] antenna selection */ +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 /* [5211] antenna selection */ #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ (ah->ah_version == AR5K_AR5210 ? \ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) - #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 +#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210 0x1c000000 /* [5210] frame type */ +#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210_S 26 +#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ +#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* key is valid */ /* TX control word 1 fields/flags */ -#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ +#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ +#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ +#define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 0x0007e000 /* [5210] key table index */ +#define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211 0x000fe000 /* [5211] key table index */ +#define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX \ (ah->ah_version == AR5K_AR5210 ? \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ + AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 : \ + AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211) +#define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_S 13 +#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211 0x00700000 /* [5211] frame type */ +#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211_S 20 +#define AR5K_2W_TX_DESC_CTL1_NOACK_5211 0x00800000 /* [5211] no ACK */ +#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210 0xfff80000 /* [5210] lower 13 bit of duration */ /* Frame types */ -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 1 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 2 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 3 +#define AR5K_AR5211_TX_DESC_FRAME_TYPE_BEACON 3 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 +#define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 /* * 5212 hardware 4-word TX control descriptor */ struct ath5k_hw_4w_tx_ctl { u32 tx_control_0; /* TX control word 0 */ + 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; -#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 +/* TX control word 0 fields/flags */ +#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ +#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 /* transmit power */ #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 -#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 -#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 +#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ +#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 /* virtual end-of-list */ +#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ +#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 /* TX antenna selection */ #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 -#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 - - u32 tx_control_1; /* TX control word 1 */ +#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ +#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* destination index valid */ +#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 /* precede frame with CTS */ -#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 +/* TX control word 1 fields/flags */ +#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ +#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ +#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX 0x000fe000 /* destination table index */ +#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX_S 13 +#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 /* frame type */ #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 +#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 /* no ACK */ +#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 /* compression processing */ #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 -#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 /* length of frame IV */ #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 -#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 /* length of frame ICV */ #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 - u32 tx_control_2; /* TX control word 2 */ - -#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff -#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 - - u32 tx_control_3; /* TX control word 3 */ - -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 +/* TX control word 2 fields/flags */ +#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff /* RTS/CTS duration */ +#define AR5K_4W_TX_DESC_CTL2_DURATION_UPD_EN 0x00008000 /* frame duration update */ +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 /* series 0 max attempts */ +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 /* series 1 max attempts */ +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 /* series 2 max attempts */ +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 /* series 3 max attempts */ +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 + +/* TX control word 3 fields/flags */ +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f /* series 0 tx rate */ +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 /* series 1 tx rate */ #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 /* series 2 tx rate */ #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 /* series 3 tx rate */ #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 -#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 +#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 -} __packed; /* * Common TX status descriptor @@ -264,37 +247,34 @@ struct ath5k_hw_tx_status { } __packed; /* TX status word 0 fields/flags */ -#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 -#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 -#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 -#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 -/*??? -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 -*/ -#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 +#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ +#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 /* excessive retries */ +#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 /* FIFO underrun */ +#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 /* TX filter indication */ +/* according to the HAL sources the spec has short/long retry counts reversed. + * we have it reversed to the HAL sources as well, for 5210 and 5211. + * For 5212 these fields are defined as RTS_FAIL_COUNT and DATA_FAIL_COUNT, + * but used respectively as SHORT and LONG retry count in the code later. This + * is consistent with the definitions here... TODO: check */ +#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 /* short retry count */ #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 -/*??? -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 -*/ -#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 +#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 /* long retry count */ #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 -#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 +#define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5211 0x0000f000 /* [5211+] virtual collision count */ +#define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5212_S 12 +#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 /* TX timestamp */ #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 /* TX status word 1 fields/flags */ -#define AR5K_DESC_TX_STATUS1_DONE 0x00000001 -#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe +#define AR5K_DESC_TX_STATUS1_DONE 0x00000001 /* descriptor complete */ +#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe /* TX sequence number */ #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 -#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 +#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 /* signal strength of ACK */ #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 -#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 -#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 +#define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212 0x00600000 /* [5212] final TX attempt series ix */ +#define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212_S 21 +#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ +#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ /* * 5210/5211 hardware TX descriptor @@ -313,18 +293,15 @@ struct ath5k_hw_5212_tx_desc { } __packed; /* - * common hardware RX descriptor + * Common hardware RX descriptor */ struct ath5k_hw_all_rx_desc { - struct ath5k_hw_rx_ctl rx_ctl; - union { - struct ath5k_hw_rx_status rx_stat; - struct ath5k_hw_rx_error rx_err; - } u; + struct ath5k_hw_rx_ctl rx_ctl; + struct ath5k_hw_rx_status rx_stat; } __packed; /* - * Atheros hardware descriptor + * Atheros hardware DMA descriptor * This is read and written to by the hardware */ struct ath5k_desc { @@ -346,4 +323,3 @@ struct ath5k_desc { #define AR5K_TXDESC_CTSENA 0x0008 #define AR5K_TXDESC_INTREQ 0x0010 #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ - diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 941b51130a6f..484f31870ba8 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -48,7 +48,6 @@ */ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } @@ -62,7 +61,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) { unsigned int i; - ATH5K_TRACE(ah->ah_sc); ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); /* @@ -96,8 +94,6 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) */ void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) { - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); } @@ -125,7 +121,6 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) { u32 tx_queue; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); /* Return if queue is declared inactive */ @@ -186,7 +181,6 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) unsigned int i = 40; u32 tx_queue, pending; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); /* Return if queue is declared inactive */ @@ -297,7 +291,6 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) { u16 tx_reg; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); /* @@ -340,7 +333,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) { u16 tx_reg; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); /* @@ -400,8 +392,6 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) u32 trigger_level, imr; int ret = -EIO; - ATH5K_TRACE(ah->ah_sc); - /* * Disable interrupts by setting the mask */ @@ -451,7 +441,6 @@ done: */ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; } @@ -475,8 +464,6 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) { u32 data; - ATH5K_TRACE(ah->ah_sc); - /* * Read interrupt status from the Interrupt Status register * on 5210 diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ed0263672d6d..ae316fec4a6a 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -35,7 +35,6 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) { u32 status, timeout; - ATH5K_TRACE(ah->ah_sc); /* * Initialize EEPROM access */ @@ -715,7 +714,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, /* Only one curve for RF5111 * find out which one and place - * in in pd_curves. + * in pd_curves. * Note: ee_x_gain is reversed here */ for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c index 64a27e73d02e..bc90503f4b7a 100644 --- a/drivers/net/wireless/ath/ath5k/gpio.c +++ b/drivers/net/wireless/ath/ath5k/gpio.c @@ -34,8 +34,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) /*5210 has different led mode handling*/ u32 led_5210; - ATH5K_TRACE(ah->ah_sc); - /*Reset led status*/ if (ah->ah_version != AR5K_AR5210) AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, @@ -82,7 +80,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) */ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) { - ATH5K_TRACE(ah->ah_sc); if (gpio >= AR5K_NUM_GPIO) return -EINVAL; @@ -98,7 +95,6 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) */ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) { - ATH5K_TRACE(ah->ah_sc); if (gpio >= AR5K_NUM_GPIO) return -EINVAL; @@ -114,7 +110,6 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) */ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) { - ATH5K_TRACE(ah->ah_sc); if (gpio >= AR5K_NUM_GPIO) return 0xffffffff; @@ -129,7 +124,6 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) { u32 data; - ATH5K_TRACE(ah->ah_sc); if (gpio >= AR5K_NUM_GPIO) return -EINVAL; @@ -153,7 +147,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, { u32 data; - ATH5K_TRACE(ah->ah_sc); if (gpio >= AR5K_NUM_GPIO) return; diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 5212e275f1c7..86fdb6ddfaaa 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -59,8 +59,6 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) beacon_reg = 0; - ATH5K_TRACE(ah->ah_sc); - switch (op_mode) { case NL80211_IFTYPE_ADHOC: pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; @@ -173,7 +171,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) */ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) { - ATH5K_TRACE(ah->ah_sc); if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) <= timeout) return -EINVAL; @@ -192,7 +189,6 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) */ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) { - ATH5K_TRACE(ah->ah_sc); if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) <= timeout) return -EINVAL; @@ -297,7 +293,6 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) u32 low_id, high_id; u32 pcu_reg; - ATH5K_TRACE(ah->ah_sc); /* Set new station ID */ memcpy(common->macaddr, mac, ETH_ALEN); @@ -357,7 +352,6 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah) void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) { struct ath_common *common = ath5k_hw_common(ah); - ATH5K_TRACE(ah->ah_sc); /* Cache bssid mask so that we can restore it * on reset */ @@ -382,7 +376,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) */ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); } @@ -397,7 +390,6 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) */ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); } @@ -406,8 +398,6 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) */ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) { - ATH5K_TRACE(ah->ah_sc); - /* Set the multicat filter */ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); } @@ -427,7 +417,6 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) { u32 data, filter = 0; - ATH5K_TRACE(ah->ah_sc); filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); /*Radar detection for 5212*/ @@ -457,8 +446,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) { u32 data = 0; - ATH5K_TRACE(ah->ah_sc); - /* Set PHY error filter register on 5212*/ if (ah->ah_version == AR5K_AR5212) { if (filter & AR5K_RX_FILTER_RADARERR) @@ -533,8 +520,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) WARN_ON( i == ATH5K_MAX_TSF_READ ); - ATH5K_TRACE(ah->ah_sc); - return (((u64)tsf_upper1 << 32) | tsf_lower); } @@ -548,8 +533,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) */ void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) { - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); } @@ -565,8 +548,6 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah) { u32 val; - ATH5K_TRACE(ah->ah_sc); - val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; /* @@ -586,7 +567,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) { u32 timer1, timer2, timer3; - ATH5K_TRACE(ah->ah_sc); /* * Set the additional timers by mode */ @@ -674,7 +654,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) unsigned int i, type; u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); @@ -749,8 +728,6 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, bool is_tkip; const u8 *key_ptr; - ATH5K_TRACE(ah->ah_sc); - is_tkip = (key->alg == ALG_TKIP); /* @@ -836,7 +813,6 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) { u32 low_id, high_id; - ATH5K_TRACE(ah->ah_sc); /* Invalid entry (key table overflow) */ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 492cbb15720d..73c4fcd142bb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) u32 data, type; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_rf_banks == NULL || ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) return AR5K_RFGAIN_INACTIVE; @@ -1167,7 +1165,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) * The median of the values in the history is then loaded into the * hardware for its own use for RSSI and CCA measurements. */ -static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) +void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 val; @@ -1248,7 +1246,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) /* * Perform a PHY calibration on RF5110 * -Fix BPSK/QAM Constellation (I/Q correction) - * -Calculate Noise Floor */ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -1335,8 +1332,6 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, return ret; } - ath5k_hw_update_noise_floor(ah); - /* * Re-enable RX/TX and beacons */ @@ -1348,22 +1343,20 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, } /* - * Perform a PHY calibration on RF5111/5112 and newer chips + * Perform I/Q calibration on RF5111/5112 and newer chips */ -static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +static int +ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) { u32 i_pwr, q_pwr; s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; int i; - ATH5K_TRACE(ah->ah_sc); if (!ah->ah_calibration || ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) - goto done; + return 0; /* Calibration has finished, get the results and re-run */ - /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); @@ -1384,7 +1377,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, /* protect against divide by 0 and loss of sign bits */ if (i_coffd == 0 || q_coffd < 2) - goto done; + return -1; i_coff = (-iq_corr) / i_coffd; i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ @@ -1410,17 +1403,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); -done: - - /* TODO: Separate noise floor calibration from I/Q calibration - * since noise floor calibration interrupts rx path while I/Q - * calibration doesn't. We don't need to run noise floor calibration - * as often as I/Q calibration.*/ - ath5k_hw_update_noise_floor(ah); - - /* Initiate a gain_F calibration */ - ath5k_hw_request_rfgain_probe(ah); - return 0; } @@ -1434,8 +1416,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, if (ah->ah_radio == AR5K_RF5110) ret = ath5k_hw_rf5110_calibrate(ah, channel); - else - ret = ath5k_hw_rf511x_calibrate(ah, channel); + else { + ret = ath5k_hw_rf511x_iq_calibrate(ah); + ath5k_hw_request_rfgain_probe(ah); + } return ret; } @@ -1693,7 +1677,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, int ath5k_hw_phy_disable(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); /*Just a try M.F.*/ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); @@ -1709,8 +1692,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) u32 srev; u16 ret; - ATH5K_TRACE(ah->ah_sc); - /* * Set the radio chip access register */ @@ -1755,8 +1736,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) static void /*TODO:Boundary check*/ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version != AR5K_AR5210) ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } @@ -1789,19 +1768,50 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) if (enable) { AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0xc); + AR5K_PHY_RESTART_DIV_GC, 1); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, AR5K_PHY_FAST_ANT_DIV_EN); } else { AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0x8); + AR5K_PHY_RESTART_DIV_GC, 0); AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, AR5K_PHY_FAST_ANT_DIV_EN); } } +void +ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) +{ + u8 ant0, ant1; + + /* + * In case a fixed antenna was set as default + * use the same switch table twice. + */ + if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) + ant0 = ant1 = AR5K_ANT_SWTABLE_A; + else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) + ant0 = ant1 = AR5K_ANT_SWTABLE_B; + else { + ant0 = AR5K_ANT_SWTABLE_A; + ant1 = AR5K_ANT_SWTABLE_B; + } + + /* Set antenna idle switch table */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, + AR5K_PHY_ANT_CTL_SWTABLE_IDLE, + (ah->ah_ant_ctl[ee_mode][AR5K_ANT_CTL] | + AR5K_PHY_ANT_CTL_TXRX_EN)); + + /* Set antenna switch tables */ + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant0], + AR5K_PHY_ANT_SWITCH_TABLE_0); + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant1], + AR5K_PHY_ANT_SWITCH_TABLE_1); +} + /* * Set antenna operating mode */ @@ -1823,8 +1833,6 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) def_ant = ah->ah_def_ant; - ATH5K_TRACE(ah->ah_sc); - switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: case CHANNEL_T: @@ -1923,6 +1931,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) if (sta_id1) AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); + ath5k_hw_set_antenna_switch(ah, ee_mode); /* Note: set diversity before default antenna * because it won't work correctly */ ath5k_hw_set_fast_div(ah, ee_mode, fast_div); @@ -2988,7 +2997,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 type; int ret; - ATH5K_TRACE(ah->ah_sc); if (txpower > AR5K_TUNE_MAX_TXPOWER) { ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); return -EINVAL; @@ -3084,8 +3092,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) struct ieee80211_channel *channel = ah->ah_current_channel; u8 ee_mode; - ATH5K_TRACE(ah->ah_sc); - switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: case CHANNEL_T: diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index f5831da33f7b..4186ff4c6e9c 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -31,7 +31,6 @@ Queue Control Unit, DFS Control Unit Functions int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info) { - ATH5K_TRACE(ah->ah_sc); memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); return 0; } @@ -42,7 +41,6 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info) { - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) @@ -69,8 +67,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, unsigned int queue; int ret; - ATH5K_TRACE(ah->ah_sc); - /* * Get queue by type */ @@ -149,7 +145,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { u32 pending; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); /* Return if queue is declared inactive */ @@ -177,7 +172,6 @@ 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) { - ATH5K_TRACE(ah->ah_sc); if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) return; @@ -195,7 +189,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) u32 cw_min, cw_max, retry_lg, retry_sh; struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); tq = &ah->ah_txq[queue]; @@ -523,8 +516,6 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) { u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); - ATH5K_TRACE(ah->ah_sc); - if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) return -EINVAL; diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 307f80e83f94..498aa28ea9e6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -201,8 +201,6 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) int ret; u32 mask = val ? val : ~0U; - ATH5K_TRACE(ah->ah_sc); - /* Read-and-clear RX Descriptor Pointer*/ ath5k_hw_reg_read(ah, AR5K_RXDP); @@ -246,7 +244,6 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, unsigned int i; u32 staid, data; - ATH5K_TRACE(ah->ah_sc); staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); switch (mode) { @@ -393,8 +390,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) mode = 0; clock = 0; - ATH5K_TRACE(ah->ah_sc); - /* Wakeup the device */ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { @@ -734,7 +729,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, } static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) + struct ieee80211_channel *channel, u8 ee_mode) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; s16 cck_ofdm_pwr_delta; @@ -768,17 +763,9 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, ee->ee_cck_ofdm_gain_delta; } - /* Set antenna idle switch table */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, - AR5K_PHY_ANT_CTL_SWTABLE_IDLE, - (ah->ah_ant_ctl[ee_mode][0] | - AR5K_PHY_ANT_CTL_TXRX_EN)); - - /* Set antenna switch tables */ - ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], - AR5K_PHY_ANT_SWITCH_TABLE_0); - ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], - AR5K_PHY_ANT_SWITCH_TABLE_1); + /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode() + * too */ + ath5k_hw_set_antenna_switch(ah, ee_mode); /* Noise floor threshold */ ath5k_hw_reg_write(ah, @@ -855,7 +842,6 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_NF_THRESH62, ee->ee_thr_62[ee_mode]); - /* False detect backoff for channels * that have spur noise. Write the new * cyclic power RSSI threshold. */ @@ -891,14 +877,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel) { struct ath_common *common = ath5k_hw_common(ah); - u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; + u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; u32 phy_tst1; - u8 mode, freq, ee_mode, ant[2]; + u8 mode, freq, ee_mode; int i, ret; - ATH5K_TRACE(ah->ah_sc); - - s_ant = 0; ee_mode = 0; staid1_flags = 0; tsf_up = 0; @@ -995,9 +978,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, } } - /* Save default antenna */ - s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); - if (ah->ah_version == AR5K_AR5212) { /* Restore normal 32/40MHz clock operation * to avoid register access delay on certain @@ -1094,22 +1074,17 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Write OFDM timings on 5212*/ if (ah->ah_version == AR5K_AR5212 && channel->hw_value & CHANNEL_OFDM) { - struct ath5k_eeprom_info *ee = - &ah->ah_capabilities.cap_eeprom; ret = ath5k_hw_write_ofdm_timings(ah, channel); if (ret) return ret; - /* Note: According to docs we can have a newer - * EEPROM on old hardware, so we need to verify - * that our hardware is new enough to have spur - * mitigation registers (delta phase etc) */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424 || - (ah->ah_mac_srev >= AR5K_SREV_AR5424 && - ee->ee_version >= AR5K_EEPROM_VERSION_5_3)) + /* Spur info is available only from EEPROM versions + * bigger than 5.3 but but the EEPOM routines will use + * static values for older versions */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424) ath5k_hw_set_spur_mitigation_filter(ah, - channel); + channel); } /*Enable/disable 802.11b mode on 5111 @@ -1123,21 +1098,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, AR5K_TXCFG_B_MODE); } - /* - * In case a fixed antenna was set as default - * use the same switch table twice. - */ - if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) - ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; - else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) - ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; - else { - ant[0] = AR5K_ANT_SWTABLE_A; - ant[1] = AR5K_ANT_SWTABLE_B; - } - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); + ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); } else { /* @@ -1175,8 +1137,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); } } - - ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); } /* Ledstate */ diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c new file mode 100644 index 000000000000..90757de7bf59 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/sysfs.c @@ -0,0 +1,116 @@ +#include <linux/device.h> +#include <linux/pci.h> + +#include "base.h" +#include "ath5k.h" +#include "reg.h" + +#define SIMPLE_SHOW_STORE(name, get, set) \ +static ssize_t ath5k_attr_show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct ath5k_softc *sc = dev_get_drvdata(dev); \ + return snprintf(buf, PAGE_SIZE, "%d\n", get); \ +} \ + \ +static ssize_t ath5k_attr_store_##name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct ath5k_softc *sc = dev_get_drvdata(dev); \ + int val; \ + \ + val = (int)simple_strtoul(buf, NULL, 10); \ + set(sc->ah, val); \ + return count; \ +} \ +static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \ + ath5k_attr_show_##name, ath5k_attr_store_##name) + +#define SIMPLE_SHOW(name, get) \ +static ssize_t ath5k_attr_show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct ath5k_softc *sc = dev_get_drvdata(dev); \ + return snprintf(buf, PAGE_SIZE, "%d\n", get); \ +} \ +static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) + +/*** ANI ***/ + +SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init); +SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level, + ath5k_ani_set_noise_immunity_level); +SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level, + ath5k_ani_set_spur_immunity_level); +SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level, + ath5k_ani_set_firstep_level); +SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig, + ath5k_ani_set_ofdm_weak_signal_detection); +SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig, + ath5k_ani_set_cck_weak_signal_detection); +SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level); + +static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL); +} +static DEVICE_ATTR(noise_immunity_level_max, S_IRUGO, + ath5k_attr_show_noise_immunity_level_max, NULL); + +static ssize_t ath5k_attr_show_firstep_level_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL); +} +static DEVICE_ATTR(firstep_level_max, S_IRUGO, + ath5k_attr_show_firstep_level_max, NULL); + +static struct attribute *ath5k_sysfs_entries_ani[] = { + &dev_attr_ani_mode.attr, + &dev_attr_noise_immunity_level.attr, + &dev_attr_spur_level.attr, + &dev_attr_firstep_level.attr, + &dev_attr_ofdm_weak_signal_detection.attr, + &dev_attr_cck_weak_signal_detection.attr, + &dev_attr_noise_immunity_level_max.attr, + &dev_attr_spur_level_max.attr, + &dev_attr_firstep_level_max.attr, + NULL +}; + +static struct attribute_group ath5k_attribute_group_ani = { + .name = "ani", + .attrs = ath5k_sysfs_entries_ani, +}; + + +/*** register / unregister ***/ + +int +ath5k_sysfs_register(struct ath5k_softc *sc) +{ + struct device *dev = &sc->pdev->dev; + int err; + + err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); + if (err) { + ATH5K_ERR(sc, "failed to create sysfs group\n"); + return err; + } + + return 0; +} + +void +ath5k_sysfs_unregister(struct ath5k_softc *sc) +{ + struct device *dev = &sc->pdev->dev; + + sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); +} diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index dd112be218ab..973ae4f49f35 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -32,7 +32,8 @@ ath9k_hw-y:= \ mac.o \ ar9002_mac.o \ ar9003_mac.o \ - ar9003_eeprom.o + ar9003_eeprom.o \ + ar9003_paprd.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index ba8b20f01594..cc648b6ae31c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2010 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 @@ -17,8 +17,99 @@ #include "hw.h" #include "hw-ops.h" -static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, - struct ath9k_channel *chan) +struct ani_ofdm_level_entry { + int spur_immunity_level; + int fir_step_level; + int ofdm_weak_signal_on; +}; + +/* values here are relative to the INI */ + +/* + * Legend: + * + * SI: Spur immunity + * FS: FIR Step + * WS: OFDM / CCK Weak Signal detection + * MRC-CCK: Maximal Ratio Combining for CCK + */ + +static const struct ani_ofdm_level_entry ofdm_level_table[] = { + /* SI FS WS */ + { 0, 0, 1 }, /* lvl 0 */ + { 1, 1, 1 }, /* lvl 1 */ + { 2, 2, 1 }, /* lvl 2 */ + { 3, 2, 1 }, /* lvl 3 (default) */ + { 4, 3, 1 }, /* lvl 4 */ + { 5, 4, 1 }, /* lvl 5 */ + { 6, 5, 1 }, /* lvl 6 */ + { 7, 6, 1 }, /* lvl 7 */ + { 7, 7, 1 }, /* lvl 8 */ + { 7, 8, 0 } /* lvl 9 */ +}; +#define ATH9K_ANI_OFDM_NUM_LEVEL \ + (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) +#define ATH9K_ANI_OFDM_MAX_LEVEL \ + (ATH9K_ANI_OFDM_NUM_LEVEL-1) +#define ATH9K_ANI_OFDM_DEF_LEVEL \ + 3 /* default level - matches the INI settings */ + +/* + * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm. + * With OFDM for single stream you just add up all antenna inputs, you're + * only interested in what you get after FFT. Signal aligment is also not + * required for OFDM because any phase difference adds up in the frequency + * domain. + * + * MRC requires extra work for use with CCK. You need to align the antenna + * signals from the different antenna before you can add the signals together. + * You need aligment of signals as CCK is in time domain, so addition can cancel + * your signal completely if phase is 180 degrees (think of adding sine waves). + * You also need to remove noise before the addition and this is where ANI + * MRC CCK comes into play. One of the antenna inputs may be stronger but + * lower SNR, so just adding after alignment can be dangerous. + * + * Regardless of alignment in time, the antenna signals add constructively after + * FFT and improve your reception. For more information: + * + * http://en.wikipedia.org/wiki/Maximal-ratio_combining + */ + +struct ani_cck_level_entry { + int fir_step_level; + int mrc_cck_on; +}; + +static const struct ani_cck_level_entry cck_level_table[] = { + /* FS MRC-CCK */ + { 0, 1 }, /* lvl 0 */ + { 1, 1 }, /* lvl 1 */ + { 2, 1 }, /* lvl 2 (default) */ + { 3, 1 }, /* lvl 3 */ + { 4, 0 }, /* lvl 4 */ + { 5, 0 }, /* lvl 5 */ + { 6, 0 }, /* lvl 6 */ + { 7, 0 }, /* lvl 7 (only for high rssi) */ + { 8, 0 } /* lvl 8 (only for high rssi) */ +}; + +#define ATH9K_ANI_CCK_NUM_LEVEL \ + (sizeof(cck_level_table)/sizeof(cck_level_table[0])) +#define ATH9K_ANI_CCK_MAX_LEVEL \ + (ATH9K_ANI_CCK_NUM_LEVEL-1) +#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ + (ATH9K_ANI_CCK_NUM_LEVEL-3) +#define ATH9K_ANI_CCK_DEF_LEVEL \ + 2 /* default level - matches the INI settings */ + +/* Private to ani.c */ +static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) +{ + ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); +} + +int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, + struct ath9k_channel *chan) { int i; @@ -48,7 +139,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, stats->beacons += REG_READ(ah, AR_BEACON_CNT); } -static void ath9k_ani_restart(struct ath_hw *ah) +static void ath9k_ani_restart_old(struct ath_hw *ah) { struct ar5416AniState *aniState; struct ath_common *common = ath9k_hw_common(ah); @@ -96,7 +187,42 @@ static void ath9k_ani_restart(struct ath_hw *ah) aniState->cckPhyErrCount = 0; } -static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) +static void ath9k_ani_restart_new(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + struct ath_common *common = ath9k_hw_common(ah); + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + aniState->listenTime = 0; + + aniState->ofdmPhyErrBase = 0; + aniState->cckPhyErrBase = 0; + + ath_print(common, ATH_DBG_ANI, + "Writing ofdmbase=%08x cckbase=%08x\n", + aniState->ofdmPhyErrBase, + aniState->cckPhyErrBase); + + ENABLE_REGWRITE_BUFFER(ah); + + REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); + + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; struct ar5416AniState *aniState; @@ -168,7 +294,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) } } -static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) +static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; struct ar5416AniState *aniState; @@ -206,7 +332,125 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) } } -static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) +/* Adjust the OFDM Noise Immunity Level */ +static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) +{ + struct ar5416AniState *aniState = ah->curani; + struct ath_common *common = ath9k_hw_common(ah); + const struct ani_ofdm_level_entry *entry_ofdm; + const struct ani_cck_level_entry *entry_cck; + + aniState->noiseFloor = BEACON_RSSI(ah); + + ath_print(common, ATH_DBG_ANI, + "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", + aniState->ofdmNoiseImmunityLevel, + immunityLevel, aniState->noiseFloor, + aniState->rssiThrLow, aniState->rssiThrHigh); + + aniState->ofdmNoiseImmunityLevel = immunityLevel; + + entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; + entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; + + if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level) + ath9k_hw_ani_control(ah, + ATH9K_ANI_SPUR_IMMUNITY_LEVEL, + entry_ofdm->spur_immunity_level); + + if (aniState->firstepLevel != entry_ofdm->fir_step_level && + entry_ofdm->fir_step_level >= entry_cck->fir_step_level) + ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, + entry_ofdm->fir_step_level); + + if ((ah->opmode != NL80211_IFTYPE_STATION && + ah->opmode != NL80211_IFTYPE_ADHOC) || + aniState->noiseFloor <= aniState->rssiThrHigh) { + if (aniState->ofdmWeakSigDetectOff) + /* force on ofdm weak sig detect */ + ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + true); + else if (aniState->ofdmWeakSigDetectOff == + entry_ofdm->ofdm_weak_signal_on) + ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + entry_ofdm->ofdm_weak_signal_on); + } +} + +static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + + if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) + ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); +} + +/* + * Set the ANI settings to match an CCK level. + */ +static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) +{ + struct ar5416AniState *aniState = ah->curani; + struct ath_common *common = ath9k_hw_common(ah); + const struct ani_ofdm_level_entry *entry_ofdm; + const struct ani_cck_level_entry *entry_cck; + + aniState->noiseFloor = BEACON_RSSI(ah); + ath_print(common, ATH_DBG_ANI, + "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", + aniState->cckNoiseImmunityLevel, immunityLevel, + aniState->noiseFloor, aniState->rssiThrLow, + aniState->rssiThrHigh); + + if ((ah->opmode == NL80211_IFTYPE_STATION || + ah->opmode == NL80211_IFTYPE_ADHOC) && + aniState->noiseFloor <= aniState->rssiThrLow && + immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) + immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; + + aniState->cckNoiseImmunityLevel = immunityLevel; + + entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; + entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; + + if (aniState->firstepLevel != entry_cck->fir_step_level && + entry_cck->fir_step_level >= entry_ofdm->fir_step_level) + ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, + entry_cck->fir_step_level); + + /* Skip MRC CCK for pre AR9003 families */ + if (!AR_SREV_9300_20_OR_LATER(ah)) + return; + + if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) + ath9k_hw_ani_control(ah, + ATH9K_ANI_MRC_CCK, + entry_cck->mrc_cck_on); +} + +static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + + if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) + ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); +} + +static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) { struct ar5416AniState *aniState; int32_t rssi; @@ -259,9 +503,53 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) } } +/* + * only lower either OFDM or CCK errors per turn + * we lower the other one next time + */ +static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + + aniState = ah->curani; + + /* lower OFDM noise immunity */ + if (aniState->ofdmNoiseImmunityLevel > 0 && + (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { + ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1); + return; + } + + /* lower CCK noise immunity */ + if (aniState->cckNoiseImmunityLevel > 0) + ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); +} + +static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) +{ + struct ath9k_channel *chan = ah->curchan; + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + u8 clockrate; /* in MHz */ + + if (!ah->curchan) /* should really check for CCK instead */ + clockrate = ATH9K_CLOCK_RATE_CCK; + else if (conf->channel->band == IEEE80211_BAND_2GHZ) + clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; + else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; + else + clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; + + if (conf_is_ht40(conf)) + return clockrate * 2; + + return clockrate * 2; +} + static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) { struct ar5416AniState *aniState; + struct ath_common *common = ath9k_hw_common(ah); u32 txFrameCount, rxFrameCount, cycleCount; int32_t listenTime; @@ -271,15 +559,31 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) aniState = ah->curani; if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { - listenTime = 0; ah->stats.ast_ani_lzero++; + ath_print(common, ATH_DBG_ANI, + "1st call: aniState->cycleCount=%d\n", + aniState->cycleCount); } else { int32_t ccdelta = cycleCount - aniState->cycleCount; int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; int32_t tfdelta = txFrameCount - aniState->txFrameCount; - listenTime = (ccdelta - rfdelta - tfdelta) / 44000; + int32_t clock_rate; + + /* + * convert HW counter values to ms using mode + * specifix clock rate + */ + clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; + + listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; + + ath_print(common, ATH_DBG_ANI, + "cyclecount=%d, rfcount=%d, " + "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", + ccdelta, rfdelta, tfdelta, listenTime, clock_rate); } + aniState->cycleCount = cycleCount; aniState->txFrameCount = txFrameCount; aniState->rxFrameCount = rxFrameCount; @@ -287,7 +591,7 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) return listenTime; } -void ath9k_ani_reset(struct ath_hw *ah) +static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) { struct ar5416AniState *aniState; struct ath9k_channel *chan = ah->curchan; @@ -340,7 +644,7 @@ void ath9k_ani_reset(struct ath_hw *ah) ah->curani->cckTrigLow = ah->config.cck_trig_low; } - ath9k_ani_restart(ah); + ath9k_ani_restart_old(ah); return; } @@ -362,7 +666,7 @@ void ath9k_ani_reset(struct ath_hw *ah) ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & ~ATH9K_RX_FILTER_PHYERR); - ath9k_ani_restart(ah); + ath9k_ani_restart_old(ah); ENABLE_REGWRITE_BUFFER(ah); @@ -373,8 +677,102 @@ void ath9k_ani_reset(struct ath_hw *ah) DISABLE_REGWRITE_BUFFER(ah); } -void ath9k_hw_ani_monitor(struct ath_hw *ah, - struct ath9k_channel *chan) +/* + * Restore the ANI parameters in the HAL and reset the statistics. + * This routine should be called for every hardware reset and for + * every channel change. + */ +static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) +{ + struct ar5416AniState *aniState = ah->curani; + struct ath9k_channel *chan = ah->curchan; + struct ath_common *common = ath9k_hw_common(ah); + + if (!DO_ANI(ah)) + return; + + BUG_ON(aniState == NULL); + ah->stats.ast_ani_reset++; + + /* only allow a subset of functions in AP mode */ + if (ah->opmode == NL80211_IFTYPE_AP) { + if (IS_CHAN_2GHZ(chan)) { + ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | + ATH9K_ANI_FIRSTEP_LEVEL); + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->ani_function |= ATH9K_ANI_MRC_CCK; + } else + ah->ani_function = 0; + } + + /* always allow mode (on/off) to be controlled */ + ah->ani_function |= ATH9K_ANI_MODE; + + if (is_scanning || + (ah->opmode != NL80211_IFTYPE_STATION && + ah->opmode != NL80211_IFTYPE_ADHOC)) { + /* + * If we're scanning or in AP mode, the defaults (ini) + * should be in place. For an AP we assume the historical + * levels for this channel are probably outdated so start + * from defaults instead. + */ + if (aniState->ofdmNoiseImmunityLevel != + ATH9K_ANI_OFDM_DEF_LEVEL || + aniState->cckNoiseImmunityLevel != + ATH9K_ANI_CCK_DEF_LEVEL) { + ath_print(common, ATH_DBG_ANI, + "Restore defaults: opmode %u " + "chan %d Mhz/0x%x is_scanning=%d " + "ofdm:%d cck:%d\n", + ah->opmode, + chan->channel, + chan->channelFlags, + is_scanning, + aniState->ofdmNoiseImmunityLevel, + aniState->cckNoiseImmunityLevel); + + ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); + ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); + } + } else { + /* + * restore historical levels for this channel + */ + ath_print(common, ATH_DBG_ANI, + "Restore history: opmode %u " + "chan %d Mhz/0x%x is_scanning=%d " + "ofdm:%d cck:%d\n", + ah->opmode, + chan->channel, + chan->channelFlags, + is_scanning, + aniState->ofdmNoiseImmunityLevel, + aniState->cckNoiseImmunityLevel); + + ath9k_hw_set_ofdm_nil(ah, + aniState->ofdmNoiseImmunityLevel); + ath9k_hw_set_cck_nil(ah, + aniState->cckNoiseImmunityLevel); + } + + /* + * enable phy counters if hw supports or if not, enable phy + * interrupts (so we can count each one) + */ + ath9k_ani_restart_new(ah); + + ENABLE_REGWRITE_BUFFER(ah); + + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + REGWRITE_BUFFER_FLUSH(ah); + DISABLE_REGWRITE_BUFFER(ah); +} + +static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, + struct ath9k_channel *chan) { struct ar5416AniState *aniState; struct ath_common *common = ath9k_hw_common(ah); @@ -390,7 +788,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, listenTime = ath9k_hw_ani_get_listen_time(ah); if (listenTime < 0) { ah->stats.ast_ani_lneg++; - ath9k_ani_restart(ah); + ath9k_ani_restart_old(ah); return; } @@ -444,21 +842,166 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, aniState->cckPhyErrCount <= aniState->listenTime * aniState->cckTrigLow / 1000) ath9k_hw_ani_lower_immunity(ah); - ath9k_ani_restart(ah); + ath9k_ani_restart_old(ah); } else if (aniState->listenTime > ah->aniperiod) { if (aniState->ofdmPhyErrCount > aniState->listenTime * aniState->ofdmTrigHigh / 1000) { - ath9k_hw_ani_ofdm_err_trigger(ah); - ath9k_ani_restart(ah); + ath9k_hw_ani_ofdm_err_trigger_old(ah); + ath9k_ani_restart_old(ah); } else if (aniState->cckPhyErrCount > aniState->listenTime * aniState->cckTrigHigh / 1000) { - ath9k_hw_ani_cck_err_trigger(ah); - ath9k_ani_restart(ah); + ath9k_hw_ani_cck_err_trigger_old(ah); + ath9k_ani_restart_old(ah); + } + } +} + +static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ar5416AniState *aniState; + struct ath_common *common = ath9k_hw_common(ah); + int32_t listenTime; + u32 phyCnt1, phyCnt2; + u32 ofdmPhyErrCnt, cckPhyErrCnt; + u32 ofdmPhyErrRate, cckPhyErrRate; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + if (WARN_ON(!aniState)) + return; + + listenTime = ath9k_hw_ani_get_listen_time(ah); + if (listenTime <= 0) { + ah->stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + ath_print(common, ATH_DBG_ANI, + "listenTime=%d - on new ani monitor\n", + listenTime); + ath9k_ani_restart_new(ah); + return; + } + + aniState->listenTime += listenTime; + + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + + phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); + + if (phyCnt1 < aniState->ofdmPhyErrBase || + phyCnt2 < aniState->cckPhyErrBase) { + if (phyCnt1 < aniState->ofdmPhyErrBase) { + ath_print(common, ATH_DBG_ANI, + "phyCnt1 0x%x, resetting " + "counter value to 0x%x\n", + phyCnt1, + aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_1, + aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, + AR_PHY_ERR_OFDM_TIMING); + } + if (phyCnt2 < aniState->cckPhyErrBase) { + ath_print(common, ATH_DBG_ANI, + "phyCnt2 0x%x, resetting " + "counter value to 0x%x\n", + phyCnt2, + aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_2, + aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, + AR_PHY_ERR_CCK_TIMING); + } + return; + } + + ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; + ah->stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; + ah->stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + ath_print(common, ATH_DBG_ANI, + "Errors: OFDM=0x%08x-0x%08x=%d " + "CCK=0x%08x-0x%08x=%d\n", + phyCnt1, + aniState->ofdmPhyErrBase, + ofdmPhyErrCnt, + phyCnt2, + aniState->cckPhyErrBase, + cckPhyErrCnt); + + ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / + aniState->listenTime; + cckPhyErrRate = aniState->cckPhyErrCount * 1000 / + aniState->listenTime; + + ath_print(common, ATH_DBG_ANI, + "listenTime=%d OFDM:%d errs=%d/s CCK:%d " + "errs=%d/s ofdm_turn=%d\n", + listenTime, aniState->ofdmNoiseImmunityLevel, + ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, + cckPhyErrRate, aniState->ofdmsTurn); + + if (aniState->listenTime > 5 * ah->aniperiod) { + if (ofdmPhyErrRate <= aniState->ofdmTrigLow && + cckPhyErrRate <= aniState->cckTrigLow) { + ath_print(common, ATH_DBG_ANI, + "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " + "CCK:%d errs=%d/s(<%d) -> " + "ath9k_hw_ani_lower_immunity()\n", + aniState->listenTime, + aniState->ofdmNoiseImmunityLevel, + ofdmPhyErrRate, + aniState->ofdmTrigLow, + aniState->cckNoiseImmunityLevel, + cckPhyErrRate, + aniState->cckTrigLow); + ath9k_hw_ani_lower_immunity(ah); + aniState->ofdmsTurn = !aniState->ofdmsTurn; + } + ath_print(common, ATH_DBG_ANI, + "1 listenTime=%d ofdm=%d/s cck=%d/s - " + "calling ath9k_ani_restart_new()\n", + aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); + ath9k_ani_restart_new(ah); + } else if (aniState->listenTime > ah->aniperiod) { + /* check to see if need to raise immunity */ + if (ofdmPhyErrRate > aniState->ofdmTrigHigh && + (cckPhyErrRate <= aniState->cckTrigHigh || + aniState->ofdmsTurn)) { + ath_print(common, ATH_DBG_ANI, + "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " + "ath9k_hw_ani_ofdm_err_trigger_new()\n", + aniState->listenTime, + aniState->ofdmNoiseImmunityLevel, + ofdmPhyErrRate, + aniState->ofdmTrigHigh); + ath9k_hw_ani_ofdm_err_trigger_new(ah); + ath9k_ani_restart_new(ah); + aniState->ofdmsTurn = false; + } else if (cckPhyErrRate > aniState->cckTrigHigh) { + ath_print(common, ATH_DBG_ANI, + "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " + "ath9k_hw_ani_cck_err_trigger_new()\n", + aniState->listenTime, + aniState->cckNoiseImmunityLevel, + cckPhyErrRate, + aniState->cckTrigHigh); + ath9k_hw_ani_cck_err_trigger_new(ah); + ath9k_ani_restart_new(ah); + aniState->ofdmsTurn = true; } } } -EXPORT_SYMBOL(ath9k_hw_ani_monitor); void ath9k_enable_mib_counters(struct ath_hw *ah) { @@ -495,6 +1038,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) REG_WRITE(ah, AR_FILT_OFDM, 0); REG_WRITE(ah, AR_FILT_CCK, 0); } +EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, @@ -542,7 +1086,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, * any of the MIB counters overflow/trigger so don't assume we're * here because a PHY error counter triggered. */ -void ath9k_hw_procmibevent(struct ath_hw *ah) +static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) { u32 phyCnt1, phyCnt2; @@ -555,8 +1099,15 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) /* Clear the mib counters and save them in the stats */ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - if (!DO_ANI(ah)) + if (!DO_ANI(ah)) { + /* + * We must always clear the interrupt cause by + * resetting the phy error regs. + */ + REG_WRITE(ah, AR_PHY_ERR_1, 0); + REG_WRITE(ah, AR_PHY_ERR_2, 0); return; + } /* NB: these are not reset-on-read */ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); @@ -584,14 +1135,51 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) * check will never be true. */ if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) - ath9k_hw_ani_ofdm_err_trigger(ah); + ath9k_hw_ani_ofdm_err_trigger_new(ah); if (aniState->cckPhyErrCount > aniState->cckTrigHigh) - ath9k_hw_ani_cck_err_trigger(ah); + ath9k_hw_ani_cck_err_trigger_old(ah); /* NB: always restart to insure the h/w counters are reset */ - ath9k_ani_restart(ah); + ath9k_ani_restart_old(ah); } } -EXPORT_SYMBOL(ath9k_hw_procmibevent); + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) +{ + u32 phyCnt1, phyCnt2; + + /* Reset these counters regardless */ + REG_WRITE(ah, AR_FILT_OFDM, 0); + REG_WRITE(ah, AR_FILT_CCK, 0); + if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) + REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + + /* Clear the mib counters and save them in the stats */ + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + + if (!DO_ANI(ah)) { + /* + * We must always clear the interrupt cause by + * resetting the phy error regs. + */ + REG_WRITE(ah, AR_PHY_ERR_1, 0); + REG_WRITE(ah, AR_PHY_ERR_2, 0); + return; + } + + /* NB: these are not reset-on-read */ + phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); + + /* NB: always restart to insure the h/w counters are reset */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) + ath9k_ani_restart_new(ah); +} void ath9k_hw_ani_setup(struct ath_hw *ah) { @@ -619,22 +1207,70 @@ void ath9k_hw_ani_init(struct ath_hw *ah) memset(ah->ani, 0, sizeof(ah->ani)); for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { - ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; - ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; - ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; + if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { + ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; + ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; + + ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; + ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; + + ah->ani[i].spurImmunityLevel = + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; + + ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; + + ah->ani[i].ofdmPhyErrBase = 0; + ah->ani[i].cckPhyErrBase = 0; + + if (AR_SREV_9300_20_OR_LATER(ah)) + ah->ani[i].mrcCCKOff = + !ATH9K_ANI_ENABLE_MRC_CCK; + else + ah->ani[i].mrcCCKOff = true; + + ah->ani[i].ofdmsTurn = true; + } else { + ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; + ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; + + ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; + ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; + + ah->ani[i].spurImmunityLevel = + ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; + ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; + + ah->ani[i].ofdmPhyErrBase = + AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; + ah->ani[i].cckPhyErrBase = + AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; + ah->ani[i].cckWeakSigThreshold = + ATH9K_ANI_CCK_WEAK_SIG_THR; + } + ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; ah->ani[i].ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; - ah->ani[i].cckWeakSigThreshold = - ATH9K_ANI_CCK_WEAK_SIG_THR; - ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; - ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - ah->ani[i].ofdmPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].cckPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; + ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; + } + + /* + * since we expect some ongoing maintenance on the tables, let's sanity + * check here default level should not modify INI setting. + */ + if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { + const struct ani_ofdm_level_entry *entry_ofdm; + const struct ani_cck_level_entry *entry_cck; + + entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; + entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; + + ah->aniperiod = ATH9K_ANI_PERIOD_NEW; + ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; + } else { + ah->aniperiod = ATH9K_ANI_PERIOD_OLD; + ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; } ath_print(common, ATH_DBG_ANI, @@ -653,7 +1289,34 @@ void ath9k_hw_ani_init(struct ath_hw *ah) ath9k_enable_mib_counters(ah); - ah->aniperiod = ATH9K_ANI_PERIOD; if (ah->config.enable_ani) ah->proc_phyerr |= HAL_PROCESS_ANI; } + +void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->ani_reset = ath9k_ani_reset_old; + priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; + + ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; + ops->ani_monitor = ath9k_hw_ani_monitor_old; + + ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); +} + +void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->ani_reset = ath9k_ani_reset_new; + priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; + + ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; + ops->ani_monitor = ath9k_hw_ani_monitor_new; + + ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); +} diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 3356762ea384..f4d0a4d48b37 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -23,23 +23,55 @@ #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) -#define ATH9K_ANI_OFDM_TRIG_HIGH 500 -#define ATH9K_ANI_OFDM_TRIG_LOW 200 -#define ATH9K_ANI_CCK_TRIG_HIGH 200 -#define ATH9K_ANI_CCK_TRIG_LOW 100 +/* units are errors per second */ +#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 +#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000 + +/* units are errors per second */ +#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 +#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 + +/* units are errors per second */ +#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 +#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600 + +/* units are errors per second */ +#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 +#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300 + #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 #define ATH9K_ANI_USE_OFDM_WEAK_SIG true #define ATH9K_ANI_CCK_WEAK_SIG_THR false -#define ATH9K_ANI_SPUR_IMMUNE_LVL 7 -#define ATH9K_ANI_FIRSTEP_LVL 0 + +#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7 +#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3 + +#define ATH9K_ANI_FIRSTEP_LVL_OLD 0 +#define ATH9K_ANI_FIRSTEP_LVL_NEW 2 + #define ATH9K_ANI_RSSI_THR_HIGH 40 #define ATH9K_ANI_RSSI_THR_LOW 7 -#define ATH9K_ANI_PERIOD 100 + +#define ATH9K_ANI_PERIOD_OLD 100 +#define ATH9K_ANI_PERIOD_NEW 1000 + +/* in ms */ +#define ATH9K_ANI_POLLINTERVAL_OLD 100 +#define ATH9K_ANI_POLLINTERVAL_NEW 1000 #define HAL_NOISE_IMMUNE_MAX 4 #define HAL_SPUR_IMMUNE_MAX 7 #define HAL_FIRST_STEP_MAX 2 +#define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 +#define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 +#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 +#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 + +#define ATH9K_ANI_ENABLE_MRC_CCK true + +/* values here are relative to the INI */ + enum ath9k_ani_cmd { ATH9K_ANI_PRESENT = 0x1, ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, @@ -49,7 +81,8 @@ enum ath9k_ani_cmd { ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, ATH9K_ANI_MODE = 0x40, ATH9K_ANI_PHYERR_RESET = 0x80, - ATH9K_ANI_ALL = 0xff + ATH9K_ANI_MRC_CCK = 0x100, + ATH9K_ANI_ALL = 0xfff }; struct ath9k_mib_stats { @@ -60,9 +93,31 @@ struct ath9k_mib_stats { u32 beacons; }; +/* INI default values for ANI registers */ +struct ath9k_ani_default { + u16 m1ThreshLow; + u16 m2ThreshLow; + u16 m1Thresh; + u16 m2Thresh; + u16 m2CountThr; + u16 m2CountThrLow; + u16 m1ThreshLowExt; + u16 m2ThreshLowExt; + u16 m1ThreshExt; + u16 m2ThreshExt; + u16 firstep; + u16 firstepLow; + u16 cycpwrThr1; + u16 cycpwrThr1Ext; +}; + struct ar5416AniState { struct ath9k_channel *c; u8 noiseImmunityLevel; + u8 ofdmNoiseImmunityLevel; + u8 cckNoiseImmunityLevel; + bool ofdmsTurn; + u8 mrcCCKOff; u8 spurImmunityLevel; u8 firstepLevel; u8 ofdmWeakSigDetectOff; @@ -85,6 +140,7 @@ struct ar5416AniState { int16_t pktRssi[2]; int16_t ofdmErrRssi[2]; int16_t cckErrRssi[2]; + struct ath9k_ani_default iniDef; }; struct ar5416Stats { @@ -108,15 +164,13 @@ struct ar5416Stats { }; #define ah_mibStats stats.ast_mibstats -void ath9k_ani_reset(struct ath_hw *ah); -void ath9k_hw_ani_monitor(struct ath_hw *ah, - struct ath9k_channel *chan); void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah); u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, u32 *rxf_pcnt, u32 *txf_pcnt); -void ath9k_hw_procmibevent(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); +int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, + struct ath9k_channel *chan); #endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index b2c17c98bb38..ee34a495b0be 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -19,7 +19,30 @@ #include "../regd.h" #include "ar9002_phy.h" -/* All code below is for non single-chip solutions */ +/* All code below is for AR5008, AR9001, AR9002 */ + +static const int firstep_table[] = +/* level: 0 1 2 3 4 5 6 7 8 */ + { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ + +static const int cycpwrThr1_table[] = +/* level: 0 1 2 3 4 5 6 7 8 */ + { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ + +/* + * register values to turn OFDM weak signal detection OFF + */ +static const int m1ThreshLow_off = 127; +static const int m2ThreshLow_off = 127; +static const int m1Thresh_off = 127; +static const int m2Thresh_off = 127; +static const int m2CountThr_off = 31; +static const int m2CountThrLow_off = 63; +static const int m1ThreshLowExt_off = 127; +static const int m2ThreshLowExt_off = 127; +static const int m1ThreshExt_off = 127; +static const int m2ThreshExt_off = 127; + /** * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters @@ -742,17 +765,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, return -EINVAL; } - if (AR_SREV_9287_12_OR_LATER(ah)) { - /* Enable ASYNC FIFO */ - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); - REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); - REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - } - /* * Set correct baseband to analog shift setting to * access analog chips. @@ -1037,8 +1049,9 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, return pll; } -static bool ar5008_hw_ani_control(struct ath_hw *ah, - enum ath9k_ani_cmd cmd, int param) +static bool ar5008_hw_ani_control_old(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, + int param) { struct ar5416AniState *aniState = ah->curani; struct ath_common *common = ath9k_hw_common(ah); @@ -1220,6 +1233,265 @@ static bool ar5008_hw_ani_control(struct ath_hw *ah, return true; } +static bool ar5008_hw_ani_control_new(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, + int param) +{ + struct ar5416AniState *aniState = ah->curani; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + s32 value, value2; + + switch (cmd & ah->ani_function) { + case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ + /* + * on == 1 means ofdm weak signal detection is ON + * on == 1 is the default, for less noise immunity + * + * on == 0 means ofdm weak signal detection is OFF + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; + /* + * make register setting for default + * (weak sig detect ON) come from INI file + */ + int m1ThreshLow = on ? + aniState->iniDef.m1ThreshLow : m1ThreshLow_off; + int m2ThreshLow = on ? + aniState->iniDef.m2ThreshLow : m2ThreshLow_off; + int m1Thresh = on ? + aniState->iniDef.m1Thresh : m1Thresh_off; + int m2Thresh = on ? + aniState->iniDef.m2Thresh : m2Thresh_off; + int m2CountThr = on ? + aniState->iniDef.m2CountThr : m2CountThr_off; + int m2CountThrLow = on ? + aniState->iniDef.m2CountThrLow : m2CountThrLow_off; + int m1ThreshLowExt = on ? + aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; + int m2ThreshLowExt = on ? + aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; + int m1ThreshExt = on ? + aniState->iniDef.m1ThreshExt : m1ThreshExt_off; + int m2ThreshExt = on ? + aniState->iniDef.m2ThreshExt : m2ThreshExt_off; + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, + m1ThreshLow); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, + m2ThreshLow); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, + m2CountThrLow); + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + else + REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + + if (!on != aniState->ofdmWeakSigDetectOff) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: ofdm weak signal: %s=>%s\n", + chan->channel, + !aniState->ofdmWeakSigDetectOff ? + "on" : "off", + on ? "on" : "off"); + if (on) + ah->stats.ast_ani_ofdmon++; + else + ah->stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + } + break; + } + case ATH9K_ANI_FIRSTEP_LEVEL:{ + u32 level = param; + + if (level >= ARRAY_SIZE(firstep_table)) { + ath_print(common, ATH_DBG_ANI, + "ATH9K_ANI_FIRSTEP_LEVEL: level " + "out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(firstep_table)); + return false; + } + + /* + * make register setting relative to default + * from INI file & cap value + */ + value = firstep_table[level] - + firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + + aniState->iniDef.firstep; + if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) + value = ATH9K_SIG_FIRSTEP_SETTING_MIN; + if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) + value = ATH9K_SIG_FIRSTEP_SETTING_MAX; + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, + value); + /* + * we need to set first step low register too + * make register setting relative to default + * from INI file & cap value + */ + value2 = firstep_table[level] - + firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + + aniState->iniDef.firstepLow; + if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) + value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; + if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) + value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; + + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, + AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); + + if (level != aniState->firstepLevel) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "firstep[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value, + aniState->iniDef.firstep); + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "firstep_low[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value2, + aniState->iniDef.firstepLow); + if (level > aniState->firstepLevel) + ah->stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ah->stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + } + break; + } + case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ + u32 level = param; + + if (level >= ARRAY_SIZE(cycpwrThr1_table)) { + ath_print(common, ATH_DBG_ANI, + "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " + "out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(cycpwrThr1_table)); + return false; + } + /* + * make register setting relative to default + * from INI file & cap value + */ + value = cycpwrThr1_table[level] - + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + + aniState->iniDef.cycpwrThr1; + if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) + value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; + if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) + value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; + REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, + value); + + /* + * set AR_PHY_EXT_CCA for extension channel + * make register setting relative to default + * from INI file & cap value + */ + value2 = cycpwrThr1_table[level] - + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + + aniState->iniDef.cycpwrThr1Ext; + if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) + value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; + if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) + value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; + REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, + AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); + + if (level != aniState->spurImmunityLevel) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "cycpwrThr1[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value, + aniState->iniDef.cycpwrThr1); + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "cycpwrThr1Ext[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value2, + aniState->iniDef.cycpwrThr1Ext); + if (level > aniState->spurImmunityLevel) + ah->stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ah->stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + } + break; + } + case ATH9K_ANI_MRC_CCK: + /* + * You should not see this as AR5008, AR9001, AR9002 + * does not have hardware support for MRC CCK. + */ + WARN_ON(1); + break; + case ATH9K_ANI_PRESENT: + break; + default: + ath_print(common, ATH_DBG_ANI, + "invalid cmd %u\n", cmd); + return false; + } + + ath_print(common, ATH_DBG_ANI, + "ANI parameters: SI=%d, ofdmWS=%s FS=%d " + "MRCcck=%s listenTime=%d CC=%d listen=%d " + "ofdmErrs=%d cckErrs=%d\n", + aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff ? "on" : "off", + aniState->firstepLevel, + !aniState->mrcCCKOff ? "on" : "off", + aniState->listenTime, + aniState->cycleCount, + aniState->listenTime, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); + return true; +} + static void ar5008_hw_do_getnf(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]) { @@ -1340,6 +1612,71 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) DISABLE_REGWRITE_BUFFER(ah); } +/* + * Initialize the ANI register values with default (ini) values. + * This routine is called during a (full) hardware reset after + * all the registers are initialised from the INI. + */ +static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + struct ath9k_ani_default *iniDef; + int index; + u32 val; + + index = ath9k_hw_get_ani_channel_idx(ah, chan); + aniState = &ah->ani[index]; + ah->curani = aniState; + iniDef = &aniState->iniDef; + + ath_print(common, ATH_DBG_ANI, + "ver %d.%d opmode %u chan %d Mhz/0x%x\n", + ah->hw_version.macVersion, + ah->hw_version.macRev, + ah->opmode, + chan->channel, + chan->channelFlags); + + val = REG_READ(ah, AR_PHY_SFCORR); + iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); + iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); + iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); + + val = REG_READ(ah, AR_PHY_SFCORR_LOW); + iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); + iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); + iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); + + val = REG_READ(ah, AR_PHY_SFCORR_EXT); + iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); + iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); + iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); + iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); + iniDef->firstep = REG_READ_FIELD(ah, + AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP); + iniDef->firstepLow = REG_READ_FIELD(ah, + AR_PHY_FIND_SIG_LOW, + AR_PHY_FIND_SIG_FIRSTEP_LOW); + iniDef->cycpwrThr1 = REG_READ_FIELD(ah, + AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1); + iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, + AR_PHY_EXT_CCA, + AR_PHY_EXT_TIMING5_CYCPWR_THR1); + + /* these levels just got reset to defaults by the INI */ + aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; + aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; + aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; + aniState->mrcCCKOff = true; /* not available on pre AR9003 */ + + aniState->cycleCount = 0; +} + + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -1361,10 +1698,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->set_diversity = ar5008_set_diversity; - priv_ops->ani_control = ar5008_hw_ani_control; priv_ops->do_getnf = ar5008_hw_do_getnf; priv_ops->loadnf = ar5008_hw_loadnf; + if (modparam_force_new_ani) { + priv_ops->ani_control = ar5008_hw_ani_control_new; + priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs; + } else + priv_ops->ani_control = ar5008_hw_ani_control_old; + if (AR_SREV_9100(ah)) priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; else if (AR_SREV_9160_10_OR_LATER(ah)) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index a8a8cdc04afa..0317ac9fc1b7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -18,6 +18,11 @@ #include "ar5008_initvals.h" #include "ar9001_initvals.h" #include "ar9002_initvals.h" +#include "ar9002_phy.h" + +int modparam_force_new_ani; +module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); +MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002"); /* General hardware code for the A5008/AR9001/AR9002 hadware families */ @@ -436,55 +441,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, } udelay(1000); + } - /* set bit 19 to allow forcing of pcie core into L1 state */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + if (power_off) { + /* clear bit 19 to disable L1 */ + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + val = REG_READ(ah, AR_WA); + + /* + * Set PCIe workaround bits + * In AR9280 and AR9285, bit 14 in WA register (disable L1) + * should only be set when device enters D3 and be + * cleared when device comes back to D0. + */ + if (ah->config.pcie_waen) { + if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) + val |= AR_WA_D3_L1_DISABLE; + } else { + if (((AR_SREV_9285(ah) || + AR_SREV_9271(ah) || + AR_SREV_9287(ah)) && + (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || + (AR_SREV_9280(ah) && + (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { + val |= AR_WA_D3_L1_DISABLE; + } + } + + if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { + /* + * Disable bit 6 and 7 before entering D3 to + * prevent system hang. + */ + val &= ~(AR_WA_BIT6 | AR_WA_BIT7); + } - /* Several PCIe massages to ensure proper behaviour */ + if (AR_SREV_9285E_20(ah)) + val |= AR_WA_BIT23; + + REG_WRITE(ah, AR_WA, val); + } else { if (ah->config.pcie_waen) { val = ah->config.pcie_waen; if (!power_off) val &= (~AR_WA_D3_L1_DISABLE); } else { - if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || + if (AR_SREV_9285(ah) || + AR_SREV_9271(ah) || AR_SREV_9287(ah)) { val = AR9285_WA_DEFAULT; if (!power_off) val &= (~AR_WA_D3_L1_DISABLE); - } else if (AR_SREV_9280(ah)) { + } + else if (AR_SREV_9280(ah)) { /* - * On AR9280 chips bit 22 of 0x4004 needs to be - * set otherwise card may disappear. + * For AR9280 chips, bit 22 of 0x4004 + * needs to be set. */ val = AR9280_WA_DEFAULT; if (!power_off) val &= (~AR_WA_D3_L1_DISABLE); - } else + } else { val = AR_WA_DEFAULT; + } + } + + /* WAR for ASPM system hang */ + if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { + val |= (AR_WA_BIT6 | AR_WA_BIT7); } + if (AR_SREV_9285E_20(ah)) + val |= AR_WA_BIT23; + REG_WRITE(ah, AR_WA, val); - } - if (power_off) { - /* - * Set PCIe workaround bits - * bit 14 in WA register (disable L1) should only - * be set when device enters D3 and be cleared - * when device comes back to D0. - */ - if (ah->config.pcie_waen) { - if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } else { - if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || - AR_SREV_9287(ah)) && - (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || - (AR_SREV_9280(ah) && - (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } - } + /* set bit 19 to allow forcing of pcie core into L1 state */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); } } @@ -536,18 +570,29 @@ int ar9002_hw_rf_claim(struct ath_hw *ah) return 0; } +void ar9002_hw_enable_async_fifo(struct ath_hw *ah) +{ + if (AR_SREV_9287_13_OR_LATER(ah)) { + REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); + REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); + REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, + AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); + } +} + /* - * Enable ASYNC FIFO - * * If Async FIFO is enabled, the following counters change as MAC now runs * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. * * The values below tested for ht40 2 chain. * Overwrite the delay/timeouts initialized in process ini. */ -void ar9002_hw_enable_async_fifo(struct ath_hw *ah) +void ar9002_hw_update_async_fifo(struct ath_hw *ah) { - if (AR_SREV_9287_12_OR_LATER(ah)) { + if (AR_SREV_9287_13_OR_LATER(ah)) { REG_WRITE(ah, AR_D_GBL_IFS_SIFS, AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); REG_WRITE(ah, AR_D_GBL_IFS_SLOT, @@ -571,9 +616,9 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah) */ void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) { - if (AR_SREV_9287_12_OR_LATER(ah)) { + if (AR_SREV_9287_13_OR_LATER(ah)) { REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_ENABLE_AGGWEP); + AR_PCU_MISC_MODE2_ENABLE_AGGWEP); } } @@ -595,4 +640,9 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) ar9002_hw_attach_calib_ops(ah); ar9002_hw_attach_mac_ops(ah); + + if (modparam_force_new_ani) + ath9k_hw_attach_ani_ops_new(ah); + else + ath9k_hw_attach_ani_ops_old(ah); } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index dae7f3304eb8..8ab24ee8564b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -4492,7 +4492,7 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { }; -/* AR9271 initialization values automaticaly created: 06/04/09 */ +/* AR9271 initialization values automaticaly created: 03/31/10 */ static const u32 ar9271Modes_9271[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -5011,7 +5011,7 @@ static const u32 ar9271Common_9271[][2] = { { 0x0000783c, 0x72ee0a72 }, { 0x00007840, 0xbbfffffc }, { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, + { 0x00007848, 0x6db6246f }, { 0x0000784c, 0x6d9b66db }, { 0x00007850, 0x6d8c6dba }, { 0x00007854, 0x00040000 }, @@ -5218,7 +5218,7 @@ static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652 }, { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 81bf6e5840e1..ce8bb001c6d1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -114,6 +114,10 @@ #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 #define AR_PHY_FIND_SIG_FIRPWR_S 18 +#define AR_PHY_FIND_SIG_LOW 0x9840 +#define AR_PHY_FIND_SIG_FIRSTEP_LOW 0x00000FC0L +#define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6 + #define AR_PHY_AGC_CTL1 0x985C #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 @@ -325,6 +329,9 @@ #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 #define AR_PHY_EXT_CCA_THRESH62_S 16 +#define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00L +#define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9 + #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 #define AR_PHY_EXT_MINCCA_PWR_S 23 #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h index db019dd220b7..d3375fc4ce8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h @@ -14,8 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef INITVALS_9003_H -#define INITVALS_9003_H +#ifndef INITVALS_9003_2P0_H +#define INITVALS_9003_2P0_H /* AR9003 2.0 */ @@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, - {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, - {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, - {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, - {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, - {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, @@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, - {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, - {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, - {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, - {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, - {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -1781,4 +1781,4 @@ static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { {0x00004044, 0x00000000}, }; -#endif /* INITVALS_9003_H */ +#endif /* INITVALS_9003_2P0_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h new file mode 100644 index 000000000000..ec98ab50748a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -0,0 +1,1785 @@ +/* + * Copyright (c) 2010 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. + */ + +#ifndef INITVALS_9003_2P2_H +#define INITVALS_9003_2P2_H + +/* AR9003 2.2 */ + +static const u32 ar9300_2p2_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, + {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, + {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, + {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, + {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, + {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +}; + +static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Modes_fast_clock_2p2[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00001030, 0x00000268, 0x000004d0}, + {0x00001070, 0x0000018c, 0x00000318}, + {0x000010b0, 0x00000fd0, 0x00001fa0}, + {0x00008014, 0x044c044c, 0x08980898}, + {0x0000801c, 0x148ec02b, 0x148ec057}, + {0x00008318, 0x000044c0, 0x00008980}, + {0x00009e00, 0x03721821, 0x03721821}, + {0x0000a230, 0x0000000b, 0x00000016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9300_2p2_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x0001604c, 0x76d005b5}, + {0x00016050, 0x556cf031}, + {0x00016054, 0x13449440}, + {0x00016058, 0x0c51c92c}, + {0x0001605c, 0x3db7fffc}, + {0x00016060, 0xfffffffc}, + {0x00016064, 0x000f0278}, + {0x0001606c, 0x6db60000}, + {0x00016080, 0x00000000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x54214514}, + {0x0001608c, 0x119f481e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd2888888}, + {0x000160a0, 0x0a108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480080}, + {0x000160c0, 0x00adb6d0}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x01e6c000}, + {0x00016100, 0x3fffbe01}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00080010}, + {0x00016144, 0x02084080}, + {0x00016148, 0x00000000}, + {0x00016280, 0x058a0001}, + {0x00016284, 0x3d840208}, + {0x00016288, 0x05a20408}, + {0x0001628c, 0x00038c07}, + {0x00016290, 0x00000004}, + {0x00016294, 0x458aa14f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016400, 0x36db6db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016440, 0x7f80fff8}, + {0x0001644c, 0x76d005b5}, + {0x00016450, 0x556cf031}, + {0x00016454, 0x13449440}, + {0x00016458, 0x0c51c92c}, + {0x0001645c, 0x3db7fffc}, + {0x00016460, 0xfffffffc}, + {0x00016464, 0x000f0278}, + {0x0001646c, 0x6db60000}, + {0x00016500, 0x3fffbe01}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00080010}, + {0x00016544, 0x02084080}, + {0x00016548, 0x00000000}, + {0x00016780, 0x00000000}, + {0x00016784, 0x00000000}, + {0x00016788, 0x00800700}, + {0x0001678c, 0x00800700}, + {0x00016790, 0x00800700}, + {0x00016794, 0x00000000}, + {0x00016798, 0x00000000}, + {0x0001679c, 0x00000000}, + {0x000167a0, 0x00000001}, + {0x000167a4, 0x00000001}, + {0x000167a8, 0x00000000}, + {0x000167ac, 0x00000000}, + {0x000167b0, 0x00000000}, + {0x000167b4, 0x00000000}, + {0x000167b8, 0x00000000}, + {0x000167bc, 0x00000000}, + {0x000167c0, 0x000000a0}, + {0x000167c4, 0x000c0000}, + {0x000167c8, 0x14021402}, + {0x000167cc, 0x00001402}, + {0x000167d0, 0x00000000}, + {0x000167d4, 0x00000000}, + {0x00016800, 0x36db6db6}, + {0x00016804, 0x6db6db40}, + {0x00016808, 0x73f00000}, + {0x0001680c, 0x00000000}, + {0x00016840, 0x7f80fff8}, + {0x0001684c, 0x76d005b5}, + {0x00016850, 0x556cf031}, + {0x00016854, 0x13449440}, + {0x00016858, 0x0c51c92c}, + {0x0001685c, 0x3db7fffc}, + {0x00016860, 0xfffffffc}, + {0x00016864, 0x000f0278}, + {0x0001686c, 0x6db60000}, + {0x00016900, 0x3fffbe01}, + {0x00016904, 0xfff80000}, + {0x00016908, 0x00080010}, + {0x00016944, 0x02084080}, + {0x00016948, 0x00000000}, + {0x00016b80, 0x00000000}, + {0x00016b84, 0x00000000}, + {0x00016b88, 0x00800700}, + {0x00016b8c, 0x00800700}, + {0x00016b90, 0x00800700}, + {0x00016b94, 0x00000000}, + {0x00016b98, 0x00000000}, + {0x00016b9c, 0x00000000}, + {0x00016ba0, 0x00000001}, + {0x00016ba4, 0x00000001}, + {0x00016ba8, 0x00000000}, + {0x00016bac, 0x00000000}, + {0x00016bb0, 0x00000000}, + {0x00016bb4, 0x00000000}, + {0x00016bb8, 0x00000000}, + {0x00016bbc, 0x00000000}, + {0x00016bc0, 0x000000a0}, + {0x00016bc4, 0x000c0000}, + {0x00016bc8, 0x14021402}, + {0x00016bcc, 0x00001402}, + {0x00016bd0, 0x00000000}, + {0x00016bd4, 0x00000000}, +}; + +static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x02000101}, + {0x0000a004, 0x02000102}, + {0x0000a008, 0x02000103}, + {0x0000a00c, 0x02000104}, + {0x0000a010, 0x02000200}, + {0x0000a014, 0x02000201}, + {0x0000a018, 0x02000202}, + {0x0000a01c, 0x02000203}, + {0x0000a020, 0x02000204}, + {0x0000a024, 0x02000205}, + {0x0000a028, 0x02000208}, + {0x0000a02c, 0x02000302}, + {0x0000a030, 0x02000303}, + {0x0000a034, 0x02000304}, + {0x0000a038, 0x02000400}, + {0x0000a03c, 0x02010300}, + {0x0000a040, 0x02010301}, + {0x0000a044, 0x02010302}, + {0x0000a048, 0x02000500}, + {0x0000a04c, 0x02010400}, + {0x0000a050, 0x02020300}, + {0x0000a054, 0x02020301}, + {0x0000a058, 0x02020302}, + {0x0000a05c, 0x02020303}, + {0x0000a060, 0x02020400}, + {0x0000a064, 0x02030300}, + {0x0000a068, 0x02030301}, + {0x0000a06c, 0x02030302}, + {0x0000a070, 0x02030303}, + {0x0000a074, 0x02030400}, + {0x0000a078, 0x02040300}, + {0x0000a07c, 0x02040301}, + {0x0000a080, 0x02040302}, + {0x0000a084, 0x02040303}, + {0x0000a088, 0x02030500}, + {0x0000a08c, 0x02040400}, + {0x0000a090, 0x02050203}, + {0x0000a094, 0x02050204}, + {0x0000a098, 0x02050205}, + {0x0000a09c, 0x02040500}, + {0x0000a0a0, 0x02050301}, + {0x0000a0a4, 0x02050302}, + {0x0000a0a8, 0x02050303}, + {0x0000a0ac, 0x02050400}, + {0x0000a0b0, 0x02050401}, + {0x0000a0b4, 0x02050402}, + {0x0000a0b8, 0x02050403}, + {0x0000a0bc, 0x02050500}, + {0x0000a0c0, 0x02050501}, + {0x0000a0c4, 0x02050502}, + {0x0000a0c8, 0x02050503}, + {0x0000a0cc, 0x02050504}, + {0x0000a0d0, 0x02050600}, + {0x0000a0d4, 0x02050601}, + {0x0000a0d8, 0x02050602}, + {0x0000a0dc, 0x02050603}, + {0x0000a0e0, 0x02050604}, + {0x0000a0e4, 0x02050700}, + {0x0000a0e8, 0x02050701}, + {0x0000a0ec, 0x02050702}, + {0x0000a0f0, 0x02050703}, + {0x0000a0f4, 0x02050704}, + {0x0000a0f8, 0x02050705}, + {0x0000a0fc, 0x02050708}, + {0x0000a100, 0x02050709}, + {0x0000a104, 0x0205070a}, + {0x0000a108, 0x0205070b}, + {0x0000a10c, 0x0205070c}, + {0x0000a110, 0x0205070d}, + {0x0000a114, 0x02050710}, + {0x0000a118, 0x02050711}, + {0x0000a11c, 0x02050712}, + {0x0000a120, 0x02050713}, + {0x0000a124, 0x02050714}, + {0x0000a128, 0x02050715}, + {0x0000a12c, 0x02050730}, + {0x0000a130, 0x02050731}, + {0x0000a134, 0x02050732}, + {0x0000a138, 0x02050733}, + {0x0000a13c, 0x02050734}, + {0x0000a140, 0x02050735}, + {0x0000a144, 0x02050750}, + {0x0000a148, 0x02050751}, + {0x0000a14c, 0x02050752}, + {0x0000a150, 0x02050753}, + {0x0000a154, 0x02050754}, + {0x0000a158, 0x02050755}, + {0x0000a15c, 0x02050770}, + {0x0000a160, 0x02050771}, + {0x0000a164, 0x02050772}, + {0x0000a168, 0x02050773}, + {0x0000a16c, 0x02050774}, + {0x0000a170, 0x02050775}, + {0x0000a174, 0x00000776}, + {0x0000a178, 0x00000776}, + {0x0000a17c, 0x00000776}, + {0x0000a180, 0x00000776}, + {0x0000a184, 0x00000776}, + {0x0000a188, 0x00000776}, + {0x0000a18c, 0x00000776}, + {0x0000a190, 0x00000776}, + {0x0000a194, 0x00000776}, + {0x0000a198, 0x00000776}, + {0x0000a19c, 0x00000776}, + {0x0000a1a0, 0x00000776}, + {0x0000a1a4, 0x00000776}, + {0x0000a1a8, 0x00000776}, + {0x0000a1ac, 0x00000776}, + {0x0000a1b0, 0x00000776}, + {0x0000a1b4, 0x00000776}, + {0x0000a1b8, 0x00000776}, + {0x0000a1bc, 0x00000776}, + {0x0000a1c0, 0x00000776}, + {0x0000a1c4, 0x00000776}, + {0x0000a1c8, 0x00000776}, + {0x0000a1cc, 0x00000776}, + {0x0000a1d0, 0x00000776}, + {0x0000a1d4, 0x00000776}, + {0x0000a1d8, 0x00000776}, + {0x0000a1dc, 0x00000776}, + {0x0000a1e0, 0x00000776}, + {0x0000a1e4, 0x00000776}, + {0x0000a1e8, 0x00000776}, + {0x0000a1ec, 0x00000776}, + {0x0000a1f0, 0x00000776}, + {0x0000a1f4, 0x00000776}, + {0x0000a1f8, 0x00000776}, + {0x0000a1fc, 0x00000776}, + {0x0000b000, 0x02000101}, + {0x0000b004, 0x02000102}, + {0x0000b008, 0x02000103}, + {0x0000b00c, 0x02000104}, + {0x0000b010, 0x02000200}, + {0x0000b014, 0x02000201}, + {0x0000b018, 0x02000202}, + {0x0000b01c, 0x02000203}, + {0x0000b020, 0x02000204}, + {0x0000b024, 0x02000205}, + {0x0000b028, 0x02000208}, + {0x0000b02c, 0x02000302}, + {0x0000b030, 0x02000303}, + {0x0000b034, 0x02000304}, + {0x0000b038, 0x02000400}, + {0x0000b03c, 0x02010300}, + {0x0000b040, 0x02010301}, + {0x0000b044, 0x02010302}, + {0x0000b048, 0x02000500}, + {0x0000b04c, 0x02010400}, + {0x0000b050, 0x02020300}, + {0x0000b054, 0x02020301}, + {0x0000b058, 0x02020302}, + {0x0000b05c, 0x02020303}, + {0x0000b060, 0x02020400}, + {0x0000b064, 0x02030300}, + {0x0000b068, 0x02030301}, + {0x0000b06c, 0x02030302}, + {0x0000b070, 0x02030303}, + {0x0000b074, 0x02030400}, + {0x0000b078, 0x02040300}, + {0x0000b07c, 0x02040301}, + {0x0000b080, 0x02040302}, + {0x0000b084, 0x02040303}, + {0x0000b088, 0x02030500}, + {0x0000b08c, 0x02040400}, + {0x0000b090, 0x02050203}, + {0x0000b094, 0x02050204}, + {0x0000b098, 0x02050205}, + {0x0000b09c, 0x02040500}, + {0x0000b0a0, 0x02050301}, + {0x0000b0a4, 0x02050302}, + {0x0000b0a8, 0x02050303}, + {0x0000b0ac, 0x02050400}, + {0x0000b0b0, 0x02050401}, + {0x0000b0b4, 0x02050402}, + {0x0000b0b8, 0x02050403}, + {0x0000b0bc, 0x02050500}, + {0x0000b0c0, 0x02050501}, + {0x0000b0c4, 0x02050502}, + {0x0000b0c8, 0x02050503}, + {0x0000b0cc, 0x02050504}, + {0x0000b0d0, 0x02050600}, + {0x0000b0d4, 0x02050601}, + {0x0000b0d8, 0x02050602}, + {0x0000b0dc, 0x02050603}, + {0x0000b0e0, 0x02050604}, + {0x0000b0e4, 0x02050700}, + {0x0000b0e8, 0x02050701}, + {0x0000b0ec, 0x02050702}, + {0x0000b0f0, 0x02050703}, + {0x0000b0f4, 0x02050704}, + {0x0000b0f8, 0x02050705}, + {0x0000b0fc, 0x02050708}, + {0x0000b100, 0x02050709}, + {0x0000b104, 0x0205070a}, + {0x0000b108, 0x0205070b}, + {0x0000b10c, 0x0205070c}, + {0x0000b110, 0x0205070d}, + {0x0000b114, 0x02050710}, + {0x0000b118, 0x02050711}, + {0x0000b11c, 0x02050712}, + {0x0000b120, 0x02050713}, + {0x0000b124, 0x02050714}, + {0x0000b128, 0x02050715}, + {0x0000b12c, 0x02050730}, + {0x0000b130, 0x02050731}, + {0x0000b134, 0x02050732}, + {0x0000b138, 0x02050733}, + {0x0000b13c, 0x02050734}, + {0x0000b140, 0x02050735}, + {0x0000b144, 0x02050750}, + {0x0000b148, 0x02050751}, + {0x0000b14c, 0x02050752}, + {0x0000b150, 0x02050753}, + {0x0000b154, 0x02050754}, + {0x0000b158, 0x02050755}, + {0x0000b15c, 0x02050770}, + {0x0000b160, 0x02050771}, + {0x0000b164, 0x02050772}, + {0x0000b168, 0x02050773}, + {0x0000b16c, 0x02050774}, + {0x0000b170, 0x02050775}, + {0x0000b174, 0x00000776}, + {0x0000b178, 0x00000776}, + {0x0000b17c, 0x00000776}, + {0x0000b180, 0x00000776}, + {0x0000b184, 0x00000776}, + {0x0000b188, 0x00000776}, + {0x0000b18c, 0x00000776}, + {0x0000b190, 0x00000776}, + {0x0000b194, 0x00000776}, + {0x0000b198, 0x00000776}, + {0x0000b19c, 0x00000776}, + {0x0000b1a0, 0x00000776}, + {0x0000b1a4, 0x00000776}, + {0x0000b1a8, 0x00000776}, + {0x0000b1ac, 0x00000776}, + {0x0000b1b0, 0x00000776}, + {0x0000b1b4, 0x00000776}, + {0x0000b1b8, 0x00000776}, + {0x0000b1bc, 0x00000776}, + {0x0000b1c0, 0x00000776}, + {0x0000b1c4, 0x00000776}, + {0x0000b1c8, 0x00000776}, + {0x0000b1cc, 0x00000776}, + {0x0000b1d0, 0x00000776}, + {0x0000b1d4, 0x00000776}, + {0x0000b1d8, 0x00000776}, + {0x0000b1dc, 0x00000776}, + {0x0000b1e0, 0x00000776}, + {0x0000b1e4, 0x00000776}, + {0x0000b1e8, 0x00000776}, + {0x0000b1ec, 0x00000776}, + {0x0000b1f0, 0x00000776}, + {0x0000b1f4, 0x00000776}, + {0x0000b1f8, 0x00000776}, + {0x0000b1fc, 0x00000776}, +}; + +static const u32 ar9300_2p2_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9300_2p2_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, +}; + +static const u32 ar9200_merlin_2p2_radio_core[][2] = { + /* Addr allmodes */ + {0x00007800, 0x00040000}, + {0x00007804, 0xdb005012}, + {0x00007808, 0x04924914}, + {0x0000780c, 0x21084210}, + {0x00007810, 0x6d801300}, + {0x00007814, 0x0019beff}, + {0x00007818, 0x07e41000}, + {0x0000781c, 0x00392000}, + {0x00007820, 0x92592480}, + {0x00007824, 0x00040000}, + {0x00007828, 0xdb005012}, + {0x0000782c, 0x04924914}, + {0x00007830, 0x21084210}, + {0x00007834, 0x6d801300}, + {0x00007838, 0x0019beff}, + {0x0000783c, 0x07e40000}, + {0x00007840, 0x00392000}, + {0x00007844, 0x92592480}, + {0x00007848, 0x00100000}, + {0x0000784c, 0x773f0567}, + {0x00007850, 0x54214514}, + {0x00007854, 0x12035828}, + {0x00007858, 0x92592692}, + {0x0000785c, 0x00000000}, + {0x00007860, 0x56400000}, + {0x00007864, 0x0a8e370e}, + {0x00007868, 0xc0102850}, + {0x0000786c, 0x812d4000}, + {0x00007870, 0x807ec400}, + {0x00007874, 0x001b6db0}, + {0x00007878, 0x00376b63}, + {0x0000787c, 0x06db6db6}, + {0x00007880, 0x006d8000}, + {0x00007884, 0xffeffffe}, + {0x00007888, 0xffeffffe}, + {0x0000788c, 0x00010000}, + {0x00007890, 0x02060aeb}, + {0x00007894, 0x5a108000}, +}; + +static const u32 ar9300_2p2_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, + {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, + {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, + {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9300_2p2_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a9f6b}, + {0x0000980c, 0x04900000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x52440bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0xff55ff55}, + {0x00009c08, 0x0320ff55}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x9883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c0040b}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038230c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0c6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e3c, 0xcf946222}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009e54, 0x00000000}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x00009fd0, 0x01193b93}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a22c, 0x01036a1e}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000246}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x06000080}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00000000}, + {0x0000a610, 0x00000000}, + {0x0000a614, 0x00000000}, + {0x0000a618, 0x00000000}, + {0x0000a61c, 0x00000000}, + {0x0000a620, 0x00000000}, + {0x0000a624, 0x00000000}, + {0x0000a628, 0x00000000}, + {0x0000a62c, 0x00000000}, + {0x0000a630, 0x00000000}, + {0x0000a634, 0x00000000}, + {0x0000a638, 0x00000000}, + {0x0000a63c, 0x00000000}, + {0x0000a640, 0x00000000}, + {0x0000a644, 0x3fad9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00000637}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000001}, + {0x0000a8d0, 0x004b6a8e}, + {0x0000a8d4, 0x00000820}, + {0x0000a8dc, 0x00000000}, + {0x0000a8f0, 0x00000000}, + {0x0000a8f4, 0x00000000}, + {0x0000b2d0, 0x00000080}, + {0x0000b2d4, 0x00000000}, + {0x0000b2dc, 0x00000000}, + {0x0000b2e0, 0x00000000}, + {0x0000b2e4, 0x00000000}, + {0x0000b2e8, 0x00000000}, + {0x0000b2ec, 0x00000000}, + {0x0000b2f0, 0x00000000}, + {0x0000b2f4, 0x00000000}, + {0x0000b2f8, 0x00000000}, + {0x0000b408, 0x0e79e5c0}, + {0x0000b40c, 0x00820820}, + {0x0000b420, 0x00000000}, + {0x0000b8d0, 0x004b6a8e}, + {0x0000b8d4, 0x00000820}, + {0x0000b8dc, 0x00000000}, + {0x0000b8f0, 0x00000000}, + {0x0000b8f4, 0x00000000}, + {0x0000c2d0, 0x00000080}, + {0x0000c2d4, 0x00000000}, + {0x0000c2dc, 0x00000000}, + {0x0000c2e0, 0x00000000}, + {0x0000c2e4, 0x00000000}, + {0x0000c2e8, 0x00000000}, + {0x0000c2ec, 0x00000000}, + {0x0000c2f0, 0x00000000}, + {0x0000c2f4, 0x00000000}, + {0x0000c2f8, 0x00000000}, + {0x0000c408, 0x0e79e5c0}, + {0x0000c40c, 0x00820820}, + {0x0000c420, 0x00000000}, +}; + +static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, + {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, + {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, + {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, + {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, + {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, + {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, +}; + +static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Common_rx_gain_table_2p2[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300_2p2_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486200}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f424}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e848}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x9bc00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xaa48105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + +static const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300_2p2_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c1c9}, + {0x00007008, 0x00000000}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, + {0x00007048, 0x00000008}, +}; + +static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x08212e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x08253e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { + /* Addr allmodes */ + {0x00004040, 0x08213e5e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +#endif /* INITVALS_9003_2P2_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 56a9e5fa6d66..5a0650399136 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -739,6 +739,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, */ ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + /* Do Tx IQ Calibration */ + ar9003_hw_tx_iq_cal(ah); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); + udelay(5); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | @@ -753,10 +759,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } - /* Do Tx IQ Calibration */ - if (ah->config.tx_iq_calibration) - ar9003_hw_tx_iq_cal(ah); - /* Revert chainmasks to their original values before NF cal */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 23eb60ea5455..343c9a427acb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -67,6 +67,7 @@ static const struct ar9300_eeprom ar9300_default = { * 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 = 3, @@ -129,9 +130,11 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, - .futureModal = { /* [32] */ + .papdRateMaskHt20 = LE32(0x80c080), + .papdRateMaskHt40 = LE32(0x80c080), + .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, 0, 0, 0, 0, 0, 0 }, }, .calFreqPier2G = { @@ -326,9 +329,11 @@ static const struct ar9300_eeprom ar9300_default = { .txEndToRxOn = 0x2, .txFrameToXpaOn = 0xe, .thresh62 = 28, + .papdRateMaskHt20 = LE32(0xf0e0e0), + .papdRateMaskHt40 = LE32(0xf0e0e0), .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, 0, 0, 0, 0, 0, 0 }, }, .calFreqPier5G = { @@ -644,6 +649,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, return (pBase->featureEnable & 0x10) >> 4; case EEP_SWREG: return le32_to_cpu(pBase->swreg); + case EEP_PAPRD: + return !!(pBase->featureEnable & BIT(5)); default: return 0; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 23fb353c3bba..3c533bb983c7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -234,7 +234,9 @@ struct ar9300_modal_eep_header { u8 txEndToRxOn; u8 txFrameToXpaOn; u8 thresh62; - u8 futureModal[32]; + __le32 papdRateMaskHt20; + __le32 papdRateMaskHt40; + u8 futureModal[24]; } __packed; struct ar9300_cal_data_per_freq_op_loop { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index b15309caf1da..82c3ab756cd0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -16,7 +16,8 @@ #include "hw.h" #include "ar9003_mac.h" -#include "ar9003_initvals.h" +#include "ar9003_2p0_initvals.h" +#include "ar9003_2p2_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -31,12 +32,8 @@ static bool ar9003_hw_macversion_supported(u32 macversion) return false; } -/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ -/* - * XXX: move TX/RX gain INI to its own init_mode_gain_regs after - * ensuring it does not affect hardware bring up - */ -static void ar9003_hw_init_mode_regs(struct ath_hw *ah) +/* AR9003 2.0 */ +static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -106,27 +103,128 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) 3); } +/* AR9003 2.2 */ +static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah) +{ + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9300_2p2_mac_core, + ARRAY_SIZE(ar9300_2p2_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9300_2p2_mac_postamble, + ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9300_2p2_baseband_core, + ARRAY_SIZE(ar9300_2p2_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9300_2p2_baseband_postamble, + ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9300_2p2_radio_core, + ARRAY_SIZE(ar9300_2p2_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9300_2p2_radio_postamble, + ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9300_2p2_soc_preamble, + ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9300_2p2_soc_postamble, + ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), + 5); + + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, + ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), + 2); + + /* Sleep Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9300PciePhy_clkreq_enable_L1_2p2, + ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), + 2); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9300Modes_fast_clock_2p2, + ARRAY_SIZE(ar9300Modes_fast_clock_2p2), + 3); +} + +/* + * The AR9003 family uses a new INI format (pre, core, post + * arrays per subsystem). + */ +static void ar9003_hw_init_mode_regs(struct ath_hw *ah) +{ + if (AR_SREV_9300_20(ah)) + ar9003_2p0_hw_init_mode_regs(ah); + else + ar9003_2p2_hw_init_mode_regs(ah); +} + static void ar9003_tx_gain_table_apply(struct ath_hw *ah) { switch (ar9003_hw_get_tx_gain_idx(ah)) { case 0: default: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), - 5); + if (AR_SREV_9300_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), + 5); break; case 1: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_high_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), - 5); + if (AR_SREV_9300_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), + 5); break; case 2: - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_low_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), - 5); + if (AR_SREV_9300_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_low_ob_db_tx_gain_table_2p0, + ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), + 5); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_low_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), + 5); break; } } @@ -136,15 +234,28 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_rx_gain_idx(ah)) { case 0: default: - INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), - 2); + if (AR_SREV_9300_20(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), + 2); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), + 2); break; case 1: - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_wo_xlna_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), - 2); + if (AR_SREV_9300_20(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_wo_xlna_rx_gain_table_2p0, + ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), + 2); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_wo_xlna_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), + 2); break; } } @@ -202,4 +313,6 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) ar9003_hw_attach_phy_ops(ah); ar9003_hw_attach_calib_ops(ah); ar9003_hw_attach_mac_ops(ah); + + ath9k_hw_attach_ani_ops_new(ah); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 37ba37481a47..06ef71019c12 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -90,6 +90,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) MAP_ISR_S2_CST); mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_TSFOOR); + mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >> + MAP_ISR_S2_BB_WATCHDOG); if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { REG_WRITE(ah, AR_ISR_S2, isr2); @@ -167,6 +169,9 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) (void) REG_READ(ah, AR_ISR); } + + if (*masked & ATH9K_INT_BB_WATCHDOG) + ar9003_hw_bb_watchdog_read(ah); } if (sync_cause) { @@ -465,6 +470,14 @@ static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, ads->ctl11 &= ~AR_VirtMoreFrag; } +void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) +{ + struct ar9003_txc *ads = ds; + + ads->ctl12 |= SM(chains, AR_PAPRDChainMask); +} +EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); + void ar9003_hw_attach_mac_ops(struct ath_hw *hw) { struct ath_hw_ops *ops = ath9k_hw_ops(hw); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index f17558b14539..f76f27d16f77 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -40,6 +40,10 @@ #define AR_Not_Sounding 0x20000000 +/* ctl 12 */ +#define AR_PAPRDChainMask 0x00000e00 +#define AR_PAPRDChainMask_S 9 + #define MAP_ISR_S2_CST 6 #define MAP_ISR_S2_GTT 6 #define MAP_ISR_S2_TIM 3 @@ -47,6 +51,7 @@ #define MAP_ISR_S2_DTIMSYNC 7 #define MAP_ISR_S2_DTIM 7 #define MAP_ISR_S2_TSFOOR 4 +#define MAP_ISR_S2_BB_WATCHDOG 6 #define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c new file mode 100644 index 000000000000..49e0c865ce5c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2010 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 "hw.h" +#include "ar9003_phy.h" + +void ar9003_paprd_enable(struct ath_hw *ah, bool val) +{ + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, + AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, + AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, + AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); +} +EXPORT_SYMBOL(ar9003_paprd_enable); + +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] = { + AR_PHY_PAPRD_CTRL0_B0, + AR_PHY_PAPRD_CTRL0_B1, + AR_PHY_PAPRD_CTRL0_B2 + }; + const u32 ctrl1[3] = { + AR_PHY_PAPRD_CTRL1_B0, + AR_PHY_PAPRD_CTRL1_B1, + AR_PHY_PAPRD_CTRL1_B2 + }; + u32 am_mask, ht40_mask; + int i; + + if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) + hdr = &eep->modalHeader5G; + else + hdr = &eep->modalHeader2G; + + am_mask = le32_to_cpu(hdr->papdRateMaskHt20); + ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); + + for (i = 0; i < 3; i++) { + REG_RMW_FIELD(ah, ctrl0[i], + AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361); + REG_RMW_FIELD(ah, ctrl1[i], + AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); + REG_RMW_FIELD(ah, ctrl0[i], + AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3); + } + + ar9003_paprd_enable(ah, false); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, + AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2, + AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, + -15); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, + AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, + AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, + AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, + 100); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 261376); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 248079); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 233759); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 220464); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 208194); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 196949); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 185706); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, + AR_PHY_PAPRD_PRE_POST_SCALING, 175487); +} + +static void ar9003_paprd_get_gain_table(struct ath_hw *ah) +{ + u32 *entry = ah->paprd_gain_table_entries; + u8 *index = ah->paprd_gain_table_index; + u32 reg = AR_PHY_TXGAIN_TABLE; + int i; + + memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); + memset(index, 0, sizeof(ah->paprd_gain_table_index)); + + for (i = 0; i < 32; i++) { + entry[i] = REG_READ(ah, reg); + index[i] = (entry[i] >> 24) & 0xff; + reg += 4; + } +} + +static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain, + int target_power) +{ + int olpc_gain_delta = 0; + int alpha_therm, alpha_volt; + int therm_cal_value, volt_cal_value; + int therm_value, volt_value; + int thermal_gain_corr, voltage_gain_corr; + int desired_scale, desired_gain = 0; + u32 reg; + + REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, + AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); + desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12, + AR_PHY_TPC_12_DESIRED_SCALE_HT40_5); + alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19, + AR_PHY_TPC_19_ALPHA_THERM); + alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19, + AR_PHY_TPC_19_ALPHA_VOLT); + therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, + AR_PHY_TPC_18_THERM_CAL_VALUE); + volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, + AR_PHY_TPC_18_VOLT_CAL_VALUE); + therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, + AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE); + volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, + AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE); + + if (chain == 0) + reg = AR_PHY_TPC_11_B0; + else if (chain == 1) + reg = AR_PHY_TPC_11_B1; + else + reg = AR_PHY_TPC_11_B2; + + olpc_gain_delta = REG_READ_FIELD(ah, reg, + AR_PHY_TPC_11_OLPC_GAIN_DELTA); + + if (olpc_gain_delta >= 128) + olpc_gain_delta = olpc_gain_delta - 256; + + thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) + + (256 / 2)) / 256; + voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) + + (128 / 2)) / 128; + desired_gain = target_power - olpc_gain_delta - thermal_gain_corr - + voltage_gain_corr + desired_scale; + + return desired_gain; +} + +static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index) +{ + int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain; + int padrvgnA, padrvgnB, padrvgnC, padrvgnD; + u32 *gain_table_entries = ah->paprd_gain_table_entries; + + selected_gain_entry = gain_table_entries[gain_index]; + txbb1dbgain = selected_gain_entry & 0x7; + txbb6dbgain = (selected_gain_entry >> 3) & 0x3; + txmxrgain = (selected_gain_entry >> 5) & 0xf; + padrvgnA = (selected_gain_entry >> 9) & 0xf; + padrvgnB = (selected_gain_entry >> 13) & 0xf; + padrvgnC = (selected_gain_entry >> 17) & 0xf; + padrvgnD = (selected_gain_entry >> 21) & 0x3; + + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0); + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0); + REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0); + REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0); +} + +static inline int find_expn(int num) +{ + return fls(num) - 1; +} + +static inline int find_proper_scale(int expn, int N) +{ + return (expn > N) ? expn - 10 : 0; +} + +#define NUM_BIN 23 + +static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) +{ + unsigned int thresh_accum_cnt; + int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1]; + int PA_in[NUM_BIN + 1]; + int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1]; + unsigned int B1_abs_max, B2_abs_max; + int max_index, scale_factor; + int y_est[NUM_BIN + 1]; + int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1]; + unsigned int x_tilde_abs; + int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad; + int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B; + int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2; + int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem; + int y5, y3, tmp; + int theta_low_bin = 0; + int i; + + /* disregard any bin that contains <= 16 samples */ + thresh_accum_cnt = 16; + scale_factor = 5; + max_index = 0; + memset(theta, 0, sizeof(theta)); + memset(x_est, 0, sizeof(x_est)); + memset(Y, 0, sizeof(Y)); + memset(y_est, 0, sizeof(y_est)); + memset(x_tilde, 0, sizeof(x_tilde)); + + for (i = 0; i < NUM_BIN; i++) { + s32 accum_cnt, accum_tx, accum_rx, accum_ang; + + /* number of samples */ + accum_cnt = data_L[i] & 0xffff; + + if (accum_cnt <= thresh_accum_cnt) + continue; + + /* sum(tx amplitude) */ + accum_tx = ((data_L[i] >> 16) & 0xffff) | + ((data_U[i] & 0x7ff) << 16); + + /* sum(rx amplitude distance to lower bin edge) */ + accum_rx = ((data_U[i] >> 11) & 0x1f) | + ((data_L[i + 23] & 0xffff) << 5); + + /* sum(angles) */ + accum_ang = ((data_L[i + 23] >> 16) & 0xffff) | + ((data_U[i + 23] & 0x7ff) << 16); + + accum_tx <<= scale_factor; + accum_rx <<= scale_factor; + x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >> + scale_factor; + + Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> + scale_factor) + + (1 << scale_factor) * max_index + 16; + + if (accum_ang >= (1 << 26)) + accum_ang -= 1 << 27; + + theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) / + accum_cnt; + + max_index++; + } + + /* + * Find average theta of first 5 bin and all of those to same value. + * Curve is linear at that range. + */ + for (i = 1; i < 6; i++) + theta_low_bin += theta[i]; + + theta_low_bin = theta_low_bin / 5; + for (i = 1; i < 6; i++) + theta[i] = theta_low_bin; + + /* Set values at origin */ + theta[0] = theta_low_bin; + for (i = 0; i <= max_index; i++) + theta[i] -= theta_low_bin; + + x_est[0] = 0; + Y[0] = 0; + scale_factor = 8; + + /* low signal gain */ + if (x_est[6] == x_est[3]) + return false; + + G_fxp = + (((Y[6] - Y[3]) * 1 << scale_factor) + + (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); + + Y_intercept = + (G_fxp * (x_est[0] - x_est[3]) + + (1 << scale_factor)) / (1 << scale_factor) + Y[3]; + + for (i = 0; i <= max_index; i++) + y_est[i] = Y[i] - Y_intercept; + + for (i = 0; i <= 3; i++) { + y_est[i] = i * 32; + + /* prevent division by zero */ + if (G_fxp == 0) + return false; + + x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; + } + + x_est_fxp1_nonlin = + x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + + G_fxp) / G_fxp; + + order_x_by_y = + (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index]; + + if (order_x_by_y == 0) + M = 10; + else if (order_x_by_y == 1) + M = 9; + else + M = 8; + + I = (max_index > 15) ? 7 : max_index >> 1; + L = max_index - I; + scale_factor = 8; + sum_y_sqr = 0; + sum_y_quad = 0; + x_tilde_abs = 0; + + for (i = 0; i <= L; i++) { + unsigned int y_sqr; + unsigned int y_quad; + unsigned int tmp_abs; + + /* prevent division by zero */ + if (y_est[i + I] == 0) + return false; + + x_est_fxp1_nonlin = + x_est[i + I] - ((1 << scale_factor) * y_est[i + I] + + G_fxp) / G_fxp; + + x_tilde[i] = + (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i + + I]; + x_tilde[i] = + (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; + x_tilde[i] = + (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; + y_sqr = + (y_est[i + I] * y_est[i + I] + + (scale_factor * scale_factor)) / (scale_factor * + scale_factor); + tmp_abs = abs(x_tilde[i]); + if (tmp_abs > x_tilde_abs) + x_tilde_abs = tmp_abs; + + y_quad = y_sqr * y_sqr; + sum_y_sqr = sum_y_sqr + y_sqr; + sum_y_quad = sum_y_quad + y_quad; + B1_tmp[i] = y_sqr * (L + 1); + B2_tmp[i] = y_sqr; + } + + B1_abs_max = 0; + B2_abs_max = 0; + for (i = 0; i <= L; i++) { + int abs_val; + + B1_tmp[i] -= sum_y_sqr; + B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i]; + + abs_val = abs(B1_tmp[i]); + if (abs_val > B1_abs_max) + B1_abs_max = abs_val; + + abs_val = abs(B2_tmp[i]); + if (abs_val > B2_abs_max) + B2_abs_max = abs_val; + } + + Q_x = find_proper_scale(find_expn(x_tilde_abs), 10); + Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10); + Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10); + + beta_raw = 0; + alpha_raw = 0; + for (i = 0; i <= L; i++) { + x_tilde[i] = x_tilde[i] / (1 << Q_x); + B1_tmp[i] = B1_tmp[i] / (1 << Q_B1); + B2_tmp[i] = B2_tmp[i] / (1 << Q_B2); + beta_raw = beta_raw + B1_tmp[i] * x_tilde[i]; + alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i]; + } + + scale_B = + ((sum_y_quad / scale_factor) * (L + 1) - + (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor; + + Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); + scale_B = scale_B / (1 << Q_scale_B); + Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); + Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); + beta_raw = beta_raw / (1 << Q_beta); + alpha_raw = alpha_raw / (1 << Q_alpha); + alpha = (alpha_raw << 10) / scale_B; + beta = (beta_raw << 10) / scale_B; + order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B; + order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B; + order1_5x = order_1 / 5; + order2_3x = order_2 / 3; + order1_5x_rem = order_1 - 5 * order1_5x; + order2_3x_rem = order_2 - 3 * order2_3x; + + for (i = 0; i < PAPRD_TABLE_SZ; i++) { + tmp = i * 32; + y5 = ((beta * tmp) >> 6) >> order1_5x; + y5 = (y5 * tmp) >> order1_5x; + y5 = (y5 * tmp) >> order1_5x; + y5 = (y5 * tmp) >> order1_5x; + y5 = (y5 * tmp) >> order1_5x; + y5 = y5 >> order1_5x_rem; + y3 = (alpha * tmp) >> order2_3x; + y3 = (y3 * tmp) >> order2_3x; + y3 = (y3 * tmp) >> order2_3x; + y3 = y3 >> order2_3x_rem; + PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp; + + if (i >= 2) { + tmp = PA_in[i] - PA_in[i - 1]; + if (tmp < 0) + PA_in[i] = + PA_in[i - 1] + (PA_in[i - 1] - + PA_in[i - 2]); + } + + PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400; + } + + beta_raw = 0; + alpha_raw = 0; + + for (i = 0; i <= L; i++) { + int theta_tilde = + ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I]; + theta_tilde = + ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; + theta_tilde = + ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; + beta_raw = beta_raw + B1_tmp[i] * theta_tilde; + alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde; + } + + Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); + Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); + beta_raw = beta_raw / (1 << Q_beta); + alpha_raw = alpha_raw / (1 << Q_alpha); + + alpha = (alpha_raw << 10) / scale_B; + beta = (beta_raw << 10) / scale_B; + order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5; + order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5; + order1_5x = order_1 / 5; + order2_3x = order_2 / 3; + order1_5x_rem = order_1 - 5 * order1_5x; + order2_3x_rem = order_2 - 3 * order2_3x; + + for (i = 0; i < PAPRD_TABLE_SZ; i++) { + int PA_angle; + + /* pa_table[4] is calculated from PA_angle for i=5 */ + if (i == 4) + continue; + + tmp = i * 32; + if (beta > 0) + y5 = (((beta * tmp - 64) >> 6) - + (1 << order1_5x)) / (1 << order1_5x); + else + y5 = ((((beta * tmp - 64) >> 6) + + (1 << order1_5x)) / (1 << order1_5x)); + + y5 = (y5 * tmp) / (1 << order1_5x); + y5 = (y5 * tmp) / (1 << order1_5x); + y5 = (y5 * tmp) / (1 << order1_5x); + y5 = (y5 * tmp) / (1 << order1_5x); + y5 = y5 / (1 << order1_5x_rem); + + if (beta > 0) + y3 = (alpha * tmp - + (1 << order2_3x)) / (1 << order2_3x); + else + y3 = (alpha * tmp + + (1 << order2_3x)) / (1 << order2_3x); + y3 = (y3 * tmp) / (1 << order2_3x); + y3 = (y3 * tmp) / (1 << order2_3x); + y3 = y3 / (1 << order2_3x_rem); + + if (i < 4) { + PA_angle = 0; + } else { + PA_angle = y5 + y3; + if (PA_angle < -150) + PA_angle = -150; + else if (PA_angle > 150) + PA_angle = 150; + } + + pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff); + if (i == 5) { + PA_angle = (PA_angle + 2) >> 1; + pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) + + (PA_angle & 0x7ff); + } + } + + *gain = G_fxp; + return true; +} + +void ar9003_paprd_populate_single_table(struct ath_hw *ah, + struct ath9k_channel *chan, int chain) +{ + u32 *paprd_table_val = chan->pa_table[chain]; + u32 small_signal_gain = chan->small_signal_gain[chain]; + u32 training_power; + u32 reg = 0; + int i; + + training_power = + REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, + AR_PHY_POWERTX_RATE5_POWERTXHT20_0); + training_power -= 4; + + if (chain == 0) + reg = AR_PHY_PAPRD_MEM_TAB_B0; + else if (chain == 1) + reg = AR_PHY_PAPRD_MEM_TAB_B1; + else if (chain == 2) + reg = AR_PHY_PAPRD_MEM_TAB_B2; + + for (i = 0; i < PAPRD_TABLE_SZ; i++) { + REG_WRITE(ah, reg, paprd_table_val[i]); + reg = reg + 4; + } + + if (chain == 0) + reg = AR_PHY_PA_GAIN123_B0; + else if (chain == 1) + reg = AR_PHY_PA_GAIN123_B1; + else + reg = AR_PHY_PA_GAIN123_B2; + + REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0, + AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, + training_power); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, + AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, + training_power); + + REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, + AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, + training_power); +} +EXPORT_SYMBOL(ar9003_paprd_populate_single_table); + +int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) +{ + + unsigned int i, desired_gain, gain_index; + unsigned int train_power; + + train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, + AR_PHY_POWERTX_RATE5_POWERTXHT20_0); + + train_power = train_power - 4; + + desired_gain = ar9003_get_desired_gain(ah, chain, train_power); + + gain_index = 0; + for (i = 0; i < 32; i++) { + if (ah->paprd_gain_table_index[i] >= desired_gain) + break; + gain_index++; + } + + ar9003_tx_force_gain(ah, gain_index); + + REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, + AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); + + return 0; +} +EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); + +int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, + int chain) +{ + u16 *small_signal_gain = &chan->small_signal_gain[chain]; + u32 *pa_table = chan->pa_table[chain]; + u32 *data_L, *data_U; + int i, status = 0; + u32 *buf; + u32 reg; + + memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); + + buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); + if (!buf) + return -ENOMEM; + + data_L = &buf[0]; + data_U = &buf[48]; + + REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); + + reg = AR_PHY_CHAN_INFO_TAB_0; + for (i = 0; i < 48; i++) + data_L[i] = REG_READ(ah, reg + (i << 2)); + + REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); + + for (i = 0; i < 48; i++) + data_U[i] = REG_READ(ah, reg + (i << 2)); + + if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) + status = -2; + + REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, + AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); + + kfree(buf); + + return status; +} +EXPORT_SYMBOL(ar9003_paprd_create_curve); + +int ar9003_paprd_init_table(struct ath_hw *ah) +{ + ar9003_paprd_setup_single_table(ah); + ar9003_paprd_get_gain_table(ah); + return 0; +} +EXPORT_SYMBOL(ar9003_paprd_init_table); + +bool ar9003_paprd_is_done(struct ath_hw *ah) +{ + return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, + AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); +} +EXPORT_SYMBOL(ar9003_paprd_is_done); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 80431a2f6dc1..19bc05c41136 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -17,6 +17,28 @@ #include "hw.h" #include "ar9003_phy.h" +static const int firstep_table[] = +/* level: 0 1 2 3 4 5 6 7 8 */ + { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ + +static const int cycpwrThr1_table[] = +/* level: 0 1 2 3 4 5 6 7 8 */ + { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ + +/* + * register values to turn OFDM weak signal detection OFF + */ +static const int m1ThreshLow_off = 127; +static const int m2ThreshLow_off = 127; +static const int m1Thresh_off = 127; +static const int m2Thresh_off = 127; +static const int m2CountThr_off = 31; +static const int m2CountThrLow_off = 63; +static const int m1ThreshLowExt_off = 127; +static const int m2ThreshLowExt_off = 127; +static const int m1ThreshExt_off = 127; +static const int m2ThreshExt_off = 127; + /** * ar9003_hw_set_channel - set channel on single-chip device * @ah: atheros hardware structure @@ -94,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) } /** - * ar9003_hw_spur_mitigate - convert baseband spur frequency + * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency * @ah: atheros hardware structure * @chan: * @@ -521,15 +543,6 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, u32 val = INI_RA(iniArr, i, column); REG_WRITE(ah, reg, val); - - /* - * Determine if this is a shift register value, and insert the - * configured delay if so. - */ - if (reg >= 0x16000 && reg < 0x17000 - && ah->config.analog_shiftreg) - udelay(100); - DO_DELAY(regWrites); } } @@ -732,71 +745,68 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, { struct ar5416AniState *aniState = ah->curani; struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + s32 value, value2; switch (cmd & ah->ani_function) { - case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ - u32 level = param; - - if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { - ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); - return false; - } - - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_TOT_DES, - ah->totalSizeDesired[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC, - AR_PHY_AGC_COARSE_LOW, - ah->coarse_low[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC, - AR_PHY_AGC_COARSE_HIGH, - ah->coarse_high[level]); - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); - - if (level > aniState->noiseImmunityLevel) - ah->stats.ast_ani_niup++; - else if (level < aniState->noiseImmunityLevel) - ah->stats.ast_ani_nidown++; - aniState->noiseImmunityLevel = level; - 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 }; + /* + * on == 1 means ofdm weak signal detection is ON + * on == 1 is the default, for less noise immunity + * + * on == 0 means ofdm weak signal detection is OFF + * on == 0 means more noise imm + */ u32 on = param ? 1 : 0; + /* + * make register setting for default + * (weak sig detect ON) come from INI file + */ + int m1ThreshLow = on ? + aniState->iniDef.m1ThreshLow : m1ThreshLow_off; + int m2ThreshLow = on ? + aniState->iniDef.m2ThreshLow : m2ThreshLow_off; + int m1Thresh = on ? + aniState->iniDef.m1Thresh : m1Thresh_off; + int m2Thresh = on ? + aniState->iniDef.m2Thresh : m2Thresh_off; + int m2CountThr = on ? + aniState->iniDef.m2CountThr : m2CountThr_off; + int m2CountThrLow = on ? + aniState->iniDef.m2CountThrLow : m2CountThrLow_off; + int m1ThreshLowExt = on ? + aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; + int m2ThreshLowExt = on ? + aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; + int m1ThreshExt = on ? + aniState->iniDef.m1ThreshExt : m1ThreshExt_off; + int m2ThreshExt = on ? + aniState->iniDef.m2ThreshExt : m2ThreshExt_off; REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, - m1ThreshLow[on]); + m1ThreshLow); REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, - m2ThreshLow[on]); + m2ThreshLow); REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + AR_PHY_SFCORR_M1_THRESH, m1Thresh); REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + AR_PHY_SFCORR_M2_THRESH, m2Thresh); REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, - m2CountThrLow[on]); + m2CountThrLow); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); + AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); if (on) REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, @@ -806,6 +816,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); if (!on != aniState->ofdmWeakSigDetectOff) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: ofdm weak signal: %s=>%s\n", + chan->channel, + !aniState->ofdmWeakSigDetectOff ? + "on" : "off", + on ? "on" : "off"); if (on) ah->stats.ast_ani_ofdmon++; else @@ -814,64 +830,167 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, } break; } - case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; - u32 high = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, - AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, - weakSigThrCck[high]); - if (high != aniState->cckWeakSigThreshold) { - if (high) - ah->stats.ast_ani_cckhigh++; - else - ah->stats.ast_ani_ccklow++; - aniState->cckWeakSigThreshold = high; - } - break; - } case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; u32 level = param; - if (level >= ARRAY_SIZE(firstep)) { + if (level >= ARRAY_SIZE(firstep_table)) { ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", + "ATH9K_ANI_FIRSTEP_LEVEL: level " + "out of range (%u > %u)\n", level, - (unsigned) ARRAY_SIZE(firstep)); + (unsigned) ARRAY_SIZE(firstep_table)); return false; } + + /* + * make register setting relative to default + * from INI file & cap value + */ + value = firstep_table[level] - + firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + + aniState->iniDef.firstep; + if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) + value = ATH9K_SIG_FIRSTEP_SETTING_MIN; + if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) + value = ATH9K_SIG_FIRSTEP_SETTING_MAX; REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP, - firstep[level]); - if (level > aniState->firstepLevel) - ah->stats.ast_ani_stepup++; - else if (level < aniState->firstepLevel) - ah->stats.ast_ani_stepdown++; - aniState->firstepLevel = level; + value); + /* + * we need to set first step low register too + * make register setting relative to default + * from INI file & cap value + */ + value2 = firstep_table[level] - + firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + + aniState->iniDef.firstepLow; + if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) + value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; + if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) + value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; + + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, + AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); + + if (level != aniState->firstepLevel) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "firstep[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value, + aniState->iniDef.firstep); + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "firstep_low[level]=%d ini=%d\n", + chan->channel, + aniState->firstepLevel, + level, + ATH9K_ANI_FIRSTEP_LVL_NEW, + value2, + aniState->iniDef.firstepLow); + if (level > aniState->firstepLevel) + ah->stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ah->stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + } break; } case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; u32 level = param; - if (level >= ARRAY_SIZE(cycpwrThr1)) { + if (level >= ARRAY_SIZE(cycpwrThr1_table)) { ath_print(common, ATH_DBG_ANI, - "level out of range (%u > %u)\n", + "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " + "out of range (%u > %u)\n", level, - (unsigned) ARRAY_SIZE(cycpwrThr1)); + (unsigned) ARRAY_SIZE(cycpwrThr1_table)); return false; } + /* + * make register setting relative to default + * from INI file & cap value + */ + value = cycpwrThr1_table[level] - + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + + aniState->iniDef.cycpwrThr1; + if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) + value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; + if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) + value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_CYCPWR_THR1, - cycpwrThr1[level]); - if (level > aniState->spurImmunityLevel) - ah->stats.ast_ani_spurup++; - else if (level < aniState->spurImmunityLevel) - ah->stats.ast_ani_spurdown++; - aniState->spurImmunityLevel = level; + value); + + /* + * set AR_PHY_EXT_CCA for extension channel + * make register setting relative to default + * from INI file & cap value + */ + value2 = cycpwrThr1_table[level] - + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + + aniState->iniDef.cycpwrThr1Ext; + if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) + value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; + if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) + value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; + REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, + AR_PHY_EXT_CYCPWR_THR1, value2); + + if (level != aniState->spurImmunityLevel) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "cycpwrThr1[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value, + aniState->iniDef.cycpwrThr1); + ath_print(common, ATH_DBG_ANI, + "** ch %d: level %d=>%d[def:%d] " + "cycpwrThr1Ext[level]=%d ini=%d\n", + chan->channel, + aniState->spurImmunityLevel, + level, + ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, + value2, + aniState->iniDef.cycpwrThr1Ext); + if (level > aniState->spurImmunityLevel) + ah->stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ah->stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + } break; } + case ATH9K_ANI_MRC_CCK:{ + /* + * is_on == 1 means MRC CCK ON (default, less noise imm) + * is_on == 0 means MRC CCK is OFF (more noise imm) + */ + bool is_on = param ? 1 : 0; + REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, + AR_PHY_MRC_CCK_ENABLE, is_on); + REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, + AR_PHY_MRC_CCK_MUX_REG, is_on); + if (!is_on != aniState->mrcCCKOff) { + ath_print(common, ATH_DBG_ANI, + "** ch %d: MRC CCK: %s=>%s\n", + chan->channel, + !aniState->mrcCCKOff ? "on" : "off", + is_on ? "on" : "off"); + if (is_on) + ah->stats.ast_ani_ccklow++; + else + ah->stats.ast_ani_cckhigh++; + aniState->mrcCCKOff = !is_on; + } + break; + } case ATH9K_ANI_PRESENT: break; default: @@ -880,25 +999,19 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, return false; } - ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); ath_print(common, ATH_DBG_ANI, - "noiseImmunityLevel=%d, spurImmunityLevel=%d, " - "ofdmWeakSigDetectOff=%d\n", - aniState->noiseImmunityLevel, + "ANI parameters: SI=%d, ofdmWS=%s FS=%d " + "MRCcck=%s listenTime=%d CC=%d listen=%d " + "ofdmErrs=%d cckErrs=%d\n", aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff); - ath_print(common, ATH_DBG_ANI, - "cckWeakSigThreshold=%d, " - "firstepLevel=%d, listenTime=%d\n", - aniState->cckWeakSigThreshold, + !aniState->ofdmWeakSigDetectOff ? "on" : "off", aniState->firstepLevel, - aniState->listenTime); - ath_print(common, ATH_DBG_ANI, - "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", - aniState->cycleCount, - aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); - + !aniState->mrcCCKOff ? "on" : "off", + aniState->listenTime, + aniState->cycleCount, + aniState->listenTime, + aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); return true; } @@ -1111,6 +1224,70 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) } } +/* + * Initialize the ANI register values with default (ini) values. + * This routine is called during a (full) hardware reset after + * all the registers are initialised from the INI. + */ +static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + struct ath9k_ani_default *iniDef; + int index; + u32 val; + + index = ath9k_hw_get_ani_channel_idx(ah, chan); + aniState = &ah->ani[index]; + ah->curani = aniState; + iniDef = &aniState->iniDef; + + ath_print(common, ATH_DBG_ANI, + "ver %d.%d opmode %u chan %d Mhz/0x%x\n", + ah->hw_version.macVersion, + ah->hw_version.macRev, + ah->opmode, + chan->channel, + chan->channelFlags); + + val = REG_READ(ah, AR_PHY_SFCORR); + iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); + iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); + iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); + + val = REG_READ(ah, AR_PHY_SFCORR_LOW); + iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); + iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); + iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); + + val = REG_READ(ah, AR_PHY_SFCORR_EXT); + iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); + iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); + iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); + iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); + iniDef->firstep = REG_READ_FIELD(ah, + AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP); + iniDef->firstepLow = REG_READ_FIELD(ah, + AR_PHY_FIND_SIG_LOW, + AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW); + iniDef->cycpwrThr1 = REG_READ_FIELD(ah, + AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1); + iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, + AR_PHY_EXT_CCA, + AR_PHY_EXT_CYCPWR_THR1); + + /* these levels just got reset to defaults by the INI */ + aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; + aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; + aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; + aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; + + aniState->cycleCount = 0; +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -1131,4 +1308,124 @@ 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->loadnf = ar9003_hw_loadnf; + priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; +} + +void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 idle_tmo_ms = ah->bb_watchdog_timeout_ms; + u32 val, idle_count; + + if (!idle_tmo_ms) { + /* disable IRQ, disable chip-reset for BB panic */ + REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2, + REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & + ~(AR_PHY_WATCHDOG_RST_ENABLE | + AR_PHY_WATCHDOG_IRQ_ENABLE)); + + /* disable watchdog in non-IDLE mode, disable in IDLE mode */ + REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1, + REG_READ(ah, AR_PHY_WATCHDOG_CTL_1) & + ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE | + AR_PHY_WATCHDOG_IDLE_ENABLE)); + + ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); + return; + } + + /* enable IRQ, disable chip-reset for BB watchdog */ + val = REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & AR_PHY_WATCHDOG_CNTL2_MASK; + REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2, + (val | AR_PHY_WATCHDOG_IRQ_ENABLE) & + ~AR_PHY_WATCHDOG_RST_ENABLE); + + /* bound limit to 10 secs */ + if (idle_tmo_ms > 10000) + idle_tmo_ms = 10000; + + /* + * The time unit for watchdog event is 2^15 44/88MHz cycles. + * + * For HT20 we have a time unit of 2^15/44 MHz = .74 ms per tick + * For HT40 we have a time unit of 2^15/88 MHz = .37 ms per tick + * + * Given we use fast clock now in 5 GHz, these time units should + * be common for both 2 GHz and 5 GHz. + */ + idle_count = (100 * idle_tmo_ms) / 74; + if (ah->curchan && IS_CHAN_HT40(ah->curchan)) + idle_count = (100 * idle_tmo_ms) / 37; + + /* + * enable watchdog in non-IDLE mode, disable in IDLE mode, + * set idle time-out. + */ + REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1, + AR_PHY_WATCHDOG_NON_IDLE_ENABLE | + AR_PHY_WATCHDOG_IDLE_MASK | + (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2))); + + ath_print(common, ATH_DBG_RESET, + "Enabled BB Watchdog timeout (%u ms)\n", + idle_tmo_ms); +} + +void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) +{ + /* + * we want to avoid printing in ISR context so we save the + * watchdog status to be printed later in bottom half context. + */ + ah->bb_watchdog_last_status = REG_READ(ah, AR_PHY_WATCHDOG_STATUS); + + /* + * the watchdog timer should reset on status read but to be sure + * sure we write 0 to the watchdog status bit. + */ + REG_WRITE(ah, AR_PHY_WATCHDOG_STATUS, + ah->bb_watchdog_last_status & ~AR_PHY_WATCHDOG_STATUS_CLR); +} + +void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status; + + if (likely(!(common->debug_mask & ATH_DBG_RESET))) + return; + + status = ah->bb_watchdog_last_status; + ath_print(common, ATH_DBG_RESET, + "\n==== BB update: BB status=0x%08x ====\n", status); + ath_print(common, ATH_DBG_RESET, + "** BB state: wd=%u det=%u rdar=%u rOFDM=%d " + "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", + MS(status, AR_PHY_WATCHDOG_INFO), + MS(status, AR_PHY_WATCHDOG_DET_HANG), + MS(status, AR_PHY_WATCHDOG_RADAR_SM), + MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), + MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), + MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), + MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), + MS(status, AR_PHY_WATCHDOG_AGC_SM), + MS(status,AR_PHY_WATCHDOG_SRCH_SM)); + + ath_print(common, ATH_DBG_RESET, + "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", + REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), + REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); + ath_print(common, ATH_DBG_RESET, + "** BB mode: BB_gen_controls=0x%08x **\n", + REG_READ(ah, AR_PHY_GEN_CTRL)); + + if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt)) + ath_print(common, ATH_DBG_RESET, + "** BB busy times: rx_clear=%d%%, " + "rx_frame=%d%%, tx_frame=%d%% **\n", + rxc_pcnt, rxf_pcnt, txf_pcnt); + + ath_print(common, ATH_DBG_RESET, + "==== BB update: done ====\n\n"); } +EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index f08cc8bda005..3394dfe52b42 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -149,6 +149,8 @@ #define AR_PHY_EXT_CCA_THRESH62_S 16 #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 #define AR_PHY_EXT_MINCCA_PWR_S 16 +#define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L +#define AR_PHY_EXT_CYCPWR_THR1_S 9 #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 #define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 @@ -283,6 +285,12 @@ #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 +#define AR_PHY_MRC_CCK_CTRL (AR_AGC_BASE + 0x1d0) +#define AR_PHY_MRC_CCK_ENABLE 0x00000001 +#define AR_PHY_MRC_CCK_ENABLE_S 0 +#define AR_PHY_MRC_CCK_MUX_REG 0x00000002 +#define AR_PHY_MRC_CCK_MUX_REG_S 1 + #define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) #define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 @@ -451,7 +459,11 @@ #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) -#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) + +#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) +#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008 +#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3 + #define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) #define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) #define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) @@ -467,30 +479,86 @@ #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) -#define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) -#define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) -#define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) -#define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) -#define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) -#define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) +#define AR_PHY_TPC_1 (AR_SM_BASE + 0x1f8) +#define AR_PHY_TPC_1_FORCED_DAC_GAIN 0x0000003e +#define AR_PHY_TPC_1_FORCED_DAC_GAIN_S 1 +#define AR_PHY_TPC_1_FORCE_DAC_GAIN 0x00000001 +#define AR_PHY_TPC_1_FORCE_DAC_GAIN_S 0 + +#define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) +#define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) +#define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) + +#define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) +#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) +#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) +#define AR_PHY_TPC_11_OLPC_GAIN_DELTA 0x00ff0000 +#define AR_PHY_TPC_11_OLPC_GAIN_DELTA_S 16 + +#define AR_PHY_TPC_12 (AR_SM_BASE + 0x224) +#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5 0x3e000000 +#define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5_S 25 + +#define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) +#define AR_PHY_TPC_18_THERM_CAL_VALUE 0x000000ff +#define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 +#define AR_PHY_TPC_18_VOLT_CAL_VALUE 0x0000ff00 +#define AR_PHY_TPC_18_VOLT_CAL_VALUE_S 8 + +#define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) +#define AR_PHY_TPC_19_ALPHA_VOLT 0x001f0000 +#define AR_PHY_TPC_19_ALPHA_VOLT_S 16 +#define AR_PHY_TPC_19_ALPHA_THERM 0xff +#define AR_PHY_TPC_19_ALPHA_THERM_S 0 + +#define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) +#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN 0x00000001 +#define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN_S 0 +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN 0x0000000e +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN_S 1 +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN 0x00000030 +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN_S 4 +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN 0x000003c0 +#define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN_S 6 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA 0x00003c00 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA_S 10 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB 0x0003c000 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB_S 14 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC 0x003c0000 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC_S 18 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND 0x00c00000 +#define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND_S 22 +#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL 0x01000000 +#define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL_S 24 -#define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) #define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) +#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) + #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) -#define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0) -#define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4) -#define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8) -#define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc) +#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) +#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) +#define AR_PHY_WATCHDOG_CTL_2 (AR_SM_BASE + 0x5c8) +#define AR_PHY_WATCHDOG_CTL (AR_SM_BASE + 0x5cc) #define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) #define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) #define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) -#define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) + +#define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 + +#define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254) +#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff +#define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0 +#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 +#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 + #define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 @@ -660,17 +728,9 @@ #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 -#define AR_PHY_TPC_18_THERM_CAL_VALUE 0xff -#define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 -#define AR_PHY_TPC_19_ALPHA_THERM 0xff -#define AR_PHY_TPC_19_ALPHA_THERM_S 0 - #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 -#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff -#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 - /* * Channel 1 Register Map */ @@ -812,35 +872,173 @@ #define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) #define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) -#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001 -#define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002 -#define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000 -#define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC - -#define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002 -#define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004 -#define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9 - -#define AR_PHY_BB_WD_STATUS 0x00000007 -#define AR_PHY_BB_WD_STATUS_S 0 -#define AR_PHY_BB_WD_DET_HANG 0x00000008 -#define AR_PHY_BB_WD_DET_HANG_S 3 -#define AR_PHY_BB_WD_RADAR_SM 0x000000F0 -#define AR_PHY_BB_WD_RADAR_SM_S 4 -#define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00 -#define AR_PHY_BB_WD_RX_OFDM_SM_S 8 -#define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000 -#define AR_PHY_BB_WD_RX_CCK_SM_S 12 -#define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000 -#define AR_PHY_BB_WD_TX_OFDM_SM_S 16 -#define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000 -#define AR_PHY_BB_WD_TX_CCK_SM_S 20 -#define AR_PHY_BB_WD_AGC_SM 0x0F000000 -#define AR_PHY_BB_WD_AGC_SM_S 24 -#define AR_PHY_BB_WD_SRCH_SM 0xF0000000 -#define AR_PHY_BB_WD_SRCH_SM_S 28 - -#define AR_PHY_BB_WD_STATUS_CLR 0x00000008 +#define AR_PHY_WATCHDOG_NON_IDLE_ENABLE 0x00000001 +#define AR_PHY_WATCHDOG_IDLE_ENABLE 0x00000002 +#define AR_PHY_WATCHDOG_IDLE_MASK 0xFFFF0000 +#define AR_PHY_WATCHDOG_NON_IDLE_MASK 0x0000FFFC + +#define AR_PHY_WATCHDOG_RST_ENABLE 0x00000002 +#define AR_PHY_WATCHDOG_IRQ_ENABLE 0x00000004 +#define AR_PHY_WATCHDOG_CNTL2_MASK 0xFFFFFFF9 + +#define AR_PHY_WATCHDOG_INFO 0x00000007 +#define AR_PHY_WATCHDOG_INFO_S 0 +#define AR_PHY_WATCHDOG_DET_HANG 0x00000008 +#define AR_PHY_WATCHDOG_DET_HANG_S 3 +#define AR_PHY_WATCHDOG_RADAR_SM 0x000000F0 +#define AR_PHY_WATCHDOG_RADAR_SM_S 4 +#define AR_PHY_WATCHDOG_RX_OFDM_SM 0x00000F00 +#define AR_PHY_WATCHDOG_RX_OFDM_SM_S 8 +#define AR_PHY_WATCHDOG_RX_CCK_SM 0x0000F000 +#define AR_PHY_WATCHDOG_RX_CCK_SM_S 12 +#define AR_PHY_WATCHDOG_TX_OFDM_SM 0x000F0000 +#define AR_PHY_WATCHDOG_TX_OFDM_SM_S 16 +#define AR_PHY_WATCHDOG_TX_CCK_SM 0x00F00000 +#define AR_PHY_WATCHDOG_TX_CCK_SM_S 20 +#define AR_PHY_WATCHDOG_AGC_SM 0x0F000000 +#define AR_PHY_WATCHDOG_AGC_SM_S 24 +#define AR_PHY_WATCHDOG_SRCH_SM 0xF0000000 +#define AR_PHY_WATCHDOG_SRCH_SM_S 28 + +#define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008 + +/* + * PAPRD registers + */ +#define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64) + +#define AR_PHY_PAPRD_AM2AM (AR_CHAN_BASE + 0xe4) +#define AR_PHY_PAPRD_AM2AM_MASK 0x01ffffff +#define AR_PHY_PAPRD_AM2AM_MASK_S 0 + +#define AR_PHY_PAPRD_AM2PM (AR_CHAN_BASE + 0xe8) +#define AR_PHY_PAPRD_AM2PM_MASK 0x01ffffff +#define AR_PHY_PAPRD_AM2PM_MASK_S 0 + +#define AR_PHY_PAPRD_HT40 (AR_CHAN_BASE + 0xec) +#define AR_PHY_PAPRD_HT40_MASK 0x01ffffff +#define AR_PHY_PAPRD_HT40_MASK_S 0 + +#define AR_PHY_PAPRD_CTRL0_B0 (AR_CHAN_BASE + 0xf0) +#define AR_PHY_PAPRD_CTRL0_B1 (AR_CHAN1_BASE + 0xf0) +#define AR_PHY_PAPRD_CTRL0_B2 (AR_CHAN2_BASE + 0xf0) +#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE 0x00000001 +#define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE_S 0 +#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK 0x00000002 +#define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK_S 1 +#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH 0xf8000000 +#define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH_S 27 + +#define AR_PHY_PAPRD_CTRL1_B0 (AR_CHAN_BASE + 0xf4) +#define AR_PHY_PAPRD_CTRL1_B1 (AR_CHAN1_BASE + 0xf4) +#define AR_PHY_PAPRD_CTRL1_B2 (AR_CHAN2_BASE + 0xf4) +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA 0x00000001 +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA_S 0 +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE 0x00000002 +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE_S 1 +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE 0x00000004 +#define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE_S 2 +#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL 0x000001f8 +#define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL_S 3 +#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK 0x0001fe00 +#define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK_S 9 +#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 +#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 + +#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + 0x490) +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING_S 1 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE 0x00000100 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE_S 8 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE 0x00000200 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE_S 9 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE 0x00000400 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE_S 10 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE 0x00000800 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE_S 11 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 +#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 + +#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + 0x494) +#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF +#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 + +#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + 0x498) +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP_S 6 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL 0x0001f000 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL_S 12 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES 0x000e0000 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES_S 17 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN 0x00f00000 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN_S 20 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN 0x0f000000 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN_S 24 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 +#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 + +#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + 0x49c) +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA_S 12 +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR 0x00000fff +#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR_S 0 + +#define AR_PHY_PAPRD_PRE_POST_SCALE_0_B0 (AR_CHAN_BASE + 0x100) +#define AR_PHY_PAPRD_PRE_POST_SCALE_1_B0 (AR_CHAN_BASE + 0x104) +#define AR_PHY_PAPRD_PRE_POST_SCALE_2_B0 (AR_CHAN_BASE + 0x108) +#define AR_PHY_PAPRD_PRE_POST_SCALE_3_B0 (AR_CHAN_BASE + 0x10c) +#define AR_PHY_PAPRD_PRE_POST_SCALE_4_B0 (AR_CHAN_BASE + 0x110) +#define AR_PHY_PAPRD_PRE_POST_SCALE_5_B0 (AR_CHAN_BASE + 0x114) +#define AR_PHY_PAPRD_PRE_POST_SCALE_6_B0 (AR_CHAN_BASE + 0x118) +#define AR_PHY_PAPRD_PRE_POST_SCALE_7_B0 (AR_CHAN_BASE + 0x11c) +#define AR_PHY_PAPRD_PRE_POST_SCALING 0x3FFFF +#define AR_PHY_PAPRD_PRE_POST_SCALING_S 0 + +#define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + 0x4a0) +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE 0x00000001 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S 0 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE 0x00000002 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE_S 1 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR 0x00000004 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR_S 2 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE 0x00000008 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE_S 3 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX 0x000001f0 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX_S 4 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR 0x0001fe00 +#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S 9 + +#define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + 0x4a4) +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL 0x0000ffff +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S 0 +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX 0x001f0000 +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX_S 16 +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX 0x00600000 +#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S 21 + +#define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + 0x4a8) +#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT 0x000fffff +#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S 0 + +#define AR_PHY_PAPRD_MEM_TAB_B0 (AR_CHAN_BASE + 0x120) +#define AR_PHY_PAPRD_MEM_TAB_B1 (AR_CHAN1_BASE + 0x120) +#define AR_PHY_PAPRD_MEM_TAB_B2 (AR_CHAN2_BASE + 0x120) + +#define AR_PHY_PA_GAIN123_B0 (AR_CHAN_BASE + 0xf8) +#define AR_PHY_PA_GAIN123_B1 (AR_CHAN1_BASE + 0xf8) +#define AR_PHY_PA_GAIN123_B2 (AR_CHAN2_BASE + 0xf8) +#define AR_PHY_PA_GAIN123_PA_GAIN1 0x3FF +#define AR_PHY_PA_GAIN123_PA_GAIN1_S 0 + +#define AR_PHY_POWERTX_RATE5 (AR_SM_BASE + 0x1d0) +#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F +#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index fbb7dec6ddeb..8d163ae4255e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -20,6 +20,7 @@ #include <linux/etherdevice.h> #include <linux/device.h> #include <linux/leds.h> +#include <linux/completion.h> #include "debug.h" #include "common.h" @@ -136,6 +137,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_MAX_ANTENNA 3 #define ATH_RXBUF 512 #define ATH_TXBUF 512 +#define ATH_TXBUF_RESERVE 5 +#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) #define ATH_TXMAXTRY 13 #define ATH_MGT_TXMAXTRY 4 @@ -192,6 +195,7 @@ 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; @@ -206,6 +210,70 @@ struct ath_txq { u8 txq_tailidx; }; +struct ath_atx_ac { + int sched; + int qnum; + struct list_head list; + struct list_head tid_q; +}; + +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; + u32 bfs_keyix; + enum ath9k_key_type bfs_keytype; +}; + +struct ath_buf { + struct list_head list; + struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or + an aggregate) */ + struct ath_buf *bf_next; /* next subframe in the aggregate */ + struct sk_buff *bf_mpdu; /* enclosing frame structure */ + void *bf_desc; /* virtual addr of desc */ + dma_addr_t bf_daddr; /* physical addr of desc */ + dma_addr_t bf_buf_addr; /* physical addr of data buffer */ + bool bf_stale; + bool bf_isnullfunc; + bool bf_tx_aborted; + u16 bf_flags; + struct ath_buf_state bf_state; + dma_addr_t bf_dmacontext; + struct ath_wiphy *aphy; +}; + +struct ath_atx_tid { + struct list_head list; + struct list_head buf_q; + struct ath_node *an; + struct ath_atx_ac *ac; + struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; + u16 seq_start; + u16 seq_next; + u16 baw_size; + int tidno; + int baw_head; /* first un-acked tx buffer */ + int baw_tail; /* next unused tx buffer slot */ + int sched; + int paused; + u8 state; +}; + +struct ath_node { + struct ath_common *common; + struct ath_atx_tid tid[WME_NUM_TID]; + struct ath_atx_ac ac[WME_NUM_AC]; + u16 maxampdu; + u8 mpdudensity; + int last_rssi; +}; + #define AGGR_CLEANUP BIT(1) #define AGGR_ADDBA_COMPLETE BIT(2) #define AGGR_ADDBA_PROGRESS BIT(3) @@ -214,6 +282,7 @@ struct ath_tx_control { struct ath_txq *txq; int if_id; enum ath9k_internal_frame_type frame_type; + u8 paprd; }; #define ATH_TX_ERROR 0x01 @@ -223,11 +292,12 @@ struct ath_tx_control { struct ath_tx { u16 seq_no; u32 txqsetup; - int hwq_map[ATH9K_WME_AC_VO+1]; + 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_rx_edma { @@ -267,7 +337,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_init(struct ath_softc *sc, int nbufs); void ath_tx_cleanup(struct ath_softc *sc); -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, @@ -351,10 +420,12 @@ int ath_beaconq_config(struct ath_softc *sc); #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ -#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ +#define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ +#define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ +void ath_paprd_calibrate(struct work_struct *work); void ath_ani_calibrate(unsigned long data); /**********/ @@ -486,6 +557,9 @@ struct ath_softc { spinlock_t sc_serial_rw; spinlock_t sc_pm_lock; struct mutex mutex; + struct work_struct paprd_work; + struct completion paprd_complete; + int paprd_txok; u32 intrstatus; u32 sc_flags; /* SC_OP_* */ @@ -544,7 +618,6 @@ struct ath_wiphy { void ath9k_tasklet(unsigned long data); int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); @@ -560,8 +633,6 @@ irqreturn_t ath_isr(int irq, void *dev); int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); -const char *ath_mac_bb_name(u32 mac_bb_version); -const char *ath_rf_name(u16 rf_version); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, struct ath9k_channel *ichan); @@ -612,8 +683,6 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); - void ath_start_rfkill_poll(struct ath_softc *sc); extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index f43d85a302c4..4d4b22d52dfd 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -38,8 +38,7 @@ int ath_beaconq_config(struct ath_softc *sc) qi.tqi_cwmax = 0; } else { /* Adhoc mode; important thing is to use 2x cwmin. */ - qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, - ATH9K_WME_AC_BE); + qnum = sc->tx.hwq_map[WME_AC_BE]; ath9k_hw_get_txq_props(ah, qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; qi.tqi_cwmin = 4*qi_be.tqi_cwmin; diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 7707341cd0d3..16e2849f644d 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -27,270 +27,6 @@ MODULE_AUTHOR("Atheros Communications"); MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); MODULE_LICENSE("Dual BSD/GPL"); -/* Common RX processing */ - -/* Assumes you've already done the endian to CPU conversion */ -static bool ath9k_rx_accept(struct ath_common *common, - struct sk_buff *skb, - struct ieee80211_rx_status *rxs, - struct ath_rx_status *rx_stats, - bool *decrypt_error) -{ - struct ath_hw *ah = common->ah; - struct ieee80211_hdr *hdr; - __le16 fc; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; - - if (!rx_stats->rs_datalen) - return false; - /* - * rs_status follows rs_datalen so if rs_datalen is too large - * we can take a hint that hardware corrupted it, so ignore - * those frames. - */ - if (rx_stats->rs_datalen > common->rx_bufsize) - return false; - - /* - * rs_more indicates chained descriptors which can be used - * to link buffers together for a sort of scatter-gather - * operation. - * reject the frame, we don't support scatter-gather yet and - * the frame is probably corrupt anyway - */ - if (rx_stats->rs_more) - return false; - - /* - * The rx_stats->rs_status will not be set until the end of the - * chained descriptors so it can be ignored if rs_more is set. The - * rs_more will be false at the last element of the chained - * descriptors. - */ - if (rx_stats->rs_status != 0) { - if (rx_stats->rs_status & ATH9K_RXERR_CRC) - rxs->flag |= RX_FLAG_FAILED_FCS_CRC; - if (rx_stats->rs_status & ATH9K_RXERR_PHY) - return false; - - if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { - *decrypt_error = true; - } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - rx_stats->rs_status &= ~ATH9K_RXERR_MIC; - else - rxs->flag |= RX_FLAG_MMIC_ERROR; - } - /* - * Reject error frames with the exception of - * decryption and MIC failures. For monitor mode, - * we also ignore the CRC error. - */ - if (ah->opmode == NL80211_IFTYPE_MONITOR) { - if (rx_stats->rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | - ATH9K_RXERR_CRC)) - return false; - } else { - if (rx_stats->rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { - return false; - } - } - } - return true; -} - -static int ath9k_process_rate(struct ath_common *common, - struct ieee80211_hw *hw, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rxs, - struct sk_buff *skb) -{ - struct ieee80211_supported_band *sband; - enum ieee80211_band band; - unsigned int i = 0; - - band = hw->conf.channel->band; - sband = hw->wiphy->bands[band]; - - if (rx_stats->rs_rate & 0x80) { - /* HT rate */ - rxs->flag |= RX_FLAG_HT; - if (rx_stats->rs_flags & ATH9K_RX_2040) - rxs->flag |= RX_FLAG_40MHZ; - if (rx_stats->rs_flags & ATH9K_RX_GI) - rxs->flag |= RX_FLAG_SHORT_GI; - rxs->rate_idx = rx_stats->rs_rate & 0x7f; - return 0; - } - - for (i = 0; i < sband->n_bitrates; i++) { - if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { - rxs->rate_idx = i; - return 0; - } - if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { - rxs->flag |= RX_FLAG_SHORTPRE; - rxs->rate_idx = i; - return 0; - } - } - - /* - * No valid hardware bitrate found -- we should not get here - * because hardware has already validated this frame as OK. - */ - ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " - "0x%02x using 1 Mbit\n", rx_stats->rs_rate); - if ((common->debug_mask & ATH_DBG_XMIT)) - print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); - - return -EINVAL; -} - -static void ath9k_process_rssi(struct ath_common *common, - struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ath_rx_status *rx_stats) -{ - struct ath_hw *ah = common->ah; - struct ieee80211_sta *sta; - struct ieee80211_hdr *hdr; - struct ath_node *an; - int last_rssi = ATH_RSSI_DUMMY_MARKER; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - 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. - */ - sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); - 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 (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) - rx_stats->rs_rssi = ATH_EP_RND(last_rssi, - ATH_RSSI_EP_MULTIPLIER); - if (rx_stats->rs_rssi < 0) - 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; -} - -/* - * For Decrypt or Demic errors, we only mark packet status here and always push - * up the frame up to let mac80211 handle the actual error case, be it no - * decryption key or real decryption error. This let us keep statistics there. - */ -int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, - struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rx_status, - bool *decrypt_error) -{ - struct ath_hw *ah = common->ah; - - memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); - - /* - * everything but the rate is checked here, the rate check is done - * separately to avoid doing two lookups for a rate for each frame. - */ - if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) - return -EINVAL; - - ath9k_process_rssi(common, hw, skb, rx_stats); - - if (ath9k_process_rate(common, hw, rx_stats, rx_status, skb)) - return -EINVAL; - - rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); - rx_status->band = hw->conf.channel->band; - rx_status->freq = hw->conf.channel->center_freq; - rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; - rx_status->antenna = rx_stats->rs_antenna; - rx_status->flag |= RX_FLAG_TSFT; - - return 0; -} -EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess); - -void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, - struct sk_buff *skb, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rxs, - bool decrypt_error) -{ - struct ath_hw *ah = common->ah; - struct ieee80211_hdr *hdr; - int hdrlen, padpos, padsize; - u8 keyix; - __le16 fc; - - /* see if any padding is done by the hw and remove it */ - hdr = (struct ieee80211_hdr *) skb->data; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; - padpos = ath9k_cmn_padpos(hdr->frame_control); - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - padpos % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - padsize = padpos & 3; - if (padsize && skb->len>=padpos+padsize+FCS_LEN) { - memmove(skb->data + padsize, skb->data, padpos); - skb_pull(skb, padsize); - } - - keyix = rx_stats->rs_keyix; - - if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && - ieee80211_has_protected(fc)) { - rxs->flag |= RX_FLAG_DECRYPTED; - } else if (ieee80211_has_protected(fc) - && !decrypt_error && skb->len >= hdrlen + 4) { - keyix = skb->data[hdrlen + 3] >> 6; - - if (test_bit(keyix, common->keymap)) - rxs->flag |= RX_FLAG_DECRYPTED; - } - if (ah->sw_mgmt_crypto && - (rxs->flag & RX_FLAG_DECRYPTED) && - ieee80211_is_mgmt(fc)) - /* Use software decrypt for management frames. */ - rxs->flag &= ~RX_FLAG_DECRYPTED; -} -EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); - int ath9k_cmn_padpos(__le16 frame_control) { int padpos = 24; @@ -475,10 +211,14 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) return -1; } -static int ath_reserve_key_cache_slot(struct ath_common *common) +static int ath_reserve_key_cache_slot(struct ath_common *common, + enum ieee80211_key_alg alg) { int i; + if (alg == ALG_TKIP) + return ath_reserve_key_cache_slot_tkip(common); + /* First, try to find slots that would not be available for TKIP. */ if (common->splitmic) { for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { @@ -547,6 +287,7 @@ int ath9k_cmn_key_config(struct ath_common *common, struct ath_hw *ah = common->ah; struct ath9k_keyval hk; const u8 *mac = NULL; + u8 gmac[ETH_ALEN]; int ret = 0; int idx; @@ -570,9 +311,23 @@ int ath9k_cmn_key_config(struct ath_common *common, memcpy(hk.kv_val, key->key, key->keylen); if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; + switch (vif->type) { + case NL80211_IFTYPE_AP: + memcpy(gmac, vif->addr, ETH_ALEN); + gmac[0] |= 0x01; + mac = gmac; + idx = ath_reserve_key_cache_slot(common, key->alg); + break; + case NL80211_IFTYPE_ADHOC: + memcpy(gmac, sta->addr, ETH_ALEN); + gmac[0] |= 0x01; + mac = gmac; + idx = ath_reserve_key_cache_slot(common, key->alg); + break; + default: + idx = key->keyidx; + break; + } } else if (key->keyidx) { if (WARN_ON(!sta)) return -EOPNOTSUPP; @@ -589,14 +344,12 @@ int ath9k_cmn_key_config(struct ath_common *common, return -EOPNOTSUPP; mac = sta->addr; - if (key->alg == ALG_TKIP) - idx = ath_reserve_key_cache_slot_tkip(common); - else - idx = ath_reserve_key_cache_slot(common); - if (idx < 0) - return -ENOSPC; /* no free key cache entries */ + idx = ath_reserve_key_cache_slot(common, key->alg); } + if (idx < 0) + return -ENOSPC; /* no free key cache entries */ + if (key->alg == ALG_TKIP) ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, vif->type == NL80211_IFTYPE_AP); @@ -644,6 +397,19 @@ void ath9k_cmn_key_delete(struct ath_common *common, } EXPORT_SYMBOL(ath9k_cmn_key_delete); +int ath9k_cmn_count_streams(unsigned int chainmask, int max) +{ + int streams = 0; + + do { + if (++streams == max) + break; + } while ((chainmask = chainmask & (chainmask - 1))); + + return streams; +} +EXPORT_SYMBOL(ath9k_cmn_count_streams); + static int __init ath9k_cmn_init(void) { return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index e08f7e5a26e0..97809d39c73f 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -52,82 +52,6 @@ #define ATH_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) -struct ath_atx_ac { - int sched; - int qnum; - struct list_head list; - struct list_head tid_q; -}; - -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; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; -}; - -struct ath_buf { - struct list_head list; - struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or - an aggregate) */ - struct ath_buf *bf_next; /* next subframe in the aggregate */ - struct sk_buff *bf_mpdu; /* enclosing frame structure */ - void *bf_desc; /* virtual addr of desc */ - dma_addr_t bf_daddr; /* physical addr of desc */ - dma_addr_t bf_buf_addr; /* physical addr of data buffer */ - bool bf_stale; - bool bf_isnullfunc; - bool bf_tx_aborted; - u16 bf_flags; - struct ath_buf_state bf_state; - dma_addr_t bf_dmacontext; - struct ath_wiphy *aphy; -}; - -struct ath_atx_tid { - struct list_head list; - struct list_head buf_q; - struct ath_node *an; - struct ath_atx_ac *ac; - struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; - u16 seq_start; - u16 seq_next; - u16 baw_size; - int tidno; - int baw_head; /* first un-acked tx buffer */ - int baw_tail; /* next unused tx buffer slot */ - int sched; - int paused; - u8 state; -}; - -struct ath_node { - struct ath_common *common; - struct ath_atx_tid tid[WME_NUM_TID]; - struct ath_atx_ac ac[WME_NUM_AC]; - u16 maxampdu; - u8 mpdudensity; - int last_rssi; -}; - -int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, - struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rx_status, - bool *decrypt_error); - -void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, - struct sk_buff *skb, - struct ath_rx_status *rx_stats, - struct ieee80211_rx_status *rxs, - bool decrypt_error); - 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, @@ -140,3 +64,4 @@ int ath9k_cmn_key_config(struct ath_common *common, struct ieee80211_key_conf *key); void ath9k_cmn_key_delete(struct ath_common *common, struct ieee80211_key_conf *key); +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 29898f8d1893..54aae931424e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -42,7 +42,7 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf, char buf[32]; unsigned int len; - len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask); + len = sprintf(buf, "0x%08x\n", common->debug_mask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -57,7 +57,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) - return -EINVAL; + return -EFAULT; buf[len] = '\0'; if (strict_strtoul(buf, 0, &mask)) @@ -86,7 +86,7 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf, char buf[32]; unsigned int len; - len = snprintf(buf, sizeof(buf), "0x%08x\n", common->tx_chainmask); + len = sprintf(buf, "0x%08x\n", common->tx_chainmask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -101,7 +101,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) - return -EINVAL; + return -EFAULT; buf[len] = '\0'; if (strict_strtoul(buf, 0, &mask)) @@ -128,7 +128,7 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf, char buf[32]; unsigned int len; - len = snprintf(buf, sizeof(buf), "0x%08x\n", common->rx_chainmask); + len = sprintf(buf, "0x%08x\n", common->rx_chainmask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -143,7 +143,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) - return -EINVAL; + return -EFAULT; buf[len] = '\0'; if (strict_strtoul(buf, 0, &mask)) @@ -176,7 +176,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL); if (!buf) - return 0; + return -ENOMEM; ath9k_ps_wakeup(sc); @@ -248,6 +248,9 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, ath9k_ps_restore(sc); + if (len > DMA_BUF_LEN) + len = DMA_BUF_LEN; + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; @@ -269,6 +272,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) sc->debug.stats.istats.rxlp++; if (status & ATH9K_INT_RXHP) sc->debug.stats.istats.rxhp++; + if (status & ATH9K_INT_BB_WATCHDOG) + sc->debug.stats.istats.bb_watchdog++; } else { if (status & ATH9K_INT_RX) sc->debug.stats.istats.rxok++; @@ -319,6 +324,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "WATCHDOG", + sc->debug.stats.istats.bb_watchdog); } else { len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); @@ -358,6 +366,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -397,11 +408,10 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, if (sc->cur_rate_table == NULL) return 0; - max = 80 + sc->cur_rate_table->rate_cnt * 1024; - buf = kmalloc(max + 1, GFP_KERNEL); + max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1; + buf = kmalloc(max, GFP_KERNEL); if (buf == NULL) - return 0; - buf[max] = 0; + return -ENOMEM; len += sprintf(buf, "%6s %6s %6s " "%10s %10s %10s %10s\n", @@ -443,6 +453,9 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, stats->per); } + if (len > max) + len = max; + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return retval; @@ -505,6 +518,9 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "addrmask: %pM\n", addr); + if (len > sizeof(buf)) + len = sizeof(buf); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -614,10 +630,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[ATH9K_WME_AC_BE]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \ + 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); \ } while(0) static ssize_t read_file_xmit(struct file *file, char __user *user_buf, @@ -630,7 +646,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) - return 0; + return -ENOMEM; len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); @@ -648,6 +664,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, PR("DATA Underrun: ", data_underrun); PR("DELIM Underrun: ", delim_underrun); + if (len > size) + len = size; + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); @@ -700,7 +719,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) - return 0; + return -ENOMEM; len += snprintf(buf + len, size - len, "%18s : %10u\n", "CRC ERR", @@ -751,6 +770,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); + if (len > size) + len = size; + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); @@ -802,7 +824,7 @@ static ssize_t read_file_regidx(struct file *file, char __user *user_buf, char buf[32]; unsigned int len; - len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.regidx); + len = sprintf(buf, "0x%08x\n", sc->debug.regidx); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -816,7 +838,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) - return -EINVAL; + return -EFAULT; buf[len] = '\0'; if (strict_strtoul(buf, 0, ®idx)) @@ -843,7 +865,7 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf, u32 regval; regval = REG_READ_D(ah, sc->debug.regidx); - len = snprintf(buf, sizeof(buf), "0x%08x\n", regval); + len = sprintf(buf, "0x%08x\n", regval); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -858,7 +880,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) - return -EINVAL; + return -EFAULT; buf[len] = '\0'; if (strict_strtoul(buf, 0, ®val)) @@ -934,6 +956,10 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, sc, &fops_regval)) goto err; + if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) + goto err; + sc->debug.regidx = 0; return 0; err: diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5147b8709e10..5d21704e87ff 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -53,6 +53,7 @@ struct ath_buf; * @cabend: RX End of CAB traffic * @dtimsync: DTIM sync lossage * @dtim: RX Beacon with DTIM + * @bb_watchdog: Baseband watchdog */ struct ath_interrupt_stats { u32 total; @@ -76,6 +77,7 @@ struct ath_interrupt_stats { u32 cabend; u32 dtimsync; u32 dtim; + u32 bb_watchdog; }; struct ath_rc_stats { diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index ca8704a9d7ac..1266333f586d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -24,6 +24,14 @@ static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); } +void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val) +{ + REG_WRITE(ah, reg, val); + + if (ah->config.analog_shiftreg) + udelay(100); +} + void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, u32 shift, u32 val) { @@ -250,6 +258,27 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, return twiceMaxEdgePower; } +void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + + 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(common, ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); + break; + } +} + int ath9k_hw_eeprom_init(struct ath_hw *ah) { int status; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 21354c15a9a9..bdd8aa054b80 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -263,7 +263,8 @@ enum eeprom_param { EEP_PWR_TABLE_OFFSET, EEP_DRIVE_STRENGTH, EEP_INTERNAL_REGULATOR, - EEP_SWREG + EEP_SWREG, + EEP_PAPRD, }; enum ar5416_rates { @@ -679,6 +680,7 @@ struct eeprom_ops { u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); }; +void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val); void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, u32 shift, u32 val); int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, @@ -704,6 +706,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, u16 numRates, bool isHt40Target); u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, bool is2GHz, int num_band_edges); +void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); int ath9k_hw_eeprom_init(struct ath_hw *ah); #define ar5416_get_ntxchains(_txchainmask) \ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 41a77d1bd439..e25a2abbf561 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -249,6 +249,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, struct chan_centers centers; #define PD_GAIN_BOUNDARY_DEFAULT 58; + memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); ath9k_hw_get_channel_centers(ah, chan, ¢ers); for (numPiers = 0; numPiers < availPiers; numPiers++) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b471db5fb82d..39a41053705f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -17,17 +17,19 @@ #include "hw.h" #include "ar9002_phy.h" -static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) +#define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16)) + +static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) { return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; } -static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) +static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) { return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; } -static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) +static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct ath_common *common = ath9k_hw_common(ah); @@ -40,20 +42,20 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) "Reading from EEPROM, not flash\n"); } - for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); - addr++) { - if (!ath9k_hw_nvram_read(common, - addr + eep_start_loc, eep_data)) { + for (addr = 0; addr < NUM_EEP_WORDS; addr++) { + if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, + eep_data)) { ath_print(common, ATH_DBG_EEPROM, "Unable to read eeprom region\n"); return false; } eep_data++; } + return true; } -static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) +static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) { u32 sum = 0, el, integer; u16 temp, word, magic, magic2, *eepdata; @@ -63,8 +65,8 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(common, - AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, + &magic)) { ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n"); return false; @@ -72,6 +74,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) ath_print(common, ATH_DBG_EEPROM, "Read Magic = 0x%04X\n", magic); + if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -79,9 +82,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) need_swap = true; eepdata = (u16 *)(&ah->eeprom); - for (addr = 0; - addr < sizeof(struct ar9287_eeprom) / sizeof(u16); - addr++) { + for (addr = 0; addr < NUM_EEP_WORDS; addr++) { temp = swab16(*eepdata); *eepdata = temp; eepdata++; @@ -89,13 +90,14 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) } else { ath_print(common, ATH_DBG_FATAL, "Invalid EEPROM Magic. " - "endianness mismatch.\n"); + "Endianness mismatch.\n"); return -EINVAL; } } } - ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? - "True" : "False"); + + ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); if (need_swap) el = swab16(ah->eeprom.map9287.baseEepHeader.length); @@ -108,6 +110,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) el = el / sizeof(u16); eepdata = (u16 *)(&ah->eeprom); + for (i = 0; i < el; i++) sum ^= *eepdata++; @@ -161,7 +164,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) return 0; } -static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, +static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, enum eeprom_param param) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; @@ -170,6 +173,7 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, u16 ver_minor; ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; + switch (param) { case EEP_NFTHRESH_2: return pModal->noiseFloorThreshCh[0]; @@ -214,29 +218,30 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, } } - -static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_ar9287 *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) +static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, + struct ath9k_channel *chan, + struct cal_data_per_freq_ar9287 *pRawDataSet, + u8 *bChans, u16 availPiers, + u16 tPdGainOverlap, + int16_t *pMinCalPower, + u16 *pPdGainBoundaries, + u8 *pPDADCValues, + u16 numXpdGains) { -#define TMP_VAL_VPD_TABLE \ +#define TMP_VAL_VPD_TABLE \ ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR9287_NUM_PD_GAINS]; - u8 maxPwrT4[AR9287_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; + int i, j, k; + int16_t ss; + u16 idxL = 0, idxR = 0, numPiers; + u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; + u8 minPwrT4[AR9287_NUM_PD_GAINS]; + u8 maxPwrT4[AR9287_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + u16 sizeCurrVpdTable, maxIndex, tgtIndex; + bool match; + int16_t minDelta = 0; struct chan_centers centers; static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; @@ -245,6 +250,7 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); ath9k_hw_get_channel_centers(ah, chan, ¢ers); for (numPiers = 0; numPiers < availPiers; numPiers++) { @@ -253,18 +259,18 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, } match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), bChans, numPiers, - &idxL, &idxR); + (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), + bChans, numPiers, &idxL, &idxR); if (match) { for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); + pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], + AR9287_PD_GAIN_ICEPTS, + vpdTableI[i]); } } else { for (i = 0; i < numXpdGains; i++) { @@ -275,61 +281,59 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - maxPwrT4[i] = - min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], - pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); + maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], + pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR9287_PD_GAIN_ICEPTS, - vpdTableL[i]); + pPwrL, pVpdL, + AR9287_PD_GAIN_ICEPTS, + vpdTableL[i]); ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR9287_PD_GAIN_ICEPTS, - vpdTableR[i]); + pPwrR, pVpdR, + AR9287_PD_GAIN_ICEPTS, + vpdTableR[i]); for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. synth_center, - IS_CHAN_2GHZ(chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); + vpdTableI[i][j] = (u8)(ath9k_hw_interpolate( + (u16)FREQ2FBIN(centers. synth_center, + IS_CHAN_2GHZ(chan)), + bChans[idxL], bChans[idxR], + vpdTableL[i][j], vpdTableR[i][j])); } } } - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); k = 0; + for (i = 0; i < numXpdGains; i++) { if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); + pPdGainBoundaries[i] = + (u16)(maxPwrT4[i] / 2); else - pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + - minPwrT4[i+1]) / 4); + pPdGainBoundaries[i] = + (u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4); pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, - pPdGainBoundaries[i]); + pPdGainBoundaries[i]); - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else - minDelta = 0; + minDelta = 0; if (i == 0) { if (AR_SREV_9280_10_OR_LATER(ah)) ss = (int16_t)(0 - (minPwrT4[i] / 2)); else ss = 0; - } else + } else { ss = (int16_t)((pPdGainBoundaries[i-1] - - (minPwrT4[i] / 2)) - + (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); + } vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); @@ -348,12 +352,13 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + if (tgtIndex > maxIndex) { while ((ss <= tgtIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); + pPDADCValues[k++] = + (u8)((tmpVal > 255) ? 255 : tmpVal); ss++; } } @@ -375,10 +380,9 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, struct ath9k_channel *chan, struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, - u8 *pCalChans, u16 availPiers, - int8_t *pPwr) + u8 *pCalChans, u16 availPiers, int8_t *pPwr) { - u16 idxL = 0, idxR = 0, numPiers; + u16 idxL = 0, idxR = 0, numPiers; bool match; struct chan_centers centers; @@ -390,15 +394,14 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, } match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), - pCalChans, numPiers, - &idxL, &idxR); + (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), + pCalChans, numPiers, &idxL, &idxR); if (match) { *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; } else { *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + - (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; } } @@ -409,16 +412,22 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, u32 tmpVal; u32 a; + /* Enable OLPC for chain 0 */ + tmpVal = REG_READ(ah, 0xa270); tmpVal = tmpVal & 0xFCFFFFFF; tmpVal = tmpVal | (0x3 << 24); REG_WRITE(ah, 0xa270, tmpVal); + /* Enable OLPC for chain 1 */ + tmpVal = REG_READ(ah, 0xb270); tmpVal = tmpVal & 0xFCFFFFFF; tmpVal = tmpVal | (0x3 << 24); REG_WRITE(ah, 0xb270, tmpVal); + /* Write the OLPC ref power for chain 0 */ + if (chain == 0) { tmpVal = REG_READ(ah, 0xa398); tmpVal = tmpVal & 0xff00ffff; @@ -427,6 +436,8 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, REG_WRITE(ah, 0xa398, tmpVal); } + /* Write the OLPC ref power for chain 1 */ + if (chain == 1) { tmpVal = REG_READ(ah, 0xb398); tmpVal = tmpVal & 0xff00ffff; @@ -436,28 +447,29 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, } } -static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, +static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) { - struct ath_common *common = ath9k_hw_common(ah); struct cal_data_per_freq_ar9287 *pRawDataset; struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; - u8 *pCalBChans = NULL; + u8 *pCalBChans = NULL; u16 pdGainOverlap_t2; - u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; + u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; u16 numPiers = 0, i, j; - int16_t tMinCalPower; + int16_t tMinCalPower; u16 numXpdGain, xpdMask; u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; - u32 reg32, regOffset, regChainOffset; - int16_t modalIdx, diff = 0; + u32 reg32, regOffset, regChainOffset, regval; + int16_t modalIdx, diff = 0; struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; + modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; xpdMask = pEepData->modalHeader.xpdGain; + if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= - AR9287_EEP_MINOR_VER_2) + AR9287_EEP_MINOR_VER_2) pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; else pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), @@ -466,15 +478,16 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, if (IS_CHAN_2GHZ(chan)) { pCalBChans = pEepData->calFreqPier2G; numPiers = AR9287_NUM_2G_CAL_PIERS; - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { + if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { pRawDatasetOpenLoop = - (struct cal_data_op_loop_ar9287 *) - pEepData->calPierData2G[0]; + (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; } } numXpdGain = 0; + + /* Calculate the value of xpdgains from the xpdGain Mask */ for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { if (numXpdGain >= AR9287_NUM_PD_GAINS) @@ -496,99 +509,80 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, for (i = 0; i < AR9287_MAX_CHAINS; i++) { regChainOffset = i * 0x1000; + if (pEepData->baseEepHeader.txMask & (1 << i)) { - pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) - pEepData->calPierData2G[i]; - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { + pRawDatasetOpenLoop = + (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; + + if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { int8_t txPower; ar9287_eeprom_get_tx_gain_index(ah, chan, - pRawDatasetOpenLoop, - pCalBChans, numPiers, - &txPower); + pRawDatasetOpenLoop, + pCalBChans, numPiers, + &txPower); ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); } else { pRawDataset = (struct cal_data_per_freq_ar9287 *) pEepData->calPierData2G[i]; - ath9k_hw_get_AR9287_gain_boundaries_pdadcs( - ah, chan, pRawDataset, - pCalBChans, numPiers, - pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, - pdadcValues, numXpdGain); + + ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan, + pRawDataset, + pCalBChans, numPiers, + pdGainOverlap_t2, + &tMinCalPower, + gainBoundaries, + pdadcValues, + numXpdGain); } if (i == 0) { - if (!ath9k_hw_AR9287_get_eeprom( - ah, EEP_OL_PWRCTRL)) { - REG_WRITE(ah, AR_PHY_TPCRG5 + - regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM(gainBoundaries[0], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) - | SM(gainBoundaries[1], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) - | SM(gainBoundaries[2], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) - | SM(gainBoundaries[3], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + if (!ath9k_hw_ar9287_get_eeprom(ah, + EEP_OL_PWRCTRL)) { + + regval = SM(pdGainOverlap_t2, + AR_PHY_TPCRG5_PD_GAIN_OVERLAP) + | SM(gainBoundaries[0], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) + | SM(gainBoundaries[1], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) + | SM(gainBoundaries[2], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) + | SM(gainBoundaries[3], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4); + + REG_WRITE(ah, + AR_PHY_TPCRG5 + regChainOffset, + regval); } } if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != - pEepData->baseEepHeader.pwrTableOffset) { - diff = (u16) - (pEepData->baseEepHeader.pwrTableOffset - - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); + pEepData->baseEepHeader.pwrTableOffset) { + diff = (u16)(pEepData->baseEepHeader.pwrTableOffset - + (int32_t)AR9287_PWR_TABLE_OFFSET_DB); diff *= 2; - for (j = 0; - j < ((u16)AR9287_NUM_PDADC_VALUES-diff); - j++) + for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++) pdadcValues[j] = pdadcValues[j+diff]; for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); j < AR9287_NUM_PDADC_VALUES; j++) pdadcValues[j] = - pdadcValues[ - AR9287_NUM_PDADC_VALUES-diff]; + pdadcValues[AR9287_NUM_PDADC_VALUES-diff]; } - if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { - regOffset = AR_PHY_BASE + (672 << 2) + - regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4*j + 0] - & 0xFF) << 0) | - ((pdadcValues[4*j + 1] - & 0xFF) << 8) | - ((pdadcValues[4*j + 2] - & 0xFF) << 16) | - ((pdadcValues[4*j + 3] - & 0xFF) << 24) ; - REG_WRITE(ah, regOffset, reg32); + if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { + regOffset = AR_PHY_BASE + + (672 << 2) + regChainOffset; - ath_print(common, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x " - "%8.8x\n", - i, regChainOffset, regOffset, - reg32); - - ath_print(common, ATH_DBG_EEPROM, - "PDADC: Chain %d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, - pdadcValues[4 * j + 1], - 4 * j + 2, - pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) + | ((pdadcValues[4*j + 1] & 0xFF) << 8) + | ((pdadcValues[4*j + 2] & 0xFF) << 16) + | ((pdadcValues[4*j + 3] & 0xFF) << 24); + REG_WRITE(ah, regOffset, reg32); regOffset += 4; } } @@ -598,30 +592,45 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, *pTxPowerIndexOffset = 0; } -static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, - u16 AntennaReduction, u16 twiceMaxRegulatoryPower, - u16 powerLimit) +static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, + struct ath9k_channel *chan, + int16_t *ratesArray, + u16 cfgCtl, + u16 AntennaReduction, + u16 twiceMaxRegulatoryPower, + u16 powerLimit) { +#define CMP_CTL \ + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ + pEepData->ctlIndex[i]) + +#define CMP_NO_CTL \ + (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) + #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; int i; - int16_t twiceLargestAntenna; + int16_t twiceLargestAntenna; struct cal_ctl_data_ar9287 *rep; struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, targetPowerCck = {0, {0, 0, 0, 0} }; struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, targetPowerCckExt = {0, {0, 0, 0, 0} }; - struct cal_target_power_ht targetPowerHt20, + 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 ctlModesFor11g[] = {CTL_11B, + CTL_11G, + CTL_2GHT20, + CTL_11B_EXT, + CTL_11G_EXT, + CTL_2GHT40}; u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; struct chan_centers centers; int tx_chainmask; @@ -631,19 +640,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, ath9k_hw_get_channel_centers(ah, chan, ¢ers); + /* Compute TxPower reduction due to Antenna Gain */ twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], pEepData->modalHeader.antennaGainCh[1]); + twiceLargestAntenna = (int16_t)min((AntennaReduction) - + twiceLargestAntenna, 0); - twiceLargestAntenna = (int16_t)min((AntennaReduction) - - twiceLargestAntenna, 0); - + /* + * scaledPower is the minimum of the user input power level + * and the regulatory allowed power level. + */ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; + if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) maxRegAllowedPower -= (tpScaleReductionTable[(regulatory->tp_scale)] * 2); scaledPower = min(powerLimit, maxRegAllowedPower); + /* + * Reduce scaled Power by number of chains active + * to get the per chain tx power level. + */ switch (ar5416_get_ntxchains(tx_chainmask)) { case 1: break; @@ -656,9 +674,14 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, } scaledPower = max((u16)0, scaledPower); + /* + * Get TX power from EEPROM. + */ if (IS_CHAN_2GHZ(chan)) { + /* CTL_11B, CTL_11G, CTL_2GHT20 */ numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; + pCtlMode = ctlModesFor11g; ath9k_hw_get_legacy_target_powers(ah, chan, @@ -675,6 +698,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, &targetPowerHt20, 8, false); if (IS_CHAN_HT40(chan)) { + /* All 2G CTLs */ numCtlModes = ARRAY_SIZE(ctlModesFor11g); ath9k_hw_get_target_powers(ah, chan, pEepData->calTargetPower2GHT40, @@ -692,8 +716,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, } for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); + bool isHt40CtlMode = + (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false; + if (isHt40CtlMode) freq = centers.synth_center; else if (pCtlMode[ctlMode] & EXT_ADDITIVE) @@ -701,31 +726,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, else freq = centers.ctl_center; - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - + /* Walk through the CTL indices stored in EEPROM */ for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - pEepData->ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((pEepData->ctlIndex[i] & - CTL_MODE_M) | SD_NO_CTL))) { + struct cal_ctl_edges *pRdEdgesPower; + /* + * Compare test group from regulatory channel list + * with test mode from pCtlMode list + */ + if (CMP_CTL || CMP_NO_CTL) { rep = &(pEepData->ctlData[i]); - twiceMinEdgePower = ath9k_hw_get_max_edge_power( - freq, - rep->ctlEdges[ar5416_get_ntxchains( - tx_chainmask) - 1], - IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) - twiceMaxEdgePower = min( - twiceMaxEdgePower, - twiceMinEdgePower); - else { + pRdEdgesPower = + rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1]; + + twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, + pRdEdgesPower, + IS_CHAN_2GHZ(chan), + AR5416_NUM_BAND_EDGES); + + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + twiceMaxEdgePower = min(twiceMaxEdgePower, + twiceMinEdgePower); + } else { twiceMaxEdgePower = twiceMinEdgePower; break; } @@ -734,55 +756,48 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); + /* Apply ctl mode to correct target power set */ switch (pCtlMode[ctlMode]) { case CTL_11B: - for (i = 0; - i < ARRAY_SIZE(targetPowerCck.tPow2x); - i++) { - targetPowerCck.tPow2x[i] = (u8)min( - (u16)targetPowerCck.tPow2x[i], - minCtlPower); + for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = + (u8)min((u16)targetPowerCck.tPow2x[i], + minCtlPower); } break; case CTL_11A: case CTL_11G: - for (i = 0; - i < ARRAY_SIZE(targetPowerOfdm.tPow2x); - i++) { - targetPowerOfdm.tPow2x[i] = (u8)min( - (u16)targetPowerOfdm.tPow2x[i], - minCtlPower); + for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = + (u8)min((u16)targetPowerOfdm.tPow2x[i], + minCtlPower); } break; case CTL_5GHT20: case CTL_2GHT20: - for (i = 0; - i < ARRAY_SIZE(targetPowerHt20.tPow2x); - i++) { - targetPowerHt20.tPow2x[i] = (u8)min( - (u16)targetPowerHt20.tPow2x[i], - minCtlPower); + for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = + (u8)min((u16)targetPowerHt20.tPow2x[i], + minCtlPower); } break; case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = (u8)min( - (u16)targetPowerCckExt.tPow2x[0], - minCtlPower); + targetPowerCckExt.tPow2x[0] = + (u8)min((u16)targetPowerCckExt.tPow2x[0], + minCtlPower); break; case CTL_11A_EXT: case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = (u8)min( - (u16)targetPowerOfdmExt.tPow2x[0], - minCtlPower); + targetPowerOfdmExt.tPow2x[0] = + (u8)min((u16)targetPowerOfdmExt.tPow2x[0], + minCtlPower); break; case CTL_5GHT40: case CTL_2GHT40: - for (i = 0; - i < ARRAY_SIZE(targetPowerHt40.tPow2x); - i++) { - targetPowerHt40.tPow2x[i] = (u8)min( - (u16)targetPowerHt40.tPow2x[i], - minCtlPower); + for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = + (u8)min((u16)targetPowerHt40.tPow2x[i], + minCtlPower); } break; default: @@ -790,12 +805,13 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, } } + /* Now set the rates array */ + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = - ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; + ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; @@ -807,12 +823,12 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, if (IS_CHAN_2GHZ(chan)) { ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = - targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = - targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = - targetPowerCck.tPow2x[3]; + ratesArray[rate2s] = + ratesArray[rate2l] = targetPowerCck.tPow2x[1]; + ratesArray[rate5_5s] = + ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; + ratesArray[rate11s] = + ratesArray[rate11l] = targetPowerCck.tPow2x[3]; } if (IS_CHAN_HT40(chan)) { for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) @@ -821,28 +837,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; + if (IS_CHAN_2GHZ(chan)) ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; } +#undef CMP_CTL +#undef CMP_NO_CTL #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN } -static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, +static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, u8 powerLimit) { -#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 -#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 - struct ath_common *common = ath9k_hw_common(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; + int16_t txPowerIndexOffset = 0; u8 ht40PowerIncForPdadc = 2; int i; @@ -852,13 +868,13 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, AR9287_EEP_MINOR_VER_2) ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, + ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, &ratesArray[0], cfgCtl, twiceAntennaReduction, twiceMaxRegulatoryPower, powerLimit); - ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); + ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); @@ -871,6 +887,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; } + /* OFDM power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) | ATH9K_POW_SM(ratesArray[rate12mb], 16) @@ -883,6 +900,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ATH9K_POW_SM(ratesArray[rate24mb], 0)); + /* CCK power per rate */ if (IS_CHAN_2GHZ(chan)) { REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, ATH9K_POW_SM(ratesArray[rate2s], 24) @@ -896,6 +914,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); } + /* HT20 power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) @@ -908,8 +927,9 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); + /* HT40 power per rate */ if (IS_CHAN_HT40(chan)) { - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { + if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, ATH9K_POW_SM(ratesArray[rateHt40_3], 24) | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) @@ -943,6 +963,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, ht40PowerIncForPdadc, 0)); } + /* Dup/Ext power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ATH9K_POW_SM(ratesArray[rateExtCck], 16) @@ -960,37 +981,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, ratesArray[i] + AR9287_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(common, ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } } -static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, +static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, struct ath9k_channel *chan) { } -static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, +static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, struct ath9k_channel *chan) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &eep->modalHeader; u16 antWrites[AR9287_ANT_16S]; - u32 regChainOffset; + u32 regChainOffset, regval; u8 txRxAttenLocal; int i, j, offset_num; @@ -1077,42 +1081,37 @@ static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, - AR9287_AN_RF2G3_DB1_S, pModal->db1); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, - AR9287_AN_RF2G3_DB2_S, pModal->db2); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_CCK, - AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_PSK, - AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_QAM, - AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_PAL_OFF, - AR9287_AN_RF2G3_OB_PAL_OFF_S, - pModal->ob_pal_off); - - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, - pModal->db1); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, - AR9287_AN_RF2G3_DB2_S, pModal->db2); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_CCK, - AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_PSK, - AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_QAM, - AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_PAL_OFF, - AR9287_AN_RF2G3_OB_PAL_OFF_S, - pModal->ob_pal_off); + regval = REG_READ(ah, AR9287_AN_RF2G3_CH0); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval); + + regval = REG_READ(ah, AR9287_AN_RF2G3_CH1); + regval &= ~(AR9287_AN_RF2G3_DB1 | + AR9287_AN_RF2G3_DB2 | + AR9287_AN_RF2G3_OB_CCK | + AR9287_AN_RF2G3_OB_PSK | + AR9287_AN_RF2G3_OB_QAM | + AR9287_AN_RF2G3_OB_PAL_OFF); + regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | + SM(pModal->db2, AR9287_AN_RF2G3_DB2) | + SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | + SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | + SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | + SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); + + ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval); REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); @@ -1125,13 +1124,13 @@ static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, pModal->xpaBiasLvl); } -static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, +static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, enum ieee80211_band freq_band) { return 1; } -static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, +static u16 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah, struct ath9k_channel *chan) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; @@ -1140,11 +1139,12 @@ static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, return pModal->antCtrlCommon & 0xFFFF; } -static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, +static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { #define EEP_MAP9287_SPURCHAN \ (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) + struct ath_common *common = ath9k_hw_common(ah); u16 spur_val = AR_NO_SPUR; @@ -1171,15 +1171,15 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, } const struct eeprom_ops eep_ar9287_ops = { - .check_eeprom = ath9k_hw_AR9287_check_eeprom, - .get_eeprom = ath9k_hw_AR9287_get_eeprom, - .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, - .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_AR9287_set_board_values, - .set_addac = ath9k_hw_AR9287_set_addac, - .set_txpower = ath9k_hw_AR9287_set_txpower, - .get_spur_channel = ath9k_hw_AR9287_get_spur_channel + .check_eeprom = ath9k_hw_ar9287_check_eeprom, + .get_eeprom = ath9k_hw_ar9287_get_eeprom, + .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, + .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, + .get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config, + .get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg, + .set_board_values = ath9k_hw_ar9287_set_board_values, + .set_addac = ath9k_hw_ar9287_set_addac, + .set_txpower = ath9k_hw_ar9287_set_txpower, + .get_spur_channel = ath9k_hw_ar9287_get_spur_channel }; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 7e1ed78d0e64..77b1433312cc 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -617,6 +617,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, int16_t minDelta = 0; struct chan_centers centers; + memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); ath9k_hw_get_channel_centers(ah, chan, ¢ers); for (numPiers = 0; numPiers < availPiers; numPiers++) { diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 77b359162d6c..5f3ea7091ae0 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -16,12 +16,10 @@ #include "htc.h" -#define ATH9K_FW_USB_DEV(devid, fw) \ - { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw } - static struct usb_device_id ath9k_hif_usb_ids[] = { - ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), - ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"), + { USB_DEVICE(0x0cf3, 0x9271) }, + { USB_DEVICE(0x0cf3, 0x1006) }, + { USB_DEVICE(0x0cf3, 0x7010) }, { }, }; @@ -756,6 +754,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) size_t len = hif_dev->firmware->size; u32 addr = AR9271_FIRMWARE; u8 *buf = kzalloc(4096, GFP_KERNEL); + u32 firm_offset; if (!buf) return -ENOMEM; @@ -779,32 +778,37 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) } kfree(buf); + if (hif_dev->device_id == 0x7010) + firm_offset = AR7010_FIRMWARE_TEXT; + else + firm_offset = AR9271_FIRMWARE_TEXT; + /* * Issue FW download complete command to firmware. */ err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), FIRMWARE_DOWNLOAD_COMP, 0x40 | USB_DIR_OUT, - AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ); + firm_offset >> 8, 0, NULL, 0, HZ); if (err) return -EIO; dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", - "ar9271.fw", (unsigned long) hif_dev->firmware->size); + hif_dev->fw_name, (unsigned long) hif_dev->firmware->size); return 0; } -static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, - const char *fw_name) +static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) { int ret; /* Request firmware */ - ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev); + ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, + &hif_dev->udev->dev); if (ret) { dev_err(&hif_dev->udev->dev, - "ath9k_htc: Firmware - %s not found\n", fw_name); + "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name); goto err_fw_req; } @@ -820,7 +824,8 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, ret = ath9k_hif_usb_download_fw(hif_dev); if (ret) { dev_err(&hif_dev->udev->dev, - "ath9k_htc: Firmware - %s download failed\n", fw_name); + "ath9k_htc: Firmware - %s download failed\n", + hif_dev->fw_name); goto err_fw_download; } @@ -847,7 +852,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, { struct usb_device *udev = interface_to_usbdev(interface); struct hif_device_usb *hif_dev; - const char *fw_name = (const char *) id->driver_info; int ret = 0; hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); @@ -872,7 +876,29 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, goto err_htc_hw_alloc; } - ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); + /* Find out which firmware to load */ + + switch(hif_dev->device_id) { + case 0x9271: + case 0x1006: + hif_dev->fw_name = "ar9271.fw"; + break; + case 0x7010: + if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) + hif_dev->fw_name = "ar7010_1_1.fw"; + else + hif_dev->fw_name = "ar7010.fw"; + break; + default: + break; + } + + if (!hif_dev->fw_name) { + dev_err(&udev->dev, "Can't determine firmware !\n"); + goto err_htc_hw_alloc; + } + + ret = ath9k_hif_usb_dev_init(hif_dev); if (ret) { ret = -EINVAL; goto err_hif_init_usb; @@ -907,12 +933,10 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) void *buf; int ret; - buf = kmalloc(4, GFP_KERNEL); + buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL); if (!buf) return; - memcpy(buf, &reboot_cmd, 4); - ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), buf, 4, NULL, HZ); if (ret) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 0aca49b6fcb6..2daf97b11c08 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -19,6 +19,7 @@ #define AR9271_FIRMWARE 0x501000 #define AR9271_FIRMWARE_TEXT 0x903000 +#define AR7010_FIRMWARE_TEXT 0x906000 #define FIRMWARE_DOWNLOAD 0x30 #define FIRMWARE_DOWNLOAD_COMP 0x31 @@ -90,6 +91,7 @@ struct hif_device_usb { struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; struct sk_buff *remain_skb; + const char *fw_name; int rx_remain_len; int rx_pkt_len; int rx_transfer_len; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c251603ab032..58f52a1dc7ea 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -223,15 +223,6 @@ struct ath9k_htc_sta { enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; }; -struct ath9k_htc_aggr_work { - u16 tid; - u8 sta_addr[ETH_ALEN]; - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - enum ieee80211_ampdu_mlme_action action; - struct mutex mutex; -}; - #define ATH9K_HTC_RXBUF 256 #define HTC_RX_FRAME_HEADER_SIZE 40 @@ -257,12 +248,15 @@ struct ath9k_htc_tx_ctl { #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) +#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) + struct ath_tx_stats { u32 buf_queued; u32 buf_completed; u32 skb_queued; u32 skb_completed; u32 skb_dropped; + u32 queue_stats[WME_NUM_AC]; }; struct ath_rx_stats { @@ -286,6 +280,8 @@ struct ath9k_debug { #define TX_STAT_INC(c) do { } while (0) #define RX_STAT_INC(c) do { } while (0) +#define TX_QSTAT_INC(c) do { } while (0) + #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #define ATH_LED_PIN_DEF 1 @@ -326,11 +322,10 @@ struct htc_beacon_config { #define OP_LED_ON BIT(4) #define OP_PREAMBLE_SHORT BIT(5) #define OP_PROTECT_ENABLE BIT(6) -#define OP_TXAGGR BIT(7) -#define OP_ASSOCIATED BIT(8) -#define OP_ENABLE_BEACON BIT(9) -#define OP_LED_DEINIT BIT(10) -#define OP_UNPLUGGED BIT(11) +#define OP_ASSOCIATED BIT(7) +#define OP_ENABLE_BEACON BIT(8) +#define OP_LED_DEINIT BIT(9) +#define OP_UNPLUGGED BIT(10) struct ath9k_htc_priv { struct device *dev; @@ -371,8 +366,6 @@ struct ath9k_htc_priv { struct ath9k_htc_rx rx; struct tasklet_struct tx_tasklet; struct sk_buff_head tx_queue; - struct ath9k_htc_aggr_work aggr_work; - struct delayed_work ath9k_aggr_work; struct delayed_work ath9k_ani_work; struct work_struct ps_work; @@ -390,13 +383,14 @@ struct ath9k_htc_priv { int led_off_duration; int led_on_cnt; int led_off_cnt; - int hwq_map[ATH9K_WME_AC_VO+1]; + + int beaconq; + int cabq; + int hwq_map[WME_NUM_AC]; #ifdef CONFIG_ATH9K_HTC_DEBUGFS struct ath9k_debug debug; #endif - struct ath9k_htc_target_rate tgt_rate; - struct mutex mutex; }; @@ -405,6 +399,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) common->bus_ops->read_cachesize(common, csz); } +void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); @@ -424,8 +419,8 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv); void ath9k_tx_tasklet(unsigned long data); int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); -bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, - enum ath9k_tx_queue_subtype qtype); +bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); +int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); int get_hw_qnum(u16 queue, int *hwq_map); int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index c10c7d002eb7..bd1506e69105 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -222,6 +222,29 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) spin_unlock_bh(&priv->beacon_lock); } +/* Currently, only for IBSS */ +void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + struct ath9k_tx_queue_info qi, qi_be; + int qnum = priv->hwq_map[WME_AC_BE]; + + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); + + ath9k_hw_get_txq_props(ah, 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; + + if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Unable to update beacon queue %u!\n", qnum); + } else { + ath9k_hw_resettxqueue(ah, priv->beaconq); + } +} void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index dc015077a8d9..a63ae88abf3e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -34,6 +34,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); .max_power = 20, \ } +#define CHAN5G(_freq, _idx) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 20, \ +} + static struct ieee80211_channel ath9k_2ghz_channels[] = { CHAN2G(2412, 0), /* Channel 1 */ CHAN2G(2417, 1), /* Channel 2 */ @@ -51,6 +58,37 @@ static struct ieee80211_channel ath9k_2ghz_channels[] = { CHAN2G(2484, 13), /* Channel 14 */ }; +static struct ieee80211_channel ath9k_5ghz_channels[] = { + /* _We_ call this UNII 1 */ + CHAN5G(5180, 14), /* Channel 36 */ + CHAN5G(5200, 15), /* Channel 40 */ + CHAN5G(5220, 16), /* Channel 44 */ + CHAN5G(5240, 17), /* Channel 48 */ + /* _We_ call this UNII 2 */ + CHAN5G(5260, 18), /* Channel 52 */ + CHAN5G(5280, 19), /* Channel 56 */ + CHAN5G(5300, 20), /* Channel 60 */ + CHAN5G(5320, 21), /* Channel 64 */ + /* _We_ call this "Middle band" */ + CHAN5G(5500, 22), /* Channel 100 */ + CHAN5G(5520, 23), /* Channel 104 */ + CHAN5G(5540, 24), /* Channel 108 */ + CHAN5G(5560, 25), /* Channel 112 */ + CHAN5G(5580, 26), /* Channel 116 */ + CHAN5G(5600, 27), /* Channel 120 */ + CHAN5G(5620, 28), /* Channel 124 */ + CHAN5G(5640, 29), /* Channel 128 */ + CHAN5G(5660, 30), /* Channel 132 */ + CHAN5G(5680, 31), /* Channel 136 */ + CHAN5G(5700, 32), /* Channel 140 */ + /* _We_ call this UNII 3 */ + CHAN5G(5745, 33), /* Channel 149 */ + CHAN5G(5765, 34), /* Channel 153 */ + CHAN5G(5785, 35), /* Channel 157 */ + CHAN5G(5805, 36), /* Channel 161 */ + CHAN5G(5825, 37), /* Channel 165 */ +}; + /* Atheros hardware rate code addition for short premble */ #define SHPCHECK(__hw_rate, __flags) \ ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) @@ -141,7 +179,7 @@ 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) +static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) { int ret; @@ -199,10 +237,33 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) if (ret) goto err; + /* + * Setup required credits before initializing HTC. + * This is a bit hacky, but, since queuing is done in + * the HIF layer, shouldn't matter much. + */ + + switch(devid) { + case 0x9271: + case 0x1006: + priv->htc->credits = 33; + break; + case 0x7010: + priv->htc->credits = 45; + break; + default: + dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n", + devid); + goto err; + } + ret = htc_init(priv->htc); if (ret) goto err; + dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n", + priv->htc->credits); + return 0; err: @@ -398,17 +459,43 @@ static const struct ath_bus_ops ath9k_usb_bus_ops = { static void setup_ht_cap(struct ath9k_htc_priv *priv, struct ieee80211_sta_ht_cap *ht_info) { + struct ath_common *common = ath9k_hw_common(priv->ah); + u8 tx_streams, rx_streams; + int i; + ht_info->ht_supported = true; ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_DSSSCCK40; + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) + ht_info->cap |= IEEE80211_HT_CAP_SGI_20; + + ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - ht_info->mcs.rx_mask[0] = 0xff; + + /* ath9k_htc supports only 1 or 2 stream devices */ + tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); + rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); + + ath_print(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); + + if (tx_streams != rx_streams) { + ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; + ht_info->mcs.tx_params |= ((tx_streams - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); + } + + for (i = 0; i < rx_streams; i++) + ht_info->mcs.rx_mask[i] = 0xff; + ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; } @@ -420,23 +507,37 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) priv->hwq_map[i] = -1; - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { + priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); + if (priv->beaconq == -1) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup BEACON xmit queue\n"); + goto err; + } + + priv->cabq = ath9k_htc_cabq_setup(priv); + if (priv->cabq == -1) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup CAB xmit queue\n"); + goto err; + } + + if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BE traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BK traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VI traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VO traffic\n"); goto err; @@ -468,36 +569,6 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) */ for (i = 0; i < common->keymax; i++) ath9k_hw_keyreset(priv->ah, (u16) i); - - if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); - } - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - common->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, - 1, 1, NULL); } static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) @@ -512,6 +583,17 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = ARRAY_SIZE(ath9k_legacy_rates); } + + if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { + priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; + priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; + priv->sbands[IEEE80211_BAND_5GHZ].n_channels = + ARRAY_SIZE(ath9k_5ghz_channels); + priv->sbands[IEEE80211_BAND_5GHZ].bitrates = + ath9k_legacy_rates + 4; + priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates) - 4; + } } static void ath9k_init_misc(struct ath9k_htc_priv *priv) @@ -524,7 +606,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); - priv->op_flags |= OP_TXAGGR; priv->ah->opmode = NL80211_IFTYPE_STATION; } @@ -556,14 +637,12 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) spin_lock_init(&priv->beacon_lock); spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); - mutex_init(&priv->aggr_work.mutex); mutex_init(&priv->htc_pm_lock); tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, (unsigned long)priv); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, (unsigned long)priv); tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); - INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); INIT_WORK(&priv->ps_work, ath9k_ps_work); @@ -643,11 +722,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->sbands[IEEE80211_BAND_2GHZ]; + if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &priv->sbands[IEEE80211_BAND_5GHZ]; if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) setup_ht_cap(priv, &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); + if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) + setup_ht_cap(priv, + &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); } SET_IEEE80211_PERM_ADDR(hw, common->macaddr); @@ -747,7 +832,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, goto err_free; } - ret = ath9k_init_htc_services(priv); + ret = ath9k_init_htc_services(priv, devid); if (ret) goto err_init; @@ -790,7 +875,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle) if (ret) return ret; - ret = ath9k_init_htc_services(htc_handle->drv_priv); + ret = ath9k_init_htc_services(htc_handle->drv_priv, + htc_handle->drv_priv->ah->hw_version.devid); 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 9d371c18eb41..05445d8a9818 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -27,13 +27,11 @@ static struct dentry *ath9k_debugfs_root; static void ath_update_txpow(struct ath9k_htc_priv *priv) { struct ath_hw *ah = priv->ah; - u32 txpow; if (priv->curtxpow != priv->txpowlimit) { ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); /* read back in case value is clamped */ - ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); - priv->curtxpow = txpow; + priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } } @@ -325,142 +323,128 @@ static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) tcap.flags_ext = 0x80601000; tcap.ampdu_limit = 0xffff0000; tcap.ampdu_subframes = 20; - tcap.tx_chainmask_legacy = 1; + tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; tcap.protmode = 1; - tcap.tx_chainmask = 1; + tcap.tx_chainmask = priv->ah->caps.tx_chainmask; WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); return ret; } -static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, + struct ieee80211_sta *sta, + struct ath9k_htc_target_rate *trate) { - struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; struct ieee80211_supported_band *sband; - struct ath9k_htc_target_rate trate; u32 caps = 0; - u8 cmd_rsp; - int i, j, ret; - - memset(&trate, 0, sizeof(trate)); + int i, j; - /* Only 2GHz is supported */ - sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band]; for (i = 0, j = 0; i < sband->n_bitrates; i++) { if (sta->supp_rates[sband->band] & BIT(i)) { - priv->tgt_rate.rates.legacy_rates.rs_rates[j] + trate->rates.legacy_rates.rs_rates[j] = (sband->bitrates[i].bitrate * 2) / 10; j++; } } - priv->tgt_rate.rates.legacy_rates.rs_nrates = j; + trate->rates.legacy_rates.rs_nrates = j; if (sta->ht_cap.ht_supported) { for (i = 0, j = 0; i < 77; i++) { if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i; + trate->rates.ht_rates.rs_rates[j++] = i; if (j == ATH_HTC_RATE_MAX) break; } - priv->tgt_rate.rates.ht_rates.rs_nrates = j; + trate->rates.ht_rates.rs_nrates = j; caps = WLAN_RC_HT_FLAG; + if (sta->ht_cap.mcs.rx_mask[1]) + caps |= WLAN_RC_DS_FLAG; if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) caps |= WLAN_RC_40_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + if (conf_is_ht40(&priv->hw->conf) && + (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) + caps |= WLAN_RC_SGI_FLAG; + else if (conf_is_ht20(&priv->hw->conf) && + (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)) caps |= WLAN_RC_SGI_FLAG; - } - priv->tgt_rate.sta_index = ista->index; - priv->tgt_rate.isnew = 1; - trate = priv->tgt_rate; - priv->tgt_rate.capflags = cpu_to_be32(caps); - trate.capflags = cpu_to_be32(caps); + trate->sta_index = ista->index; + trate->isnew = 1; + trate->capflags = cpu_to_be32(caps); +} + +static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv, + struct ath9k_htc_target_rate *trate) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + int ret; + u8 cmd_rsp; - WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); + WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); if (ret) { ath_print(common, ATH_DBG_FATAL, "Unable to initialize Rate information on target\n"); - return ret; } - ath_print(common, ATH_DBG_CONFIG, - "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps); - return 0; + return ret; } -static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40) +static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv, + struct ieee80211_sta *sta) { - struct ath9k_htc_priv *priv = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (!conf_is_ht(conf)) - return false; - - if (!(priv->op_flags & OP_ASSOCIATED) || - (priv->op_flags & OP_SCANNING)) - return false; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_rate trate; + int ret; - if (conf_is_ht40(conf)) { - if (priv->ah->curchan->chanmode & - (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) { - return false; - } else { - *cw40 = true; - return true; - } - } else { /* ht20 */ - if (priv->ah->curchan->chanmode & CHANNEL_HT20) - return false; - else - return true; - } + memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); + ath9k_htc_setup_rate(priv, sta, &trate); + ret = ath9k_htc_send_rate_cmd(priv, &trate); + if (!ret) + ath_print(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); } -static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) +static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) { - struct ath9k_htc_target_rate trate; struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_rate trate; + struct ieee80211_sta *sta; int ret; - u32 caps = be32_to_cpu(priv->tgt_rate.capflags); - u8 cmd_rsp; - - memset(&trate, 0, sizeof(trate)); - - trate = priv->tgt_rate; - if (is_cw40) - caps |= WLAN_RC_40_FLAG; - else - caps &= ~WLAN_RC_40_FLAG; - - priv->tgt_rate.capflags = cpu_to_be32(caps); - trate.capflags = cpu_to_be32(caps); + memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); - WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); - if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to update Rate information on target\n"); + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); return; } + ath9k_htc_setup_rate(priv, sta, &trate); + rcu_read_unlock(); - ath_print(common, ATH_DBG_CONFIG, "Rate control updated with " - "caps:0x%x on target\n", priv->tgt_rate.capflags); + ret = ath9k_htc_send_rate_cmd(priv, &trate); + if (!ret) + ath_print(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + bss_conf->bssid, be32_to_cpu(trate.capflags)); } -static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - u8 *sta_addr, u8 tid, bool oper) +int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_ampdu_mlme_action action, u16 tid) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_aggr aggr; - struct ieee80211_sta *sta = NULL; struct ath9k_htc_sta *ista; int ret = 0; u8 cmd_rsp; @@ -469,72 +453,28 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, return -EINVAL; memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); - - rcu_read_lock(); - - /* Check if we are able to retrieve the station */ - sta = ieee80211_find_sta(vif, sta_addr); - if (!sta) { - rcu_read_unlock(); - return -EINVAL; - } - ista = (struct ath9k_htc_sta *) sta->drv_priv; - if (oper) - ista->tid_state[tid] = AGGR_START; - else - ista->tid_state[tid] = AGGR_STOP; - aggr.sta_index = ista->index; - - rcu_read_unlock(); - - aggr.tidno = tid; - aggr.aggr_enable = oper; + aggr.tidno = tid & 0xf; + aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false; WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); if (ret) ath_print(common, ATH_DBG_CONFIG, "Unable to %s TX aggregation for (%pM, %d)\n", - (oper) ? "start" : "stop", sta->addr, tid); + (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); else ath_print(common, ATH_DBG_CONFIG, - "%s aggregation for (%pM, %d)\n", - (oper) ? "Starting" : "Stopping", sta->addr, tid); - - return ret; -} + "%s TX aggregation for (%pM, %d)\n", + (aggr.aggr_enable) ? "Starting" : "Stopping", + sta->addr, tid); -void ath9k_htc_aggr_work(struct work_struct *work) -{ - int ret = 0; - struct ath9k_htc_priv *priv = - container_of(work, struct ath9k_htc_priv, - ath9k_aggr_work.work); - struct ath9k_htc_aggr_work *wk = &priv->aggr_work; - - mutex_lock(&wk->mutex); - - switch (wk->action) { - case IEEE80211_AMPDU_TX_START: - ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, - wk->tid, true); - if (!ret) - ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, - wk->tid); - break; - case IEEE80211_AMPDU_TX_STOP: - ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, - wk->tid, false); - ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); - break; - default: - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); - } + spin_lock_bh(&priv->tx_lock); + ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; + spin_unlock_bh(&priv->tx_lock); - mutex_unlock(&wk->mutex); + return ret; } /*********/ @@ -617,6 +557,19 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, "%20s : %10u\n", "SKBs dropped", priv->debug.tx_stats.skb_dropped); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BE queued", + priv->debug.tx_stats.queue_stats[WME_AC_BE]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BK queued", + priv->debug.tx_stats.queue_stats[WME_AC_BK]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VI queued", + priv->debug.tx_stats.queue_stats[WME_AC_VI]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VO queued", + priv->debug.tx_stats.queue_stats[WME_AC_VO]); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1054,6 +1007,95 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) wiphy_rfkill_start_polling(priv->hw->wiphy); } +static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + int ret; + u8 cmd_rsp; + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); + + /* Reset the HW */ + ret = ath9k_hw_reset(ah, ah->curchan, false); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %d " + "(freq %u MHz)\n", ret, ah->curchan->channel); + } + + ath_update_txpow(priv); + + /* Start RX */ + WMI_CMD(WMI_START_RECV_CMDID); + ath9k_host_rx_init(priv); + + /* Start TX */ + htc_start(priv->htc); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + ieee80211_wake_queues(hw); + + WMI_CMD(WMI_ENABLE_INTR_CMDID); + + /* Enable LED */ + ath9k_hw_cfg_output(ah, ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); +} + +static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath_common *common = ath9k_hw_common(ah); + int ret; + u8 cmd_rsp; + + ath9k_htc_ps_wakeup(priv); + + /* Disable LED */ + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + + WMI_CMD(WMI_DISABLE_INTR_CMDID); + + /* Stop TX */ + ieee80211_stop_queues(hw); + htc_stop(priv->htc); + WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + skb_queue_purge(&priv->tx_queue); + + /* Stop RX */ + WMI_CMD(WMI_STOP_RECV_CMDID); + + /* + * The MIB counters have to be disabled here, + * since the target doesn't do it. + */ + ath9k_hw_disable_mib_counters(ah); + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); + + /* Reset the HW */ + ret = ath9k_hw_reset(ah, ah->curchan, false); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %d " + "(freq %u MHz)\n", ret, ah->curchan->channel); + } + + /* Disable the PHY */ + ath9k_hw_phy_disable(ah); + + ath9k_htc_ps_restore(priv); + ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); +} + /**********************/ /* mac80211 Callbacks */ /**********************/ @@ -1099,7 +1141,7 @@ fail_tx: return 0; } -static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) +static int ath9k_htc_start(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1111,10 +1153,16 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) __be16 htc_mode; u8 cmd_rsp; + mutex_lock(&priv->mutex); + ath_print(common, ATH_DBG_CONFIG, "Starting driver with initial channel: %d MHz\n", curchan->center_freq); + /* Ensure that HW is awake before flushing RX */ + ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); + WMI_CMD(WMI_FLUSH_RECV_CMDID); + /* setup initial channel */ init_channel = ath9k_cmn_get_curchannel(hw, ah); @@ -1127,6 +1175,7 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d " "(freq %u MHz)\n", ret, curchan->center_freq); + mutex_unlock(&priv->mutex); return ret; } @@ -1147,31 +1196,14 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) priv->tx_queues_stop = false; spin_unlock_bh(&priv->tx_lock); - if (led) { - /* Enable LED */ - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); - } - ieee80211_wake_queues(hw); - return ret; -} - -static int ath9k_htc_start(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - int ret = 0; - - mutex_lock(&priv->mutex); - ret = ath9k_htc_radio_enable(hw, false); mutex_unlock(&priv->mutex); return ret; } -static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) +static void ath9k_htc_stop(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; @@ -1179,21 +1211,17 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) int ret = 0; u8 cmd_rsp; + mutex_lock(&priv->mutex); + if (priv->op_flags & OP_INVALID) { ath_print(common, ATH_DBG_ANY, "Device not present\n"); + mutex_unlock(&priv->mutex); return; } - if (led) { - /* Disable LED */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - } - /* Cancel all the running timers/work .. */ cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); - cancel_delayed_work_sync(&priv->ath9k_aggr_work); cancel_delayed_work_sync(&priv->ath9k_led_blink_work); ath9k_led_stop_brightness(priv); @@ -1202,12 +1230,6 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - ath9k_hw_phy_disable(ah); - ath9k_hw_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); - ath9k_htc_ps_restore(priv); - ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); - skb_queue_purge(&priv->tx_queue); /* Remove monitor interface here */ @@ -1220,21 +1242,18 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) "Monitor interface removed\n"); } + ath9k_hw_phy_disable(ah); + ath9k_hw_disable(ah); + ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_htc_ps_restore(priv); + ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); + priv->op_flags |= OP_INVALID; ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); -} - -static void ath9k_htc_stop(struct ieee80211_hw *hw) -{ - struct ath9k_htc_priv *priv = hw->priv; - - mutex_lock(&priv->mutex); - ath9k_htc_radio_disable(hw, false); mutex_unlock(&priv->mutex); } - static int ath9k_htc_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1302,6 +1321,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, out: ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); + return ret; } @@ -1318,6 +1338,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); @@ -1328,6 +1349,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_remove_station(priv, vif, NULL); priv->vif = NULL; + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1343,30 +1365,27 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) bool enable_radio = false; bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); + mutex_lock(&priv->htc_pm_lock); if (!idle && priv->ps_idle) enable_radio = true; - priv->ps_idle = idle; + mutex_unlock(&priv->htc_pm_lock); if (enable_radio) { - ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); - ath9k_htc_radio_enable(hw, true); ath_print(common, ATH_DBG_CONFIG, "not-idle: enabling radio\n"); + ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); + ath9k_htc_radio_enable(hw); } } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; - bool is_cw40 = false; ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", curchan->center_freq); - if (check_rc_update(hw, &is_cw40)) - ath9k_htc_rc_update(priv, is_cw40); - ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { @@ -1399,14 +1418,21 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } } - if (priv->ps_idle) { + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + mutex_lock(&priv->htc_pm_lock); + if (!priv->ps_idle) { + mutex_unlock(&priv->htc_pm_lock); + goto out; + } + mutex_unlock(&priv->htc_pm_lock); + ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); - ath9k_htc_radio_disable(hw, true); + ath9k_htc_radio_disable(hw); } +out: mutex_unlock(&priv->mutex); - return 0; } @@ -1428,8 +1454,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, u32 rfilt; mutex_lock(&priv->mutex); - ath9k_htc_ps_wakeup(priv); + changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; @@ -1444,30 +1470,38 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } -static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) +static int ath9k_htc_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct ath9k_htc_priv *priv = hw->priv; int ret; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); + ret = ath9k_htc_add_station(priv, vif, sta); + if (!ret) + ath9k_htc_init_rate(priv, sta); + ath9k_htc_ps_restore(priv); + mutex_unlock(&priv->mutex); - switch (cmd) { - case STA_NOTIFY_ADD: - ret = ath9k_htc_add_station(priv, vif, sta); - if (!ret) - ath9k_htc_init_rate(priv, vif, sta); - break; - case STA_NOTIFY_REMOVE: - ath9k_htc_remove_station(priv, vif, sta); - break; - default: - break; - } + return ret; +} + +static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath9k_htc_priv *priv = hw->priv; + int ret; + mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); + ret = ath9k_htc_remove_station(priv, vif, sta); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); + + return ret; } static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, @@ -1482,6 +1516,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -1499,9 +1534,16 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, params->cw_max, params->txop); ret = ath_htc_txq_update(priv, qnum, &qi); - if (ret) + if (ret) { ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + goto out; + } + if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && + (qnum == priv->hwq_map[WME_AC_BE])) + ath9k_htc_beaconq_config(priv); +out: + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; @@ -1574,7 +1616,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ath_start_ani(priv); } else { priv->op_flags &= ~OP_ASSOCIATED; - cancel_work_sync(&priv->ps_work); cancel_delayed_work_sync(&priv->ath9k_ani_work); } } @@ -1631,6 +1672,9 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ath9k_hw_init_global_settings(ah); } + if (changed & BSS_CHANGED_HT) + ath9k_htc_update_rate(priv, vif, bss_conf); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1641,7 +1685,9 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) u64 tsf; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); tsf = ath9k_hw_gettsf64(priv->ah); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return tsf; @@ -1652,7 +1698,9 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) struct ath9k_htc_priv *priv = hw->priv; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); ath9k_hw_settsf64(priv->ah, tsf); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1660,11 +1708,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; - ath9k_htc_ps_wakeup(priv); mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); ath9k_hw_reset_tsf(priv->ah); - mutex_unlock(&priv->mutex); ath9k_htc_ps_restore(priv); + mutex_unlock(&priv->mutex); } static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, @@ -1674,8 +1722,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, u16 tid, u16 *ssn) { struct ath9k_htc_priv *priv = hw->priv; - struct ath9k_htc_aggr_work *work = &priv->aggr_work; struct ath9k_htc_sta *ista; + int ret = 0; switch (action) { case IEEE80211_AMPDU_RX_START: @@ -1683,26 +1731,26 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); + if (!ret) + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; case IEEE80211_AMPDU_TX_STOP: - if (!(priv->op_flags & OP_TXAGGR)) - return -ENOTSUPP; - memcpy(work->sta_addr, sta->addr, ETH_ALEN); - work->hw = hw; - work->vif = vif; - work->action = action; - work->tid = tid; - ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); + ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: ista = (struct ath9k_htc_sta *) sta->drv_priv; + spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = AGGR_OPERATIONAL; + spin_unlock_bh(&priv->tx_lock); break; default: ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, "Unknown AMPDU action\n"); } - return 0; + return ret; } static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) @@ -1722,8 +1770,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; - ath9k_htc_ps_wakeup(priv); mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); spin_lock_bh(&priv->beacon_lock); priv->op_flags &= ~OP_SCANNING; spin_unlock_bh(&priv->beacon_lock); @@ -1731,8 +1779,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) if (priv->op_flags & OP_ASSOCIATED) ath9k_htc_beacon_config(priv, priv->vif); ath_start_ani(priv); - mutex_unlock(&priv->mutex); ath9k_htc_ps_restore(priv); + mutex_unlock(&priv->mutex); } static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) @@ -1746,8 +1794,10 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, struct ath9k_htc_priv *priv = hw->priv; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); priv->ah->coverage_class = coverage_class; ath9k_hw_init_global_settings(priv->ah); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -1759,7 +1809,8 @@ struct ieee80211_ops ath9k_htc_ops = { .remove_interface = ath9k_htc_remove_interface, .config = ath9k_htc_config, .configure_filter = ath9k_htc_configure_filter, - .sta_notify = ath9k_htc_sta_notify, + .sta_add = ath9k_htc_sta_add, + .sta_remove = ath9k_htc_sta_remove, .conf_tx = ath9k_htc_conf_tx, .bss_info_changed = ath9k_htc_bss_info_changed, .set_key = ath9k_htc_set_key, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2571b443ac82..bd0b4acc3ece 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -20,19 +20,29 @@ /* TX */ /******/ +#define ATH9K_HTC_INIT_TXQ(subtype) do { \ + qi.tqi_subtype = subtype; \ + qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ + qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ + qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ + qi.tqi_physCompBuf = 0; \ + qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | \ + TXQ_FLAG_TXDESCINT_ENABLE; \ + } while (0) + int get_hw_qnum(u16 queue, int *hwq_map) { switch (queue) { case 0: - return hwq_map[ATH9K_WME_AC_VO]; + return hwq_map[WME_AC_VO]; case 1: - return hwq_map[ATH9K_WME_AC_VI]; + return hwq_map[WME_AC_VI]; case 2: - return hwq_map[ATH9K_WME_AC_BE]; + return hwq_map[WME_AC_BE]; case 3: - return hwq_map[ATH9K_WME_AC_BK]; + return hwq_map[WME_AC_BK]; default: - return hwq_map[ATH9K_WME_AC_BE]; + return hwq_map[WME_AC_BE]; } } @@ -71,7 +81,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) struct ath9k_htc_vif *avp; struct ath9k_htc_tx_ctl tx_ctl; enum htc_endpoint_id epid; - u16 qnum, hw_qnum; + u16 qnum; __le16 fc; u8 *tx_fhdr; u8 sta_idx; @@ -131,20 +141,23 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); qnum = skb_get_queue_mapping(skb); - hw_qnum = get_hw_qnum(qnum, priv->hwq_map); - switch (hw_qnum) { + switch (qnum) { case 0: - epid = priv->data_be_ep; + TX_QSTAT_INC(WME_AC_VO); + epid = priv->data_vo_ep; break; - case 2: + case 1: + TX_QSTAT_INC(WME_AC_VI); epid = priv->data_vi_ep; break; - case 3: - epid = priv->data_vo_ep; + case 2: + TX_QSTAT_INC(WME_AC_BE); + epid = priv->data_be_ep; break; - case 1: + case 3: default: + TX_QSTAT_INC(WME_AC_BK); epid = priv->data_bk_ep; break; } @@ -174,6 +187,19 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) return htc_send(priv->htc, skb, epid, &tx_ctl); } +static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, + struct ath9k_htc_sta *ista, u8 tid) +{ + bool ret = false; + + spin_lock_bh(&priv->tx_lock); + if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) + ret = true; + spin_unlock_bh(&priv->tx_lock); + + return ret; +} + void ath9k_tx_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; @@ -203,8 +229,7 @@ void ath9k_tx_tasklet(unsigned long data) /* Check if we need to start aggregation */ if (sta && conf_is_ht(&priv->hw->conf) && - (priv->op_flags & OP_TXAGGR) - && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { if (ieee80211_is_data_qos(fc)) { u8 *qc, tid; struct ath9k_htc_sta *ista; @@ -213,10 +238,11 @@ void ath9k_tx_tasklet(unsigned long data) tid = qc[0] & 0xf; ista = (struct ath9k_htc_sta *)sta->drv_priv; - if ((tid < ATH9K_HTC_MAX_TID) && - ista->tid_state[tid] == AGGR_STOP) { + if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { ieee80211_start_tx_ba_session(sta, tid); + spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = AGGR_PROGRESS; + spin_unlock_bh(&priv->tx_lock); } } } @@ -284,8 +310,7 @@ void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) } -bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, - enum ath9k_tx_queue_subtype subtype) +bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype) { struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); @@ -293,13 +318,7 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int qnum; memset(&qi, 0, sizeof(qi)); - - qi.tqi_subtype = subtype; - qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; - qi.tqi_physCompBuf = 0; - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE; + ATH9K_HTC_INIT_TXQ(subtype); qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); if (qnum == -1) @@ -317,6 +336,16 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, return true; } +int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv) +{ + struct ath9k_tx_queue_info qi; + + memset(&qi, 0, sizeof(qi)); + ATH9K_HTC_INIT_TXQ(0); + + return ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_CAB, &qi); +} + /******/ /* RX */ /******/ @@ -387,9 +416,6 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) /* configure operational mode */ ath9k_hw_setopmode(ah); - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, common->macaddr); - /* calculate and install multicast filter */ mfilt[0] = mfilt[1] = ~0; ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); @@ -399,7 +425,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv) { ath9k_hw_rxena(priv->ah); ath9k_htc_opmode_init(priv); - ath9k_hw_startpcureceive(priv->ah); + ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING)); priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 064397fd738e..705c0f342e1c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -89,7 +89,6 @@ static void htc_process_target_rdy(struct htc_target *target, struct htc_endpoint *endpoint; struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; - target->credits = be16_to_cpu(htc_ready_msg->credits); target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); endpoint = &target->endpoint[ENDPOINT0]; @@ -159,7 +158,7 @@ static int htc_config_pipe_credits(struct htc_target *target) cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); cp_msg->pipe_id = USB_WLAN_TX_PIPE; - cp_msg->credits = 28; + cp_msg->credits = target->credits; target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 624422a8169e..381da6c93b14 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -128,6 +128,17 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); } +static inline void ath9k_hw_procmibevent(struct ath_hw *ah) +{ + ath9k_hw_ops(ah)->ani_proc_mib_event(ah); +} + +static inline void ath9k_hw_ani_monitor(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + ath9k_hw_ops(ah)->ani_monitor(ah, chan); +} + /* Private hardware call ops */ /* PHY ops */ @@ -277,4 +288,9 @@ static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); } +static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) +{ + ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning); +} + #endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c33f17dbe6f1..62597f4ca319 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -23,11 +23,6 @@ #include "rc.h" #include "ar9003_mac.h" -#define ATH9K_CLOCK_RATE_CCK 22 -#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 -#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 -#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 - static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); MODULE_AUTHOR("Atheros Communications"); @@ -80,6 +75,15 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); } +static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) +{ + /* You will not have this callback if using the old ANI */ + if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) + return; + + ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); +} + /********************/ /* Helper Functions */ /********************/ @@ -371,13 +375,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.ofdm_trig_high = 500; ah->config.cck_trig_high = 200; ah->config.cck_trig_low = 100; - - /* - * For now ANI is disabled for AR9003, it is still - * being tested. - */ - if (!AR_SREV_9300_20_OR_LATER(ah)) - ah->config.enable_ani = 1; + ah->config.enable_ani = true; for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { ah->config.spurchans[i][0] = AR_NO_SPUR; @@ -392,12 +390,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.rx_intr_mitigation = true; /* - * Tx IQ Calibration (ah->config.tx_iq_calibration) is only - * used by AR9003, but it is showing reliability issues. - * It will take a while to fix so this is currently disabled. - */ - - /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) * _and_ if on non-uniprocessor systems (Multiprocessor/HT). * This means we use it for all AR5416 devices, and the few @@ -433,7 +425,9 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->ah_flags = AH_USE_EEPROM; ah->atim_window = 0; - ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; + ah->sta_id1_defaults = + AR_STA_ID1_CRPT_MIC_ENABLE | + AR_STA_ID1_MCAST_KSRCH; ah->beacon_interval = 100; ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->slottime = (u32) -1; @@ -571,6 +565,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) ah->ani_function = ATH9K_ANI_ALL; if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; + if (!AR_SREV_9300_20_OR_LATER(ah)) + ah->ani_function &= ~ATH9K_ANI_MRC_CCK; ath9k_hw_init_mode_regs(ah); @@ -627,6 +623,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ar9003_hw_set_nf_limits(ah); ath9k_init_nfcal_hist_buffer(ah); + ah->bb_watchdog_timeout_ms = 25; common->state = ATH_HW_INITIALIZED; @@ -1303,6 +1300,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9280_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); + if (!AR_SREV_9300_20_OR_LATER(ah)) + ar9002_hw_enable_async_fifo(ah); + r = ath9k_hw_process_ini(ah, chan); if (r) return r; @@ -1367,6 +1367,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_resettxqueue(ah, i); ath9k_hw_init_interrupt_masks(ah, ah->opmode); + ath9k_hw_ani_cache_ini_regs(ah); ath9k_hw_init_qos(ah); if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) @@ -1375,7 +1376,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_global_settings(ah); if (!AR_SREV_9300_20_OR_LATER(ah)) { - ar9002_hw_enable_async_fifo(ah); + ar9002_hw_update_async_fifo(ah); ar9002_hw_enable_wep_aggregation(ah); } @@ -1426,9 +1427,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); } } else { - /* Configure AR9271 target WLAN */ - if (AR_SREV_9271(ah)) - REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); + if (common->bus_ops->ath_bus_type == ATH_USB) { + /* Configure AR9271 target WLAN */ + if (AR_SREV_9271(ah)) + REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); + else + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); + } #ifdef __BIG_ENDIAN else REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); @@ -1441,6 +1446,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9300_20_OR_LATER(ah)) { ath9k_hw_loadnf(ah, curchan); ath9k_hw_start_nfcal(ah); + ar9003_hw_bb_watchdog_config(ah); } return 0; @@ -1489,6 +1495,7 @@ EXPORT_SYMBOL(ath9k_hw_keyreset); bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) { u32 macHi, macLo; + u32 unicast_flag = AR_KEYTABLE_VALID; if (entry >= ah->caps.keycache_size) { ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, @@ -1497,6 +1504,16 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) } if (mac != NULL) { + /* + * AR_KEYTABLE_VALID indicates that the address is a unicast + * address, which must match the transmitter address for + * decrypting frames. + * Not setting this bit allows the hardware to use the key + * for multicast frame decryption. + */ + if (mac[0] & 0x01) + unicast_flag = 0; + macHi = (mac[5] << 8) | mac[4]; macLo = (mac[3] << 24) | (mac[2] << 16) | @@ -1509,7 +1526,7 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) macLo = macHi = 0; } REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); return true; } @@ -2165,7 +2182,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; } #endif - if (AR_SREV_9271(ah)) + if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah)) pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; else pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; @@ -2220,6 +2237,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); + if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); if (AR_SREV_9280_20(ah) && @@ -2232,100 +2251,11 @@ 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; - return 0; -} - -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - switch (type) { - case ATH9K_CAP_CIPHER: - switch (capability) { - case ATH9K_CIPHER_AES_CCM: - case ATH9K_CIPHER_AES_OCB: - case ATH9K_CIPHER_TKIP: - case ATH9K_CIPHER_WEP: - case ATH9K_CIPHER_MIC: - case ATH9K_CIPHER_CLR: - return true; - default: - return false; - } - case ATH9K_CAP_TKIP_MIC: - switch (capability) { - case 0: - return true; - case 1: - return (ah->sta_id1_defaults & - AR_STA_ID1_CRPT_MIC_ENABLE) ? true : - false; - } - case ATH9K_CAP_TKIP_SPLIT: - return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? - false : true; - case ATH9K_CAP_MCAST_KEYSRCH: - switch (capability) { - case 0: - return true; - case 1: - if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { - return false; - } else { - return (ah->sta_id1_defaults & - AR_STA_ID1_MCAST_KSRCH) ? true : - false; - } - } - return false; - case ATH9K_CAP_TXPOW: - switch (capability) { - case 0: - return 0; - case 1: - *result = regulatory->power_limit; - return 0; - case 2: - *result = regulatory->max_power_level; - return 0; - case 3: - *result = regulatory->tp_scale; - return 0; - } - return false; - case ATH9K_CAP_DS: - return (AR_SREV_9280_20_OR_LATER(ah) && - (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) - ? false : true; - default: - return false; - } -} -EXPORT_SYMBOL(ath9k_hw_getcapability); + if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status) -{ - switch (type) { - case ATH9K_CAP_TKIP_MIC: - if (setting) - ah->sta_id1_defaults |= - AR_STA_ID1_CRPT_MIC_ENABLE; - else - ah->sta_id1_defaults &= - ~AR_STA_ID1_CRPT_MIC_ENABLE; - return true; - case ATH9K_CAP_MCAST_KEYSRCH: - if (setting) - ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; - else - ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; - return true; - default: - return false; - } + return 0; } -EXPORT_SYMBOL(ath9k_hw_setcapability); /****************************/ /* GPIO / RFKILL / Antennae */ @@ -2520,12 +2450,6 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) } EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); -void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) -{ - memcpy(ath9k_hw_common(ah)->macaddr, mac, ETH_ALEN); -} -EXPORT_SYMBOL(ath9k_hw_setmac); - void ath9k_hw_setopmode(struct ath_hw *ah) { ath9k_hw_set_operating_mode(ah, ah->opmode); @@ -2598,21 +2522,6 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) } EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); -/* - * Extend 15-bit time stamp from rx descriptor to - * a full 64-bit TSF using the current h/w TSF. -*/ -u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) -{ - u64 tsf; - - tsf = ath9k_hw_gettsf64(ah); - if ((tsf & 0x7fff) < rstamp) - tsf -= 0x8000; - return (tsf & ~0x7fff) | rstamp; -} -EXPORT_SYMBOL(ath9k_hw_extend_tsf); - void ath9k_hw_set11nmac2040(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 77245dff5993..5ecbfcf7470a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -158,6 +158,9 @@ #define ATH9K_HW_RX_HP_QDEPTH 16 #define ATH9K_HW_RX_LP_QDEPTH 128 +#define PAPRD_GAIN_TABLE_ENTRIES 32 +#define PAPRD_TABLE_SZ 24 + enum ath_ini_subsys { ATH_INI_PRE = 0, ATH_INI_CORE, @@ -199,15 +202,8 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), ATH9K_HW_CAP_LDPC = BIT(19), ATH9K_HW_CAP_FASTCLOCK = BIT(20), -}; - -enum ath9k_capability_type { - ATH9K_CAP_CIPHER = 0, - ATH9K_CAP_TKIP_MIC, - ATH9K_CAP_TKIP_SPLIT, - ATH9K_CAP_TXPOW, - ATH9K_CAP_MCAST_KEYSRCH, - ATH9K_CAP_DS + ATH9K_HW_CAP_SGI_20 = BIT(21), + ATH9K_HW_CAP_PAPRD = BIT(22), }; struct ath9k_hw_capabilities { @@ -237,7 +233,7 @@ struct ath9k_ops_config { int sw_beacon_response_time; int additional_swba_backoff; int ack_6mb; - int cwm_ignore_extcca; + u32 cwm_ignore_extcca; u8 pcie_powersave_enable; u8 pcie_clock_req; u32 pcie_waen; @@ -262,10 +258,10 @@ struct ath9k_ops_config { #define AR_BASE_FREQ_5GHZ 4900 #define AR_SPUR_FEEQ_BOUND_HT40 19 #define AR_SPUR_FEEQ_BOUND_HT20 10 - bool tx_iq_calibration; /* Only available for >= AR9003 */ int spurmode; u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; u8 max_txtrig_level; + u16 ani_poll_interval; /* ANI poll interval in ms */ }; enum ath9k_int { @@ -279,6 +275,7 @@ enum ath9k_int { ATH9K_INT_TX = 0x00000040, ATH9K_INT_TXDESC = 0x00000080, ATH9K_INT_TIM_TIMER = 0x00000100, + ATH9K_INT_BB_WATCHDOG = 0x00000400, ATH9K_INT_TXURN = 0x00000800, ATH9K_INT_MIB = 0x00001000, ATH9K_INT_RXPHY = 0x00004000, @@ -358,6 +355,9 @@ struct ath9k_channel { int8_t iCoff; int8_t qCoff; int16_t rawNoiseFloor; + bool paprd_done; + u16 small_signal_gain[AR9300_MAX_CHAINS]; + u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; }; #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ @@ -459,7 +459,7 @@ struct ath9k_hw_version { #define AR_GENTMR_BIT(_index) (1 << (_index)) /* - * Using de Bruijin sequence to to look up 1's index in a 32 bit number + * Using de Bruijin sequence to look up 1's index in a 32 bit number * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 */ #define debruijn32 0x077CB531U @@ -510,6 +510,17 @@ struct ath_gen_timer_table { * @setup_calibration: set up calibration * @iscal_supported: used to query if a type of calibration is supported * @loadnf: load noise floor read from each chain on the CCA registers + * + * @ani_reset: reset ANI parameters to default values + * @ani_lower_immunity: lower the noise immunity level. The level controls + * the power-based packet detection on hardware. If a power jump is + * detected the adapter takes it as an indication that a packet has + * arrived. The level ranges from 0-5. Each level corresponds to a + * few dB more of noise immunity. If you have a strong time-varying + * interference that is causing false detections (OFDM timing errors or + * CCK timing errors) the level can be increased. + * @ani_cache_ini_regs: cache the values for ANI from the initial + * register settings through the register initialization. */ struct ath_hw_private_ops { /* Calibration ops */ @@ -553,6 +564,11 @@ struct ath_hw_private_ops { int param); void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); + + /* ANI */ + void (*ani_reset)(struct ath_hw *ah, bool is_scanning); + void (*ani_lower_immunity)(struct ath_hw *ah); + void (*ani_cache_ini_regs)(struct ath_hw *ah); }; /** @@ -563,6 +579,11 @@ struct ath_hw_private_ops { * * @config_pci_powersave: * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * + * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI + * thresholds being reached or having overflowed. + * @ani_monitor: called periodically by the core driver to collect + * MIB stats and adjust ANI if specific thresholds have been reached. */ struct ath_hw_ops { void (*config_pci_powersave)(struct ath_hw *ah, @@ -603,6 +624,9 @@ struct ath_hw_ops { u32 burstDuration); void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, u32 vmf); + + void (*ani_proc_mib_event)(struct ath_hw *ah); + void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); }; struct ath_hw { @@ -789,6 +813,12 @@ struct ath_hw { u32 ts_paddr_end; u16 ts_tail; u8 ts_size; + + u32 bb_watchdog_last_status; + u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ + + u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; + u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -818,10 +848,6 @@ int ath9k_hw_init(struct ath_hw *ah); int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); int ath9k_hw_fill_cap_info(struct ath_hw *ah); -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result); -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status); u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); /* Key Cache Management */ @@ -856,7 +882,6 @@ 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_setmac(struct ath_hw *ah, const u8 *mac); 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); @@ -865,7 +890,6 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah); void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); -u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); void ath9k_hw_init_global_settings(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); @@ -907,13 +931,26 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); int ar9002_hw_rf_claim(struct ath_hw *ah); void ar9002_hw_enable_async_fifo(struct ath_hw *ah); +void ar9002_hw_update_async_fifo(struct ath_hw *ah); void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); /* - * Code specifric to AR9003, we stuff these here to avoid callbacks + * Code specific to AR9003, we stuff these here to avoid callbacks * for older families */ void ar9003_hw_set_nf_limits(struct ath_hw *ah); +void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); +void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); +void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); +void ar9003_paprd_enable(struct ath_hw *ah, bool val); +void ar9003_paprd_populate_single_table(struct ath_hw *ah, + struct ath9k_channel *chan, int chain); +int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, + int chain); +int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); +int ar9003_paprd_init_table(struct ath_hw *ah); +bool ar9003_paprd_is_done(struct ath_hw *ah); +void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); /* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); @@ -926,8 +963,24 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); void ar9002_hw_attach_ops(struct ath_hw *ah); void ar9003_hw_attach_ops(struct ath_hw *ah); +/* + * ANI work can be shared between all families but a next + * generation implementation of ANI will be used only for AR9003 only + * for now as the other families still need to be tested with the same + * next generation ANI. Feel free to start testing it though for the + * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. + */ +extern int modparam_force_new_ani; +void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); +void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 +#define ATH9K_CLOCK_RATE_CCK 22 +#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 +#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 +#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 + #endif diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d457cb3bd772..514a4014c198 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -175,18 +175,6 @@ static const struct ath_ops ath9k_common_ops = { .write = ath9k_iowrite32, }; -static int count_streams(unsigned int chainmask, int max) -{ - int streams = 0; - - do { - if (++streams == max) - break; - } while ((chainmask = chainmask & (chainmask - 1))); - - return streams; -} - /**************************/ /* Initialization */ /**************************/ @@ -208,6 +196,9 @@ static void setup_ht_cap(struct ath_softc *sc, if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) + ht_info->cap |= IEEE80211_HT_CAP_SGI_20; + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; @@ -224,8 +215,8 @@ static void setup_ht_cap(struct ath_softc *sc, /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = count_streams(common->tx_chainmask, max_streams); - rx_streams = count_streams(common->rx_chainmask, max_streams); + tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); + rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); ath_print(common, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", @@ -388,36 +379,14 @@ static void ath9k_init_crypto(struct ath_softc *sc) for (i = 0; i < common->keymax; i++) ath9k_hw_keyreset(sc->sc_ah, (u16) i); - if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); - } - /* * Check whether the separate key cache entries * are required to handle both tx+rx MIC keys. * With split mic keys the number of stations is limited * to 27 otherwise 59. */ - if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) + if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) common->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, - 1, 1, NULL); - } static int ath9k_init_btcoex(struct ath_softc *sc) @@ -435,7 +404,7 @@ static int ath9k_init_btcoex(struct ath_softc *sc) r = ath_init_btcoex_timer(sc); if (r) return -1; - qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); + qnum = sc->tx.hwq_map[WME_AC_BE]; ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; break; @@ -472,23 +441,23 @@ static int ath9k_init_queues(struct ath_softc *sc) sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); - if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { + 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, ATH9K_WME_AC_BE)) { + 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, ATH9K_WME_AC_VI)) { + 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, ATH9K_WME_AC_VO)) { + 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; @@ -745,6 +714,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, goto error_world; } + INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); 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); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0e425cb4bbb1..e955bb9d98cb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "hw-ops.h" static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) @@ -554,8 +555,13 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REGWRITE_BUFFER_FLUSH(ah); DISABLE_REGWRITE_BUFFER(ah); - /* cwmin and cwmax should be 0 for beacon queue */ - if (AR_SREV_9300_20_OR_LATER(ah)) { + /* + * cwmin and cwmax should be 0 for beacon queue + * but not for IBSS as we would create an imbalance + * on beaconing fairness for participating nodes. + */ + if (AR_SREV_9300_20_OR_LATER(ah) && + ah->opmode != NL80211_IFTYPE_ADHOC) { REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) | SM(0, AR_D_LCL_IFS_CWMAX) | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); @@ -756,11 +762,11 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) } EXPORT_SYMBOL(ath9k_hw_putrxbuf); -void ath9k_hw_startpcureceive(struct ath_hw *ah) +void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) { ath9k_enable_mib_counters(ah); - ath9k_ani_reset(ah); + ath9k_ani_reset(ah, is_scanning); REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); } diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 00f3e0c7528a..7559fb2b28a5 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -577,13 +577,8 @@ enum ath9k_tx_queue { #define ATH9K_NUM_TX_QUEUES 10 -enum ath9k_tx_queue_subtype { - ATH9K_WME_AC_BK = 0, - ATH9K_WME_AC_BE, - ATH9K_WME_AC_VI, - ATH9K_WME_AC_VO, - ATH9K_WME_UPSD -}; +/* Used as a queue subtype instead of a WMM AC */ +#define ATH9K_WME_UPSD 4 enum ath9k_tx_queue_flags { TXQ_FLAG_TXOKINT_ENABLE = 0x0001, @@ -617,7 +612,7 @@ enum ath9k_pkt_type { struct ath9k_tx_queue_info { u32 tqi_ver; enum ath9k_tx_queue tqi_type; - enum ath9k_tx_queue_subtype tqi_subtype; + int tqi_subtype; enum ath9k_tx_queue_flags tqi_qflags; u32 tqi_priority; u32 tqi_aifs; @@ -715,7 +710,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags); 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); +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); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index abfa0493236f..c8de50fa6378 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -51,13 +51,11 @@ static void ath_cache_conf_rate(struct ath_softc *sc, static void ath_update_txpow(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; - u32 txpow; if (sc->curtxpow != sc->config.txpowlimit) { ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); /* read back in case value is clamped */ - ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); - sc->curtxpow = txpow; + sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } } @@ -232,6 +230,113 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, return r; } +static void ath_paprd_activate(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + int chain; + + if (!ah->curchan->paprd_done) + return; + + ath9k_ps_wakeup(sc); + for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { + if (!(ah->caps.tx_chainmask & BIT(chain))) + continue; + + ar9003_paprd_populate_single_table(ah, ah->curchan, chain); + } + + ar9003_paprd_enable(ah, true); + ath9k_ps_restore(sc); +} + +void ath_paprd_calibrate(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); + struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_hdr *hdr; + struct sk_buff *skb = NULL; + struct ieee80211_tx_info *tx_info; + int band = hw->conf.channel->band; + struct ieee80211_supported_band *sband = &sc->sbands[band]; + struct ath_tx_control txctl; + int qnum, ftype; + int chain_ok = 0; + int chain; + int len = 1800; + int time_left; + int i; + + ath9k_ps_wakeup(sc); + skb = alloc_skb(len, GFP_KERNEL); + if (!skb) + return; + + tx_info = IEEE80211_SKB_CB(skb); + + skb_put(skb, len); + memset(skb->data, 0, len); + hdr = (struct ieee80211_hdr *)skb->data; + ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; + hdr->frame_control = cpu_to_le16(ftype); + hdr->duration_id = 10; + memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); + 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]; + + ar9003_paprd_init_table(ah); + for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { + if (!(ah->caps.tx_chainmask & BIT(chain))) + continue; + + chain_ok = 0; + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->band = band; + + for (i = 0; i < 4; i++) { + tx_info->control.rates[i].idx = sband->n_bitrates - 1; + tx_info->control.rates[i].count = 6; + } + + init_completion(&sc->paprd_complete); + ar9003_paprd_setup_gain_table(ah, chain); + txctl.paprd = BIT(chain); + if (ath_tx_start(hw, skb, &txctl) != 0) + break; + + time_left = wait_for_completion_timeout(&sc->paprd_complete, + 100); + if (!time_left) { + ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "Timeout waiting for paprd training on " + "TX chain %d\n", + chain); + break; + } + + if (!ar9003_paprd_is_done(ah)) + break; + + if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) + break; + + chain_ok = 1; + } + kfree_skb(skb); + + if (chain_ok) { + ah->curchan->paprd_done = true; + ath_paprd_activate(sc); + } + + ath9k_ps_restore(sc); +} + /* * This routine performs the periodic noise floor calibration function * that is used to adjust and optimize the chip performance. This @@ -285,7 +390,8 @@ void ath_ani_calibrate(unsigned long data) } /* Verify whether we must check ANI */ - if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + if ((timestamp - common->ani.checkani_timer) >= + ah->config.ani_poll_interval) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -326,15 +432,24 @@ set_timer: */ cal_interval = ATH_LONG_CALINTERVAL; if (sc->sc_ah->config.enable_ani) - cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); + cal_interval = min(cal_interval, + (u32)ah->config.ani_poll_interval); if (!common->ani.caldone) cal_interval = min(cal_interval, (u32)short_cal_interval); mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && + !(sc->sc_flags & SC_OP_SCANNING)) { + if (!sc->sc_ah->curchan->paprd_done) + ieee80211_queue_work(sc->hw, &sc->paprd_work); + else + ath_paprd_activate(sc); + } } static void ath_start_ani(struct ath_common *common) { + struct ath_hw *ah = common->ah; unsigned long timestamp = jiffies_to_msecs(jiffies); common->ani.longcal_timer = timestamp; @@ -342,7 +457,8 @@ static void ath_start_ani(struct ath_common *common) common->ani.checkani_timer = timestamp; mod_timer(&common->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + jiffies + + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); } /* @@ -520,6 +636,12 @@ irqreturn_t ath_isr(int irq, void *dev) !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) goto chip_reset; + if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && + (status & ATH9K_INT_BB_WATCHDOG)) { + ar9003_hw_bb_watchdog_dbg_info(ah); + goto chip_reset; + } + if (status & ATH9K_INT_SWBA) tasklet_schedule(&sc->bcon_tasklet); @@ -615,234 +737,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, return chanmode; } -static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, - struct ath9k_keyval *hk, const u8 *addr, - bool authenticator) -{ - struct ath_hw *ah = common->ah; - const u8 *key_rxmic; - const u8 *key_txmic; - - key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; - key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; - - if (addr == NULL) { - /* - * Group key installation - only two key cache entries are used - * regardless of splitmic capability since group key is only - * used either for TX or RX. - */ - if (authenticator) { - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); - } else { - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); - } - return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); - } - if (!common->splitmic) { - /* TX and RX keys share the same key cache entry. */ - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); - return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); - } - - /* Separate key cache entries for TX and RX */ - - /* TX key goes at first index, RX key at +32. */ - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { - /* TX MIC entry failed. No need to proceed further */ - ath_print(common, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); - return 0; - } - - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - /* XXX delete tx key on failure? */ - return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); -} - -static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) -{ - int i; - - for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { - if (test_bit(i, common->keymap) || - test_bit(i + 64, common->keymap)) - continue; /* At least one part of TKIP key allocated */ - if (common->splitmic && - (test_bit(i + 32, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - continue; /* At least one part of TKIP key allocated */ - - /* Found a free slot for a TKIP key */ - return i; - } - return -1; -} - -static int ath_reserve_key_cache_slot(struct ath_common *common) -{ - int i; - - /* First, try to find slots that would not be available for TKIP. */ - if (common->splitmic) { - for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { - if (!test_bit(i, common->keymap) && - (test_bit(i + 32, common->keymap) || - test_bit(i + 64, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i; - if (!test_bit(i + 32, common->keymap) && - (test_bit(i, common->keymap) || - test_bit(i + 64, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i + 32; - if (!test_bit(i + 64, common->keymap) && - (test_bit(i , common->keymap) || - test_bit(i + 32, common->keymap) || - test_bit(i + 64 + 32, common->keymap))) - return i + 64; - if (!test_bit(i + 64 + 32, common->keymap) && - (test_bit(i, common->keymap) || - test_bit(i + 32, common->keymap) || - test_bit(i + 64, common->keymap))) - return i + 64 + 32; - } - } else { - for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { - if (!test_bit(i, common->keymap) && - test_bit(i + 64, common->keymap)) - return i; - if (test_bit(i, common->keymap) && - !test_bit(i + 64, common->keymap)) - return i + 64; - } - } - - /* No partially used TKIP slots, pick any available slot */ - for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { - /* Do not allow slots that could be needed for TKIP group keys - * to be used. This limitation could be removed if we know that - * TKIP will not be used. */ - if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) - continue; - if (common->splitmic) { - if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) - continue; - if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) - continue; - } - - if (!test_bit(i, common->keymap)) - return i; /* Found a free slot for a key */ - } - - /* No free slot found */ - return -1; -} - -static int ath_key_config(struct ath_common *common, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath_hw *ah = common->ah; - struct ath9k_keyval hk; - const u8 *mac = NULL; - int ret = 0; - int idx; - - memset(&hk, 0, sizeof(hk)); - - switch (key->alg) { - case ALG_WEP: - hk.kv_type = ATH9K_CIPHER_WEP; - break; - case ALG_TKIP: - hk.kv_type = ATH9K_CIPHER_TKIP; - break; - case ALG_CCMP: - hk.kv_type = ATH9K_CIPHER_AES_CCM; - break; - default: - return -EOPNOTSUPP; - } - - hk.kv_len = key->keylen; - memcpy(hk.kv_val, key->key, key->keylen); - - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; - } else if (key->keyidx) { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (vif->type != NL80211_IFTYPE_AP) { - /* Only keyidx 0 should be used with unicast key, but - * allow this for client mode for now. */ - idx = key->keyidx; - } else - return -EIO; - } else { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (key->alg == ALG_TKIP) - idx = ath_reserve_key_cache_slot_tkip(common); - else - idx = ath_reserve_key_cache_slot(common); - if (idx < 0) - return -ENOSPC; /* no free key cache entries */ - } - - if (key->alg == ALG_TKIP) - ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, - vif->type == NL80211_IFTYPE_AP); - else - ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); - - if (!ret) - return -EIO; - - set_bit(idx, common->keymap); - if (key->alg == ALG_TKIP) { - set_bit(idx + 64, common->keymap); - if (common->splitmic) { - set_bit(idx + 32, common->keymap); - set_bit(idx + 64 + 32, common->keymap); - } - } - - return idx; -} - -static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) -{ - struct ath_hw *ah = common->ah; - - ath9k_hw_keyreset(ah, key->hw_key_idx); - if (key->hw_key_idx < IEEE80211_WEP_NKID) - return; - - clear_bit(key->hw_key_idx, common->keymap); - if (key->alg != ALG_TKIP) - return; - - clear_bit(key->hw_key_idx + 64, common->keymap); - if (common->splitmic) { - ath9k_hw_keyreset(ah, key->hw_key_idx + 32); - clear_bit(key->hw_key_idx + 32, common->keymap); - clear_bit(key->hw_key_idx + 64 + 32, common->keymap); - } -} - static void ath9k_bss_assoc_info(struct ath_softc *sc, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) @@ -1026,25 +920,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return r; } -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) +static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) { int qnum; switch (queue) { case 0: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; + qnum = sc->tx.hwq_map[WME_AC_VO]; break; case 1: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; + qnum = sc->tx.hwq_map[WME_AC_VI]; break; case 2: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; + qnum = sc->tx.hwq_map[WME_AC_BE]; break; case 3: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; + qnum = sc->tx.hwq_map[WME_AC_BK]; break; default: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; + qnum = sc->tx.hwq_map[WME_AC_BE]; break; } @@ -1056,16 +950,16 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) int qnum; switch (queue) { - case ATH9K_WME_AC_VO: + case WME_AC_VO: qnum = 0; break; - case ATH9K_WME_AC_VI: + case WME_AC_VI: qnum = 1; break; - case ATH9K_WME_AC_BE: + case WME_AC_BE: qnum = 2; break; - case ATH9K_WME_AC_BK: + case WME_AC_BK: qnum = 3; break; default: @@ -1195,7 +1089,9 @@ static int ath9k_start(struct ieee80211_hw *hw) ATH9K_INT_GLOBAL; if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP; + ah->imask |= ATH9K_INT_RXHP | + ATH9K_INT_RXLP | + ATH9K_INT_BB_WATCHDOG; else ah->imask |= ATH9K_INT_RX; @@ -1245,6 +1141,7 @@ static int ath9k_tx(struct ieee80211_hw *hw, 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, @@ -1274,7 +1171,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, * completed and if needed, also for RX of buffered frames. */ ath9k_ps_wakeup(sc); - ath9k_hw_setrxabort(sc->sc_ah, 0); + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + ath9k_hw_setrxabort(sc->sc_ah, 0); if (ieee80211_is_pspoll(hdr->frame_control)) { ath_print(common, ATH_DBG_PS, "Sending PS-Poll to pick a buffered frame\n"); @@ -1316,11 +1214,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, memmove(skb->data, skb->data + padsize, padpos); } - /* Check if a tx queue is available */ - - txctl.txq = ath_test_get_txq(sc, skb); - if (!txctl.txq) - goto exit; + qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); + txctl.txq = &sc->tx.txq[qnum]; ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); @@ -1348,6 +1243,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&sc->ath_led_blink_work); cancel_delayed_work_sync(&sc->tx_complete_work); + cancel_work_sync(&sc->paprd_work); if (!sc->num_sec_wiphy) { cancel_delayed_work_sync(&sc->wiphy_work); @@ -1538,8 +1434,8 @@ void ath9k_enable_ps(struct ath_softc *sc) ah->imask |= ATH9K_INT_TIM_TIMER; ath9k_hw_set_interrupts(ah, ah->imask); } + ath9k_hw_setrxabort(ah, 1); } - ath9k_hw_setrxabort(ah, 1); } static int ath9k_config(struct ieee80211_hw *hw, u32 changed) @@ -1776,7 +1672,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) - if ((qnum == sc->tx.hwq_map[ATH9K_WME_AC_BE]) && !ret) + if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) ath_beaconq_config(sc); mutex_unlock(&sc->mutex); @@ -1804,7 +1700,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, switch (cmd) { case SET_KEY: - ret = ath_key_config(common, vif, sta, key); + ret = ath9k_cmn_key_config(common, vif, sta, key); if (ret >= 0) { key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */ @@ -1817,7 +1713,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, } break; case DISABLE_KEY: - ath_key_delete(common, key); + ath9k_cmn_key_delete(common, key); break; default: ret = -EINVAL; @@ -1990,6 +1886,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ath_softc *sc = aphy->sc; int ret = 0; + local_bh_disable(); + switch (action) { case IEEE80211_AMPDU_RX_START: if (!(sc->sc_flags & SC_OP_RXAGGR)) @@ -2019,6 +1917,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, "Unknown AMPDU action\n"); } + local_bh_enable(); + return ret; } @@ -2063,6 +1963,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) ath9k_wiphy_pause_all_forced(sc, aphy); sc->sc_flags |= SC_OP_SCANNING; del_timer_sync(&common->ani.timer); + cancel_work_sync(&sc->paprd_work); cancel_delayed_work_sync(&sc->tx_complete_work); mutex_unlock(&sc->mutex); } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ec836cf1c0d..257b10ba6f57 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ { 0 } }; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8519452c95f1..600ee0ba2880 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -20,7 +20,7 @@ #include "ath9k.h" static const struct ath_rate_table ar5416_11na_ratetable = { - 42, + 43, 8, /* MCS start */ { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ @@ -40,73 +40,75 @@ static const struct ath_rate_table ar5416_11na_ratetable = { { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 29300, 7, 108, 4, 7, 7, 7, 7 }, { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0, 0, 0, 8, 24, 8, 24 }, + 6400, 0, 0, 0, 8, 25, 8, 25 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 1, 1, 2, 9, 25, 9, 25 }, + 12700, 1, 1, 2, 9, 26, 9, 26 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 2, 2, 2, 10, 26, 10, 26 }, + 18800, 2, 2, 2, 10, 27, 10, 27 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 3, 3, 4, 11, 27, 11, 27 }, + 25000, 3, 3, 4, 11, 28, 11, 28 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 4, 4, 4, 12, 28, 12, 28 }, + 36700, 4, 4, 4, 12, 29, 12, 29 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 5, 5, 4, 13, 29, 13, 29 }, + 48100, 5, 5, 4, 13, 30, 13, 30 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 6, 6, 4, 14, 30, 14, 30 }, + 53500, 6, 6, 4, 14, 31, 14, 31 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 7, 7, 4, 15, 31, 15, 32 }, + 59000, 7, 7, 4, 15, 32, 15, 33 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 8, 8, 3, 16, 33, 16, 33 }, + 12700, 8, 8, 3, 16, 34, 16, 34 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 9, 9, 2, 17, 34, 17, 34 }, + 24800, 9, 9, 2, 17, 35, 17, 35 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 10, 10, 2, 18, 35, 18, 35 }, + 36600, 10, 10, 2, 18, 36, 18, 36 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 11, 11, 4, 19, 36, 19, 36 }, + 48100, 11, 11, 4, 19, 37, 19, 37 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 12, 12, 4, 20, 37, 20, 37 }, + 69500, 12, 12, 4, 20, 38, 20, 38 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 13, 13, 4, 21, 38, 21, 38 }, + 89500, 13, 13, 4, 21, 39, 21, 39 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 14, 14, 4, 22, 39, 22, 39 }, + 98900, 14, 14, 4, 22, 40, 22, 40 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 15, 15, 4, 23, 40, 23, 41 }, + 108300, 15, 15, 4, 23, 41, 24, 42 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */ + 12000, 15, 15, 4, 23, 41, 24, 42 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0, 0, 0, 8, 24, 24, 24 }, + 13200, 0, 0, 0, 8, 25, 25, 25 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 1, 1, 2, 9, 25, 25, 25 }, + 25900, 1, 1, 2, 9, 26, 26, 26 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 2, 2, 2, 10, 26, 26, 26 }, + 38600, 2, 2, 2, 10, 27, 27, 27 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 3, 3, 4, 11, 27, 27, 27 }, + 49800, 3, 3, 4, 11, 28, 28, 28 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 4, 4, 4, 12, 28, 28, 28 }, + 72200, 4, 4, 4, 12, 29, 29, 29 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 5, 5, 4, 13, 29, 29, 29 }, + 92900, 5, 5, 4, 13, 30, 30, 30 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 6, 6, 4, 14, 30, 30, 30 }, + 102700, 6, 6, 4, 14, 31, 31, 31 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 7, 7, 4, 15, 31, 32, 32 }, + 112000, 7, 7, 4, 15, 32, 33, 33 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 7, 7, 4, 15, 31, 32, 32 }, + 122000, 7, 7, 4, 15, 32, 33, 33 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 8, 8, 0, 16, 33, 33, 33 }, + 25800, 8, 8, 0, 16, 34, 34, 34 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 9, 9, 2, 17, 34, 34, 34 }, + 49800, 9, 9, 2, 17, 35, 35, 35 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 10, 10, 2, 18, 35, 35, 35 }, + 71900, 10, 10, 2, 18, 36, 36, 36 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 11, 11, 4, 19, 36, 36, 36 }, + 92500, 11, 11, 4, 19, 37, 37, 37 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 12, 12, 4, 20, 37, 37, 37 }, + 130300, 12, 12, 4, 20, 38, 38, 38 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 13, 13, 4, 21, 38, 38, 38 }, + 162800, 13, 13, 4, 21, 39, 39, 39 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 14, 14, 4, 22, 39, 39, 39 }, + 178200, 14, 14, 4, 22, 40, 40, 40 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 15, 15, 4, 23, 40, 41, 41 }, + 192100, 15, 15, 4, 23, 41, 42, 42 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 15, 15, 4, 23, 40, 41, 41 }, + 207000, 15, 15, 4, 23, 41, 42, 42 }, }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -116,7 +118,7 @@ static const struct ath_rate_table ar5416_11na_ratetable = { * for HT are the 64K max aggregate limit */ static const struct ath_rate_table ar5416_11ng_ratetable = { - 46, + 47, 12, /* MCS start */ { { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -144,73 +146,75 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 30900, 11, 108, 8, 11, 11, 11, 11 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0, 0, 4, 12, 28, 12, 28 }, + 6400, 0, 0, 4, 12, 29, 12, 29 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 1, 1, 6, 13, 29, 13, 29 }, + 12700, 1, 1, 6, 13, 30, 13, 30 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 2, 2, 6, 14, 30, 14, 30 }, + 18800, 2, 2, 6, 14, 31, 14, 31 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 3, 3, 8, 15, 31, 15, 31 }, + 25000, 3, 3, 8, 15, 32, 15, 32 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 4, 4, 8, 16, 32, 16, 32 }, + 36700, 4, 4, 8, 16, 33, 16, 33 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 5, 5, 8, 17, 33, 17, 33 }, + 48100, 5, 5, 8, 17, 34, 17, 34 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 6, 6, 8, 18, 34, 18, 34 }, + 53500, 6, 6, 8, 18, 35, 18, 35 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 7, 7, 8, 19, 35, 19, 36 }, + 59000, 7, 7, 8, 19, 36, 19, 37 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 8, 8, 4, 20, 37, 20, 37 }, + 12700, 8, 8, 4, 20, 38, 20, 38 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 9, 9, 6, 21, 38, 21, 38 }, + 24800, 9, 9, 6, 21, 39, 21, 39 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 10, 10, 6, 22, 39, 22, 39 }, + 36600, 10, 10, 6, 22, 40, 22, 40 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 11, 11, 8, 23, 40, 23, 40 }, + 48100, 11, 11, 8, 23, 41, 23, 41 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 12, 12, 8, 24, 41, 24, 41 }, + 69500, 12, 12, 8, 24, 42, 24, 42 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 13, 13, 8, 25, 42, 25, 42 }, + 89500, 13, 13, 8, 25, 43, 25, 43 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 14, 14, 8, 26, 43, 26, 44 }, + 98900, 14, 14, 8, 26, 44, 26, 44 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 15, 15, 8, 27, 44, 27, 45 }, + 108300, 15, 15, 8, 27, 45, 28, 46 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */ + 120000, 15, 15, 8, 27, 45, 28, 46 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0, 0, 8, 12, 28, 28, 28 }, + 13200, 0, 0, 8, 12, 29, 29, 29 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 1, 1, 8, 13, 29, 29, 29 }, + 25900, 1, 1, 8, 13, 30, 30, 30 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 2, 2, 8, 14, 30, 30, 30 }, + 38600, 2, 2, 8, 14, 31, 31, 31 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 3, 3, 8, 15, 31, 31, 31 }, + 49800, 3, 3, 8, 15, 32, 32, 32 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 4, 4, 8, 16, 32, 32, 32 }, + 72200, 4, 4, 8, 16, 33, 33, 33 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 5, 5, 8, 17, 33, 33, 33 }, + 92900, 5, 5, 8, 17, 34, 34, 34 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 6, 6, 8, 18, 34, 34, 34 }, + 102700, 6, 6, 8, 18, 35, 35, 35 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 7, 7, 8, 19, 35, 36, 36 }, + 112000, 7, 7, 8, 19, 36, 37, 37 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 7, 7, 8, 19, 35, 36, 36 }, + 122000, 7, 7, 8, 19, 36, 37, 37 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 8, 8, 8, 20, 37, 37, 37 }, + 25800, 8, 8, 8, 20, 38, 38, 38 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 9, 9, 8, 21, 38, 38, 38 }, + 49800, 9, 9, 8, 21, 39, 39, 39 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 10, 10, 8, 22, 39, 39, 39 }, + 71900, 10, 10, 8, 22, 40, 40, 40 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 11, 11, 8, 23, 40, 40, 40 }, + 92500, 11, 11, 8, 23, 41, 41, 41 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 12, 12, 8, 24, 41, 41, 41 }, + 130300, 12, 12, 8, 24, 42, 42, 42 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 13, 13, 8, 25, 42, 42, 42 }, + 162800, 13, 13, 8, 25, 43, 43, 43 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 14, 14, 8, 26, 43, 43, 43 }, + 178200, 14, 14, 8, 26, 44, 44, 44 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 15, 15, 8, 27, 44, 45, 45 }, + 192100, 15, 15, 8, 27, 45, 46, 46 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 15, 15, 8, 27, 44, 45, 45 }, + 207000, 15, 15, 8, 27, 45, 46, 46 }, }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -1193,21 +1197,19 @@ static void ath_rc_init(struct ath_softc *sc, } static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, - bool is_cw40, bool is_sgi40) + bool is_cw40, bool is_sgi) { u8 caps = 0; if (sta->ht_cap.ht_supported) { caps = WLAN_RC_HT_FLAG; - if (sc->sc_ah->caps.tx_chainmask != 1 && - ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { - if (sta->ht_cap.mcs.rx_mask[1]) - caps |= WLAN_RC_DS_FLAG; - } + if (sta->ht_cap.mcs.rx_mask[1]) + caps |= WLAN_RC_DS_FLAG; if (is_cw40) caps |= WLAN_RC_40_FLAG; - if (is_sgi40) + if (is_sgi) caps |= WLAN_RC_SGI_FLAG; + } return caps; @@ -1300,7 +1302,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table; - bool is_cw40, is_sgi40; + bool is_cw40, is_sgi = false; int i, j = 0; for (i = 0; i < sband->n_bitrates; i++) { @@ -1323,7 +1325,11 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, } is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; - is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + + if (is_cw40) + 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; /* Choose rate table first */ @@ -1336,7 +1342,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, rate_table = hw_rate_table[sc->cur_rate_mode]; } - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); } @@ -1347,10 +1353,10 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table = NULL; - bool oper_cw40 = false, oper_sgi40; + bool oper_cw40 = false, oper_sgi; bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? true : false; - bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? + bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? true : false; /* FIXME: Handle AP mode later when we support CWM */ @@ -1363,15 +1369,21 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, oper_chan_type == NL80211_CHAN_HT40PLUS) oper_cw40 = true; - oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - true : false; + if (oper_cw40) + oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + true : false; + else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) + oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + true : false; + else + oper_sgi = false; - if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { + if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { rate_table = ath_choose_rate_table(sc, sband->band, sta->ht_cap.ht_supported, oper_cw40); ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, - oper_cw40, oper_sgi40); + oper_cw40, oper_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ca6065b71b46..da0cfe90c38a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -116,9 +116,6 @@ static void ath_opmode_init(struct ath_softc *sc) /* configure operational mode */ ath9k_hw_setopmode(ah); - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, common->macaddr); - /* calculate and install multicast filter */ mfilt[0] = mfilt[1] = ~0; ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); @@ -295,7 +292,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) ath_opmode_init(sc); - ath9k_hw_startpcureceive(sc->sc_ah); + ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); } static void ath_edma_stop_recv(struct ath_softc *sc) @@ -501,7 +498,7 @@ int ath_startrecv(struct ath_softc *sc) start_recv: spin_unlock_bh(&sc->rx.rxbuflock); ath_opmode_init(sc); - ath9k_hw_startpcureceive(ah); + ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); return 0; } @@ -700,12 +697,16 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, bf = SKB_CB_ATHBUF(skb); BUG_ON(!bf); - dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, common->rx_bufsize, DMA_FROM_DEVICE); ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); - if (ret == -EINPROGRESS) + if (ret == -EINPROGRESS) { + /*let device gain the buffer again*/ + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + common->rx_bufsize, DMA_FROM_DEVICE); return false; + } __skb_unlink(skb, &rx_edma->rx_fifo); if (ret == -EINVAL) { @@ -814,13 +815,263 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, * 1. accessing the frame * 2. requeueing the same buffer to h/w */ - dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, common->rx_bufsize, DMA_FROM_DEVICE); return bf; } +/* Assumes you've already done the endian to CPU conversion */ +static bool ath9k_rx_accept(struct ath_common *common, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rxs, + struct ath_rx_status *rx_stats, + bool *decrypt_error) +{ + struct ath_hw *ah = common->ah; + __le16 fc; + u8 rx_status_len = ah->caps.rx_status_len; + + fc = hdr->frame_control; + + if (!rx_stats->rs_datalen) + return false; + /* + * rs_status follows rs_datalen so if rs_datalen is too large + * we can take a hint that hardware corrupted it, so ignore + * those frames. + */ + if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) + return false; + + /* + * rs_more indicates chained descriptors which can be used + * to link buffers together for a sort of scatter-gather + * operation. + * reject the frame, we don't support scatter-gather yet and + * the frame is probably corrupt anyway + */ + if (rx_stats->rs_more) + return false; + + /* + * The rx_stats->rs_status will not be set until the end of the + * chained descriptors so it can be ignored if rs_more is set. The + * rs_more will be false at the last element of the chained + * descriptors. + */ + if (rx_stats->rs_status != 0) { + if (rx_stats->rs_status & ATH9K_RXERR_CRC) + rxs->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_stats->rs_status & ATH9K_RXERR_PHY) + return false; + + if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { + *decrypt_error = true; + } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { + if (ieee80211_is_ctl(fc)) + /* + * Sometimes, we get invalid + * MIC failures on valid control frames. + * Remove these mic errors. + */ + rx_stats->rs_status &= ~ATH9K_RXERR_MIC; + else + rxs->flag |= RX_FLAG_MMIC_ERROR; + } + /* + * Reject error frames with the exception of + * decryption and MIC failures. For monitor mode, + * we also ignore the CRC error. + */ + if (ah->opmode == NL80211_IFTYPE_MONITOR) { + if (rx_stats->rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | + ATH9K_RXERR_CRC)) + return false; + } else { + if (rx_stats->rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { + return false; + } + } + } + return true; +} + +static int ath9k_process_rate(struct ath_common *common, + struct ieee80211_hw *hw, + struct ath_rx_status *rx_stats, + struct ieee80211_rx_status *rxs) +{ + struct ieee80211_supported_band *sband; + enum ieee80211_band band; + unsigned int i = 0; + + band = hw->conf.channel->band; + sband = hw->wiphy->bands[band]; + + if (rx_stats->rs_rate & 0x80) { + /* HT rate */ + rxs->flag |= RX_FLAG_HT; + if (rx_stats->rs_flags & ATH9K_RX_2040) + rxs->flag |= RX_FLAG_40MHZ; + if (rx_stats->rs_flags & ATH9K_RX_GI) + rxs->flag |= RX_FLAG_SHORT_GI; + rxs->rate_idx = rx_stats->rs_rate & 0x7f; + return 0; + } + + for (i = 0; i < sband->n_bitrates; i++) { + if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { + rxs->rate_idx = i; + return 0; + } + if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { + rxs->flag |= RX_FLAG_SHORTPRE; + rxs->rate_idx = i; + return 0; + } + } + + /* + * No valid hardware bitrate found -- we should not get here + * because hardware has already validated this frame as OK. + */ + ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " + "0x%02x using 1 Mbit\n", rx_stats->rs_rate); + + return -EINVAL; +} + +static void ath9k_process_rssi(struct ath_common *common, + struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, + struct ath_rx_status *rx_stats) +{ + struct ath_hw *ah = common->ah; + struct ieee80211_sta *sta; + struct ath_node *an; + int last_rssi = ATH_RSSI_DUMMY_MARKER; + __le16 fc; + + fc = hdr->frame_control; + + 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. + */ + sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); + 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 (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) + rx_stats->rs_rssi = ATH_EP_RND(last_rssi, + ATH_RSSI_EP_MULTIPLIER); + if (rx_stats->rs_rssi < 0) + 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; +} + +/* + * For Decrypt or Demic errors, we only mark packet status here and always push + * up the frame up to let mac80211 handle the actual error case, be it no + * decryption key or real decryption error. This let us keep statistics there. + */ +static int ath9k_rx_skb_preprocess(struct ath_common *common, + struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, + struct ath_rx_status *rx_stats, + struct ieee80211_rx_status *rx_status, + bool *decrypt_error) +{ + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + + /* + * everything but the rate is checked here, the rate check is done + * separately to avoid doing two lookups for a rate for each frame. + */ + if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) + return -EINVAL; + + ath9k_process_rssi(common, hw, hdr, rx_stats); + + if (ath9k_process_rate(common, hw, rx_stats, rx_status)) + return -EINVAL; + + rx_status->band = hw->conf.channel->band; + rx_status->freq = hw->conf.channel->center_freq; + rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; + rx_status->antenna = rx_stats->rs_antenna; + rx_status->flag |= RX_FLAG_TSFT; + + return 0; +} + +static void ath9k_rx_skb_postprocess(struct ath_common *common, + struct sk_buff *skb, + struct ath_rx_status *rx_stats, + struct ieee80211_rx_status *rxs, + bool decrypt_error) +{ + struct ath_hw *ah = common->ah; + struct ieee80211_hdr *hdr; + int hdrlen, padpos, padsize; + u8 keyix; + __le16 fc; + + /* see if any padding is done by the hw and remove it */ + hdr = (struct ieee80211_hdr *) skb->data; + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + fc = hdr->frame_control; + padpos = ath9k_cmn_padpos(hdr->frame_control); + + /* The MAC header is padded to have 32-bit boundary if the + * packet payload is non-zero. The general calculation for + * padsize would take into account odd header lengths: + * padsize = (4 - padpos % 4) % 4; However, since only + * even-length headers are used, padding can only be 0 or 2 + * bytes and we can optimize this a bit. In addition, we must + * not try to remove padding from short control frames that do + * not have payload. */ + padsize = padpos & 3; + if (padsize && skb->len>=padpos+padsize+FCS_LEN) { + memmove(skb->data + padsize, skb->data, padpos); + skb_pull(skb, padsize); + } + + keyix = rx_stats->rs_keyix; + + if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && + ieee80211_has_protected(fc)) { + rxs->flag |= RX_FLAG_DECRYPTED; + } else if (ieee80211_has_protected(fc) + && !decrypt_error && skb->len >= hdrlen + 4) { + keyix = skb->data[hdrlen + 3] >> 6; + + if (test_bit(keyix, common->keymap)) + rxs->flag |= RX_FLAG_DECRYPTED; + } + if (ah->sw_mgmt_crypto && + (rxs->flag & RX_FLAG_DECRYPTED) && + ieee80211_is_mgmt(fc)) + /* Use software decrypt for management frames. */ + rxs->flag &= ~RX_FLAG_DECRYPTED; +} int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) { @@ -842,15 +1093,21 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); int dma_type; + u8 rx_status_len = ah->caps.rx_status_len; + u64 tsf = 0; + u32 tsf_lower = 0; if (edma) - dma_type = DMA_FROM_DEVICE; - else dma_type = DMA_BIDIRECTIONAL; + else + dma_type = DMA_FROM_DEVICE; qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; spin_lock_bh(&sc->rx.rxbuflock); + tsf = ath9k_hw_gettsf64(ah); + tsf_lower = tsf & 0xffffffff; + do { /* If handling rx interrupt and flush is in progress => exit */ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) @@ -869,7 +1126,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if (!skb) continue; - hdr = (struct ieee80211_hdr *) skb->data; + hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); rxs = IEEE80211_SKB_RXCB(skb); hw = ath_get_virt_hw(sc, hdr); @@ -883,8 +1140,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if (flush) goto requeue; - retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs, - rxs, &decrypt_error); + rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; + if (rs.rs_tstamp > tsf_lower && + unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) + rxs->mactime -= 0x100000000ULL; + + if (rs.rs_tstamp < tsf_lower && + unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) + rxs->mactime += 0x100000000ULL; + + retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, + rxs, &decrypt_error); if (retval) goto requeue; @@ -908,8 +1174,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if (ah->caps.rx_status_len) skb_pull(skb, ah->caps.rx_status_len); - ath9k_cmn_rx_skb_postprocess(common, skb, &rs, - rxs, decrypt_error); + ath9k_rx_skb_postprocess(common, skb, &rs, + rxs, decrypt_error); /* We will now give hardware our shiny new allocated skb */ bf->bf_mpdu = requeue_skb; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d4371a43bdaa..3e3ccef438db 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -222,6 +222,7 @@ #define AR_ISR_S2 0x008c #define AR_ISR_S2_QCU_TXURN 0x000003FF +#define AR_ISR_S2_BB_WATCHDOG 0x00010000 #define AR_ISR_S2_CST 0x00400000 #define AR_ISR_S2_GTT 0x00800000 #define AR_ISR_S2_TIM 0x01000000 @@ -699,6 +700,9 @@ #define AR_RC_HOSTIF 0x00000100 #define AR_WA 0x4004 +#define AR_WA_BIT6 (1 << 6) +#define AR_WA_BIT7 (1 << 7) +#define AR_WA_BIT23 (1 << 23) #define AR_WA_D3_L1_DISABLE (1 << 14) #define AR9285_WA_DEFAULT 0x004a050b #define AR9280_WA_DEFAULT 0x0040073b @@ -756,32 +760,33 @@ #define AR_SREV_REVISION2 0x00000F00 #define AR_SREV_REVISION2_S 8 -#define AR_SREV_VERSION_5416_PCI 0xD -#define AR_SREV_VERSION_5416_PCIE 0xC -#define AR_SREV_REVISION_5416_10 0 -#define AR_SREV_REVISION_5416_20 1 -#define AR_SREV_REVISION_5416_22 2 -#define AR_SREV_VERSION_9100 0x14 -#define AR_SREV_VERSION_9160 0x40 -#define AR_SREV_REVISION_9160_10 0 -#define AR_SREV_REVISION_9160_11 1 -#define AR_SREV_VERSION_9280 0x80 -#define AR_SREV_REVISION_9280_10 0 -#define AR_SREV_REVISION_9280_20 1 -#define AR_SREV_REVISION_9280_21 2 -#define AR_SREV_VERSION_9285 0xC0 -#define AR_SREV_REVISION_9285_10 0 -#define AR_SREV_REVISION_9285_11 1 -#define AR_SREV_REVISION_9285_12 2 -#define AR_SREV_VERSION_9287 0x180 -#define AR_SREV_REVISION_9287_10 0 -#define AR_SREV_REVISION_9287_11 1 -#define AR_SREV_REVISION_9287_12 2 -#define AR_SREV_VERSION_9271 0x140 -#define AR_SREV_REVISION_9271_10 0 -#define AR_SREV_REVISION_9271_11 1 -#define AR_SREV_VERSION_9300 0x1c0 -#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ +#define AR_SREV_VERSION_5416_PCI 0xD +#define AR_SREV_VERSION_5416_PCIE 0xC +#define AR_SREV_REVISION_5416_10 0 +#define AR_SREV_REVISION_5416_20 1 +#define AR_SREV_REVISION_5416_22 2 +#define AR_SREV_VERSION_9100 0x14 +#define AR_SREV_VERSION_9160 0x40 +#define AR_SREV_REVISION_9160_10 0 +#define AR_SREV_REVISION_9160_11 1 +#define AR_SREV_VERSION_9280 0x80 +#define AR_SREV_REVISION_9280_10 0 +#define AR_SREV_REVISION_9280_20 1 +#define AR_SREV_REVISION_9280_21 2 +#define AR_SREV_VERSION_9285 0xC0 +#define AR_SREV_REVISION_9285_10 0 +#define AR_SREV_REVISION_9285_11 1 +#define AR_SREV_REVISION_9285_12 2 +#define AR_SREV_VERSION_9287 0x180 +#define AR_SREV_REVISION_9287_10 0 +#define AR_SREV_REVISION_9287_11 1 +#define AR_SREV_REVISION_9287_12 2 +#define AR_SREV_REVISION_9287_13 3 +#define AR_SREV_VERSION_9271 0x140 +#define AR_SREV_REVISION_9271_10 0 +#define AR_SREV_REVISION_9271_11 1 +#define AR_SREV_VERSION_9300 0x1c0 +#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -859,6 +864,11 @@ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) +#define AR_SREV_9287_13_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13))) + #define AR_SREV_9271(_ah) \ (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) #define AR_SREV_9271_10(_ah) \ diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 105ad40968f6..89423ca23d2c 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -219,7 +219,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[ATH9K_WME_AC_VO]]; + txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; if (ath_tx_start(aphy->hw, skb, &txctl) != 0) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index e23172c9caaf..6260faa658a2 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -279,9 +279,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, if (wmi->drv_priv->op_flags & OP_UNPLUGGED) return 0; - if (!wmi) - return -EINVAL; - skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); if (!skb) return -ENOMEM; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 859aa4ab0769..20221b8c04fd 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -941,6 +941,7 @@ 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); @@ -958,58 +959,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) return &sc->tx.txq[qnum]; } -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) -{ - int qnum; - - switch (qtype) { - case ATH9K_TX_QUEUE_DATA: - 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 -1; - } - qnum = sc->tx.hwq_map[haltype]; - break; - case ATH9K_TX_QUEUE_BEACON: - qnum = sc->beacon.beaconq; - break; - case ATH9K_TX_QUEUE_CAB: - qnum = sc->beacon.cabq->axq_qnum; - break; - default: - qnum = -1; - } - return qnum; -} - -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_txq *txq = NULL; - u16 skb_queue = skb_get_queue_mapping(skb); - int qnum; - - qnum = ath_get_hal_qnum(skb_queue, sc); - txq = &sc->tx.txq[qnum]; - - spin_lock_bh(&txq->axq_lock); - - if (txq->axq_depth >= (ATH_TXBUF - 20)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT, - "TX queue: %d is full, depth: %d\n", - qnum, txq->axq_depth); - ath_mac80211_stop_queue(sc, skb_queue); - txq->stopped = 1; - spin_unlock_bh(&txq->axq_lock); - return NULL; - } - - spin_unlock_bh(&txq->axq_lock); - - return txq; -} - int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -1688,12 +1637,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen -= padsize; } - if (conf_is_ht(&hw->conf)) { + 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; bf->bf_flags = setup_tx_flags(skb, use_ldpc); bf->bf_keytype = get_hw_crypto_keytype(skb); @@ -1768,6 +1718,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, bf->bf_buf_addr, txctl->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); if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && @@ -1809,8 +1762,9 @@ int ath_tx_start(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_txq *txq = txctl->txq; struct ath_buf *bf; - int r; + int q, r; bf = ath_tx_get_buffer(sc); if (!bf) { @@ -1820,8 +1774,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, r = ath_tx_setup_buffer(hw, bf, skb, txctl); if (unlikely(r)) { - struct ath_txq *txq = txctl->txq; - ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); /* upon ath_tx_processq() this TX queue will be resumed, we @@ -1829,7 +1781,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, * we will at least have to run TX completionon one buffer * on the queue */ spin_lock_bh(&txq->axq_lock); - if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { + if (!txq->stopped && txq->axq_depth > 1) { ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); txq->stopped = 1; } @@ -1840,6 +1792,17 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, 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; @@ -1909,7 +1872,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; - int padpos, padsize; + int q, padpos, padsize; ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); @@ -1948,8 +1911,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) ath9k_tx_status(hw, skb); - else + 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; + ieee80211_tx_status(hw, skb); + } } static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, @@ -1971,8 +1942,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, } dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); - ath_tx_complete(sc, skb, bf->aphy, tx_flags); - ath_debug_stat_tx(sc, txq, bf, ts); + + if (bf->bf_state.bfs_paprd) { + sc->paprd_txok = txok; + complete(&sc->paprd_complete); + } else { + ath_tx_complete(sc, skb, bf->aphy, tx_flags); + ath_debug_stat_tx(sc, txq, bf, ts); + } /* * Return the list of ath_buf of this mpdu to free queue @@ -2057,14 +2034,14 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) { int qnum; + qnum = ath_get_mac80211_qnum(txq->axq_class, sc); + if (qnum == -1) + return; + spin_lock_bh(&txq->axq_lock); - if (txq->stopped && - sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { - qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); - if (qnum != -1) { - ath_mac80211_start_queue(sc, qnum); - txq->stopped = 0; - } + if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { + ath_mac80211_start_queue(sc, qnum); + txq->stopped = 0; } spin_unlock_bh(&txq->axq_lock); } @@ -2279,6 +2256,17 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) txok = !(txs.ts_status & ATH9K_TXERR_MASK); + /* + * Make sure null func frame is acked before configuring + * hw into ps mode. + */ + if (bf->bf_isnullfunc && txok) { + if ((sc->ps_flags & PS_ENABLED)) + ath9k_enable_ps(sc); + else + sc->ps_flags |= PS_NULLFUNC_COMPLETED; + } + if (!bf_isampdu(bf)) { bf->bf_retries = txs.ts_longretry; if (txs.ts_status & ATH9K_TXERR_XRETRY) @@ -2424,26 +2412,8 @@ 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]; INIT_LIST_HEAD(&ac->tid_q); - - switch (acno) { - case WME_AC_BE: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - break; - case WME_AC_BK: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); - break; - case WME_AC_VI: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); - break; - case WME_AC_VO: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); - break; - } } } diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 3a003e6803a5..8674a99356af 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -530,7 +530,7 @@ struct b43_fw_header { /* Size of the data. For ucode and PCM this is in bytes. * For IV this is number-of-ivs. */ __be32 size; -} __attribute__((__packed__)); +} __packed; /* Initial Value file format */ #define B43_IV_OFFSET_MASK 0x7FFF @@ -540,8 +540,8 @@ struct b43_iv { union { __be16 d16; __be32 d32; - } data __attribute__((__packed__)); -} __attribute__((__packed__)); + } data __packed; +} __packed; /* Data structures for DMA transmission, per 80211 core. */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index fa40fdfea719..10d0aaf754c5 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -333,11 +333,11 @@ static inline dma_addr_t dmaaddr; if (tx) { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_TO_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, DMA_TO_DEVICE); } else { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_FROM_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, DMA_FROM_DEVICE); } return dmaaddr; @@ -348,11 +348,11 @@ static inline dma_addr_t addr, size_t len, int tx) { if (tx) { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_TO_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, DMA_TO_DEVICE); } else { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } } @@ -361,7 +361,7 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_cpu(ring->dev->dev, + dma_sync_single_for_cpu(ring->dev->dev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -370,8 +370,8 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_device(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -401,9 +401,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring) */ if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; @@ -420,8 +420,8 @@ static void free_ringmemory(struct b43_dmaring *ring) if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, flags); + dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase); } /* Reset the RX DMA channel */ @@ -528,7 +528,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, size_t buffersize, bool dma_to_device) { - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) + if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) return 1; switch (ring->type) { @@ -874,10 +874,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dma_dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -889,10 +889,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dma_dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -903,9 +903,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } } - ssb_dma_unmap_single(dev->dev, - dma_test, b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_unmap_single(dev->dev->dma_dev, + dma_test, b43_txhdr_size(dev), + DMA_TO_DEVICE); } err = alloc_ringmemory(ring); @@ -1018,9 +1018,12 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) /* Try to set the DMA mask. If it fails, try falling back to a * lower mask, as we can always also support a lower one. */ while (1) { - err = ssb_dma_set_mask(dev->dev, mask); - if (!err) - break; + err = dma_set_mask(dev->dev->dma_dev, mask); + if (!err) { + err = dma_set_coherent_mask(dev->dev->dma_dev, mask); + if (!err) + break; + } if (mask == DMA_BIT_MASK(64)) { mask = DMA_BIT_MASK(32); fallback = 1; @@ -1221,14 +1224,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA); + priv_info->bouncebuffer = kmemdup(skb->data, skb->len, + GFP_ATOMIC | GFP_DMA); if (!priv_info->bouncebuffer) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -ENOMEM; goto out_unmap_hdr; } - memcpy(priv_info->bouncebuffer, skb->data, skb->len); meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1); if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index dc91944d6022..a01c2100f166 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -67,7 +67,7 @@ struct b43_dmadesc32 { __le32 control; __le32 address; -} __attribute__ ((__packed__)); +} __packed; #define B43_DMA32_DCTL_BYTECNT 0x00001FFF #define B43_DMA32_DCTL_ADDREXT_MASK 0x00030000 #define B43_DMA32_DCTL_ADDREXT_SHIFT 16 @@ -140,7 +140,7 @@ struct b43_dmadesc64 { __le32 control1; __le32 address_low; __le32 address_high; -} __attribute__ ((__packed__)); +} __packed; #define B43_DMA64_DCTL0_DTABLEEND 0x10000000 #define B43_DMA64_DCTL0_IRQ 0x20000000 #define B43_DMA64_DCTL0_FRAMEEND 0x40000000 @@ -153,8 +153,8 @@ struct b43_dmadesc_generic { union { struct b43_dmadesc32 dma32; struct b43_dmadesc64 dma64; - } __attribute__ ((__packed__)); -} __attribute__ ((__packed__)); + } __packed; +} __packed; /* Misc DMA constants */ #define B43_DMA_RINGMEMSIZE PAGE_SIZE diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index d23ff9fe0c9e..d4cf9b390af3 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -10,8 +10,8 @@ union { \ __le32 data; \ __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) + } __packed; \ + } __packed /* struct b43_plcp_hdr4 */ _b43_declare_plcp_hdr(4); @@ -57,7 +57,7 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } new_format __attribute__ ((__packed__)); + } new_format __packed; /* The old r351 format. */ struct { @@ -68,10 +68,10 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } old_format __attribute__ ((__packed__)); + } old_format __packed; - } __attribute__ ((__packed__)); -} __attribute__ ((__packed__)); + } __packed; +} __packed; /* MAC TX control */ #define B43_TXH_MAC_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */ @@ -218,20 +218,20 @@ struct b43_rxhdr_fw4 { struct { __u8 jssi; /* PHY RX Status 1: JSSI */ __u8 sig_qual; /* PHY RX Status 1: Signal Quality */ - } __attribute__ ((__packed__)); + } __packed; /* RSSI for N-PHYs */ struct { __s8 power0; /* PHY RX Status 1: Power 0 */ __s8 power1; /* PHY RX Status 1: Power 1 */ - } __attribute__ ((__packed__)); - } __attribute__ ((__packed__)); + } __packed; + } __packed; __le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status3; /* PHY RX Status 3 */ __le32 mac_status; /* MAC RX status */ __le16 mac_time; __le16 channel; -} __attribute__ ((__packed__)); +} __packed; /* PHY RX Status 0 */ #define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */ diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 89fe2f972c72..c81b2f53b0c5 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -372,7 +372,7 @@ struct b43legacy_fw_header { /* Size of the data. For ucode and PCM this is in bytes. * For IV this is number-of-ivs. */ __be32 size; -} __attribute__((__packed__)); +} __packed; /* Initial Value file format */ #define B43legacy_IV_OFFSET_MASK 0x7FFF @@ -382,8 +382,8 @@ struct b43legacy_iv { union { __be16 d16; __be32 d32; - } data __attribute__((__packed__)); -} __attribute__((__packed__)); + } data __packed; +} __packed; #define B43legacy_PHYMODE(phytype) (1 << (phytype)) #define B43legacy_PHYMODE_B B43legacy_PHYMODE \ diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index e91520d0312e..e03e01d0bc35 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -394,11 +394,11 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring, dma_addr_t dmaaddr; if (tx) - dmaaddr = ssb_dma_map_single(ring->dev->dev, + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, buf, len, DMA_TO_DEVICE); else - dmaaddr = ssb_dma_map_single(ring->dev->dev, + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, buf, len, DMA_FROM_DEVICE); @@ -412,11 +412,11 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring, int tx) { if (tx) - ssb_dma_unmap_single(ring->dev->dev, + dma_unmap_single(ring->dev->dev->dma_dev, addr, len, DMA_TO_DEVICE); else - ssb_dma_unmap_single(ring->dev->dev, + dma_unmap_single(ring->dev->dev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -428,8 +428,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring, { B43legacy_WARN_ON(ring->tx); - ssb_dma_sync_single_for_cpu(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -439,8 +439,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring, { B43legacy_WARN_ON(ring->tx); - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_device(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -460,10 +460,10 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring, static int alloc_ringmemory(struct b43legacy_dmaring *ring) { /* GFP flags must match the flags in free_ringmemory()! */ - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43legacy_DMA_RINGMEMSIZE, - &(ring->dmabase), - GFP_KERNEL); + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + B43legacy_DMA_RINGMEMSIZE, + &(ring->dmabase), + GFP_KERNEL); if (!ring->descbase) { b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" " failed\n"); @@ -476,8 +476,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring) static void free_ringmemory(struct b43legacy_dmaring *ring) { - ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, GFP_KERNEL); + dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase); } /* Reset the RX DMA channel */ @@ -589,7 +589,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, size_t buffersize, bool dma_to_device) { - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) + if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) return 1; switch (ring->type) { @@ -906,7 +906,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache, + dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, sizeof(struct b43legacy_txhdr_fw3), DMA_TO_DEVICE); @@ -920,7 +920,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = ssb_dma_map_single(dev->dev, + dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, sizeof(struct b43legacy_txhdr_fw3), DMA_TO_DEVICE); @@ -930,9 +930,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, goto err_kfree_txhdr_cache; } - ssb_dma_unmap_single(dev->dev, dma_test, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); + dma_unmap_single(dev->dev->dma_dev, dma_test, + sizeof(struct b43legacy_txhdr_fw3), + DMA_TO_DEVICE); } ring->nr_slots = nr_slots; @@ -1040,9 +1040,12 @@ static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) /* Try to set the DMA mask. If it fails, try falling back to a * lower mask, as we can always also support a lower one. */ while (1) { - err = ssb_dma_set_mask(dev->dev, mask); - if (!err) - break; + err = dma_set_mask(dev->dev->dma_dev, mask); + if (!err) { + err = dma_set_coherent_mask(dev->dev->dma_dev, mask); + if (!err) + break; + } if (mask == DMA_BIT_MASK(64)) { mask = DMA_BIT_MASK(32); fallback = 1; diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index f9681041c2d8..f89c34226288 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h @@ -72,7 +72,7 @@ struct b43legacy_dmadesc32 { __le32 control; __le32 address; -} __attribute__((__packed__)); +} __packed; #define B43legacy_DMA32_DCTL_BYTECNT 0x00001FFF #define B43legacy_DMA32_DCTL_ADDREXT_MASK 0x00030000 #define B43legacy_DMA32_DCTL_ADDREXT_SHIFT 16 @@ -147,7 +147,7 @@ struct b43legacy_dmadesc64 { __le32 control1; __le32 address_low; __le32 address_high; -} __attribute__((__packed__)); +} __packed; #define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000 #define B43legacy_DMA64_DCTL0_IRQ 0x20000000 #define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000 @@ -162,8 +162,8 @@ struct b43legacy_dmadesc_generic { union { struct b43legacy_dmadesc32 dma32; struct b43legacy_dmadesc64 dma64; - } __attribute__((__packed__)); -} __attribute__((__packed__)); + } __packed; +} __packed; /* Misc DMA constants */ diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index 91633087a20b..289db00a4a7b 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h @@ -9,8 +9,8 @@ union { \ __le32 data; \ __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) + } __packed; \ + } __packed /* struct b43legacy_plcp_hdr4 */ _b43legacy_declare_plcp_hdr(4); @@ -39,7 +39,7 @@ struct b43legacy_txhdr_fw3 { struct b43legacy_plcp_hdr6 rts_plcp; /* RTS PLCP */ __u8 rts_frame[18]; /* The RTS frame (if used) */ struct b43legacy_plcp_hdr6 plcp; -} __attribute__((__packed__)); +} __packed; /* MAC TX control */ #define B43legacy_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */ @@ -123,7 +123,7 @@ struct b43legacy_hwtxstatus { __le16 seq; u8 phy_stat; PAD_BYTES(1); -} __attribute__((__packed__)); +} __packed; /* Receive header for v3 firmware. */ @@ -138,7 +138,7 @@ struct b43legacy_rxhdr_fw3 { __le16 mac_status; /* MAC RX status */ __le16 mac_time; __le16 channel; -} __attribute__((__packed__)); +} __packed; /* PHY RX Status 0 */ diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index 7f9d8d976aa8..ed98ce7c8f65 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h @@ -19,35 +19,35 @@ struct hostap_ieee80211_mgmt { __le16 status_code; /* possibly followed by Challenge text */ u8 variable[0]; - } __attribute__ ((packed)) auth; + } __packed auth; struct { __le16 reason_code; - } __attribute__ ((packed)) deauth; + } __packed deauth; struct { __le16 capab_info; __le16 listen_interval; /* followed by SSID and Supported rates */ u8 variable[0]; - } __attribute__ ((packed)) assoc_req; + } __packed assoc_req; struct { __le16 capab_info; __le16 status_code; __le16 aid; /* followed by Supported rates */ u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; + } __packed assoc_resp, reassoc_resp; struct { __le16 capab_info; __le16 listen_interval; u8 current_ap[6]; /* followed by SSID and Supported rates */ u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; + } __packed reassoc_req; struct { __le16 reason_code; - } __attribute__ ((packed)) disassoc; + } __packed disassoc; struct { - } __attribute__ ((packed)) probe_req; + } __packed probe_req; struct { u8 timestamp[8]; __le16 beacon_int; @@ -55,9 +55,9 @@ struct hostap_ieee80211_mgmt { /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params, TIM */ u8 variable[0]; - } __attribute__ ((packed)) beacon, probe_resp; + } __packed beacon, probe_resp; } u; -} __attribute__ ((packed)); +} __packed; #define IEEE80211_MGMT_HDR_LEN 24 diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h index 90b64b092007..4230102ac9e4 100644 --- a/drivers/net/wireless/hostap/hostap_common.h +++ b/drivers/net/wireless/hostap/hostap_common.h @@ -179,7 +179,7 @@ struct hfa384x_comp_ident __le16 variant; __le16 major; __le16 minor; -} __attribute__ ((packed)); +} __packed; #define HFA384X_COMP_ID_PRI 0x15 #define HFA384X_COMP_ID_STA 0x1f @@ -192,14 +192,14 @@ struct hfa384x_sup_range __le16 variant; __le16 bottom; __le16 top; -} __attribute__ ((packed)); +} __packed; struct hfa384x_build_id { __le16 pri_seq; __le16 sec_seq; -} __attribute__ ((packed)); +} __packed; /* FD01 - Download Buffer */ struct hfa384x_rid_download_buffer @@ -207,14 +207,14 @@ struct hfa384x_rid_download_buffer __le16 page; __le16 offset; __le16 length; -} __attribute__ ((packed)); +} __packed; /* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */ struct hfa384x_comms_quality { __le16 comm_qual; /* 0 .. 92 */ __le16 signal_level; /* 27 .. 154 */ __le16 noise_level; /* 27 .. 154 */ -} __attribute__ ((packed)); +} __packed; /* netdevice private ioctls (used, e.g., with iwpriv from user space) */ diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 1ba33be98b25..1c66b3c1030d 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -31,14 +31,14 @@ struct linux_wlan_ng_val { u32 did; u16 status, len; u32 data; -} __attribute__ ((packed)); +} __packed; struct linux_wlan_ng_prism_hdr { u32 msgcode, msglen; char devname[16]; struct linux_wlan_ng_val hosttime, mactime, channel, rssi, sq, signal, noise, rate, istx, frmlen; -} __attribute__ ((packed)); +} __packed; struct linux_wlan_ng_cap_hdr { __be32 version; @@ -55,7 +55,7 @@ struct linux_wlan_ng_cap_hdr { __be32 ssi_noise; __be32 preamble; __be32 encoding; -} __attribute__ ((packed)); +} __packed; struct hostap_radiotap_rx { struct ieee80211_radiotap_header hdr; @@ -66,7 +66,7 @@ struct hostap_radiotap_rx { __le16 chan_flags; s8 dbm_antsignal; s8 dbm_antnoise; -} __attribute__ ((packed)); +} __packed; #define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */ #define LWNG_CAPHDR_VERSION 0x80211001 @@ -97,7 +97,7 @@ struct hfa384x_rx_frame { __be16 len; /* followed by frame data; max 2304 bytes */ -} __attribute__ ((packed)); +} __packed; struct hfa384x_tx_frame { @@ -126,14 +126,14 @@ struct hfa384x_tx_frame { __be16 len; /* followed by frame data; max 2304 bytes */ -} __attribute__ ((packed)); +} __packed; struct hfa384x_rid_hdr { __le16 len; __le16 rid; -} __attribute__ ((packed)); +} __packed; /* Macro for converting signal levels (range 27 .. 154) to wireless ext @@ -145,24 +145,24 @@ struct hfa384x_rid_hdr struct hfa384x_scan_request { __le16 channel_list; __le16 txrate; /* HFA384X_RATES_* */ -} __attribute__ ((packed)); +} __packed; struct hfa384x_hostscan_request { __le16 channel_list; __le16 txrate; __le16 target_ssid_len; u8 target_ssid[32]; -} __attribute__ ((packed)); +} __packed; struct hfa384x_join_request { u8 bssid[6]; __le16 channel; -} __attribute__ ((packed)); +} __packed; struct hfa384x_info_frame { __le16 len; __le16 type; -} __attribute__ ((packed)); +} __packed; struct hfa384x_comm_tallies { __le16 tx_unicast_frames; @@ -186,7 +186,7 @@ struct hfa384x_comm_tallies { __le16 rx_discards_wep_undecryptable; __le16 rx_message_in_msg_fragments; __le16 rx_message_in_bad_msg_fragments; -} __attribute__ ((packed)); +} __packed; struct hfa384x_comm_tallies32 { __le32 tx_unicast_frames; @@ -210,7 +210,7 @@ struct hfa384x_comm_tallies32 { __le32 rx_discards_wep_undecryptable; __le32 rx_message_in_msg_fragments; __le32 rx_message_in_bad_msg_fragments; -} __attribute__ ((packed)); +} __packed; struct hfa384x_scan_result_hdr { __le16 reserved; @@ -219,7 +219,7 @@ struct hfa384x_scan_result_hdr { #define HFA384X_SCAN_HOST_INITIATED 1 #define HFA384X_SCAN_FIRMWARE_INITIATED 2 #define HFA384X_SCAN_INQUIRY_FROM_HOST 3 -} __attribute__ ((packed)); +} __packed; #define HFA384X_SCAN_MAX_RESULTS 32 @@ -234,7 +234,7 @@ struct hfa384x_scan_result { u8 ssid[32]; u8 sup_rates[10]; __le16 rate; -} __attribute__ ((packed)); +} __packed; struct hfa384x_hostscan_result { __le16 chid; @@ -248,7 +248,7 @@ struct hfa384x_hostscan_result { u8 sup_rates[10]; __le16 rate; __le16 atim; -} __attribute__ ((packed)); +} __packed; struct comm_tallies_sums { unsigned int tx_unicast_frames; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 0bd4dfa59a8a..56350d571960 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -3467,10 +3467,8 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) dma_addr_t p; priv->msg_buffers = - (struct ipw2100_tx_packet *)kmalloc(IPW_COMMAND_POOL_SIZE * - sizeof(struct - ipw2100_tx_packet), - GFP_KERNEL); + kmalloc(IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet), + GFP_KERNEL); if (!priv->msg_buffers) { printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg " "buffers.\n", priv->net_dev->name); @@ -4499,10 +4497,8 @@ static int ipw2100_tx_allocate(struct ipw2100_priv *priv) } priv->tx_buffers = - (struct ipw2100_tx_packet *)kmalloc(TX_PENDED_QUEUE_LENGTH * - sizeof(struct - ipw2100_tx_packet), - GFP_ATOMIC); + kmalloc(TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet), + GFP_ATOMIC); if (!priv->tx_buffers) { printk(KERN_ERR DRV_NAME ": %s: alloc failed form tx buffers.\n", @@ -4651,9 +4647,9 @@ static int ipw2100_rx_allocate(struct ipw2100_priv *priv) /* * allocate packets */ - priv->rx_buffers = (struct ipw2100_rx_packet *) - kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet), - GFP_KERNEL); + priv->rx_buffers = kmalloc(RX_QUEUE_LENGTH * + sizeof(struct ipw2100_rx_packet), + GFP_KERNEL); if (!priv->rx_buffers) { IPW_DEBUG_INFO("can't allocate rx packet buffer table\n"); @@ -5233,7 +5229,7 @@ struct security_info_params { u8 auth_mode; u8 replay_counters_number; u8 unicast_using_group; -} __attribute__ ((packed)); +} __packed; static int ipw2100_set_security_information(struct ipw2100_priv *priv, int auth_mode, @@ -8475,7 +8471,7 @@ struct ipw2100_fw_header { short mode; unsigned int fw_size; unsigned int uc_size; -} __attribute__ ((packed)); +} __packed; static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw) { diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index 1eab0d698f4d..838002b4881e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h @@ -164,7 +164,7 @@ struct bd_status { } fields; u8 field; } info; -} __attribute__ ((packed)); +} __packed; struct ipw2100_bd { u32 host_addr; @@ -174,7 +174,7 @@ struct ipw2100_bd { * 1st TBD) */ u8 num_fragments; u8 reserved[6]; -} __attribute__ ((packed)); +} __packed; #define IPW_BD_QUEUE_LENGTH(n) (1<<n) #define IPW_BD_ALIGNMENT(L) (L*sizeof(struct ipw2100_bd)) @@ -232,7 +232,7 @@ struct ipw2100_status { #define IPW_STATUS_FLAG_WEP_ENCRYPTED (1<<1) #define IPW_STATUS_FLAG_CRC_ERROR (1<<2) u8 rssi; -} __attribute__ ((packed)); +} __packed; struct ipw2100_status_queue { /* driver (virtual) pointer to queue */ @@ -293,7 +293,7 @@ struct ipw2100_cmd_header { u32 reserved1[3]; u32 *ordinal1_ptr; u32 *ordinal2_ptr; -} __attribute__ ((packed)); +} __packed; struct ipw2100_data_header { u32 host_command_reg; @@ -307,7 +307,7 @@ struct ipw2100_data_header { u8 src_addr[ETH_ALEN]; u8 dst_addr[ETH_ALEN]; u16 fragment_size; -} __attribute__ ((packed)); +} __packed; /* Host command data structure */ struct host_command { @@ -316,7 +316,7 @@ struct host_command { u32 host_command_sequence; // UNIQUE COMMAND NUMBER (ID) u32 host_command_length; // LENGTH u32 host_command_parameters[HOST_COMMAND_PARAMS_REG_LEN]; // COMMAND PARAMETERS -} __attribute__ ((packed)); +} __packed; typedef enum { POWER_ON_RESET, @@ -382,7 +382,7 @@ struct ipw2100_notification { u32 hnhdr_size; /* size in bytes of data or number of entries, if table. Does NOT include header */ -} __attribute__ ((packed)); +} __packed; #define MAX_KEY_SIZE 16 #define MAX_KEYS 8 @@ -814,7 +814,7 @@ struct ipw2100_rx { struct ipw2100_notification notification; struct ipw2100_cmd_header command; } rx_data; -} __attribute__ ((packed)); +} __packed; /* Bit 0-7 are for 802.11b tx rates - . Bit 5-7 are reserved */ #define TX_RATE_1_MBIT 0x0001 diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 3aa3bb18f615..cb2552a6777c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -96,7 +96,7 @@ static int network_mode = 0; static u32 ipw_debug_level; static int associate; static int auto_create = 1; -static int led_support = 0; +static int led_support = 1; static int disable = 0; static int bt_coexist = 0; static int hwcrypto = 0; @@ -6624,13 +6624,12 @@ static int ipw_wx_set_genie(struct net_device *dev, return -EINVAL; if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); if (buf == NULL) { err = -ENOMEM; goto out; } - memcpy(buf, extra, wrqu->data.length); kfree(ieee->wpa_ie); ieee->wpa_ie = buf; ieee->wpa_ie_len = wrqu->data.length; @@ -12083,7 +12082,7 @@ module_param(auto_create, int, 0444); MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); module_param_named(led, led_support, int, 0444); -MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); +MODULE_PARM_DESC(led, "enable led control on some systems (default 1 on)"); module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index bf0eeb2e873a..d7d049c7a4fa 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h @@ -388,7 +388,7 @@ struct clx2_queue { dma_addr_t dma_addr; /**< physical addr for BD's */ int low_mark; /**< low watermark, resume queue if free space more than this */ int high_mark; /**< high watermark, stop queue if free space less than this */ -} __attribute__ ((packed)); /* XXX */ +} __packed; /* XXX */ struct machdr32 { __le16 frame_ctl; @@ -399,7 +399,7 @@ struct machdr32 { __le16 seq_ctrl; // more endians! u8 addr4[MACADRR_BYTE_LEN]; __le16 qos_ctrl; -} __attribute__ ((packed)); +} __packed; struct machdr30 { __le16 frame_ctl; @@ -409,7 +409,7 @@ struct machdr30 { u8 addr3[MACADRR_BYTE_LEN]; __le16 seq_ctrl; // more endians! u8 addr4[MACADRR_BYTE_LEN]; -} __attribute__ ((packed)); +} __packed; struct machdr26 { __le16 frame_ctl; @@ -419,7 +419,7 @@ struct machdr26 { u8 addr3[MACADRR_BYTE_LEN]; __le16 seq_ctrl; // more endians! __le16 qos_ctrl; -} __attribute__ ((packed)); +} __packed; struct machdr24 { __le16 frame_ctl; @@ -428,20 +428,20 @@ struct machdr24 { u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; __le16 seq_ctrl; // more endians! -} __attribute__ ((packed)); +} __packed; // TX TFD with 32 byte MAC Header struct tx_tfd_32 { struct machdr32 mchdr; // 32 __le32 uivplaceholder[2]; // 8 -} __attribute__ ((packed)); +} __packed; // TX TFD with 30 byte MAC Header struct tx_tfd_30 { struct machdr30 mchdr; // 30 u8 reserved[2]; // 2 __le32 uivplaceholder[2]; // 8 -} __attribute__ ((packed)); +} __packed; // tx tfd with 26 byte mac header struct tx_tfd_26 { @@ -449,14 +449,14 @@ struct tx_tfd_26 { u8 reserved1[2]; // 2 __le32 uivplaceholder[2]; // 8 u8 reserved2[4]; // 4 -} __attribute__ ((packed)); +} __packed; // tx tfd with 24 byte mac header struct tx_tfd_24 { struct machdr24 mchdr; // 24 __le32 uivplaceholder[2]; // 8 u8 reserved[8]; // 8 -} __attribute__ ((packed)); +} __packed; #define DCT_WEP_KEY_FIELD_LENGTH 16 @@ -465,7 +465,7 @@ struct tfd_command { u8 length; __le16 reserved; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct tfd_data { /* Header */ @@ -504,14 +504,14 @@ struct tfd_data { __le32 num_chunks; __le32 chunk_ptr[NUM_TFD_CHUNKS]; __le16 chunk_len[NUM_TFD_CHUNKS]; -} __attribute__ ((packed)); +} __packed; struct txrx_control_flags { u8 message_type; u8 rx_seq_num; u8 control_bits; u8 reserved; -} __attribute__ ((packed)); +} __packed; #define TFD_SIZE 128 #define TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH (TFD_SIZE - sizeof(struct txrx_control_flags)) @@ -523,7 +523,7 @@ struct tfd_frame { struct tfd_command cmd; u8 raw[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH]; } u; -} __attribute__ ((packed)); +} __packed; typedef void destructor_func(const void *); @@ -559,7 +559,7 @@ struct rate_histogram { __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; } failed; -} __attribute__ ((packed)); +} __packed; /* statistics command response */ struct ipw_cmd_stats { @@ -586,13 +586,13 @@ struct ipw_cmd_stats { __le16 rx_autodetec_no_ofdm; __le16 rx_autodetec_no_barker; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct notif_channel_result { u8 channel_num; struct ipw_cmd_stats stats; u8 uReserved; -} __attribute__ ((packed)); +} __packed; #define SCAN_COMPLETED_STATUS_COMPLETE 1 #define SCAN_COMPLETED_STATUS_ABORTED 2 @@ -602,24 +602,24 @@ struct notif_scan_complete { u8 num_channels; u8 status; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct notif_frag_length { __le16 frag_length; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct notif_beacon_state { __le32 state; __le32 number; -} __attribute__ ((packed)); +} __packed; struct notif_tgi_tx_key { u8 key_state; u8 security_type; u8 station_index; u8 reserved; -} __attribute__ ((packed)); +} __packed; #define SILENCE_OVER_THRESH (1) #define SILENCE_UNDER_THRESH (2) @@ -631,25 +631,25 @@ struct notif_link_deterioration { struct rate_histogram histogram; u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ __le16 silence_count; -} __attribute__ ((packed)); +} __packed; struct notif_association { u8 state; -} __attribute__ ((packed)); +} __packed; struct notif_authenticate { u8 state; struct machdr24 addr; __le16 status; -} __attribute__ ((packed)); +} __packed; struct notif_calibration { u8 data[104]; -} __attribute__ ((packed)); +} __packed; struct notif_noise { __le32 value; -} __attribute__ ((packed)); +} __packed; struct ipw_rx_notification { u8 reserved[8]; @@ -669,7 +669,7 @@ struct ipw_rx_notification { struct notif_noise noise; u8 raw[0]; } u; -} __attribute__ ((packed)); +} __packed; struct ipw_rx_frame { __le32 reserved1; @@ -692,14 +692,14 @@ struct ipw_rx_frame { u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen __le16 length; u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct ipw_rx_header { u8 message_type; u8 rx_seq_num; u8 control_bits; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_rx_packet { struct ipw_rx_header header; @@ -707,7 +707,7 @@ struct ipw_rx_packet { struct ipw_rx_frame frame; struct ipw_rx_notification notification; } u; -} __attribute__ ((packed)); +} __packed; #define IPW_RX_NOTIFICATION_SIZE sizeof(struct ipw_rx_header) + 12 #define IPW_RX_FRAME_SIZE (unsigned int)(sizeof(struct ipw_rx_header) + \ @@ -717,7 +717,7 @@ struct ipw_rx_mem_buffer { dma_addr_t dma_addr; struct sk_buff *skb; struct list_head list; -}; /* Not transferred over network, so not __attribute__ ((packed)) */ +}; /* Not transferred over network, so not __packed */ struct ipw_rx_queue { struct ipw_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; @@ -730,7 +730,7 @@ struct ipw_rx_queue { struct list_head rx_free; /* Own an SKBs */ struct list_head rx_used; /* No SKB allocated */ spinlock_t lock; -}; /* Not transferred over network, so not __attribute__ ((packed)) */ +}; /* Not transferred over network, so not __packed */ struct alive_command_responce { u8 alive_command; @@ -745,21 +745,21 @@ struct alive_command_responce { __le16 reserved4; u8 time_stamp[5]; /* month, day, year, hours, minutes */ u8 ucode_valid; -} __attribute__ ((packed)); +} __packed; #define IPW_MAX_RATES 12 struct ipw_rates { u8 num_rates; u8 rates[IPW_MAX_RATES]; -} __attribute__ ((packed)); +} __packed; struct command_block { unsigned int control; u32 source_addr; u32 dest_addr; unsigned int status; -} __attribute__ ((packed)); +} __packed; #define CB_NUMBER_OF_ELEMENTS_SMALL 64 struct fw_image_desc { @@ -792,7 +792,7 @@ struct ipw_sys_config { u8 accept_all_mgmt_frames; u8 pass_noise_stats_to_host; u8 reserved3; -} __attribute__ ((packed)); +} __packed; struct ipw_multicast_addr { u8 num_of_multicast_addresses; @@ -801,7 +801,7 @@ struct ipw_multicast_addr { u8 mac2[6]; u8 mac3[6]; u8 mac4[6]; -} __attribute__ ((packed)); +} __packed; #define DCW_WEP_KEY_INDEX_MASK 0x03 /* bits [0:1] */ #define DCW_WEP_KEY_SEC_TYPE_MASK 0x30 /* bits [4:5] */ @@ -822,7 +822,7 @@ struct ipw_wep_key { u8 key_index; u8 key_size; u8 key[16]; -} __attribute__ ((packed)); +} __packed; struct ipw_tgi_tx_key { u8 key_id; @@ -831,7 +831,7 @@ struct ipw_tgi_tx_key { u8 flags; u8 key[16]; __le32 tx_counter[2]; -} __attribute__ ((packed)); +} __packed; #define IPW_SCAN_CHANNELS 54 @@ -840,7 +840,7 @@ struct ipw_scan_request { __le16 dwell_time; u8 channels_list[IPW_SCAN_CHANNELS]; u8 channels_reserved[3]; -} __attribute__ ((packed)); +} __packed; enum { IPW_SCAN_PASSIVE_TILL_FIRST_BEACON_SCAN = 0, @@ -857,7 +857,7 @@ struct ipw_scan_request_ext { u8 scan_type[IPW_SCAN_CHANNELS / 2]; u8 reserved; __le16 dwell_time[IPW_SCAN_TYPES]; -} __attribute__ ((packed)); +} __packed; static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) { @@ -902,7 +902,7 @@ struct ipw_associate { u8 smr; u8 reserved1; __le16 reserved2; -} __attribute__ ((packed)); +} __packed; struct ipw_supported_rates { u8 ieee_mode; @@ -910,36 +910,36 @@ struct ipw_supported_rates { u8 purpose; u8 reserved; u8 supported_rates[IPW_MAX_RATES]; -} __attribute__ ((packed)); +} __packed; struct ipw_rts_threshold { __le16 rts_threshold; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_frag_threshold { __le16 frag_threshold; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_retry_limit { u8 short_retry_limit; u8 long_retry_limit; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_dino_config { __le32 dino_config_addr; __le16 dino_config_size; u8 dino_response; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_aironet_info { u8 id; u8 length; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_rx_key { u8 station_index; @@ -950,25 +950,25 @@ struct ipw_rx_key { u8 station_address[6]; u8 key_index; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct ipw_country_channel_info { u8 first_channel; u8 no_channels; s8 max_tx_power; -} __attribute__ ((packed)); +} __packed; struct ipw_country_info { u8 id; u8 length; u8 country_str[3]; struct ipw_country_channel_info groups[7]; -} __attribute__ ((packed)); +} __packed; struct ipw_channel_tx_power { u8 channel_number; s8 tx_power; -} __attribute__ ((packed)); +} __packed; #define SCAN_ASSOCIATED_INTERVAL (HZ) #define SCAN_INTERVAL (HZ / 10) @@ -979,18 +979,18 @@ struct ipw_tx_power { u8 num_channels; u8 ieee_mode; struct ipw_channel_tx_power channels_tx_power[MAX_A_CHANNELS]; -} __attribute__ ((packed)); +} __packed; struct ipw_rsn_capabilities { u8 id; u8 length; __le16 version; -} __attribute__ ((packed)); +} __packed; struct ipw_sensitivity_calib { __le16 beacon_rssi_raw; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /** * Host command structure. @@ -1019,7 +1019,7 @@ struct ipw_cmd { /* XXX */ * nParams=(len+3)/4+status_len */ u32 param[0]; -} __attribute__ ((packed)); +} __packed; #define STATUS_HCMD_ACTIVE (1<<0) /**< host command in progress */ @@ -1114,7 +1114,7 @@ struct ipw_event { /* XXX */ u32 event; u32 time; u32 data; -} __attribute__ ((packed)); +} __packed; struct ipw_fw_error { /* XXX */ unsigned long jiffies; @@ -1125,7 +1125,7 @@ struct ipw_fw_error { /* XXX */ struct ipw_error_elem *elem; struct ipw_event *log; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; #ifdef CONFIG_IPW2200_PROMISCUOUS @@ -1170,7 +1170,7 @@ struct ipw_rt_hdr { s8 rt_dbmnoise; u8 rt_antenna; /* antenna number */ u8 payload[0]; /* payload... */ -} __attribute__ ((packed)); +} __packed; #endif struct ipw_priv { @@ -1957,7 +1957,7 @@ enum { struct ipw_fixed_rate { __le16 tx_rates; __le16 reserved; -} __attribute__ ((packed)); +} __packed; #define IPW_INDIRECT_ADDR_MASK (~0x3ul) @@ -1966,14 +1966,14 @@ struct host_cmd { u8 len; u16 reserved; u32 *param; -} __attribute__ ((packed)); /* XXX */ +} __packed; /* XXX */ struct cmdlog_host_cmd { u8 cmd; u8 len; __le16 reserved; char param[124]; -} __attribute__ ((packed)); +} __packed; struct ipw_cmd_log { unsigned long jiffies; diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 284b0e4cb815..4736861bc4f8 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -154,7 +154,7 @@ struct libipw_snap_hdr { u8 ctrl; /* always 0x03 */ u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __attribute__ ((packed)); +} __packed; #define SNAP_SIZE sizeof(struct libipw_snap_hdr) @@ -323,7 +323,7 @@ struct libipw_security { u8 keys[WEP_KEYS][SCM_KEY_LEN]; u8 level; u16 flags; -} __attribute__ ((packed)); +} __packed; /* @@ -347,7 +347,7 @@ struct libipw_hdr_1addr { __le16 duration_id; u8 addr1[ETH_ALEN]; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_hdr_2addr { __le16 frame_ctl; @@ -355,7 +355,7 @@ struct libipw_hdr_2addr { u8 addr1[ETH_ALEN]; u8 addr2[ETH_ALEN]; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_hdr_3addr { __le16 frame_ctl; @@ -365,7 +365,7 @@ struct libipw_hdr_3addr { u8 addr3[ETH_ALEN]; __le16 seq_ctl; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_hdr_4addr { __le16 frame_ctl; @@ -376,7 +376,7 @@ struct libipw_hdr_4addr { __le16 seq_ctl; u8 addr4[ETH_ALEN]; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_hdr_3addrqos { __le16 frame_ctl; @@ -387,13 +387,13 @@ struct libipw_hdr_3addrqos { __le16 seq_ctl; u8 payload[0]; __le16 qos_ctl; -} __attribute__ ((packed)); +} __packed; struct libipw_info_element { u8 id; u8 len; u8 data[0]; -} __attribute__ ((packed)); +} __packed; /* * These are the data types that can make up management packets @@ -406,7 +406,7 @@ struct libipw_info_element { u16 listen_interval; struct { u16 association_id:14, reserved:2; - } __attribute__ ((packed)); + } __packed; u32 time_stamp[2]; u16 reason; u16 status; @@ -419,7 +419,7 @@ struct libipw_auth { __le16 status; /* challenge */ struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_channel_switch { u8 id; @@ -427,7 +427,7 @@ struct libipw_channel_switch { u8 mode; u8 channel; u8 count; -} __attribute__ ((packed)); +} __packed; struct libipw_action { struct libipw_hdr_3addr header; @@ -441,12 +441,12 @@ struct libipw_action { struct libipw_channel_switch channel_switch; } format; -} __attribute__ ((packed)); +} __packed; struct libipw_disassoc { struct libipw_hdr_3addr header; __le16 reason; -} __attribute__ ((packed)); +} __packed; /* Alias deauth for disassoc */ #define libipw_deauth libipw_disassoc @@ -455,7 +455,7 @@ struct libipw_probe_request { struct libipw_hdr_3addr header; /* SSID, supported rates */ struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_probe_response { struct libipw_hdr_3addr header; @@ -465,7 +465,7 @@ struct libipw_probe_response { /* SSID, supported rates, FH params, DS params, * CF params, IBSS params, TIM (if beacon), RSN */ struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; /* Alias beacon for probe_response */ #define libipw_beacon libipw_probe_response @@ -476,7 +476,7 @@ struct libipw_assoc_request { __le16 listen_interval; /* SSID, supported rates, RSN */ struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_reassoc_request { struct libipw_hdr_3addr header; @@ -484,7 +484,7 @@ struct libipw_reassoc_request { __le16 listen_interval; u8 current_ap[ETH_ALEN]; struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_assoc_response { struct libipw_hdr_3addr header; @@ -493,7 +493,7 @@ struct libipw_assoc_response { __le16 aid; /* supported rates */ struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_txb { u8 nr_frags; @@ -555,19 +555,19 @@ struct libipw_qos_information_element { u8 qui_subtype; u8 version; u8 ac_info; -} __attribute__ ((packed)); +} __packed; struct libipw_qos_ac_parameter { u8 aci_aifsn; u8 ecw_min_max; __le16 tx_op_limit; -} __attribute__ ((packed)); +} __packed; struct libipw_qos_parameter_info { struct libipw_qos_information_element info_element; u8 reserved; struct libipw_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; -} __attribute__ ((packed)); +} __packed; struct libipw_qos_parameters { __le16 cw_min[QOS_QUEUE_NUM]; @@ -575,7 +575,7 @@ struct libipw_qos_parameters { u8 aifs[QOS_QUEUE_NUM]; u8 flag[QOS_QUEUE_NUM]; __le16 tx_op_limit[QOS_QUEUE_NUM]; -} __attribute__ ((packed)); +} __packed; struct libipw_qos_data { struct libipw_qos_parameters parameters; @@ -588,7 +588,7 @@ struct libipw_qos_data { struct libipw_tim_parameters { u8 tim_count; u8 tim_period; -} __attribute__ ((packed)); +} __packed; /*******************************************************/ @@ -606,7 +606,7 @@ struct libipw_basic_report { __le64 start_time; __le16 duration; u8 map; -} __attribute__ ((packed)); +} __packed; enum { /* libipw_measurement_request.mode */ /* Bit 0 is reserved */ @@ -627,7 +627,7 @@ struct libipw_measurement_params { u8 channel; __le64 start_time; __le16 duration; -} __attribute__ ((packed)); +} __packed; struct libipw_measurement_request { struct libipw_info_element ie; @@ -635,7 +635,7 @@ struct libipw_measurement_request { u8 mode; u8 type; struct libipw_measurement_params params[0]; -} __attribute__ ((packed)); +} __packed; struct libipw_measurement_report { struct libipw_info_element ie; @@ -645,17 +645,17 @@ struct libipw_measurement_report { union { struct libipw_basic_report basic[0]; } u; -} __attribute__ ((packed)); +} __packed; struct libipw_tpc_report { u8 transmit_power; u8 link_margin; -} __attribute__ ((packed)); +} __packed; struct libipw_channel_map { u8 channel; u8 map; -} __attribute__ ((packed)); +} __packed; struct libipw_ibss_dfs { struct libipw_info_element ie; @@ -668,14 +668,14 @@ struct libipw_csa { u8 mode; u8 channel; u8 count; -} __attribute__ ((packed)); +} __packed; struct libipw_quiet { u8 count; u8 period; u8 duration; u8 offset; -} __attribute__ ((packed)); +} __packed; struct libipw_network { /* These entries are used to identify a unique network */ diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index dc8ed1527666..6491e27baac5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -30,9 +30,11 @@ config IWLWIFI_DEBUG config IWLWIFI_DEBUGFS bool "iwlagn debugfs support" - depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS + depends on IWLWIFI && MAC80211_DEBUGFS ---help--- - Enable creation of debugfs files for the iwlwifi drivers. + Enable creation of debugfs files for the iwlwifi drivers. This + is a low-impact option that allows getting insight into the + driver's state at runtime. config IWLWIFI_DEVICE_TRACING bool "iwlwifi device access tracing" diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 6be2992f8f21..dba91e0233b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -158,6 +158,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c index 6a9c64a50e36..ef0835b01b6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c @@ -28,6 +28,28 @@ #include "iwl-3945-debugfs.h" + +static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) +{ + int p = 0; + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", + le32_to_cpu(priv->_3945.statistics.flag)); + if (le32_to_cpu(priv->_3945.statistics.flag) & + UCODE_STATISTICS_CLEAR_MSK) + p += scnprintf(buf + p, bufsz - p, + "\tStatistics have been cleared\n"); + p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", + (le32_to_cpu(priv->_3945.statistics.flag) & + UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); + p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", + (le32_to_cpu(priv->_3945.statistics.flag) & + UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + return p; +} + ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -70,7 +92,7 @@ ssize_t iwl3945_ucode_rx_stats_read(struct file *file, max_cck = &priv->_3945.max_delta.rx.cck; max_general = &priv->_3945.max_delta.rx.general; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl3945_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_Rx - OFDM:"); @@ -331,7 +353,7 @@ ssize_t iwl3945_ucode_tx_stats_read(struct file *file, accum_tx = &priv->_3945.accum_statistics.tx; delta_tx = &priv->_3945.delta_statistics.tx; max_tx = &priv->_3945.max_delta.tx; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl3945_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_Tx:"); @@ -438,7 +460,7 @@ ssize_t iwl3945_ucode_general_stats_read(struct file *file, accum_div = &priv->_3945.accum_statistics.general.div; delta_div = &priv->_3945.delta_statistics.general.div; max_div = &priv->_3945.max_delta.general.div; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl3945_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_General:"); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h index 042f6bc0df13..2c9ed2b502a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h @@ -175,13 +175,13 @@ struct iwl3945_tfd_tb { __le32 addr; __le32 len; -} __attribute__ ((packed)); +} __packed; struct iwl3945_tfd { __le32 control_flags; struct iwl3945_tfd_tb tbs[4]; u8 __pad[28]; -} __attribute__ ((packed)); +} __packed; #endif /* __iwl_3945_fh_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 91bcb4e3cdfb..7c731a793632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -96,7 +96,7 @@ struct iwl3945_eeprom_txpower_sample { u8 gain_index; /* index into power (gain) setup table ... */ s8 power; /* ... for this pwr level for this chnl group */ u16 v_det; /* PA output voltage */ -} __attribute__ ((packed)); +} __packed; /* * Mappings of Tx power levels -> nominal radio/DSP gain table indexes. @@ -117,7 +117,7 @@ struct iwl3945_eeprom_txpower_group { u8 group_channel; /* "representative" channel # in this band */ s16 temperature; /* h/w temperature at factory calib this band * (signed) */ -} __attribute__ ((packed)); +} __packed; /* * Temperature-based Tx-power compensation data, not band-specific. @@ -131,7 +131,7 @@ struct iwl3945_eeprom_temperature_corr { u32 Tc; u32 Td; u32 Te; -} __attribute__ ((packed)); +} __packed; /* * EEPROM map @@ -215,7 +215,7 @@ struct iwl3945_eeprom { /* abs.ofs: 512 */ struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ u8 reserved16[172]; /* fill out to full 1024 byte block */ -} __attribute__ ((packed)); +} __packed; #define IWL3945_EEPROM_IMG_SIZE 1024 @@ -274,7 +274,7 @@ static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */ struct iwl3945_shared { __le32 tx_base_ptr[8]; -} __attribute__ ((packed)); +} __packed; static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index c44a303e62ed..93d513e14186 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -279,8 +279,8 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); - tx_info->skb[0] = NULL; + ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); + tx_info->skb = NULL; priv->cfg->ops->lib->txq_free_tfd(priv, txq); } @@ -315,7 +315,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, return; } - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); + info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); ieee80211_tx_info_clear_status(info); /* Fill the MRR chain with some info about on-chip retransmissions */ @@ -352,7 +352,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, * RX handler implementations * *****************************************************************************/ -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS /* * based on the assumption of all statistics counter are in DWORD * FIXME: This function is for debugging, do not deal with @@ -460,7 +460,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); #endif iwl_recover_from_statistics(priv, pkt); @@ -475,7 +475,7 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, __le32 *flag = (__le32 *)&pkt->u.raw; if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS memset(&priv->_3945.accum_statistics, 0, sizeof(struct iwl3945_notif_statistics)); memset(&priv->_3945.delta_statistics, 0, @@ -494,158 +494,6 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, * Misc. internal state and helper functions * ******************************************************************************/ -#ifdef CONFIG_IWLWIFI_DEBUG - -/** - * iwl3945_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good frames. - */ -static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - __le16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - u16 length; - u16 status; - u16 bcn_tmr; - u32 tsf_low; - u64 tsf; - u8 rssi; - u8 agc; - u16 sig_avg; - u16 noise_diff; - struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u8 *data = IWL_RX_DATA(pkt); - - /* MAC header */ - fc = header->frame_control; - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(rx_hdr->channel); - phy_flags = le16_to_cpu(rx_hdr->phy_flags); - length = le16_to_cpu(rx_hdr->len); - - /* end-of-frame status and timestamp */ - status = le32_to_cpu(rx_end->status); - bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); - tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; - tsf = le64_to_cpu(rx_end->timestamp); - - /* signal statistics */ - rssi = rx_stats->rssi; - agc = rx_stats->agc; - sig_avg = le16_to_cpu(rx_stats->sig_avg); - noise_diff = le16_to_cpu(rx_stats->noise_diff); - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == - cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - int rate; - - if (hundred) - title = "100Frames"; - else if (ieee80211_has_retry(fc)) - title = "Retry"; - else if (ieee80211_is_assoc_resp(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_resp(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_resp(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); - if (rate == -1) - rate = 0; - else - rate = iwl3945_rates[rate].ieee / 2; - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%d,\n", - title, le16_to_cpu(fc), header->addr1[5], - length, rssi, channel, rate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, " - "src=0x%02x, rssi=%u, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, le16_to_cpu(fc), header->addr1[5], - header->addr3[5], rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, data, length); -} - -static void iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - if (iwl_get_debug_level(priv) & IWL_DL_RX) - _iwl3945_dbg_report_frame(priv, pkt, header, group100); -} - -#else -static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ -} -#endif /* This is necessary only for a number of statistics, see the caller. */ static int iwl3945_is_network_packet(struct iwl_priv *priv, @@ -777,8 +625,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, rx_status.signal, rx_status.signal, rx_status.rate_idx); - /* Set "1" to report good data frames in groups of 100 */ - iwl3945_dbg_report_frame(priv, pkt, header, 1); iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); if (network_packet) { @@ -850,25 +696,28 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* Unmap tx_cmd */ if (counter) pci_unmap_single(dev, - pci_unmap_addr(&txq->meta[index], mapping), - pci_unmap_len(&txq->meta[index], len), + dma_unmap_addr(&txq->meta[index], mapping), + dma_unmap_len(&txq->meta[index], len), PCI_DMA_TODEVICE); /* unmap chunks if any */ - for (i = 1; i < counter; i++) { + for (i = 1; i < counter; i++) pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); - if (txq->txb[txq->q.read_ptr].skb[0]) { - struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0]; - if (txq->txb[txq->q.read_ptr].skb[0]) { - /* Can be called from interrupt context */ - dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb[0] = NULL; - } + + /* free SKB */ + if (txq->txb) { + struct sk_buff *skb; + + skb = txq->txb[txq->q.read_ptr].skb; + + /* can be called from irqs-disabled context */ + if (skb) { + dev_kfree_skb_any(skb); + txq->txb[txq->q.read_ptr].skb = NULL; } } - return ; } /** @@ -947,8 +796,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); } -static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags) +static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate) { unsigned long flags_spin; struct iwl_station_entry *station; @@ -962,10 +810,9 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; station->sta.rate_n_flags = cpu_to_le16(tx_rate); station->sta.mode = STA_CONTROL_MODIFY_MSK; - + iwl_send_add_sta(priv, &station->sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - iwl_send_add_sta(priv, &station->sta, flags); IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", sta_id, tx_rate); return sta_id; @@ -997,7 +844,7 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { - iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); + iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma); iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), @@ -2473,8 +2320,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, - CMD_ASYNC); + IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP); iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); return 0; @@ -2590,6 +2436,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; + priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index cd4b61ae25b7..9166794eda0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -787,6 +787,6 @@ enum { struct iwl4965_scd_bc_tbl { __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; -} __attribute__ ((packed)); +} __packed; #endif /* !__iwl_4965_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d3afddae8d9f..83e6a42ca2da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) { struct iwl_chain_noise_data *data = &(priv->chain_noise_data); - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { + if ((data->state == IWL_CHAIN_NOISE_ALIVE) && + iwl_is_associated(priv)) { struct iwl_calib_diff_gain_cmd cmd; + /* clear data for chain noise calibration algorithm */ + data->chain_noise_a = 0; + data->chain_noise_b = 0; + data->chain_noise_c = 0; + data->chain_signal_a = 0; + data->chain_signal_b = 0; + data->chain_signal_c = 0; + data->beacon_count = 0; + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; cmd.diff_gain_a = 0; @@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, /* Mark so we run this algo only once! */ data->state = IWL_CHAIN_NOISE_CALIBRATED; } - data->chain_noise_a = 0; - data->chain_noise_b = 0; - data->chain_noise_c = 0; - data->chain_signal_a = 0; - data->chain_signal_b = 0; - data->chain_signal_c = 0; - data->beacon_count = 0; } static void iwl4965_bg_txpower_work(struct work_struct *work) @@ -669,6 +672,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); priv->hw_params.sens = &iwl4965_sensitivity; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -1441,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) return ret; } -static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) +static int iwl4965_hw_channel_switch(struct iwl_priv *priv, + struct ieee80211_channel_switch *ch_switch) { int rc; u8 band = 0; @@ -1449,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) u8 ctrl_chan_high = 0; struct iwl4965_channel_switch_cmd cmd; const struct iwl_channel_info *ch_info; - + u32 switch_time_in_usec, ucode_switch_time; + u16 ch; + u32 tsf_low; + u8 switch_count; + u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + struct ieee80211_vif *vif = priv->vif; band = priv->band == IEEE80211_BAND_2GHZ; - ch_info = iwl_get_channel_info(priv, priv->band, channel); - is_ht40 = is_ht40_channel(priv->staging_rxon.flags); if (is_ht40 && @@ -1462,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) cmd.band = band; cmd.expect_beacon = 0; - cmd.channel = cpu_to_le16(channel); + ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + cmd.channel = cpu_to_le16(ch); cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + switch_count = ch_switch->count; + tsf_low = ch_switch->timestamp & 0x0ffffffff; + /* + * calculate the ucode channel switch time + * adding TSF as one of the factor for when to switch + */ + if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { + if (switch_count > ((priv->ucode_beacon_time - tsf_low) / + beacon_interval)) { + switch_count -= (priv->ucode_beacon_time - + tsf_low) / beacon_interval; + } else + switch_count = 0; + } + if (switch_count <= 1) + cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + else { + switch_time_in_usec = + vif->bss_conf.beacon_int * switch_count * TIME_UNIT; + ucode_switch_time = iwl_usecs_to_beacons(priv, + switch_time_in_usec, + beacon_interval); + cmd.switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); + } + IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", + cmd.switch_time); + ch_info = iwl_get_channel_info(priv, priv->band, ch); if (ch_info) cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, channel); + priv->active_rxon.channel, ch); return -EFAULT; } - rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, + rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40, ctrl_chan_high, &cmd.tx_power); if (rc) { IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); return rc; } - priv->switch_rxon.channel = cpu_to_le16(channel); + priv->switch_rxon.channel = cmd.channel; priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); @@ -1870,7 +1908,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); + info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_tx_status_to_mac80211(status); @@ -2026,6 +2064,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, int sta_id; int freed; u8 *qc = NULL; + unsigned long flags; if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " @@ -2035,7 +2074,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, return; } - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); + info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); memset(&info->status, 0, sizeof(info->status)); hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); @@ -2050,10 +2089,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, return; } + spin_lock_irqsave(&priv->sta_lock, flags); if (txq->sched_retry) { const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); struct iwl_ht_agg *agg = NULL; - WARN_ON(!qc); agg = &priv->stations[sta_id].tid[tid].agg; @@ -2110,6 +2149,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); iwl_check_abort_status(priv, tx_resp->frame_count, status); + + spin_unlock_irqrestore(&priv->sta_lock, flags); } static int iwl4965_calc_rssi(struct iwl_priv *priv, @@ -2285,7 +2326,7 @@ struct iwl_cfg iwl4965_agn_cfg = { * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. */ - .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, + .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a28af7eb67eb..32710a801cb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -208,6 +208,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + return 0; } @@ -252,6 +254,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + return 0; } @@ -267,33 +271,69 @@ static void iwl5150_temperature(struct iwl_priv *priv) iwl_tt_handler(priv); } -static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) +static int iwl5000_hw_channel_switch(struct iwl_priv *priv, + struct ieee80211_channel_switch *ch_switch) { struct iwl5000_channel_switch_cmd cmd; const struct iwl_channel_info *ch_info; + u32 switch_time_in_usec, ucode_switch_time; + u16 ch; + u32 tsf_low; + u8 switch_count; + u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + struct ieee80211_vif *vif = priv->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, .len = sizeof(cmd), - .flags = CMD_SIZE_HUGE, + .flags = CMD_SYNC, .data = &cmd, }; - IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", - priv->active_rxon.channel, channel); cmd.band = priv->band == IEEE80211_BAND_2GHZ; - cmd.channel = cpu_to_le16(channel); + ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", + priv->active_rxon.channel, ch); + cmd.channel = cpu_to_le16(ch); cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); - ch_info = iwl_get_channel_info(priv, priv->band, channel); + switch_count = ch_switch->count; + tsf_low = ch_switch->timestamp & 0x0ffffffff; + /* + * calculate the ucode channel switch time + * adding TSF as one of the factor for when to switch + */ + if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { + if (switch_count > ((priv->ucode_beacon_time - tsf_low) / + beacon_interval)) { + switch_count -= (priv->ucode_beacon_time - + tsf_low) / beacon_interval; + } else + switch_count = 0; + } + if (switch_count <= 1) + cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + else { + switch_time_in_usec = + vif->bss_conf.beacon_int * switch_count * TIME_UNIT; + ucode_switch_time = iwl_usecs_to_beacons(priv, + switch_time_in_usec, + beacon_interval); + cmd.switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); + } + IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", + cmd.switch_time); + ch_info = iwl_get_channel_info(priv, priv->band, ch); if (ch_info) cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, channel); + priv->active_rxon.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cpu_to_le16(channel); + priv->switch_rxon.channel = cmd.channel; priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9fbf54cd3e1a..afdeec56b13f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -71,6 +71,10 @@ #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) +#define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-" +#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" +#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) + static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { @@ -183,6 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + return 0; } @@ -228,37 +234,74 @@ static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + return 0; } -static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) +static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + struct ieee80211_channel_switch *ch_switch) { struct iwl6000_channel_switch_cmd cmd; const struct iwl_channel_info *ch_info; + u32 switch_time_in_usec, ucode_switch_time; + u16 ch; + u32 tsf_low; + u8 switch_count; + u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); + struct ieee80211_vif *vif = priv->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, .len = sizeof(cmd), - .flags = CMD_SIZE_HUGE, + .flags = CMD_SYNC, .data = &cmd, }; - IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", - priv->active_rxon.channel, channel); - cmd.band = priv->band == IEEE80211_BAND_2GHZ; - cmd.channel = cpu_to_le16(channel); + ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); + IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", + priv->active_rxon.channel, ch); + cmd.channel = cpu_to_le16(ch); cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); - ch_info = iwl_get_channel_info(priv, priv->band, channel); + switch_count = ch_switch->count; + tsf_low = ch_switch->timestamp & 0x0ffffffff; + /* + * calculate the ucode channel switch time + * adding TSF as one of the factor for when to switch + */ + if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { + if (switch_count > ((priv->ucode_beacon_time - tsf_low) / + beacon_interval)) { + switch_count -= (priv->ucode_beacon_time - + tsf_low) / beacon_interval; + } else + switch_count = 0; + } + if (switch_count <= 1) + cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + else { + switch_time_in_usec = + vif->bss_conf.beacon_int * switch_count * TIME_UNIT; + ucode_switch_time = iwl_usecs_to_beacons(priv, + switch_time_in_usec, + beacon_interval); + cmd.switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); + } + IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", + cmd.switch_time); + ch_info = iwl_get_channel_info(priv, priv->band, ch); if (ch_info) cmd.expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", - priv->active_rxon.channel, channel); + priv->active_rxon.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cpu_to_le16(channel); + priv->switch_rxon.channel = cmd.channel; priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); @@ -335,6 +378,25 @@ static const struct iwl_ops iwl6000_ops = { .led = &iwlagn_led_ops, }; +static void do_not_send_bt_config(struct iwl_priv *priv) +{ +} + +static struct iwl_hcmd_ops iwl6000g2b_hcmd = { + .rxon_assoc = iwlagn_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, + .set_tx_ant = iwlagn_send_tx_ant_config, + .send_bt_config = do_not_send_bt_config, +}; + +static const struct iwl_ops iwl6000g2b_ops = { + .lib = &iwl6000_lib, + .hcmd = &iwl6000g2b_hcmd, + .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, +}; + static struct iwl_lib_ops iwl6050_lib = { .set_hw_params = iwl6050_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, @@ -445,6 +507,268 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .chain_noise_calib_by_driver = true, }; +struct iwl_cfg iwl6000g2a_2abg_cfg = { + .name = "6000 Series 2x2 ABG Gen2a", + .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, + .ops = &iwl6000_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2a_2bg_cfg = { + .name = "6000 Series 2x2 BG Gen2a", + .fw_name_pre = IWL6000G2A_FW_PRE, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, + .sku = IWL_SKU_G, + .ops = &iwl6000_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_2agn_cfg = { + .name = "6000 Series 2x2 AGN Gen2b", + .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, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .ht_greenfield_support = true, + .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_2abg_cfg = { + .name = "6000 Series 2x2 ABG Gen2b", + .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, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_2bgn_cfg = { + .name = "6000 Series 2x2 BGN Gen2b", + .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, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .ht_greenfield_support = true, + .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_2bg_cfg = { + .name = "6000 Series 2x2 BG Gen2b", + .fw_name_pre = IWL6000G2B_FW_PRE, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, + .sku = IWL_SKU_G, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_AB, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_bgn_cfg = { + .name = "6000 Series 1x2 BGN Gen2b", + .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, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_A, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .ht_greenfield_support = true, + .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + +struct iwl_cfg iwl6000g2b_bg_cfg = { + .name = "6000 Series 1x2 BG Gen2b", + .fw_name_pre = IWL6000G2B_FW_PRE, + .ucode_api_max = IWL6000G2_UCODE_API_MAX, + .ucode_api_min = IWL6000G2_UCODE_API_MIN, + .sku = IWL_SKU_G, + .ops = &iwl6000g2b_ops, + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .mod_params = &iwlagn_mod_params, + .valid_tx_ant = ANT_A, + .valid_rx_ant = ANT_AB, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, +}; + /* * "i": Internal configuration, use internal Power Amplifier */ @@ -667,3 +991,4 @@ struct iwl_cfg iwl6000_3agn_cfg = { 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)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 48c023b4ca36..3d08dc8af143 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -28,6 +28,27 @@ #include "iwl-agn-debugfs.h" +static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) +{ + int p = 0; + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", + le32_to_cpu(priv->statistics.flag)); + if (le32_to_cpu(priv->statistics.flag) & + UCODE_STATISTICS_CLEAR_MSK) + p += scnprintf(buf + p, bufsz - p, + "\tStatistics have been cleared\n"); + p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", + (le32_to_cpu(priv->statistics.flag) & + UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); + p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", + (le32_to_cpu(priv->statistics.flag) & + UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + return p; +} + ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -75,7 +96,7 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, max_general = &priv->max_delta.rx.general; max_ht = &priv->max_delta.rx.ofdm_ht; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_Rx - OFDM:"); @@ -543,7 +564,7 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, accum_tx = &priv->accum_statistics.tx; delta_tx = &priv->delta_statistics.tx; max_tx = &priv->max_delta.tx; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_Tx:"); @@ -768,7 +789,7 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, accum_div = &priv->accum_statistics.general.div; delta_div = &priv->delta_statistics.general.div; max_div = &priv->max_delta.general.div; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", "Statistics_General:"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 44ef5d93befc..3f765ba15cb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -37,7 +37,7 @@ #include "iwl-io.h" #include "iwl-agn.h" -static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) +int iwlagn_send_rxon_assoc(struct iwl_priv *priv) { int ret = 0; struct iwl5000_rxon_assoc_cmd rxon_assoc; @@ -84,7 +84,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) return ret; } -static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) +int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) { struct iwl_tx_ant_config_cmd tx_ant_cmd = { .valid = cpu_to_le32(valid_tx_ant), @@ -176,14 +176,6 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, data->radio_write = 1; data->state = IWL_CHAIN_NOISE_CALIBRATED; } - - data->chain_noise_a = 0; - data->chain_noise_b = 0; - data->chain_noise_c = 0; - data->chain_signal_a = 0; - data->chain_signal_b = 0; - data->chain_signal_c = 0; - data->beacon_count = 0; } static void iwlagn_chain_noise_reset(struct iwl_priv *priv) @@ -191,10 +183,20 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) struct iwl_chain_noise_data *data = &priv->chain_noise_data; int ret; - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { + if ((data->state == IWL_CHAIN_NOISE_ALIVE) && + iwl_is_associated(priv)) { struct iwl_calib_chain_noise_reset_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); + /* clear data for chain noise calibration algorithm */ + data->chain_noise_a = 0; + data->chain_noise_b = 0; + data->chain_noise_c = 0; + data->chain_signal_a = 0; + data->chain_signal_b = 0; + data->chain_signal_c = 0; + data->beacon_count = 0; + + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index f9a3fbb6338f..a52b82c8e7a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -112,7 +112,7 @@ */ struct iwlagn_scd_bc_tbl { __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __attribute__ ((packed)); +} __packed; #endif /* __iwl_agn_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0f292a210ed9..0e7b0661d61d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -77,7 +77,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); + info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_tx_status_to_mac80211(status); @@ -93,6 +93,12 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, } else { /* Two or more frames were attempted; expect block-ack */ u64 bitmap = 0; + + /* + * Start is the lowest frame sent. It may not be the first + * frame in the batch; we figure this out dynamically during + * the following loop. + */ int start = agg->start_idx; /* Construct bit-map of pending frames within Tx window */ @@ -131,25 +137,58 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", i, idx, SEQ_TO_SN(sc)); + /* + * sh -> how many frames ahead of the starting frame is + * the current one? + * + * Note that all frames sent in the batch must be in a + * 64-frame window, so this number should be in [0,63]. + * If outside of this window, then we've found a new + * "first" frame in the batch and need to change start. + */ sh = idx - start; - if (sh > 64) { - sh = (start - idx) + 0xff; + + /* + * If >= 64, out of window. start must be at the front + * of the circular buffer, idx must be near the end of + * the buffer, and idx is the new "first" frame. Shift + * the indices around. + */ + if (sh >= 64) { + /* Shift bitmap by start - idx, wrapped */ + sh = 0x100 - idx + start; bitmap = bitmap << sh; + /* Now idx is the new start so sh = 0 */ sh = 0; start = idx; - } else if (sh < -64) - sh = 0xff - (start - idx); - else if (sh < 0) { + /* + * If <= -64 then wraps the 256-pkt circular buffer + * (e.g., start = 255 and idx = 0, sh should be 1) + */ + } else if (sh <= -64) { + sh = 0x100 - start + idx; + /* + * If < 0 but > -64, out of window. idx is before start + * but not wrapped. Shift the indices around. + */ + } else if (sh < 0) { + /* Shift by how far start is ahead of idx */ sh = start - idx; - start = idx; bitmap = bitmap << sh; + /* Now idx is the new start so sh = 0 */ + start = idx; sh = 0; } + /* Sequence number start + sh was sent in this batch */ bitmap |= 1ULL << sh; IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", start, (unsigned long long)bitmap); } + /* + * Store the bitmap and possibly the new start, if we wrapped + * the buffer above + */ agg->bitmap = bitmap; agg->start_idx = start; IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", @@ -184,6 +223,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, int tid; int sta_id; int freed; + unsigned long flags; if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " @@ -193,15 +233,16 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, return; } - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); + info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); memset(&info->status, 0, sizeof(info->status)); tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; + spin_lock_irqsave(&priv->sta_lock, flags); if (txq->sched_retry) { const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); - struct iwl_ht_agg *agg = NULL; + struct iwl_ht_agg *agg; agg = &priv->stations[sta_id].tid[tid].agg; @@ -256,6 +297,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); iwl_check_abort_status(priv, tx_resp->frame_count, status); + spin_unlock_irqrestore(&priv->sta_lock, flags); } void iwlagn_rx_handler_setup(struct iwl_priv *priv) @@ -444,7 +486,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) /* Tell device where to find RBD circular buffer in DRAM */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->dma_addr >> 8)); + (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, @@ -709,7 +751,7 @@ void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) } dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); + rxq->bd_dma); dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); rxq->bd = NULL; @@ -755,132 +797,6 @@ static inline int iwlagn_calc_rssi(struct iwl_priv *priv, return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); } -#ifdef CONFIG_IWLWIFI_DEBUG -/** - * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good data frames. - * All beacon and probe response frames are printed. - */ -static void iwlagn_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_phy_res *phy_res, u16 length, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - __le16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - u32 rate_n_flags; - u32 tsf_low; - int rssi; - - if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) - return; - - /* MAC header */ - fc = header->frame_control; - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(phy_res->channel); - phy_flags = le16_to_cpu(phy_res->phy_flags); - rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); - - /* signal statistics */ - rssi = iwlagn_calc_rssi(priv, phy_res); - tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == - cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - int rate_idx; - u32 bitrate; - - if (hundred) - title = "100Frames"; - else if (ieee80211_has_retry(fc)) - title = "Retry"; - else if (ieee80211_is_assoc_resp(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_resp(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_resp(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { - bitrate = 0; - WARN_ON_ONCE(1); - } else { - bitrate = iwl_rates[rate_idx].ieee / 2; - } - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u,\n", - title, le16_to_cpu(fc), header->addr1[5], - length, rssi, channel, bitrate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " - "len=%u, rssi=%d, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, le16_to_cpu(fc), header->addr1[5], - header->addr3[5], length, rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, header, length); -} -#endif - static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) { u32 decrypt_out = 0; @@ -988,7 +904,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_phy_res *phy_res; __le32 rx_pkt_status; - struct iwl4965_rx_mpdu_res_start *amsdu; + struct iwl_rx_mpdu_res_start *amsdu; u32 len; u32 ampdu_status; u32 rate_n_flags; @@ -1017,7 +933,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, return; } phy_res = &priv->_agn.last_phy_res; - amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; + amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); @@ -1060,11 +976,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, /* Find max signal strength (dBm) among 3 antenna/receiver chains */ rx_status.signal = iwlagn_calc_rssi(priv, phy_res); -#ifdef CONFIG_IWLWIFI_DEBUG - /* Set "1" to report good data frames in groups of 100 */ - if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) - iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); -#endif iwl_dbg_log_rx_data_frame(priv, len, header); IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", rx_status.signal, (unsigned long long)rx_status.mactime); @@ -1252,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) bool is_active = false; int chan_mod; u8 active_chains; + u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; conf = ieee80211_get_hw_conf(priv->hw); @@ -1403,11 +1315,14 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) band = priv->scan_band; - if (priv->cfg->scan_antennas[band]) - rx_ant = priv->cfg->scan_antennas[band]; + if (priv->cfg->scan_rx_antennas[band]) + rx_ant = priv->cfg->scan_rx_antennas[band]; - priv->scan_tx_ant[band] = - iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); + if (priv->cfg->scan_tx_antennas[band]) + scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; + + priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], + scan_tx_antennas); rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); @@ -1433,13 +1348,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (!priv->is_internal_short_scan) { cmd_len = iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, + vif->addr, priv->scan_request->ie, priv->scan_request->ie_len, IWL_MAX_SCAN_SIZE - sizeof(*scan)); } else { + /* use bcast addr, will not be transmitted but must be valid */ cmd_len = iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - NULL, 0, + iwl_bcast_addr, NULL, 0, IWL_MAX_SCAN_SIZE - sizeof(*scan)); } @@ -1502,3 +1419,18 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, vif->bss_conf.bssid); } + +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed) +{ + WARN_ON(!spin_is_locked(&priv->sta_lock)); + + if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + else { + IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", + priv->stations[sta_id].tid[tid].tfds_in_queue, + freed); + priv->stations[sta_id].tid[tid].tfds_in_queue = 0; + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cf4a95bae4ff..40933a5de027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -313,8 +313,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, */ IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", tid); - ieee80211_stop_tx_ba_session(sta, tid, - WLAN_BACK_INITIATOR); + ieee80211_stop_tx_ba_session(sta, tid); } } else IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7d614c4d3c62..84df7fca750d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -469,7 +469,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, } /* Set up antennas */ - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, + priv->hw_params.valid_tx_ant); rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* Set the rate in the TX cmd */ @@ -567,10 +568,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find index into station table for destination station */ - if (!info->control.sta) - sta_id = priv->hw_params.bcast_sta_id; - else - sta_id = iwl_sta_id(info->control.sta); + sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -598,11 +596,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); + + /* irqs already disabled/saved above when locking priv->lock */ + spin_lock(&priv->sta_lock); + if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - if (unlikely(tid >= MAX_TID_COUNT)) + if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { + spin_unlock(&priv->sta_lock); goto drop_unlock; + } seq_number = priv->stations[sta_id].tid[tid].seq_number; seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl = hdr->seq_ctrl & @@ -620,15 +624,22 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) swq_id = txq->swq_id; q = &txq->q; - if (unlikely(iwl_queue_space(q) < q->high_mark)) + if (unlikely(iwl_queue_space(q) < q->high_mark)) { + spin_unlock(&priv->sta_lock); goto drop_unlock; + } - if (ieee80211_is_data_qos(fc)) + if (ieee80211_is_data_qos(fc)) { priv->stations[sta_id].tid[tid].tfds_in_queue++; + if (!ieee80211_has_morefrags(fc)) + priv->stations[sta_id].tid[tid].seq_number = seq_number; + } + + spin_unlock(&priv->sta_lock); /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb[0] = skb; + txq->txb[q->write_ptr].skb = skb; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[q->write_ptr]; @@ -694,8 +705,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, len, PCI_DMA_BIDIRECTIONAL); - pci_unmap_addr_set(out_meta, mapping, txcmd_phys); - pci_unmap_len_set(out_meta, len, len); + dma_unmap_addr_set(out_meta, mapping, txcmd_phys); + dma_unmap_len_set(out_meta, len, len); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, @@ -703,8 +714,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; - if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; } else { wait_write_ptr = 1; txq->need_update = 0; @@ -1009,6 +1018,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, if (ret) return ret; + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; @@ -1018,6 +1029,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data->tfds_in_queue); tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; } + spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } @@ -1040,11 +1052,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } + spin_lock_irqsave(&priv->sta_lock, flags); + if (priv->stations[sta_id].tid[tid].agg.state == IWL_EMPTYING_HW_QUEUE_ADDBA) { IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -1062,13 +1077,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); priv->stations[sta_id].tid[tid].agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } IWL_DEBUG_HT(priv, "HW queue is empty\n"); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - spin_lock_irqsave(&priv->lock, flags); + /* do not restore/save irqs */ + spin_unlock(&priv->sta_lock); + spin_lock(&priv->lock); + /* * the only reason this call can fail is queue number out of range, * which can happen if uCode is reloaded and all the station @@ -1092,6 +1111,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u8 *addr = priv->stations[sta_id].sta.sta.addr; struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + WARN_ON(!spin_is_locked(&priv->sta_lock)); + switch (priv->stations[sta_id].tid[tid].agg.state) { case IWL_EMPTYING_HW_QUEUE_DELBA: /* We are reclaiming the last packet of the */ @@ -1116,6 +1137,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, } break; } + return 0; } @@ -1159,12 +1181,12 @@ 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->skb[0]); + iwlagn_tx_status(priv, tx_info->skb); - hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; + hdr = (struct ieee80211_hdr *)tx_info->skb->data; if (hdr && ieee80211_is_data_qos(hdr->frame_control)) nfreed++; - tx_info->skb[0] = NULL; + tx_info->skb = NULL; if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); @@ -1188,7 +1210,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, int i, sh, ack; u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - u64 bitmap; + u64 bitmap, sent_bitmap; int successes = 0; struct ieee80211_tx_info *info; @@ -1216,24 +1238,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* check for success or failure according to the * transmitted bitmap and block-ack bitmap */ - bitmap &= agg->bitmap; + sent_bitmap = bitmap & agg->bitmap; /* For each frame attempted in aggregation, * update driver's record of tx frame's status. */ - for (i = 0; i < agg->frame_count ; i++) { - ack = bitmap & (1ULL << i); - successes += !!ack; + 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[0]); + 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_ack_map = bitmap; info->status.ampdu_len = agg->frame_count; iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); @@ -1281,6 +1305,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, int index; int sta_id; int tid; + unsigned long flags; /* "flow" corresponds to Tx queue */ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); @@ -1308,7 +1333,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, /* Find index just before block-ack window */ index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); - /* TODO: Need to get this copy more safely - now good for debug */ + spin_lock_irqsave(&priv->sta_lock, flags); IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", @@ -1344,4 +1369,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); } + + spin_unlock_irqrestore(&priv->sta_lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 637286c396fe..6f77441cb65a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -423,3 +423,126 @@ int iwlagn_alive_notify(struct iwl_priv *priv) return 0; } + + +/** + * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, + * using sample data 100 bytes apart. If these sample points are good, + * it's a pretty good bet that everything between them is good, too. + */ +static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) +{ + u32 val; + int ret = 0; + u32 errcnt = 0; + u32 i; + + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); + + for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { + /* read data comes through single port, auto-incr addr */ + /* NOTE: Use the debugless read so we don't flood kernel log + * if IWL_DL_IO is set */ + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, + i + IWLAGN_RTC_INST_LOWER_BOUND); + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + ret = -EIO; + errcnt++; + if (errcnt >= 3) + break; + } + } + + return ret; +} + +/** + * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, + * looking at all data. + */ +static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, + u32 len) +{ + u32 val; + u32 save_len = len; + int ret = 0; + u32 errcnt; + + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); + + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, + IWLAGN_RTC_INST_LOWER_BOUND); + + errcnt = 0; + for (; len > 0; len -= sizeof(u32), image++) { + /* read data comes through single port, auto-incr addr */ + /* NOTE: Use the debugless read so we don't flood kernel log + * if IWL_DL_IO is set */ + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + IWL_ERR(priv, "uCode INST section is invalid at " + "offset 0x%x, is 0x%x, s/b 0x%x\n", + save_len - len, val, le32_to_cpu(*image)); + ret = -EIO; + errcnt++; + if (errcnt >= 20) + break; + } + } + + if (!errcnt) + IWL_DEBUG_INFO(priv, + "ucode image in INSTRUCTION memory is good\n"); + + return ret; +} + +/** + * iwl_verify_ucode - determine which instruction image is in SRAM, + * and verify its contents + */ +int iwl_verify_ucode(struct iwl_priv *priv) +{ + __le32 *image; + u32 len; + int ret; + + /* Try bootstrap */ + image = (__le32 *)priv->ucode_boot.v_addr; + len = priv->ucode_boot.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); + return 0; + } + + /* Try initialize */ + image = (__le32 *)priv->ucode_init.v_addr; + len = priv->ucode_init.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); + return 0; + } + + /* Try runtime/protocol */ + image = (__le32 *)priv->ucode_code.v_addr; + len = priv->ucode_code.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); + return 0; + } + + IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); + + /* Since nothing seems to match, show first several data entries in + * instruction SRAM, so maybe visual inspection will give a clue. + * Selection of bootstrap image (vs. other images) is arbitrary. */ + image = (__le32 *)priv->ucode_boot.v_addr; + len = priv->ucode_boot.len; + ret = iwl_verify_inst_full(priv, image, len); + + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24aff654fa9c..d857f8496f69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) (priv->switch_rxon.channel != priv->staging_rxon.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_rxon.channel)); - priv->switch_rxon.switch_in_progress = false; + iwl_chswitch_done(priv, false); } /* If we don't need to send a full RXON, we can use @@ -367,7 +367,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, /* Set up packet rate and flags */ rate = iwl_rate_get_lowest_plcp(priv); - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, + priv->hw_params.valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) rate_flags |= RATE_MCS_CCK_MSK; @@ -474,18 +475,25 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* Unmap tx_cmd */ if (num_tbs) pci_unmap_single(dev, - pci_unmap_addr(&txq->meta[index], mapping), - pci_unmap_len(&txq->meta[index], len), + dma_unmap_addr(&txq->meta[index], mapping), + dma_unmap_len(&txq->meta[index], len), PCI_DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ - for (i = 1; i < num_tbs; i++) { + for (i = 1; i < num_tbs; i++) pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); - if (txq->txb) { - dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); - txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; + /* free SKB */ + if (txq->txb) { + struct sk_buff *skb; + + skb = txq->txb[txq->q.read_ptr].skb; + + /* can be called from irqs-disabled context */ + if (skb) { + dev_kfree_skb_any(skb); + txq->txb[txq->q.read_ptr].skb = NULL; } } } @@ -933,6 +941,8 @@ void iwl_rx_handle(struct iwl_priv *priv) fill_rx = 1; while (i != r) { + int len; + rxb = rxq->queue[i]; /* If an RXB doesn't have a Rx queue slot associated with it, @@ -947,8 +957,9 @@ void iwl_rx_handle(struct iwl_priv *priv) PCI_DMA_FROMDEVICE); pkt = rxb_addr(rxb); - trace_iwlwifi_dev_rx(priv, pkt, - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); + len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + len += sizeof(u32); /* account for status word */ + trace_iwlwifi_dev_rx(priv, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -1466,7 +1477,12 @@ bool iwl_good_ack_health(struct iwl_priv *priv, " expected_ack_cnt = %d\n", actual_ack_cnt_delta, expected_ack_cnt_delta); -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS + /* + * This is ifdef'ed on DEBUGFS because otherwise the + * statistics aren't available. If DEBUGFS is set but + * DEBUG is not, these will just compile out. + */ IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", priv->delta_statistics.tx.rx_detected_cnt); IWL_DEBUG_RADIO(priv, @@ -1694,6 +1710,9 @@ struct iwlagn_firmware_pieces { size_t inst_size, data_size, init_size, init_data_size, boot_size; u32 build; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; }; static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, @@ -1871,6 +1890,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, capa->max_probe_length = le32_to_cpup((__le32 *)tlv_data); break; + case IWL_UCODE_TLV_INIT_EVTLOG_PTR: + if (tlv_len != 4) + return -EINVAL; + pieces->init_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: + if (tlv_len != 4) + return -EINVAL; + pieces->init_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_ERRLOG_PTR: + if (tlv_len != 4) + return -EINVAL; + pieces->init_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: + if (tlv_len != 4) + return -EINVAL; + pieces->inst_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: + if (tlv_len != 4) + return -EINVAL; + pieces->inst_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: + if (tlv_len != 4) + return -EINVAL; + pieces->inst_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; default: break; } @@ -2063,6 +2118,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto err_pci_alloc; } + /* Now that we can no longer fail, copy information */ + + /* + * The (size - 16) / 12 formula is based on the information recorded + * for each event, which is of mode 1 (including timestamp) for all + * new microcodes that include this information. + */ + priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; + if (pieces.init_evtlog_size) + priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + else + priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; + priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; + priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; + if (pieces.inst_evtlog_size) + priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + else + priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; + priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; + /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ @@ -2195,10 +2270,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 blink1, blink2, ilink1, ilink2; u32 pc, hcmd; - if (priv->ucode_type == UCODE_INIT) + if (priv->ucode_type == UCODE_INIT) { base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); - else + if (!base) + base = priv->_agn.init_errlog_ptr; + } else { base = le32_to_cpu(priv->card_alive.error_event_table_ptr); + if (!base) + base = priv->_agn.inst_errlog_ptr; + } if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, @@ -2258,10 +2338,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, if (num_events == 0) return pos; - if (priv->ucode_type == UCODE_INIT) + + if (priv->ucode_type == UCODE_INIT) { base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else + if (!base) + base = priv->_agn.init_evtlog_ptr; + } else { base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + if (!base) + base = priv->_agn.inst_evtlog_ptr; + } if (mode == 0) event_size = 2 * sizeof(u32); @@ -2363,13 +2449,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ u32 size; /* # entries that we'll print */ + u32 logsize; int pos = 0; size_t bufsz = 0; - if (priv->ucode_type == UCODE_INIT) + if (priv->ucode_type == UCODE_INIT) { base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else + logsize = priv->_agn.init_evtlog_size; + if (!base) + base = priv->_agn.init_evtlog_ptr; + } else { base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + logsize = priv->_agn.inst_evtlog_size; + if (!base) + base = priv->_agn.inst_evtlog_ptr; + } if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, @@ -2384,16 +2478,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - if (capacity > priv->cfg->max_event_log_size) { + if (capacity > logsize) { IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, priv->cfg->max_event_log_size); - capacity = priv->cfg->max_event_log_size; + capacity, logsize); + capacity = logsize; } - if (next_entry > priv->cfg->max_event_log_size) { + if (next_entry > logsize) { IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, priv->cfg->max_event_log_size); - next_entry = priv->cfg->max_event_log_size; + next_entry, logsize); + next_entry = logsize; } size = num_wraps ? capacity : next_entry; @@ -2518,8 +2612,6 @@ static void iwl_alive_start(struct iwl_priv *priv) if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); - - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } /* Configure Bluetooth device coexistence support */ @@ -2934,20 +3026,16 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", vif->bss_conf.aid, vif->bss_conf.beacon_int); - if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.use_short_slot) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (vif->type == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } iwlcore_commit_rxon(priv); @@ -3173,8 +3261,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->staging_rxon.assoc_id = 0; - if (vif->bss_conf.assoc_capability & - WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else @@ -3182,17 +3269,12 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.use_short_slot) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (vif->type == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; @@ -3238,17 +3320,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (sta) { - sta_id = iwl_sta_id(sta); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - sta->addr); - return -EINVAL; - } - } else { - sta_id = priv->hw_params.bcast_sta_id; - } + sta_id = iwl_sta_id_or_broadcast(priv, sta); + if (sta_id == IWL_INVALID_STATION) + return -EINVAL; mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); @@ -3423,6 +3497,98 @@ 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) +{ + struct iwl_priv *priv = hw->priv; + const struct iwl_channel_info *ch_info; + struct ieee80211_conf *conf = &hw->conf; + struct iwl_ht_config *ht_conf = &priv->current_ht_config; + u16 ch; + unsigned long flags = 0; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (iwl_is_rfkill(priv)) + goto out_exit; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status)) + goto out_exit; + + if (!iwl_is_associated(priv)) + goto out_exit; + + /* channel switch in progress */ + if (priv->switch_rxon.switch_in_progress == true) + goto out_exit; + + mutex_lock(&priv->mutex); + if (priv->cfg->ops->lib->set_channel_switch) { + + ch = ieee80211_frequency_to_channel( + ch_switch->channel->center_freq); + if (le16_to_cpu(priv->active_rxon.channel) != ch) { + ch_info = iwl_get_channel_info(priv, + conf->channel->band, + ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "invalid channel\n"); + goto out; + } + spin_lock_irqsave(&priv->lock, flags); + + priv->current_ht_config.smps = conf->smps_mode; + + /* Configure HT40 channels */ + ht_conf->is_ht = conf_is_ht(conf); + if (ht_conf->is_ht) { + if (conf_is_ht40_minus(conf)) { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ht_conf->is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ht_conf->is_40mhz = true; + } else { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ht_conf->is_40mhz = false; + } + } else + ht_conf->is_40mhz = false; + + /* 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(priv->staging_rxon.channel) != ch)) + priv->staging_rxon.flags = 0; + + iwl_set_rxon_channel(priv, conf->channel); + iwl_set_rxon_ht(priv, ht_conf); + iwl_set_flags_for_band(priv, conf->channel->band, + priv->vif); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_set_rate(priv); + /* + * at this point, staging_rxon has the + * configuration for channel switch + */ + if (priv->cfg->ops->lib->set_channel_switch(priv, + ch_switch)) + priv->switch_rxon.switch_in_progress = false; + } + } +out: + mutex_unlock(&priv->mutex); +out_exit: + if (!priv->switch_rxon.switch_in_progress) + ieee80211_chswitch_done(priv->vif, false); + IWL_DEBUG_MAC80211(priv, "leave\n"); +} + /***************************************************************************** * * driver setup and teardown @@ -3479,6 +3645,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->scan_check); cancel_work_sync(&priv->start_internal_scan); cancel_delayed_work(&priv->alive_start); + cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); del_timer_sync(&priv->ucode_trace); @@ -3594,6 +3761,7 @@ static struct ieee80211_ops iwl_hw_ops = { .sta_notify = iwl_mac_sta_notify, .sta_add = iwlagn_mac_sta_add, .sta_remove = iwl_mac_sta_remove, + .channel_switch = iwl_mac_channel_switch, }; static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -3604,6 +3772,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; u16 pci_cmd; + u8 perm_addr[ETH_ALEN]; /************************ * 1. Allocating HW data @@ -3633,9 +3802,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->pci_dev = pdev; priv->inta_mask = CSR_INI_SET_MASK; -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_set(&priv->restrict_refcnt, 0); -#endif if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); @@ -3724,9 +3890,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_eeprom; /* extract MAC Address */ - iwl_eeprom_get_mac(priv, priv->mac_addr); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + iwl_eeprom_get_mac(priv, perm_addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); + SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); /************************ * 5. Setup HW constants @@ -3993,6 +4159,47 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {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)}, + {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)}, + {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(0x008B, 0x5315, iwl6000g2b_bgn_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)}, + {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)}, + {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)}, /* 6x50 WiFi/WiMax Series */ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2d748053358e..5c32777b0a49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,6 +65,33 @@ #include "iwl-dev.h" +/* configuration for the _agn devices */ +extern struct iwl_cfg iwl4965_agn_cfg; +extern struct iwl_cfg iwl5300_agn_cfg; +extern struct iwl_cfg iwl5100_agn_cfg; +extern struct iwl_cfg iwl5350_agn_cfg; +extern struct iwl_cfg iwl5100_bgn_cfg; +extern struct iwl_cfg iwl5100_abg_cfg; +extern struct iwl_cfg iwl5150_agn_cfg; +extern struct iwl_cfg iwl5150_abg_cfg; +extern struct iwl_cfg iwl6000g2a_2agn_cfg; +extern struct iwl_cfg iwl6000g2a_2abg_cfg; +extern struct iwl_cfg iwl6000g2a_2bg_cfg; +extern struct iwl_cfg iwl6000g2b_bgn_cfg; +extern struct iwl_cfg iwl6000g2b_bg_cfg; +extern struct iwl_cfg iwl6000g2b_2agn_cfg; +extern struct iwl_cfg iwl6000g2b_2abg_cfg; +extern struct iwl_cfg iwl6000g2b_2bgn_cfg; +extern struct iwl_cfg iwl6000g2b_2bg_cfg; +extern struct iwl_cfg iwl6000i_2agn_cfg; +extern struct iwl_cfg iwl6000i_2abg_cfg; +extern struct iwl_cfg iwl6000i_2bg_cfg; +extern struct iwl_cfg iwl6000_3agn_cfg; +extern struct iwl_cfg iwl6050_2agn_cfg; +extern struct iwl_cfg iwl6050_2abg_cfg; +extern struct iwl_cfg iwl1000_bgn_cfg; +extern struct iwl_cfg iwl1000_bg_cfg; + extern struct iwl_mod_params iwlagn_mod_params; extern struct iwl_hcmd_ops iwlagn_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; @@ -93,6 +120,8 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed); /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); @@ -102,6 +131,7 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_init_alive_start(struct iwl_priv *priv); int iwlagn_alive_notify(struct iwl_priv *priv); +int iwl_verify_ucode(struct iwl_priv *priv); /* lib */ void iwl_check_abort_status(struct iwl_priv *priv, @@ -178,4 +208,8 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); +/* hcmd */ +int iwlagn_send_rxon_assoc(struct iwl_priv *priv); +int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 7e8227773213..22fa947e8756 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -846,6 +846,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, } } + if (active_chains != priv->hw_params.valid_rx_ant && + active_chains != priv->chain_noise_data.active_chains) + IWL_WARN(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", diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9aab020c474b..28b1098334f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -95,7 +95,7 @@ enum { /* Multi-Station support */ REPLY_ADD_STA = 0x18, - REPLY_REMOVE_STA = 0x19, /* not used */ + REPLY_REMOVE_STA = 0x19, REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ /* Security */ @@ -227,7 +227,7 @@ struct iwl_cmd_header { /* command or response/notification data follows immediately */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; /** @@ -247,7 +247,7 @@ struct iwl_cmd_header { struct iwl3945_tx_power { u8 tx_gain; /* gain for analog radio */ u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); +} __packed; /** * struct iwl3945_power_per_rate @@ -258,7 +258,7 @@ struct iwl3945_power_per_rate { u8 rate; /* plcp */ struct iwl3945_tx_power tpc; u8 reserved; -} __attribute__ ((packed)); +} __packed; /** * iwlagn rate_n_flags bit fields @@ -389,7 +389,7 @@ union iwl4965_tx_power_dual_stream { */ struct tx_power_dual_stream { __le32 dw; -} __attribute__ ((packed)); +} __packed; /** * struct iwl4965_tx_power_db @@ -398,7 +398,7 @@ struct tx_power_dual_stream { */ struct iwl4965_tx_power_db { struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; -} __attribute__ ((packed)); +} __packed; /** * Command REPLY_TX_POWER_DBM_CMD = 0x98 @@ -412,7 +412,7 @@ struct iwl5000_tx_power_dbm_cmd { u8 flags; s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ u8 reserved; -} __attribute__ ((packed)); +} __packed; /** * Command TX_ANT_CONFIGURATION_CMD = 0x98 @@ -422,7 +422,7 @@ struct iwl5000_tx_power_dbm_cmd { */ struct iwl_tx_ant_config_cmd { __le32 valid; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (0a) @@ -478,7 +478,7 @@ struct iwl_init_alive_resp { __le32 therm_r4[2]; /* signed */ __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, * 2 Tx chains */ -} __attribute__ ((packed)); +} __packed; /** @@ -570,7 +570,7 @@ struct iwl_alive_resp { __le32 error_event_table_ptr; /* SRAM address for error log */ __le32 timestamp; __le32 is_valid; -} __attribute__ ((packed)); +} __packed; /* * REPLY_ERROR = 0x2 (response only, not a command) @@ -582,7 +582,7 @@ struct iwl_error_resp { __le16 bad_cmd_seq_num; __le32 error_info; __le64 timestamp; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (1) @@ -718,7 +718,7 @@ struct iwl3945_rxon_cmd { __le32 filter_flags; __le16 channel; __le16 reserved5; -} __attribute__ ((packed)); +} __packed; struct iwl4965_rxon_cmd { u8 node_addr[6]; @@ -738,7 +738,7 @@ struct iwl4965_rxon_cmd { __le16 channel; u8 ofdm_ht_single_stream_basic_rates; u8 ofdm_ht_dual_stream_basic_rates; -} __attribute__ ((packed)); +} __packed; /* 5000 HW just extend this command */ struct iwl_rxon_cmd { @@ -763,7 +763,7 @@ struct iwl_rxon_cmd { u8 reserved5; __le16 acquisition_data; __le16 reserved6; -} __attribute__ ((packed)); +} __packed; /* * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) @@ -774,7 +774,7 @@ struct iwl3945_rxon_assoc_cmd { u8 ofdm_basic_rates; u8 cck_basic_rates; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwl4965_rxon_assoc_cmd { __le32 flags; @@ -785,7 +785,7 @@ struct iwl4965_rxon_assoc_cmd { u8 ofdm_ht_dual_stream_basic_rates; __le16 rx_chain_select_flags; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwl5000_rxon_assoc_cmd { __le32 flags; @@ -800,7 +800,7 @@ struct iwl5000_rxon_assoc_cmd { __le16 rx_chain_select_flags; __le16 acquisition_data; __le32 reserved3; -} __attribute__ ((packed)); +} __packed; #define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ @@ -816,7 +816,7 @@ struct iwl_rxon_time_cmd { __le32 beacon_init_val; __le16 listen_interval; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) @@ -829,7 +829,7 @@ struct iwl3945_channel_switch_cmd { __le32 rxon_filter_flags; __le32 switch_time; struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); +} __packed; struct iwl4965_channel_switch_cmd { u8 band; @@ -839,7 +839,7 @@ struct iwl4965_channel_switch_cmd { __le32 rxon_filter_flags; __le32 switch_time; struct iwl4965_tx_power_db tx_power; -} __attribute__ ((packed)); +} __packed; /** * struct iwl5000_channel_switch_cmd @@ -860,7 +860,7 @@ struct iwl5000_channel_switch_cmd { __le32 rxon_filter_flags; __le32 switch_time; __le32 reserved[2][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; -} __attribute__ ((packed)); +} __packed; /** * struct iwl6000_channel_switch_cmd @@ -881,7 +881,7 @@ struct iwl6000_channel_switch_cmd { __le32 rxon_filter_flags; __le32 switch_time; __le32 reserved[3][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; -} __attribute__ ((packed)); +} __packed; /* * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) @@ -890,7 +890,7 @@ struct iwl_csa_notification { __le16 band; __le16 channel; __le32 status; /* 0 - OK, 1 - fail */ -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (2) @@ -920,7 +920,7 @@ struct iwl_ac_qos { u8 aifsn; u8 reserved1; __le16 edca_txop; -} __attribute__ ((packed)); +} __packed; /* QoS flags defines */ #define QOS_PARAM_FLG_UPDATE_EDCA_MSK cpu_to_le32(0x01) @@ -939,7 +939,7 @@ struct iwl_ac_qos { struct iwl_qosparam_cmd { __le32 qos_flags; struct iwl_ac_qos ac[AC_NUM]; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (3) @@ -952,7 +952,6 @@ struct iwl_qosparam_cmd { /* Special, dedicated locations within device's station table */ #define IWL_AP_ID 0 -#define IWL_MULTICAST_ID 1 #define IWL_STA_ID 2 #define IWL3945_BROADCAST_ID 24 #define IWL3945_STATION_COUNT 25 @@ -1015,7 +1014,7 @@ struct iwl4965_keyinfo { u8 key_offset; u8 reserved2; u8 key[16]; /* 16-byte unicast decryption key */ -} __attribute__ ((packed)); +} __packed; /* 5000 */ struct iwl_keyinfo { @@ -1029,7 +1028,7 @@ struct iwl_keyinfo { __le64 tx_secur_seq_cnt; __le64 hw_tkip_mic_rx_key; __le64 hw_tkip_mic_tx_key; -} __attribute__ ((packed)); +} __packed; /** * struct sta_id_modify @@ -1049,7 +1048,7 @@ struct sta_id_modify { u8 sta_id; u8 modify_mask; __le16 reserved2; -} __attribute__ ((packed)); +} __packed; /* * REPLY_ADD_STA = 0x18 (command) @@ -1103,7 +1102,7 @@ struct iwl3945_addsta_cmd { /* Starting Sequence Number for added block-ack support. * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ __le16 add_immediate_ba_ssn; -} __attribute__ ((packed)); +} __packed; struct iwl4965_addsta_cmd { u8 mode; /* 1: modify existing, 0: add new station */ @@ -1140,7 +1139,7 @@ struct iwl4965_addsta_cmd { __le16 sleep_tx_count; __le16 reserved2; -} __attribute__ ((packed)); +} __packed; /* 5000 */ struct iwl_addsta_cmd { @@ -1178,7 +1177,7 @@ struct iwl_addsta_cmd { __le16 sleep_tx_count; __le16 reserved2; -} __attribute__ ((packed)); +} __packed; #define ADD_STA_SUCCESS_MSK 0x1 @@ -1190,7 +1189,7 @@ struct iwl_addsta_cmd { */ struct iwl_add_sta_resp { u8 status; /* ADD_STA_* */ -} __attribute__ ((packed)); +} __packed; #define REM_STA_SUCCESS_MSK 0x1 /* @@ -1198,7 +1197,7 @@ struct iwl_add_sta_resp { */ struct iwl_rem_sta_resp { u8 status; -} __attribute__ ((packed)); +} __packed; /* * REPLY_REM_STA = 0x19 (command) @@ -1208,7 +1207,7 @@ struct iwl_rem_sta_cmd { u8 reserved[3]; u8 addr[ETH_ALEN]; /* MAC addr of the first station */ u8 reserved2[2]; -} __attribute__ ((packed)); +} __packed; /* * REPLY_WEP_KEY = 0x20 @@ -1220,7 +1219,7 @@ struct iwl_wep_key { u8 key_size; u8 reserved2[3]; u8 key[16]; -} __attribute__ ((packed)); +} __packed; struct iwl_wep_cmd { u8 num_keys; @@ -1228,7 +1227,7 @@ struct iwl_wep_cmd { u8 flags; u8 reserved; struct iwl_wep_key key[0]; -} __attribute__ ((packed)); +} __packed; #define WEP_KEY_WEP_TYPE 1 #define WEP_KEYS_MAX 4 @@ -1282,7 +1281,7 @@ struct iwl3945_rx_frame_stats { __le16 sig_avg; __le16 noise_diff; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct iwl3945_rx_frame_hdr { __le16 channel; @@ -1291,13 +1290,13 @@ struct iwl3945_rx_frame_hdr { u8 rate; __le16 len; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct iwl3945_rx_frame_end { __le32 status; __le64 timestamp; __le32 beacon_timestamp; -} __attribute__ ((packed)); +} __packed; /* * REPLY_3945_RX = 0x1b (response only, not a command) @@ -1311,7 +1310,7 @@ struct iwl3945_rx_frame { struct iwl3945_rx_frame_stats stats; struct iwl3945_rx_frame_hdr hdr; struct iwl3945_rx_frame_end end; -} __attribute__ ((packed)); +} __packed; #define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) @@ -1327,7 +1326,7 @@ struct iwl4965_rx_non_cfg_phy { __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ u8 pad[0]; -} __attribute__ ((packed)); +} __packed; #define IWL50_RX_RES_PHY_CNT 8 @@ -1345,7 +1344,7 @@ struct iwl4965_rx_non_cfg_phy { struct iwl5000_non_cfg_phy { __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */ -} __attribute__ ((packed)); +} __packed; /* @@ -1365,12 +1364,12 @@ struct iwl_rx_phy_res { __le32 rate_n_flags; /* RATE_MCS_* */ __le16 byte_count; /* frame's byte-count */ __le16 reserved3; -} __attribute__ ((packed)); +} __packed; -struct iwl4965_rx_mpdu_res_start { +struct iwl_rx_mpdu_res_start { __le16 byte_count; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** @@ -1557,7 +1556,7 @@ struct iwl3945_tx_cmd { */ u8 payload[0]; struct ieee80211_hdr hdr[0]; -} __attribute__ ((packed)); +} __packed; /* * REPLY_TX = 0x1c (response) @@ -1569,7 +1568,7 @@ struct iwl3945_tx_resp { u8 rate; __le32 wireless_media_time; __le32 status; /* TX status */ -} __attribute__ ((packed)); +} __packed; /* @@ -1581,7 +1580,7 @@ struct iwl_dram_scratch { u8 try_cnt; /* Tx attempts */ u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */ __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwl_tx_cmd { /* @@ -1660,7 +1659,7 @@ struct iwl_tx_cmd { */ u8 payload[0]; struct ieee80211_hdr hdr[0]; -} __attribute__ ((packed)); +} __packed; /* TX command response is sent after *3945* transmission attempts. * @@ -1826,7 +1825,7 @@ enum { struct agg_tx_status { __le16 status; __le16 sequence; -} __attribute__ ((packed)); +} __packed; struct iwl4965_tx_resp { u8 frame_count; /* 1 no aggregation, >1 aggregation */ @@ -1863,7 +1862,7 @@ struct iwl4965_tx_resp { __le32 status; struct agg_tx_status agg_status[0]; /* for each agg frame */ } u; -} __attribute__ ((packed)); +} __packed; /* * definitions for initial rate index field @@ -1927,7 +1926,7 @@ struct iwl5000_tx_resp { */ struct agg_tx_status status; /* TX status (in aggregation - * status of 1st frame) */ -} __attribute__ ((packed)); +} __packed; /* * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) * @@ -1945,7 +1944,7 @@ struct iwl_compressed_ba_resp { __le64 bitmap; __le16 scd_flow; __le16 scd_ssn; -} __attribute__ ((packed)); +} __packed; /* * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) @@ -1958,14 +1957,14 @@ struct iwl3945_txpowertable_cmd { u8 reserved; __le16 channel; struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); +} __packed; struct iwl4965_txpowertable_cmd { u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ u8 reserved; __le16 channel; struct iwl4965_tx_power_db tx_power; -} __attribute__ ((packed)); +} __packed; /** @@ -1987,13 +1986,13 @@ struct iwl3945_rate_scaling_info { __le16 rate_n_flags; u8 try_cnt; u8 next_rate_index; -} __attribute__ ((packed)); +} __packed; struct iwl3945_rate_scaling_cmd { u8 table_id; u8 reserved[3]; struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; -} __attribute__ ((packed)); +} __packed; /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ @@ -2040,7 +2039,7 @@ struct iwl_link_qual_general_params { * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3. */ u8 start_rate_index[LINK_QUAL_AC_NUM]; -} __attribute__ ((packed)); +} __packed; #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) @@ -2081,7 +2080,7 @@ struct iwl_link_qual_agg_params { u8 agg_frame_cnt_limit; __le32 reserved; -} __attribute__ ((packed)); +} __packed; /* * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) @@ -2287,7 +2286,7 @@ struct iwl_link_quality_cmd { __le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */ } rs_table[LINK_QUAL_MAX_RETRY_NUM]; __le32 reserved2; -} __attribute__ ((packed)); +} __packed; /* * BT configuration enable flags: @@ -2328,7 +2327,7 @@ struct iwl_bt_cmd { u8 reserved; __le32 kill_ack_mask; __le32 kill_cts_mask; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (6) @@ -2353,7 +2352,7 @@ struct iwl_measure_channel { u8 channel; /* channel to measure */ u8 type; /* see enum iwl_measure_type */ __le16 reserved; -} __attribute__ ((packed)); +} __packed; /* * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command) @@ -2372,7 +2371,7 @@ struct iwl_spectrum_cmd { __le16 channel_count; /* minimum 1, maximum 10 */ __le16 reserved3; struct iwl_measure_channel channels[10]; -} __attribute__ ((packed)); +} __packed; /* * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response) @@ -2383,7 +2382,7 @@ struct iwl_spectrum_resp { __le16 status; /* 0 - command will be handled * 1 - cannot handle (conflicts with another * measurement) */ -} __attribute__ ((packed)); +} __packed; enum iwl_measurement_state { IWL_MEASUREMENT_START = 0, @@ -2406,13 +2405,13 @@ enum iwl_measurement_status { struct iwl_measurement_histogram { __le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */ __le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */ -} __attribute__ ((packed)); +} __packed; /* clear channel availability counters */ struct iwl_measurement_cca_counters { __le32 ofdm; __le32 cck; -} __attribute__ ((packed)); +} __packed; enum iwl_measure_type { IWL_MEASURE_BASIC = (1 << 0), @@ -2448,7 +2447,7 @@ struct iwl_spectrum_notification { struct iwl_measurement_histogram histogram; __le32 stop_time; /* lower 32-bits of TSF */ __le32 status; /* see iwl_measurement_status */ -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (7) @@ -2504,7 +2503,7 @@ struct iwl3945_powertable_cmd { __le32 rx_data_timeout; __le32 tx_data_timeout; __le32 sleep_interval[IWL_POWER_VEC_SIZE]; -} __attribute__ ((packed)); +} __packed; struct iwl_powertable_cmd { __le16 flags; @@ -2514,7 +2513,7 @@ struct iwl_powertable_cmd { __le32 tx_data_timeout; __le32 sleep_interval[IWL_POWER_VEC_SIZE]; __le32 keep_alive_beacons; -} __attribute__ ((packed)); +} __packed; /* * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command) @@ -2527,7 +2526,7 @@ struct iwl_sleep_notification { __le32 sleep_time; __le32 tsf_low; __le32 bcon_timer; -} __attribute__ ((packed)); +} __packed; /* Sleep states. 3945 and 4965 identical. */ enum { @@ -2552,14 +2551,14 @@ enum { #define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */ struct iwl_card_state_cmd { __le32 status; /* CARD_STATE_CMD_* request new power state */ -} __attribute__ ((packed)); +} __packed; /* * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command) */ struct iwl_card_state_notif { __le32 flags; -} __attribute__ ((packed)); +} __packed; #define HW_CARD_DISABLED 0x01 #define SW_CARD_DISABLED 0x02 @@ -2570,14 +2569,14 @@ struct iwl_ct_kill_config { __le32 reserved; __le32 critical_temperature_M; __le32 critical_temperature_R; -} __attribute__ ((packed)); +} __packed; /* 1000, and 6x00 */ struct iwl_ct_kill_throttling_config { __le32 critical_temperature_exit; __le32 reserved; __le32 critical_temperature_enter; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (8) @@ -2622,7 +2621,7 @@ struct iwl3945_scan_channel { struct iwl3945_tx_power tpc; __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __attribute__ ((packed)); +} __packed; /* set number of direct probes u8 type */ #define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) @@ -2641,7 +2640,7 @@ struct iwl_scan_channel { u8 dsp_atten; /* gain for DSP */ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __attribute__ ((packed)); +} __packed; /* set number of direct probes __le32 type */ #define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) @@ -2658,7 +2657,7 @@ struct iwl_ssid_ie { u8 id; u8 len; u8 ssid[32]; -} __attribute__ ((packed)); +} __packed; #define PROBE_OPTION_MAX_3945 4 #define PROBE_OPTION_MAX 20 @@ -2764,7 +2763,7 @@ struct iwl3945_scan_cmd { * before requesting another scan. */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct iwl_scan_cmd { __le16 len; @@ -2808,7 +2807,7 @@ struct iwl_scan_cmd { * before requesting another scan. */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; /* Can abort will notify by complete notification with abort status. */ #define CAN_ABORT_STATUS cpu_to_le32(0x1) @@ -2820,7 +2819,7 @@ struct iwl_scan_cmd { */ struct iwl_scanreq_notification { __le32 status; /* 1: okay, 2: cannot fulfill request */ -} __attribute__ ((packed)); +} __packed; /* * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command) @@ -2833,7 +2832,7 @@ struct iwl_scanstart_notification { u8 band; u8 reserved[2]; __le32 status; -} __attribute__ ((packed)); +} __packed; #define SCAN_OWNER_STATUS 0x1; #define MEASURE_OWNER_STATUS 0x2; @@ -2849,7 +2848,7 @@ struct iwl_scanresults_notification { __le32 tsf_low; __le32 tsf_high; __le32 statistics[NUMBER_OF_STATISTICS]; -} __attribute__ ((packed)); +} __packed; /* * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command) @@ -2861,7 +2860,7 @@ struct iwl_scancomplete_notification { u8 last_channel; __le32 tsf_low; __le32 tsf_high; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** @@ -2879,14 +2878,14 @@ struct iwl3945_beacon_notif { __le32 low_tsf; __le32 high_tsf; __le32 ibss_mgr_status; -} __attribute__ ((packed)); +} __packed; struct iwl4965_beacon_notif { struct iwl4965_tx_resp beacon_notify_hdr; __le32 low_tsf; __le32 high_tsf; __le32 ibss_mgr_status; -} __attribute__ ((packed)); +} __packed; /* * REPLY_TX_BEACON = 0x91 (command, has simple generic response) @@ -2898,7 +2897,7 @@ struct iwl3945_tx_beacon_cmd { u8 tim_size; u8 reserved1; struct ieee80211_hdr frame[0]; /* beacon frame */ -} __attribute__ ((packed)); +} __packed; struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; @@ -2906,7 +2905,7 @@ struct iwl_tx_beacon_cmd { u8 tim_size; u8 reserved1; struct ieee80211_hdr frame[0]; /* beacon frame */ -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (10) @@ -2932,7 +2931,7 @@ struct rate_histogram { __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; } failed; -} __attribute__ ((packed)); +} __packed; /* statistics command response */ @@ -2952,7 +2951,7 @@ struct iwl39_statistics_rx_phy { __le32 rxe_frame_limit_overrun; __le32 sent_ack_cnt; __le32 sent_cts_cnt; -} __attribute__ ((packed)); +} __packed; struct iwl39_statistics_rx_non_phy { __le32 bogus_cts; /* CTS received when not expecting CTS */ @@ -2963,13 +2962,13 @@ struct iwl39_statistics_rx_non_phy { * filtering process */ __le32 non_channel_beacons; /* beacons with our bss id but not on * our serving channel */ -} __attribute__ ((packed)); +} __packed; struct iwl39_statistics_rx { struct iwl39_statistics_rx_phy ofdm; struct iwl39_statistics_rx_phy cck; struct iwl39_statistics_rx_non_phy general; -} __attribute__ ((packed)); +} __packed; struct iwl39_statistics_tx { __le32 preamble_cnt; @@ -2981,20 +2980,20 @@ struct iwl39_statistics_tx { __le32 ack_timeout; __le32 expected_ack_cnt; __le32 actual_ack_cnt; -} __attribute__ ((packed)); +} __packed; struct statistics_dbg { __le32 burst_check; __le32 burst_count; __le32 reserved[4]; -} __attribute__ ((packed)); +} __packed; struct iwl39_statistics_div { __le32 tx_on_a; __le32 tx_on_b; __le32 exec_time; __le32 probe_time; -} __attribute__ ((packed)); +} __packed; struct iwl39_statistics_general { __le32 temperature; @@ -3004,7 +3003,7 @@ struct iwl39_statistics_general { __le32 slots_idle; __le32 ttl_timestamp; struct iwl39_statistics_div div; -} __attribute__ ((packed)); +} __packed; struct statistics_rx_phy { __le32 ina_cnt; @@ -3027,7 +3026,7 @@ struct statistics_rx_phy { __le32 mh_format_err; __le32 re_acq_main_rssi_sum; __le32 reserved3; -} __attribute__ ((packed)); +} __packed; struct statistics_rx_ht_phy { __le32 plcp_err; @@ -3040,7 +3039,7 @@ struct statistics_rx_ht_phy { __le32 agg_mpdu_cnt; __le32 agg_cnt; __le32 unsupport_mcs; -} __attribute__ ((packed)); +} __packed; #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) @@ -3075,14 +3074,14 @@ struct statistics_rx_non_phy { __le32 beacon_energy_a; __le32 beacon_energy_b; __le32 beacon_energy_c; -} __attribute__ ((packed)); +} __packed; struct statistics_rx { struct statistics_rx_phy ofdm; struct statistics_rx_phy cck; struct statistics_rx_non_phy general; struct statistics_rx_ht_phy ofdm_ht; -} __attribute__ ((packed)); +} __packed; /** * struct statistics_tx_power - current tx power @@ -3096,7 +3095,7 @@ struct statistics_tx_power { u8 ant_b; u8 ant_c; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct statistics_tx_non_phy_agg { __le32 ba_timeout; @@ -3109,7 +3108,7 @@ struct statistics_tx_non_phy_agg { __le32 underrun; __le32 bt_prio_kill; __le32 rx_ba_rsp_cnt; -} __attribute__ ((packed)); +} __packed; struct statistics_tx { __le32 preamble_cnt; @@ -3134,7 +3133,7 @@ struct statistics_tx { */ struct statistics_tx_power tx_power; __le32 reserved1; -} __attribute__ ((packed)); +} __packed; struct statistics_div { @@ -3144,7 +3143,7 @@ struct statistics_div { __le32 probe_time; __le32 reserved1; __le32 reserved2; -} __attribute__ ((packed)); +} __packed; struct statistics_general { __le32 temperature; /* radio temperature */ @@ -3164,7 +3163,7 @@ struct statistics_general { __le32 num_of_sos_states; __le32 reserved2; __le32 reserved3; -} __attribute__ ((packed)); +} __packed; #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) @@ -3189,7 +3188,7 @@ struct statistics_general { #define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */ struct iwl_statistics_cmd { __le32 configuration_flags; /* IWL_STATS_CONF_* */ -} __attribute__ ((packed)); +} __packed; /* * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) @@ -3214,14 +3213,14 @@ struct iwl3945_notif_statistics { struct iwl39_statistics_rx rx; struct iwl39_statistics_tx tx; struct iwl39_statistics_general general; -} __attribute__ ((packed)); +} __packed; struct iwl_notif_statistics { __le32 flag; struct statistics_rx rx; struct statistics_tx tx; struct statistics_general general; -} __attribute__ ((packed)); +} __packed; /* @@ -3253,7 +3252,7 @@ struct iwl_missed_beacon_notif { __le32 total_missed_becons; __le32 num_expected_beacons; __le32 num_recvd_beacons; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** @@ -3455,7 +3454,7 @@ struct iwl_missed_beacon_notif { struct iwl_sensitivity_cmd { __le16 control; /* always use "1" */ __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */ -} __attribute__ ((packed)); +} __packed; /** @@ -3536,31 +3535,31 @@ struct iwl_calib_cfg_elmnt_s { __le32 send_res; __le32 apply_res; __le32 reserved; -} __attribute__ ((packed)); +} __packed; struct iwl_calib_cfg_status_s { struct iwl_calib_cfg_elmnt_s once; struct iwl_calib_cfg_elmnt_s perd; __le32 flags; -} __attribute__ ((packed)); +} __packed; struct iwl_calib_cfg_cmd { struct iwl_calib_cfg_status_s ucd_calib_cfg; struct iwl_calib_cfg_status_s drv_calib_cfg; __le32 reserved1; -} __attribute__ ((packed)); +} __packed; struct iwl_calib_hdr { u8 op_code; u8 first_group; u8 groups_num; u8 data_valid; -} __attribute__ ((packed)); +} __packed; struct iwl_calib_cmd { struct iwl_calib_hdr hdr; u8 data[0]; -} __attribute__ ((packed)); +} __packed; /* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */ struct iwl_calib_diff_gain_cmd { @@ -3569,14 +3568,14 @@ struct iwl_calib_diff_gain_cmd { s8 diff_gain_b; s8 diff_gain_c; u8 reserved1; -} __attribute__ ((packed)); +} __packed; struct iwl_calib_xtal_freq_cmd { struct iwl_calib_hdr hdr; u8 cap_pin1; u8 cap_pin2; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ struct iwl_calib_chain_noise_reset_cmd { @@ -3590,7 +3589,7 @@ struct iwl_calib_chain_noise_gain_cmd { u8 delta_gain_1; u8 delta_gain_2; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** * (12) @@ -3613,7 +3612,7 @@ struct iwl_led_cmd { u8 on; /* # intervals on while blinking; * "0", regardless of "off", turns LED off */ u8 reserved; -} __attribute__ ((packed)); +} __packed; /* * station priority table entries @@ -3749,7 +3748,7 @@ struct iwl_wimax_coex_event_entry { u8 win_medium_prio; u8 reserved; u8 flags; -} __attribute__ ((packed)); +} __packed; /* COEX flag masks */ @@ -3766,7 +3765,7 @@ struct iwl_wimax_coex_cmd { u8 flags; u8 reserved[3]; struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS]; -} __attribute__ ((packed)); +} __packed; /* * Coexistence MEDIUM NOTIFICATION @@ -3795,7 +3794,7 @@ struct iwl_wimax_coex_cmd { struct iwl_coex_medium_notification { __le32 status; __le32 events; -} __attribute__ ((packed)); +} __packed; /* * Coexistence EVENT Command @@ -3810,11 +3809,11 @@ struct iwl_coex_event_cmd { u8 flags; u8 event; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwl_coex_event_resp { __le32 status; -} __attribute__ ((packed)); +} __packed; /****************************************************************************** @@ -3858,7 +3857,7 @@ struct iwl_rx_packet { __le32 status; u8 raw[0]; } u; -} __attribute__ ((packed)); +} __packed; int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 426e95567de3..62c50bc0089a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -141,13 +141,14 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) } EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) +u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) { int i; u8 ind = ant; + for (i = 0; i < RATE_ANT_NUM - 1; i++) { ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; - if (priv->hw_params.valid_tx_ant & BIT(ind)) + if (valid & BIT(ind)) return ind; } return ant; @@ -457,7 +458,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, if (!sta_ht_inf->ht_supported) return 0; } -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS if (priv->disable_ht40) return 0; #endif @@ -506,11 +507,11 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) } beacon_int = iwl_adjust_beacon_interval(beacon_int, - priv->hw_params.max_beacon_itrvl * 1024); + priv->hw_params.max_beacon_itrvl * TIME_UNIT); priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ - interval_tm = beacon_int * 1024; + interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); @@ -932,9 +933,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) } EXPORT_SYMBOL(iwl_set_rxon_channel); -static void iwl_set_flags_for_band(struct iwl_priv *priv, - enum ieee80211_band band, - struct ieee80211_vif *vif) +void iwl_set_flags_for_band(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_vif *vif) { if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= @@ -943,19 +944,17 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv, priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { /* Copied from iwl_post_associate() */ - if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif && vif->bss_conf.use_short_slot) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (vif && vif->type == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; } } +EXPORT_SYMBOL(iwl_set_flags_for_band); /* * initialize rxon structure with default values from eeprom @@ -1021,15 +1020,17 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, /* clear both MIX and PURE40 mode flag */ priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); + + if (vif) + memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN); + priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; } EXPORT_SYMBOL(iwl_connection_init_rx_config); -static void iwl_set_rate(struct iwl_priv *priv) +void iwl_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; @@ -1057,6 +1058,21 @@ static void iwl_set_rate(struct iwl_priv *priv) priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } +EXPORT_SYMBOL(iwl_set_rate); + +void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (priv->switch_rxon.switch_in_progress) { + ieee80211_chswitch_done(priv->vif, is_success); + mutex_lock(&priv->mutex); + priv->switch_rxon.switch_in_progress = false; + mutex_unlock(&priv->mutex); + } +} +EXPORT_SYMBOL(iwl_chswitch_done); void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -1071,11 +1087,12 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) priv->staging_rxon.channel = csa->channel; IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); - } else + iwl_chswitch_done(priv, true); + } else { IWL_ERR(priv, "CSA notif (fail) : channel %d\n", le16_to_cpu(csa->channel)); - - priv->switch_rxon.switch_in_progress = false; + iwl_chswitch_done(priv, false); + } } } EXPORT_SYMBOL(iwl_rx_csa); @@ -1502,130 +1519,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) } EXPORT_SYMBOL(iwl_send_statistics_request); -/** - * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, - * using sample data 100 bytes apart. If these sample points are good, - * it's a pretty good bet that everything between them is good, too. - */ -static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) -{ - u32 val; - int ret = 0; - u32 errcnt = 0; - u32 i; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + IWL49_RTC_INST_LOWER_BOUND); - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - ret = -EIO; - errcnt++; - if (errcnt >= 3) - break; - } - } - - return ret; -} - -/** - * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, - * looking at all data. - */ -static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, - u32 len) -{ - u32 val; - u32 save_len = len; - int ret = 0; - u32 errcnt; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - IWL49_RTC_INST_LOWER_BOUND); - - errcnt = 0; - for (; len > 0; len -= sizeof(u32), image++) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "uCode INST section is invalid at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - save_len - len, val, le32_to_cpu(*image)); - ret = -EIO; - errcnt++; - if (errcnt >= 20) - break; - } - } - - if (!errcnt) - IWL_DEBUG_INFO(priv, - "ucode image in INSTRUCTION memory is good\n"); - - return ret; -} - -/** - * iwl_verify_ucode - determine which instruction image is in SRAM, - * and verify its contents - */ -int iwl_verify_ucode(struct iwl_priv *priv) -{ - __le32 *image; - u32 len; - int ret; - - /* Try bootstrap */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); - return 0; - } - - /* Try initialize */ - image = (__le32 *)priv->ucode_init.v_addr; - len = priv->ucode_init.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); - return 0; - } - - /* Try runtime/protocol */ - image = (__le32 *)priv->ucode_code.v_addr; - len = priv->ucode_code.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - - /* Since nothing seems to match, show first several data entries in - * instruction SRAM, so maybe visual inspection will give a clue. - * Selection of bootstrap image (vs. other images) is arbitrary. */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - ret = iwl_verify_inst_full(priv, image, len); - - return ret; -} -EXPORT_SYMBOL(iwl_verify_ucode); - - void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; @@ -2046,8 +1939,6 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - return iwlcore_commit_rxon(priv); } @@ -2056,7 +1947,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct iwl_priv *priv = hw->priv; int err = 0; - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); + IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", + vif->type, vif->addr); mutex_lock(&priv->mutex); @@ -2074,9 +1966,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) priv->vif = vif; priv->iw_mode = vif->type; - IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); - memcpy(priv->mac_addr, vif->addr, ETH_ALEN); - err = iwl_set_mode(priv, vif); if (err) goto out_err; @@ -2110,6 +1999,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, } if (priv->vif == vif) { priv->vif = NULL; + if (priv->scan_vif == vif) { + ieee80211_scan_completed(priv->hw, true); + priv->scan_vif = NULL; + priv->scan_request = NULL; + } memset(priv->bssid, 0, ETH_ALEN); } mutex_unlock(&priv->mutex); @@ -2210,22 +2104,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); spin_unlock_irqrestore(&priv->lock, flags); - if (iwl_is_associated(priv) && - (le16_to_cpu(priv->active_rxon.channel) != ch) && - priv->cfg->ops->lib->set_channel_switch) { - iwl_set_rate(priv); - /* - * at this point, staging_rxon has the - * configuration for channel switch - */ - ret = priv->cfg->ops->lib->set_channel_switch(priv, - ch); - if (!ret) { - iwl_print_rx_config_cmd(priv); - goto out; - } - priv->switch_rxon.switch_in_progress = false; - } + set_ch_out: /* The list of supported rates and rate mask can be different * for each band; since the band may have changed, reset @@ -2583,7 +2462,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) EXPORT_SYMBOL(iwl_update_stats); #endif -const static char *get_csr_string(int cmd) +static const char *get_csr_string(int cmd) { switch (cmd) { IWL_CMD(CSR_HW_IF_CONFIG_REG); @@ -2654,7 +2533,7 @@ void iwl_dump_csr(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_dump_csr); -const static char *get_fh_string(int cmd) +static const char *get_fh_string(int cmd) { switch (cmd) { IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); @@ -2876,6 +2755,61 @@ void iwl_bg_monitor_recover(unsigned long data) } EXPORT_SYMBOL(iwl_bg_monitor_recover); + +/* + * extended beacon time format + * time in usec will be changed into a 32-bit value in extended:internal format + * the extended part is the beacon counts + * the internal part is the time in usec within one beacon interval + */ +u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) +{ + u32 quot; + u32 rem; + u32 interval = beacon_interval * TIME_UNIT; + + if (!interval || !usec) + return 0; + + quot = (usec / interval) & + (iwl_beacon_time_mask_high(priv, + priv->hw_params.beacon_time_tsf_bits) >> + priv->hw_params.beacon_time_tsf_bits); + rem = (usec % interval) & iwl_beacon_time_mask_low(priv, + priv->hw_params.beacon_time_tsf_bits); + + return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; +} +EXPORT_SYMBOL(iwl_usecs_to_beacons); + +/* base is usually what we get from ucode with each received frame, + * the same as HW timer counter counting down + */ +__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, + u32 addon, u32 beacon_interval) +{ + u32 base_low = base & iwl_beacon_time_mask_low(priv, + priv->hw_params.beacon_time_tsf_bits); + u32 addon_low = addon & iwl_beacon_time_mask_low(priv, + priv->hw_params.beacon_time_tsf_bits); + u32 interval = beacon_interval * TIME_UNIT; + u32 res = (base & iwl_beacon_time_mask_high(priv, + priv->hw_params.beacon_time_tsf_bits)) + + (addon & iwl_beacon_time_mask_high(priv, + priv->hw_params.beacon_time_tsf_bits)); + + if (base_low > addon_low) + res += base_low - addon_low; + else if (base_low < addon_low) { + res += interval + base_low - addon_low; + res += (1 << priv->hw_params.beacon_time_tsf_bits); + } else + res += (1 << priv->hw_params.beacon_time_tsf_bits); + + return cpu_to_le32(res); +} +EXPORT_SYMBOL(iwl_add_beacon_time); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 31775bd9c361..76288c56a7d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -79,6 +79,8 @@ struct iwl_cmd; .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ .driver_data = (kernel_ulong_t)&(cfg) +#define TIME_UNIT 1024 + #define IWL_SKU_G 0x1 #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 @@ -173,7 +175,8 @@ struct iwl_lib_ops { void (*dump_nic_error_log)(struct iwl_priv *priv); void (*dump_csr)(struct iwl_priv *priv); int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); - int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); + int (*set_channel_switch)(struct iwl_priv *priv, + struct ieee80211_channel_switch *ch_switch); /* power management */ struct iwl_apm_ops apm_ops; @@ -325,7 +328,8 @@ struct iwl_cfg { const bool ucode_tracing; const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; - u8 scan_antennas[IEEE80211_NUM_BANDS]; + u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; + u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; }; /*************************** @@ -343,6 +347,9 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv); void iwl_set_rxon_chain(struct iwl_priv *priv); int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); +void iwl_set_flags_for_band(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_vif *vif); u8 iwl_get_single_channel_number(struct iwl_priv *priv, enum ieee80211_band band); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); @@ -350,6 +357,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *sta_ht_inf); void iwl_connection_init_rx_config(struct iwl_priv *priv, struct ieee80211_vif *vif); +void iwl_set_rate(struct iwl_priv *priv); int iwl_set_decrypted_flag(struct iwl_priv *priv, struct ieee80211_hdr *hdr, u32 decrypt_res, @@ -461,6 +469,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_reply_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* TX helpers */ @@ -474,8 +483,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, dma_addr_t addr, u16 len, u8 reset, u8 pad); int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed); void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); @@ -495,7 +502,7 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); +u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) { @@ -528,7 +535,7 @@ void iwl_bg_start_internal_scan(struct work_struct *work); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ie, int ie_len, int left); + const u8 *ta, const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); u16 iwl_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, @@ -595,6 +602,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) } void iwl_bg_monitor_recover(unsigned long data); +u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); +__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); @@ -693,7 +703,6 @@ extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); -extern int iwl_verify_ucode(struct iwl_priv *priv); extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq, u8 flags, bool init); void iwl_apm_stop(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 9659c5d01df9..cee3d12eb383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -106,27 +106,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .open = iwl_dbgfs_open_file_generic, \ }; -int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) -{ - int p = 0; - - p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", - le32_to_cpu(priv->statistics.flag)); - if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) - p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); - p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); - p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); - return p; -} -EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); - static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -330,45 +309,35 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, for (i = 0; i < max_sta; i++) { station = &priv->stations[i]; - if (station->used) { - pos += scnprintf(buf + pos, bufsz - pos, - "station %d:\ngeneral data:\n", i+1); - pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", - station->sta.sta.sta_id); - pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", - station->sta.mode); - pos += scnprintf(buf + pos, bufsz - pos, - "flags: 0x%x\n", - station->sta.station_flags_msk); - pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "seq_num\t\ttxq_id"); - pos += scnprintf(buf + pos, bufsz - pos, - "\tframe_count\twait_for_ba\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "start_idx\tbitmap0\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "bitmap1\trate_n_flags"); - pos += scnprintf(buf + pos, bufsz - pos, "\n"); + if (!station->used) + continue; + pos += scnprintf(buf + pos, bufsz - pos, + "station %d - addr: %pM, flags: %#x\n", + i, station->sta.sta.addr, + station->sta.station_flags_msk); + pos += scnprintf(buf + pos, bufsz - pos, + "TID\tseq_num\ttxq_id\tframes\ttfds\t"); + pos += scnprintf(buf + pos, bufsz - pos, + "start_idx\tbitmap\t\t\trate_n_flags\n"); - for (j = 0; j < MAX_TID_COUNT; j++) { - pos += scnprintf(buf + pos, bufsz - pos, - "[%d]:\t\t%u", j, - station->tid[j].seq_number); - pos += scnprintf(buf + pos, bufsz - pos, - "\t%u\t\t%u\t\t%u\t\t", - station->tid[j].agg.txq_id, - station->tid[j].agg.frame_count, - station->tid[j].agg.wait_for_ba); + for (j = 0; j < MAX_TID_COUNT; j++) { + pos += scnprintf(buf + pos, bufsz - pos, + "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", + j, station->tid[j].seq_number, + station->tid[j].agg.txq_id, + station->tid[j].agg.frame_count, + station->tid[j].tfds_in_queue, + station->tid[j].agg.start_idx, + station->tid[j].agg.bitmap, + station->tid[j].agg.rate_n_flags); + + if (station->tid[j].agg.wait_for_ba) pos += scnprintf(buf + pos, bufsz - pos, - "%u\t%llu\t%u", - station->tid[j].agg.start_idx, - (unsigned long long)station->tid[j].agg.bitmap, - station->tid[j].agg.rate_n_flags); - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - } + " - waitforba"); pos += scnprintf(buf + pos, bufsz - pos, "\n"); } + + pos += scnprintf(buf + pos, bufsz - pos, "\n"); } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -1049,8 +1018,13 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, rxq->write); pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", rxq->free_count); - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "closed_rb_num: Not Allocated\n"); + } return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f3f3473c5c7e..338b5177029d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -48,25 +48,6 @@ #include "iwl-power.h" #include "iwl-agn-rs.h" -/* configuration for the iwl4965 */ -extern struct iwl_cfg iwl4965_agn_cfg; -extern struct iwl_cfg iwl5300_agn_cfg; -extern struct iwl_cfg iwl5100_agn_cfg; -extern struct iwl_cfg iwl5350_agn_cfg; -extern struct iwl_cfg iwl5100_bgn_cfg; -extern struct iwl_cfg iwl5100_abg_cfg; -extern struct iwl_cfg iwl5150_agn_cfg; -extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6000g2a_2agn_cfg; -extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_2abg_cfg; -extern struct iwl_cfg iwl6000i_2bg_cfg; -extern struct iwl_cfg iwl6000_3agn_cfg; -extern struct iwl_cfg iwl6050_2agn_cfg; -extern struct iwl_cfg iwl6050_2abg_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; -extern struct iwl_cfg iwl1000_bg_cfg; - struct iwl_tx_queue; /* CT-KILL constants */ @@ -133,8 +114,8 @@ struct iwl_cmd_meta { * structure is stored at the end of the shared queue memory. */ u32 flags; - DECLARE_PCI_UNMAP_ADDR(mapping) - DECLARE_PCI_UNMAP_LEN(len) + DEFINE_DMA_UNMAP_ADDR(mapping); + DEFINE_DMA_UNMAP_LEN(len); }; /* @@ -157,11 +138,11 @@ struct iwl_queue { * space more than this */ int high_mark; /* high watermark, stop queue if free * space less than this */ -} __attribute__ ((packed)); +} __packed; /* One for each TFD */ struct iwl_tx_info { - struct sk_buff *skb[IWL_NUM_OF_TBS - 1]; + struct sk_buff *skb; }; /** @@ -343,8 +324,8 @@ struct iwl_device_cmd { struct iwl_tx_cmd tx; struct iwl6000_channel_switch_cmd chswitch; u8 payload[DEF_CMD_PAYLOAD_SIZE]; - } __attribute__ ((packed)) cmd; -} __attribute__ ((packed)); + } __packed cmd; +} __packed; #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) @@ -367,7 +348,7 @@ struct iwl_host_cmd { /** * struct iwl_rx_queue - Rx queue * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) - * @dma_addr: bus address of buffer of receive buffer descriptors (rbd) + * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) * @read: Shared index to newest available Rx buffer * @write: Shared index to oldest written Rx packet * @free_count: Number of pre-allocated buffers in rx_free @@ -381,7 +362,7 @@ struct iwl_host_cmd { */ struct iwl_rx_queue { __le32 *bd; - dma_addr_t dma_addr; + dma_addr_t bd_dma; struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; u32 read; @@ -433,7 +414,7 @@ struct iwl_ht_agg { struct iwl_tid_data { - u16 seq_number; + u16 seq_number; /* agn only */ u16 tfds_in_queue; struct iwl_ht_agg agg; }; @@ -583,6 +564,12 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_DATA = 4, IWL_UCODE_TLV_BOOT = 5, IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ + IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, + IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, + IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, + IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, + IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, + IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, }; struct iwl_ucode_tlv { @@ -590,7 +577,7 @@ struct iwl_ucode_tlv { __le16 alternative; /* see comment */ __le32 length; /* not including type/length fields */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 @@ -675,6 +662,7 @@ struct iwl_sensitivity_ranges { * @sw_crypto: 0 for hw, 1 for sw * @max_xxx_size: for ucode uses * @ct_kill_threshold: temperature threshold + * @beacon_time_tsf_bits: number of valid tsf bits for beacon time * @calib_init_cfg: setup initial calibrations for the hw * @struct iwl_sensitivity_ranges: range of sensitivity values */ @@ -701,6 +689,7 @@ struct iwl_hw_params { u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_exit_threshold; /* value in hw-dependent units */ /* for 1000, 6000 series and up */ + u16 beacon_time_tsf_bits; u32 calib_init_cfg; const struct iwl_sensitivity_ranges *sens; }; @@ -1075,6 +1064,20 @@ struct iwl_force_reset { unsigned long last_force_reset_jiffies; }; +/* extend beacon time format bit shifting */ +/* + * for _3945 devices + * bits 31:24 - extended + * bits 23:0 - interval + */ +#define IWL3945_EXT_BEACON_TIME_POS 24 +/* + * for _agn devices + * bits 31:22 - extended + * bits 21:0 - interval + */ +#define IWLAGN_EXT_BEACON_TIME_POS 22 + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1109,7 +1112,7 @@ struct iwl_priv { /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; - /* we allocate array of iwl4965_channel_info for NIC's valid channels. + /* we allocate array of iwl_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ @@ -1127,6 +1130,7 @@ struct iwl_priv { void *scan_cmd; enum ieee80211_band scan_band; struct cfg80211_scan_request *scan_request; + struct ieee80211_vif *scan_vif; bool is_internal_short_scan; u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; @@ -1174,7 +1178,7 @@ struct iwl_priv { struct iwl_switch_rxon switch_rxon; /* 1st responses from initialize and runtime uCode images. - * 4965's initialize alive response contains some calibration data. */ + * _agn's initialize alive response contains some calibration data. */ struct iwl_init_alive_resp card_alive_init; struct iwl_alive_resp card_alive; @@ -1221,7 +1225,7 @@ struct iwl_priv { struct iwl_tt_mgmt thermal_throttle; struct iwl_notif_statistics statistics; -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_notif_statistics accum_statistics; struct iwl_notif_statistics delta_statistics; struct iwl_notif_statistics max_delta; @@ -1229,9 +1233,10 @@ struct iwl_priv { /* context information */ u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ - u8 mac_addr[ETH_ALEN]; - /*station table variables */ + /* station table variables */ + + /* Note: if lock and sta_lock are needed, lock must be acquired first */ spinlock_t sta_lock; int num_stations; struct iwl_station_entry stations[IWL_STATION_COUNT]; @@ -1273,7 +1278,7 @@ struct iwl_priv { struct delayed_work rfkill_poll; struct iwl3945_notif_statistics statistics; -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl3945_notif_statistics accum_statistics; struct iwl3945_notif_statistics delta_statistics; struct iwl3945_notif_statistics max_delta; @@ -1315,6 +1320,9 @@ struct iwl_priv { bool last_phy_res_valid; struct completion firmware_loading_complete; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; } _agn; #endif }; @@ -1353,9 +1361,7 @@ struct iwl_priv { /* debugging info */ u32 debug_level; /* per device debugging will override global iwl_debug_level if set */ - u32 framecnt_to_us; - atomic_t restrict_refcnt; - bool disable_ht40; +#endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS /* debugfs */ u16 tx_traffic_idx; @@ -1364,8 +1370,8 @@ struct iwl_priv { u8 *rx_traffic; struct dentry *debugfs_dir; u32 dbgfs_sram_offset, dbgfs_sram_len; + bool disable_ht40; #endif /* CONFIG_IWLWIFI_DEBUGFS */ -#endif /* CONFIG_IWLWIFI_DEBUG */ struct work_struct txpower_work; u32 disable_sens_cal; @@ -1419,9 +1425,9 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv) static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, int txq_id, int idx) { - if (priv->txq[txq_id].txb[idx].skb[0]) + if (priv->txq[txq_id].txb[idx].skb) return (struct ieee80211_hdr *)priv->txq[txq_id]. - txb[idx].skb[0]->data; + txb[idx].skb->data; return NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 95aa202c85e3..5488006491a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -118,7 +118,7 @@ enum { struct iwl_eeprom_channel { u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ -} __attribute__ ((packed)); +} __packed; /** * iwl_eeprom_enhanced_txpwr structure @@ -144,7 +144,7 @@ struct iwl_eeprom_enhanced_txpwr { s8 reserved; s8 mimo2_max; s8 mimo3_max; -} __attribute__ ((packed)); +} __packed; /* 3945 Specific */ #define EEPROM_3945_EEPROM_VERSION (0x2f) @@ -312,7 +312,7 @@ struct iwl_eeprom_calib_measure { u8 gain_idx; /* Index into gain table */ u8 actual_pow; /* Measured RF output power, half-dBm */ s8 pa_det; /* Power amp detector level (not used) */ -} __attribute__ ((packed)); +} __packed; /* @@ -328,7 +328,7 @@ struct iwl_eeprom_calib_ch_info { struct iwl_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS] [EEPROM_TX_POWER_MEASUREMENTS]; -} __attribute__ ((packed)); +} __packed; /* * txpower subband info. @@ -345,7 +345,7 @@ struct iwl_eeprom_calib_subband_info { u8 ch_to; /* channel number of highest channel in subband */ struct iwl_eeprom_calib_ch_info ch1; struct iwl_eeprom_calib_ch_info ch2; -} __attribute__ ((packed)); +} __packed; /* @@ -374,7 +374,7 @@ struct iwl_eeprom_calib_info { __le16 voltage; /* signed */ struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; -} __attribute__ ((packed)); +} __packed; #define ADDRESS_MSK 0x0000FFFF diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 113c3669b9ce..a3fcbb5f2c70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -449,7 +449,7 @@ struct iwl_rb_status { __le16 finished_rb_num; __le16 finished_fr_nam; __le32 __unused; /* 3945 only */ -} __attribute__ ((packed)); +} __packed; #define TFD_QUEUE_SIZE_MAX (256) @@ -475,7 +475,7 @@ static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) struct iwl_tfd_tb { __le32 lo; __le16 hi_n_len; -} __attribute__((packed)); +} __packed; /** * struct iwl_tfd @@ -510,7 +510,7 @@ struct iwl_tfd { u8 num_tbs; struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS]; __le32 __pad; -} __attribute__ ((packed)); +} __packed; /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 3ff6b9d25a10..621abe3c5afc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -92,6 +92,11 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) { + if (!desc->len) { + desc->v_addr = NULL; + return -EINVAL; + } + desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, &desc->p_addr, GFP_KERNEL); return (desc->v_addr != NULL) ? 0 : -ENOMEM; @@ -170,4 +175,26 @@ static inline void iwl_enable_interrupts(struct iwl_priv *priv) iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); } +/** + * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time + * @priv -- pointer to iwl_priv data structure + * @tsf_bits -- number of bits need to shift for masking) + */ +static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, + u16 tsf_bits) +{ + return (1 << tsf_bits) - 1; +} + +/** + * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time + * @priv -- pointer to iwl_priv data structure + * @tsf_bits -- number of bits need to shift for masking) + */ +static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, + u16 tsf_bits) +{ + return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; +} + #endif /* __iwl_helpers_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0a5d7cf25196..86a353765796 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -175,7 +175,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) INIT_LIST_HEAD(&rxq->rx_used); /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, + rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, GFP_KERNEL); if (!rxq->bd) goto err_bd; @@ -199,7 +199,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) err_rb: dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); + rxq->bd_dma); err_bd: return -ENOMEM; } @@ -286,7 +286,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) last_rx_noise); } -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS /* * based on the assumption of all statistics counter are in DWORD * FIXME: This function is for debugging, do not deal with @@ -448,7 +448,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, STATISTICS_REPLY_FLG_HT40_MODE_MSK) != (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif iwl_recover_from_statistics(priv, pkt); @@ -480,7 +480,7 @@ void iwl_reply_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { -#ifdef CONFIG_IWLWIFI_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUGFS memset(&priv->accum_statistics, 0, sizeof(struct iwl_notif_statistics)); memset(&priv->delta_statistics, 0, diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 386c5f96eff8..798f93e0ff50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -333,7 +333,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - if (test_bit(STATUS_SCANNING, &priv->status)) { + if (test_bit(STATUS_SCANNING, &priv->status) && + !priv->is_internal_short_scan) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); ret = -EAGAIN; goto out_unlock; @@ -348,8 +349,16 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, /* mac80211 will only ask for one band at a time */ priv->scan_band = req->channels[0]->band; priv->scan_request = req; + priv->scan_vif = vif; - ret = iwl_scan_initiate(priv, vif); + /* + * If an internal scan is in progress, just set + * up the scan_request as per above. + */ + if (priv->is_internal_short_scan) + ret = 0; + else + ret = iwl_scan_initiate(priv, vif); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -438,7 +447,7 @@ EXPORT_SYMBOL(iwl_bg_scan_check); */ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ies, int ie_len, int left) + const u8 *ta, const u8 *ies, int ie_len, int left) { int len = 0; u8 *pos = NULL; @@ -451,7 +460,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); - memcpy(frame->sa, priv->mac_addr, ETH_ALEN); + memcpy(frame->sa, ta, ETH_ALEN); memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); frame->seq_ctrl = 0; @@ -514,7 +523,21 @@ void iwl_bg_scan_completed(struct work_struct *work) priv->is_internal_short_scan = false; IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); internal = true; + } else { + priv->scan_request = NULL; + priv->scan_vif = NULL; } + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + goto out; + + if (internal && priv->scan_request) + iwl_scan_initiate(priv, priv->scan_vif); + + /* 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); + out: mutex_unlock(&priv->mutex); /* @@ -524,15 +547,6 @@ void iwl_bg_scan_completed(struct work_struct *work) */ if (!internal) ieee80211_scan_completed(priv->hw, false); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - mutex_lock(&priv->mutex); - iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - mutex_unlock(&priv->mutex); } EXPORT_SYMBOL(iwl_bg_scan_completed); diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index af6babee2891..c4ca0b5d77da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -42,7 +42,7 @@ struct ieee80211_basic_report { __le64 start_time; __le16 duration; u8 map; -} __attribute__ ((packed)); +} __packed; enum { /* ieee80211_measurement_request.mode */ /* Bit 0 is reserved */ @@ -63,13 +63,13 @@ struct ieee80211_measurement_params { u8 channel; __le64 start_time; __le16 duration; -} __attribute__ ((packed)); +} __packed; struct ieee80211_info_element { u8 id; u8 len; u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct ieee80211_measurement_request { struct ieee80211_info_element ie; @@ -77,7 +77,7 @@ struct ieee80211_measurement_request { u8 mode; u8 type; struct ieee80211_measurement_params params[0]; -} __attribute__ ((packed)); +} __packed; struct ieee80211_measurement_report { struct ieee80211_info_element ie; @@ -87,6 +87,6 @@ struct ieee80211_measurement_report { union { struct ieee80211_basic_report basic[0]; } u; -} __attribute__ ((packed)); +} __packed; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c27c13fbb1ae..d57df6c02db3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -311,10 +311,10 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r) { - struct iwl_station_entry *station; unsigned long flags_spin; int ret = 0; u8 sta_id; + struct iwl_addsta_cmd sta_cmd; *sta_id_r = 0; spin_lock_irqsave(&priv->sta_lock, flags_spin); @@ -347,14 +347,15 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, } priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; - station = &priv->stations[sta_id]; + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ - ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); + ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); spin_lock_irqsave(&priv->sta_lock, flags_spin); + IWL_ERR(priv, "Adding station %pM failed.\n", + priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; spin_unlock_irqrestore(&priv->sta_lock, flags_spin); @@ -488,7 +489,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) } static int iwl_send_remove_station(struct iwl_priv *priv, - struct iwl_station_entry *station) + const u8 *addr, int sta_id) { struct iwl_rx_packet *pkt; int ret; @@ -505,7 +506,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); rm_sta_cmd.num_sta = 1; - memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); + memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN); cmd.flags |= CMD_WANT_SKB; @@ -525,7 +526,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: spin_lock_irqsave(&priv->sta_lock, flags_spin); - iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); + 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; @@ -546,7 +547,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr) { - struct iwl_station_entry *station; unsigned long flags; if (!iwl_is_ready(priv)) { @@ -592,10 +592,9 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, BUG_ON(priv->num_stations < 0); - station = &priv->stations[sta_id]; spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_remove_station(priv, station); + return iwl_send_remove_station(priv, addr, sta_id); out_err: spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; @@ -643,11 +642,13 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); */ void iwl_restore_stations(struct iwl_priv *priv) { - struct iwl_station_entry *station; + struct iwl_addsta_cmd sta_cmd; + struct iwl_link_quality_cmd lq; unsigned long flags_spin; int i; bool found = false; int ret; + bool send_lq; if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); @@ -669,13 +670,20 @@ void iwl_restore_stations(struct iwl_priv *priv) for (i = 0; i < priv->hw_params.max_stations; i++) { if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { + memcpy(&sta_cmd, &priv->stations[i].sta, + sizeof(struct iwl_addsta_cmd)); + send_lq = false; + if (priv->stations[i].lq) { + memcpy(&lq, priv->stations[i].lq, + sizeof(struct iwl_link_quality_cmd)); + send_lq = true; + } spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - station = &priv->stations[i]; - ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); + ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - IWL_ERR(priv, "Adding station %pM failed.\n", - station->sta.sta.addr); spin_lock_irqsave(&priv->sta_lock, flags_spin); + IWL_ERR(priv, "Adding station %pM failed.\n", + priv->stations[i].sta.sta.addr); priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; spin_unlock_irqrestore(&priv->sta_lock, flags_spin); @@ -684,8 +692,8 @@ void iwl_restore_stations(struct iwl_priv *priv) * Rate scaling has already been initialized, send * current LQ command */ - if (station->lq) - iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); + if (send_lq) + iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true); spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } @@ -972,24 +980,16 @@ void iwl_update_tkip_key(struct iwl_priv *priv, unsigned long flags; int i; - if (sta) { - sta_id = iwl_sta_id(sta); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", - sta->addr); - return; - } - } else - sta_id = priv->hw_params.bcast_sta_id; - - if (iwl_scan_cancel(priv)) { /* cancel scan failed, just live w/ bad key and rely briefly on SW decryption */ return; } + sta_id = iwl_sta_id_or_broadcast(priv, sta); + if (sta_id == IWL_INVALID_STATION) + return; + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; @@ -1277,9 +1277,8 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + spin_unlock_irqrestore(&priv->sta_lock, flags); } EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); @@ -1310,7 +1309,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid) { unsigned long flags; - int sta_id; + int sta_id, ret; sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { @@ -1323,10 +1322,11 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, - CMD_ASYNC); + return ret; + } EXPORT_SYMBOL(iwl_sta_rx_agg_stop); @@ -1340,9 +1340,9 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) priv->stations[sta_id].sta.sta.modify_mask = 0; priv->stations[sta_id].sta.sleep_tx_count = 0; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } EXPORT_SYMBOL(iwl_sta_modify_ps_wake); @@ -1357,9 +1357,9 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) STA_MODIFY_SLEEP_TX_COUNT_MSK; priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index c2a453a1a991..5b1b1e461eb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -107,4 +107,33 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; } + +/** + * iwl_sta_id_or_broadcast - return sta_id or broadcast sta + * @priv: iwl priv + * @sta: mac80211 station + * + * In certain circumstances mac80211 passes a station pointer + * that may be %NULL, for example during TX or key setup. In + * that case, we need to use the broadcast station, so this + * inline wraps that pattern. + */ +static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, + struct ieee80211_sta *sta) +{ + int sta_id; + + if (!sta) + return priv->hw_params.bcast_sta_id; + + sta_id = iwl_sta_id(sta); + + /* + * mac80211 should not be passing a partially + * initialised station! + */ + WARN_ON(sta_id == IWL_INVALID_STATION); + + return sta_id; +} #endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ece2ea09773..a81989c06983 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -77,21 +77,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) } EXPORT_SYMBOL(iwl_txq_update_write_ptr); - -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed) -{ - if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->stations[sta_id].tid[tid].tfds_in_queue, - freed); - priv->stations[sta_id].tid[tid].tfds_in_queue = 0; - } -} -EXPORT_SYMBOL(iwl_free_tfds_in_queue); - /** * iwl_tx_queue_free - Deallocate DMA queue. * @txq: Transmit queue to deallocate. @@ -169,15 +154,15 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) } pci_unmap_single(priv->pci_dev, - pci_unmap_addr(&txq->meta[i], mapping), - pci_unmap_len(&txq->meta[i], len), + dma_unmap_addr(&txq->meta[i], mapping), + dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); } if (huge) { i = q->n_window; pci_unmap_single(priv->pci_dev, - pci_unmap_addr(&txq->meta[i], mapping), - pci_unmap_len(&txq->meta[i], len), + dma_unmap_addr(&txq->meta[i], mapping), + dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); } @@ -287,7 +272,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, /* Driver private data, only for Tx (not command) queues, * not shared with device. */ if (id != IWL_CMD_QUEUE_NUM) { - txq->txb = kmalloc(sizeof(txq->txb[0]) * + txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { IWL_ERR(priv, "kmalloc for auxiliary BD " @@ -531,8 +516,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, fix_size, PCI_DMA_BIDIRECTIONAL); - pci_unmap_addr_set(out_meta, mapping, phys_addr); - pci_unmap_len_set(out_meta, len, fix_size); + dma_unmap_addr_set(out_meta, mapping, phys_addr); + dma_unmap_len_set(out_meta, len, fix_size); trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); @@ -626,8 +611,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) meta = &txq->meta[cmd_index]; pci_unmap_single(priv->pci_dev, - pci_unmap_addr(meta, mapping), - pci_unmap_len(meta, len), + dma_unmap_addr(meta, mapping), + dma_unmap_len(meta, len), PCI_DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a27872de4106..697fa6caaceb 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -197,6 +197,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) { unsigned long flags; + struct iwl_addsta_cmd sta_cmd; spin_lock_irqsave(&priv->sta_lock, flags); memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); @@ -205,11 +206,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); - return 0; + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } static int iwl3945_set_dynamic_key(struct iwl_priv *priv, @@ -474,10 +475,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 unicast; u8 sta_id; u8 tid = 0; - u16 seq_number = 0; __le16 fc; u8 wait_write_ptr = 0; - u8 *qc = NULL; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -510,10 +509,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find index into station table for destination station */ - if (!info->control.sta) - sta_id = priv->hw_params.bcast_sta_id; - else - sta_id = iwl_sta_id(info->control.sta); + sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -523,16 +519,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); + u8 *qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; if (unlikely(tid >= MAX_TID_COUNT)) goto drop; - seq_number = priv->stations[sta_id].tid[tid].seq_number & - IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = cpu_to_le16(seq_number) | - (hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)); - seq_number += 0x10; } /* Descriptor for chosen Tx queue */ @@ -548,7 +538,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb[0] = skb; + txq->txb[q->write_ptr].skb = skb; /* Init first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[idx]; @@ -591,8 +581,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; - if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; } else { wait_write_ptr = 1; txq->need_update = 0; @@ -631,8 +619,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) len, PCI_DMA_TODEVICE); /* we do not map meta data ... so we can safely access address to * provide to unmap command*/ - pci_unmap_addr_set(out_meta, mapping, txcmd_phys); - pci_unmap_len_set(out_meta, len, len); + dma_unmap_addr_set(out_meta, mapping, txcmd_phys); + dma_unmap_len_set(out_meta, len, len); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ @@ -677,55 +665,6 @@ drop: return -1; } -#define BEACON_TIME_MASK_LOW 0x00FFFFFF -#define BEACON_TIME_MASK_HIGH 0xFF000000 -#define TIME_UNIT 1024 - -/* - * extended beacon time format - * time in usec will be changed into a 32-bit value in 8:24 format - * the high 1 byte is the beacon counts - * the lower 3 bytes is the time in usec within one beacon interval - */ - -static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval) -{ - u32 quot; - u32 rem; - u32 interval = beacon_interval * 1024; - - if (!interval || !usec) - return 0; - - quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); - rem = (usec % interval) & BEACON_TIME_MASK_LOW; - - return (quot << 24) + rem; -} - -/* base is usually what we get from ucode with each received frame, - * the same as HW timer counter counting down - */ - -static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) -{ - u32 base_low = base & BEACON_TIME_MASK_LOW; - u32 addon_low = addon & BEACON_TIME_MASK_LOW; - u32 interval = beacon_interval * TIME_UNIT; - u32 res = (base & BEACON_TIME_MASK_HIGH) + - (addon & BEACON_TIME_MASK_HIGH); - - if (base_low > addon_low) - res += base_low - addon_low; - else if (base_low < addon_low) { - res += interval + base_low - addon_low; - res += (1 << 24); - } else - res += (1 << 24); - - return cpu_to_le32(res); -} - static int iwl3945_get_measurement(struct iwl_priv *priv, struct ieee80211_measurement_params *params, u8 type) @@ -743,8 +682,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, int duration = le16_to_cpu(params->duration); if (iwl_is_associated(priv)) - add_time = - iwl3945_usecs_to_beacons( + add_time = iwl_usecs_to_beacons(priv, le64_to_cpu(params->start_time) - priv->_3945.last_tsf, le16_to_cpu(priv->rxon_timing.beacon_interval)); @@ -759,8 +697,8 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, if (iwl_is_associated(priv)) spectrum.start_time = - iwl3945_add_beacon_time(priv->_3945.last_beacon_time, - add_time, + iwl_add_beacon_time(priv, + priv->_3945.last_beacon_time, add_time, le16_to_cpu(priv->rxon_timing.beacon_interval)); else spectrum.start_time = 0; @@ -1233,7 +1171,7 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx } dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); + rxq->bd_dma); dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); rxq->bd = NULL; @@ -1314,6 +1252,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); while (i != r) { + int len; + rxb = rxq->queue[i]; /* If an RXB doesn't have a Rx queue slot associated with it, @@ -1328,8 +1268,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) PCI_DMA_FROMDEVICE); pkt = rxb_addr(rxb); - trace_iwlwifi_dev_rx(priv, pkt, - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); + len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + len += sizeof(u32); /* account for status word */ + trace_iwlwifi_dev_rx(priv, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -3022,14 +2963,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->tx_cmd.len = cpu_to_le16( iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, + vif->addr, priv->scan_request->ie, priv->scan_request->ie_len, IWL_MAX_SCAN_SIZE - sizeof(*scan))); } else { + /* use bcast addr, will not be transmitted but must be valid */ scan->tx_cmd.len = cpu_to_le16( iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - NULL, 0, + iwl_bcast_addr, NULL, 0, IWL_MAX_SCAN_SIZE - sizeof(*scan))); } /* select Rx antennas */ @@ -3158,19 +3101,16 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", vif->bss_conf.aid, vif->bss_conf.beacon_int); - if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.use_short_slot) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (vif->type == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } iwlcore_commit_rxon(priv); @@ -3334,8 +3274,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->staging_rxon.assoc_id = 0; - if (vif->bss_conf.assoc_capability & - WLAN_CAPABILITY_SHORT_PREAMBLE) + if (vif->bss_conf.use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else @@ -3343,17 +3282,12 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) ~RXON_FLG_SHORT_PREAMBLE_MSK; if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (vif->bss_conf.assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) + if (vif->bss_conf.use_short_slot) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (vif->type == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; @@ -3386,17 +3320,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static_key = !iwl_is_associated(priv); if (!static_key) { - if (!sta) { - sta_id = priv->hw_params.bcast_sta_id; - } else { - sta_id = iwl_sta_id(sta); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, - "leave - %pM not in station map.\n", - sta->addr); - return -EINVAL; - } - } + sta_id = iwl_sta_id_or_broadcast(priv, sta); + if (sta_id == IWL_INVALID_STATION) + return -EINVAL; } mutex_lock(&priv->mutex); @@ -4028,9 +3954,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; priv->inta_mask = CSR_INI_SET_MASK; -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_set(&priv->restrict_refcnt, 0); -#endif if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); @@ -4099,9 +4022,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e } /* MAC Address location in EEPROM same for 3945/4965 */ eeprom = (struct iwl3945_eeprom *)priv->eeprom; - memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address); + SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address); /*********************** * 5. Setup HW Constants diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 7e16bcf59978..6421689f5e8e 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -56,7 +56,7 @@ struct iwm_umac_cmd_reset { __le32 flags; -} __attribute__ ((packed)); +} __packed; #define UMAC_PARAM_TBL_ORD_FIX 0x0 #define UMAC_PARAM_TBL_ORD_VAR 0x1 @@ -220,37 +220,37 @@ struct iwm_umac_cmd_set_param_fix { __le16 tbl; __le16 key; __le32 value; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_set_param_var { __le16 tbl; __le16 key; __le16 len; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_get_param { __le16 tbl; __le16 key; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_get_param_resp { __le16 tbl; __le16 key; __le16 len; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_eeprom_proxy_hdr { __le32 type; __le32 offset; __le32 len; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_eeprom_proxy { struct iwm_umac_cmd_eeprom_proxy_hdr hdr; u8 buf[0]; -} __attribute__ ((packed)); +} __packed; #define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1 #define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2 @@ -267,13 +267,13 @@ struct iwm_umac_channel_info { u8 reserved; u8 flags; __le32 channels_mask; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_get_channel_list { __le16 count; __le16 reserved; struct iwm_umac_channel_info ch[0]; -} __attribute__ ((packed)); +} __packed; /* UMAC WiFi interface commands */ @@ -304,7 +304,7 @@ struct iwm_umac_ssid { u8 ssid_len; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_scan_request { struct iwm_umac_wifi_if hdr; @@ -314,7 +314,7 @@ struct iwm_umac_cmd_scan_request { u8 timeout; /* In seconds */ u8 reserved; struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX]; -} __attribute__ ((packed)); +} __packed; #define UMAC_CIPHER_TYPE_NONE 0xFF #define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00 @@ -357,7 +357,7 @@ struct iwm_umac_security { u8 ucast_cipher; u8 mcast_cipher; u8 flags; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_ibss { u8 beacon_interval; /* in millisecond */ @@ -366,7 +366,7 @@ struct iwm_umac_ibss { u8 band; u8 channel; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; #define UMAC_MODE_BSS 0 #define UMAC_MODE_IBSS 1 @@ -385,13 +385,13 @@ struct iwm_umac_profile { __le16 flags; u8 wireless_mode; u8 bss_num; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_invalidate_profile { struct iwm_umac_wifi_if hdr; u8 reason; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; /* Encryption key commands */ struct iwm_umac_key_wep40 { @@ -400,7 +400,7 @@ struct iwm_umac_key_wep40 { u8 key[WLAN_KEY_LEN_WEP40]; u8 static_key; u8 reserved[2]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_key_wep104 { struct iwm_umac_wifi_if hdr; @@ -408,7 +408,7 @@ struct iwm_umac_key_wep104 { u8 key[WLAN_KEY_LEN_WEP104]; u8 static_key; u8 reserved[2]; -} __attribute__ ((packed)); +} __packed; #define IWM_TKIP_KEY_SIZE 16 #define IWM_TKIP_MIC_SIZE 8 @@ -420,7 +420,7 @@ struct iwm_umac_key_tkip { u8 tkip_key[IWM_TKIP_KEY_SIZE]; u8 mic_rx_key[IWM_TKIP_MIC_SIZE]; u8 mic_tx_key[IWM_TKIP_MIC_SIZE]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_key_ccmp { struct iwm_umac_wifi_if hdr; @@ -428,27 +428,27 @@ struct iwm_umac_key_ccmp { u8 iv_count[6]; u8 reserved[2]; u8 key[WLAN_KEY_LEN_CCMP]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_key_remove { struct iwm_umac_wifi_if hdr; struct iwm_umac_key_hdr key_hdr; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_tx_key_id { struct iwm_umac_wifi_if hdr; u8 key_idx; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_pwr_trigger { struct iwm_umac_wifi_if hdr; __le32 reseved; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_stats_req { __le32 flags; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_cmd_stop_resume_tx { u8 flags; @@ -456,7 +456,7 @@ struct iwm_umac_cmd_stop_resume_tx { __le16 stop_resume_tid_msk; __le16 last_seq_num[IWM_UMAC_TID_NR]; u16 reserved; -} __attribute__ ((packed)); +} __packed; #define IWM_CMD_PMKID_ADD 1 #define IWM_CMD_PMKID_DEL 2 @@ -468,7 +468,7 @@ struct iwm_umac_pmkid_update { u8 bssid[ETH_ALEN]; __le16 reserved; u8 pmkid[WLAN_PMKID_LEN]; -} __attribute__ ((packed)); +} __packed; /* LMAC commands */ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index 9531b18cf72a..907ac890997c 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -54,7 +54,7 @@ * LMAC. If you look at LMAC commands you'll se that they * are actually regular iwlwifi target commands encapsulated * into a special UMAC command called UMAC passthrough. - * This is due to the fact the the host talks exclusively + * This is due to the fact the host talks exclusively * to the UMAC and so there needs to be a special UMAC * command for talking to the LMAC. * This is how a wifi command is layed out: diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 13266c3842f8..51d7efa15ae6 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -162,7 +162,7 @@ struct iwm_umac_key_hdr { u8 mac[ETH_ALEN]; u8 key_idx; u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */ -} __attribute__ ((packed)); +} __packed; struct iwm_key { struct iwm_umac_key_hdr hdr; diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h index a855a99e49b8..5ddcdf8c70c0 100644 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -43,7 +43,7 @@ struct iwm_lmac_hdr { u8 id; u8 flags; __le16 seq_num; -} __attribute__ ((packed)); +} __packed; /* LMAC commands */ #define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1 @@ -54,23 +54,23 @@ struct iwm_lmac_cal_cfg_elt { __le32 send_res; /* 1 for sending back results */ __le32 apply_res; /* 1 for applying calibration results to HW */ __le32 reserved; -} __attribute__ ((packed)); +} __packed; struct iwm_lmac_cal_cfg_status { struct iwm_lmac_cal_cfg_elt init; struct iwm_lmac_cal_cfg_elt periodic; __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */ -} __attribute__ ((packed)); +} __packed; struct iwm_lmac_cal_cfg_cmd { struct iwm_lmac_cal_cfg_status ucode_cfg; struct iwm_lmac_cal_cfg_status driver_cfg; __le32 reserved; -} __attribute__ ((packed)); +} __packed; struct iwm_lmac_cal_cfg_resp { __le32 status; -} __attribute__ ((packed)); +} __packed; #define IWM_CARD_STATE_SW_HW_ENABLED 0x00 #define IWM_CARD_STATE_HW_DISABLED 0x01 @@ -80,7 +80,7 @@ struct iwm_lmac_cal_cfg_resp { struct iwm_lmac_card_state { __le32 flags; -} __attribute__ ((packed)); +} __packed; /** * COEX_PRIORITY_TABLE_CMD @@ -131,7 +131,7 @@ struct coex_event { u8 win_med_prio; u8 reserved; u8 flags; -} __attribute__ ((packed)); +} __packed; #define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1 #define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4 @@ -142,7 +142,7 @@ struct iwm_coex_prio_table_cmd { u8 flags; u8 reserved[3]; struct coex_event sta_prio[COEX_EVENTS_NUM]; -} __attribute__ ((packed)); +} __packed; /* Coexistence definitions * @@ -192,7 +192,7 @@ struct iwm_ct_kill_cfg_cmd { u32 exit_threshold; u32 reserved; u32 entry_threshold; -} __attribute__ ((packed)); +} __packed; /* LMAC OP CODES */ @@ -428,7 +428,7 @@ struct iwm_lmac_calib_hdr { u8 first_grp; u8 grp_num; u8 all_data_valid; -} __attribute__ ((packed)); +} __packed; #define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7 #define IWM_CALIB_FREQ_GROUPS_NR 5 @@ -437,20 +437,20 @@ struct iwm_lmac_calib_hdr { struct iwm_calib_rxiq_entry { u16 ptam_postdist_ars; u16 ptam_postdist_arc; -} __attribute__ ((packed)); +} __packed; struct iwm_calib_rxiq_group { struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR]; -} __attribute__ ((packed)); +} __packed; struct iwm_lmac_calib_rxiq { struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR]; -} __attribute__ ((packed)); +} __packed; struct iwm_calib_rxiq { struct iwm_lmac_calib_hdr hdr; struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR]; -} __attribute__ ((packed)); +} __packed; #define LMAC_STA_ID_SEED 0x0f #define LMAC_STA_ID_POS 0 @@ -463,7 +463,7 @@ struct iwm_lmac_power_report { u8 pa_integ_res_A[3]; u8 pa_integ_res_B[3]; u8 pa_integ_res_C[3]; -} __attribute__ ((packed)); +} __packed; struct iwm_lmac_tx_resp { u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */ @@ -479,6 +479,6 @@ struct iwm_lmac_tx_resp { u8 ra_tid; __le16 frame_ctl; __le32 status; -} __attribute__ ((packed)); +} __packed; #endif diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index e1184deca559..c02fcedea9fa 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -321,14 +321,14 @@ iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket) return ERR_PTR(-ENOMEM); } - ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL); + ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket), + GFP_KERNEL); if (!ticket_node->ticket) { IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); kfree(ticket_node); return ERR_PTR(-ENOMEM); } - memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket)); INIT_LIST_HEAD(&ticket_node->node); return ticket_node; diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 0cbba3ecc813..4a137d334a42 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -42,19 +42,19 @@ struct iwm_udma_in_hdr { __le32 cmd; __le32 size; -} __attribute__ ((packed)); +} __packed; struct iwm_udma_out_nonwifi_hdr { __le32 cmd; __le32 addr; __le32 op1_sz; __le32 op2; -} __attribute__ ((packed)); +} __packed; struct iwm_udma_out_wifi_hdr { __le32 cmd; __le32 meta_data; -} __attribute__ ((packed)); +} __packed; /* Sequence numbering */ #define UMAC_WIFI_SEQ_NUM_BASE 1 @@ -408,12 +408,12 @@ struct iwm_rx_ticket { __le16 flags; u8 payload_offset; /* includes: MAC header, pad, IV */ u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */ -} __attribute__ ((packed)); +} __packed; struct iwm_rx_mpdu_hdr { __le16 len; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /* UMAC SW WIFI API */ @@ -421,31 +421,31 @@ struct iwm_dev_cmd_hdr { u8 cmd; u8 flags; __le16 seq_num; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_fw_cmd_hdr { __le32 meta_data; struct iwm_dev_cmd_hdr cmd; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_wifi_out_hdr { struct iwm_udma_out_wifi_hdr hw_hdr; struct iwm_umac_fw_cmd_hdr sw_hdr; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_nonwifi_out_hdr { struct iwm_udma_out_nonwifi_hdr hw_hdr; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_wifi_in_hdr { struct iwm_udma_in_hdr hw_hdr; struct iwm_umac_fw_cmd_hdr sw_hdr; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_nonwifi_in_hdr { struct iwm_udma_in_hdr hw_hdr; __le32 time_stamp; -} __attribute__ ((packed)); +} __packed; #define IWM_UMAC_PAGE_SIZE 0x200 @@ -521,7 +521,7 @@ struct iwm_umac_notif_wifi_if { u8 status; u8 flags; __le16 buf_size; -} __attribute__ ((packed)); +} __packed; #define UMAC_ROAM_REASON_FIRST_SELECTION 0x1 #define UMAC_ROAM_REASON_AP_DEAUTH 0x2 @@ -535,7 +535,7 @@ struct iwm_umac_notif_assoc_start { __le32 roam_reason; u8 bssid[ETH_ALEN]; u8 reserved[2]; -} __attribute__ ((packed)); +} __packed; #define UMAC_ASSOC_COMPLETE_SUCCESS 0x0 #define UMAC_ASSOC_COMPLETE_FAILURE 0x1 @@ -546,7 +546,7 @@ struct iwm_umac_notif_assoc_complete { u8 bssid[ETH_ALEN]; u8 band; u8 channel; -} __attribute__ ((packed)); +} __packed; #define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0 #define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1 @@ -556,7 +556,7 @@ struct iwm_umac_notif_assoc_complete { struct iwm_umac_notif_profile_invalidate { struct iwm_umac_notif_wifi_if mlme_hdr; __le32 reason; -} __attribute__ ((packed)); +} __packed; #define UMAC_SCAN_RESULT_SUCCESS 0x0 #define UMAC_SCAN_RESULT_ABORTED 0x1 @@ -568,7 +568,7 @@ struct iwm_umac_notif_scan_complete { __le32 type; __le32 result; u8 seq_num; -} __attribute__ ((packed)); +} __packed; #define UMAC_OPCODE_ADD_MODIFY 0x0 #define UMAC_OPCODE_REMOVE 0x1 @@ -582,7 +582,7 @@ struct iwm_umac_notif_sta_info { u8 mac_addr[ETH_ALEN]; u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */ u8 flags; -} __attribute__ ((packed)); +} __packed; #define UMAC_BAND_2GHZ 0 #define UMAC_BAND_5GHZ 1 @@ -601,7 +601,7 @@ struct iwm_umac_notif_bss_info { s8 rssi; u8 reserved; u8 frame_buf[1]; -} __attribute__ ((packed)); +} __packed; #define IWM_BSS_REMOVE_INDEX_MSK 0x0fff #define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00 @@ -614,13 +614,13 @@ struct iwm_umac_notif_bss_removed { struct iwm_umac_notif_wifi_if mlme_hdr; __le32 count; __le16 entries[0]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_mgt_frame { struct iwm_umac_notif_wifi_if mlme_hdr; __le16 len; u8 frame[1]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_alive { struct iwm_umac_wifi_in_hdr hdr; @@ -630,13 +630,13 @@ struct iwm_umac_notif_alive { __le16 reserved2; __le16 page_grp_count; __le32 page_grp_state[IWM_MACS_OUT_GROUPS]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_init_complete { struct iwm_umac_wifi_in_hdr hdr; __le16 status; __le16 reserved; -} __attribute__ ((packed)); +} __packed; /* error categories */ enum { @@ -667,12 +667,12 @@ struct iwm_fw_error_hdr { __le32 dbm_buf_end; __le32 dbm_buf_write_ptr; __le32 dbm_buf_cycle_cnt; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_error { struct iwm_umac_wifi_in_hdr hdr; struct iwm_fw_error_hdr err; -} __attribute__ ((packed)); +} __packed; #define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0 #define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff @@ -687,20 +687,20 @@ struct iwm_umac_notif_page_dealloc { struct iwm_umac_wifi_in_hdr hdr; __le32 changes; __le32 grp_info[IWM_MACS_OUT_GROUPS]; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_wifi_status { struct iwm_umac_wifi_in_hdr hdr; __le16 status; __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct iwm_umac_notif_rx_ticket { struct iwm_umac_wifi_in_hdr hdr; u8 num_tickets; u8 reserved[3]; struct iwm_rx_ticket tickets[1]; -} __attribute__ ((packed)); +} __packed; /* Tx/Rx rates window (number of max of last update window per second) */ #define UMAC_NTF_RATE_SAMPLE_NR 4 @@ -758,7 +758,7 @@ struct iwm_umac_notif_stats { __le32 roam_unassoc; __le32 roam_deauth; __le32 roam_ap_loadblance; -} __attribute__ ((packed)); +} __packed; #define UMAC_STOP_TX_FLAG 0x1 #define UMAC_RESUME_TX_FLAG 0x2 @@ -770,7 +770,7 @@ struct iwm_umac_notif_stop_resume_tx { u8 flags; /* UMAC_*_TX_FLAG_* */ u8 sta_id; __le16 stop_resume_tid_msk; /* tid bitmask */ -} __attribute__ ((packed)); +} __packed; #define UMAC_MAX_NUM_PMKIDS 4 @@ -779,7 +779,7 @@ struct iwm_umac_wifi_if { u8 oid; u8 flags; __le16 buf_size; -} __attribute__ ((packed)); +} __packed; #define IWM_SEQ_NUM_HOST_MSK 0x0000 #define IWM_SEQ_NUM_UMAC_MSK 0x4000 diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index cdb9b9650d73..0fa6b0e59ea5 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -70,6 +70,8 @@ static u8 is_command_allowed_in_ps(u16 cmd) switch (cmd) { case CMD_802_11_RSSI: return 1; + case CMD_802_11_HOST_SLEEP_CFG: + return 1; default: break; } @@ -185,6 +187,23 @@ out: return ret; } +static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy, + struct cmd_header *resp) +{ + lbs_deb_enter(LBS_DEB_CMD); + if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { + priv->is_host_sleep_configured = 0; + if (priv->psstate == PS_STATE_FULL_POWER) { + priv->is_host_sleep_activated = 0; + wake_up_interruptible(&priv->host_sleep_q); + } + } else { + priv->is_host_sleep_configured = 1; + } + lbs_deb_leave(LBS_DEB_CMD); + return 0; +} + int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, struct wol_config *p_wol_config) { @@ -202,12 +221,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, else cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; - ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); + ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr, + le16_to_cpu(cmd_config.hdr.size), + lbs_ret_host_sleep_cfg, 0); if (!ret) { - if (criteria) { - lbs_deb_cmd("Set WOL criteria to %x\n", criteria); - priv->wol_criteria = criteria; - } else + if (p_wol_config) memcpy((uint8_t *) p_wol_config, (uint8_t *)&cmd_config.wol_conf, sizeof(struct wol_config)); @@ -712,6 +730,10 @@ static void lbs_queue_cmd(struct lbs_private *priv, } } + if (le16_to_cpu(cmdnode->cmdbuf->command) == + CMD_802_11_WAKEUP_CONFIRM) + addtail = 0; + spin_lock_irqsave(&priv->driver_lock, flags); if (addtail) @@ -1353,6 +1375,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) /* We don't get a response on the sleep-confirmation */ priv->dnld_sent = DNLD_RES_RECEIVED; + if (priv->is_host_sleep_configured) { + priv->is_host_sleep_activated = 1; + wake_up_interruptible(&priv->host_sleep_q); + } + /* If nothing to do, go back to sleep (?) */ if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 88f7131d66e9..d6c306353640 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -17,6 +17,7 @@ #include "dev.h" #include "assoc.h" #include "wext.h" +#include "cmd.h" /** * @brief This function handles disconnect event. it @@ -341,32 +342,10 @@ done: return ret; } -static int lbs_send_confirmwake(struct lbs_private *priv) -{ - struct cmd_header cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_HOST); - - cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM); - cmd.size = cpu_to_le16(sizeof(cmd)); - cmd.seqnum = cpu_to_le16(++priv->seqnum); - cmd.result = 0; - - lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd, - sizeof(cmd)); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd)); - if (ret) - lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n"); - - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - int lbs_process_event(struct lbs_private *priv, u32 event) { int ret = 0; + struct cmd_header cmd; lbs_deb_enter(LBS_DEB_CMD); @@ -410,7 +389,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event) if (priv->reset_deep_sleep_wakeup) priv->reset_deep_sleep_wakeup(priv); priv->is_deep_sleep = 0; - lbs_send_confirmwake(priv); + lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd, + sizeof(cmd)); + priv->is_host_sleep_activated = 0; + wake_up_interruptible(&priv->host_sleep_q); break; case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 709ffcad22ad..61db8bc62b3c 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -38,7 +38,7 @@ int lbs_set_mac_address(struct net_device *dev, void *addr); void lbs_set_multicast_list(struct net_device *dev); int lbs_suspend(struct lbs_private *priv); -void lbs_resume(struct lbs_private *priv); +int lbs_resume(struct lbs_private *priv); void lbs_queue_event(struct lbs_private *priv, u32 event); void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index a54880e4ad2b..71c5ad46ebf6 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -75,6 +75,7 @@ struct lbs_private { /* Deep sleep */ int is_deep_sleep; + int deep_sleep_required; int is_auto_deep_sleep_enabled; int wakeup_dev_required; int is_activity_detected; @@ -82,6 +83,11 @@ struct lbs_private { wait_queue_head_t ds_awake_q; struct timer_list auto_deepsleep_timer; + /* Host sleep*/ + int is_host_sleep_configured; + int is_host_sleep_activated; + wait_queue_head_t host_sleep_q; + /* Hardware access */ void *card; u8 fw_ready; diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 3804a58d7f4e..0cf31bbf6567 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -69,14 +69,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev, { struct lbs_private *priv = dev->ml_priv; - if (priv->wol_criteria == 0xffffffff) { - /* Interface driver didn't configure wake */ - wol->supported = wol->wolopts = 0; - return; - } - wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; + if (priv->wol_criteria == EHS_REMOVE_WAKEUP) + return; + if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) wol->wolopts |= WAKE_UCAST; if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) @@ -91,23 +88,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct lbs_private *priv = dev->ml_priv; - uint32_t criteria = 0; if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) return -EOPNOTSUPP; + priv->wol_criteria = 0; if (wol->wolopts & WAKE_UCAST) - criteria |= EHS_WAKE_ON_UNICAST_DATA; + priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA; if (wol->wolopts & WAKE_MCAST) - criteria |= EHS_WAKE_ON_MULTICAST_DATA; + priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA; if (wol->wolopts & WAKE_BCAST) - criteria |= EHS_WAKE_ON_BROADCAST_DATA; + priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA; if (wol->wolopts & WAKE_PHY) - criteria |= EHS_WAKE_ON_MAC_EVENT; + priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT; if (wol->wolopts == 0) - criteria |= EHS_REMOVE_WAKEUP; - - return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); + priv->wol_criteria |= EHS_REMOVE_WAKEUP; + return 0; } const struct ethtool_ops lbs_ethtool_ops = { diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 3809c0b49464..3bd5d3b6037a 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -326,7 +326,7 @@ struct txpd { u8 pktdelay_2ms; /* reserved */ u8 reserved1; -} __attribute__ ((packed)); +} __packed; /* RxPD Descriptor */ struct rxpd { @@ -339,8 +339,8 @@ struct rxpd { u8 bss_type; /* BSS number */ u8 bss_num; - } __attribute__ ((packed)) bss; - } __attribute__ ((packed)) u; + } __packed bss; + } __packed u; /* SNR */ u8 snr; @@ -366,14 +366,14 @@ struct rxpd { /* Pkt Priority */ u8 priority; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct cmd_header { __le16 command; __le16 size; __le16 seqnum; __le16 result; -} __attribute__ ((packed)); +} __packed; /* Generic structure to hold all key types. */ struct enc_key { @@ -387,7 +387,7 @@ struct enc_key { struct lbs_offset_value { u32 offset; u32 value; -} __attribute__ ((packed)); +} __packed; /* * Define data structure for CMD_GET_HW_SPEC @@ -426,7 +426,7 @@ struct cmd_ds_get_hw_spec { /*FW/HW capability */ __le32 fwcapinfo; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_subscribe_event { struct cmd_header hdr; @@ -440,7 +440,7 @@ struct cmd_ds_802_11_subscribe_event { * bump this up a bit. */ uint8_t tlv[128]; -} __attribute__ ((packed)); +} __packed; /* * This scan handle Country Information IE(802.11d compliant) @@ -452,7 +452,7 @@ struct cmd_ds_802_11_scan { uint8_t bsstype; uint8_t bssid[ETH_ALEN]; uint8_t tlvbuffer[0]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_scan_rsp { struct cmd_header hdr; @@ -460,7 +460,7 @@ struct cmd_ds_802_11_scan_rsp { __le16 bssdescriptsize; uint8_t nr_sets; uint8_t bssdesc_and_tlvbuffer[0]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_get_log { struct cmd_header hdr; @@ -478,20 +478,20 @@ struct cmd_ds_802_11_get_log { __le32 fcserror; __le32 txframe; __le32 wepundecryptable; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mac_control { struct cmd_header hdr; __le16 action; u16 reserved; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mac_multicast_adr { struct cmd_header hdr; __le16 action; __le16 nr_of_adrs; u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_authenticate { struct cmd_header hdr; @@ -499,14 +499,14 @@ struct cmd_ds_802_11_authenticate { u8 bssid[ETH_ALEN]; u8 authtype; u8 reserved[10]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_deauthenticate { struct cmd_header hdr; u8 macaddr[ETH_ALEN]; __le16 reasoncode; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_associate { struct cmd_header hdr; @@ -517,7 +517,7 @@ struct cmd_ds_802_11_associate { __le16 bcnperiod; u8 dtimperiod; u8 iebuf[512]; /* Enough for required and most optional IEs */ -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_associate_response { struct cmd_header hdr; @@ -526,7 +526,7 @@ struct cmd_ds_802_11_associate_response { __le16 statuscode; __le16 aid; u8 iebuf[512]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_set_wep { struct cmd_header hdr; @@ -540,7 +540,7 @@ struct cmd_ds_802_11_set_wep { /* 40, 128bit or TXWEP */ uint8_t keytype[4]; uint8_t keymaterial[4][16]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_snmp_mib { struct cmd_header hdr; @@ -549,40 +549,40 @@ struct cmd_ds_802_11_snmp_mib { __le16 oid; __le16 bufsize; u8 value[128]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mac_reg_access { __le16 action; __le16 offset; __le32 value; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_bbp_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_rf_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_radio_control { struct cmd_header hdr; __le16 action; __le16 control; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_beacon_control { __le16 action; __le16 beacon_enable; __le16 beacon_period; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_sleep_params { struct cmd_header hdr; @@ -607,7 +607,7 @@ struct cmd_ds_802_11_sleep_params { /* reserved field, should be set to zero */ __le16 reserved; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_rf_channel { struct cmd_header hdr; @@ -617,7 +617,7 @@ struct cmd_ds_802_11_rf_channel { __le16 rftype; /* unused */ __le16 reserved; /* unused */ u8 channellist[32]; /* unused */ -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_rssi { /* weighting factor */ @@ -626,21 +626,21 @@ struct cmd_ds_802_11_rssi { __le16 reserved_0; __le16 reserved_1; __le16 reserved_2; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_rssi_rsp { __le16 SNR; __le16 noisefloor; __le16 avgSNR; __le16 avgnoisefloor; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_mac_address { struct cmd_header hdr; __le16 action; u8 macadd[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_rf_tx_power { struct cmd_header hdr; @@ -649,26 +649,26 @@ struct cmd_ds_802_11_rf_tx_power { __le16 curlevel; s8 maxlevel; s8 minlevel; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_monitor_mode { __le16 action; __le16 mode; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_set_boot2_ver { struct cmd_header hdr; __le16 action; __le16 version; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_fw_wake_method { struct cmd_header hdr; __le16 action; __le16 method; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_ps_mode { __le16 action; @@ -676,7 +676,7 @@ struct cmd_ds_802_11_ps_mode { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -} __attribute__ ((packed)); +} __packed; struct cmd_confirm_sleep { struct cmd_header hdr; @@ -686,7 +686,7 @@ struct cmd_confirm_sleep { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_data_rate { struct cmd_header hdr; @@ -694,14 +694,14 @@ struct cmd_ds_802_11_data_rate { __le16 action; __le16 reserved; u8 rates[MAX_RATES]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_rate_adapt_rateset { struct cmd_header hdr; __le16 action; __le16 enablehwauto; __le16 bitmap; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_ad_hoc_start { struct cmd_header hdr; @@ -718,14 +718,14 @@ struct cmd_ds_802_11_ad_hoc_start { __le16 capability; u8 rates[MAX_RATES]; u8 tlv_memory_size_pad[100]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_ad_hoc_result { struct cmd_header hdr; u8 pad[3]; u8 bssid[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct adhoc_bssdesc { u8 bssid[ETH_ALEN]; @@ -746,7 +746,7 @@ struct adhoc_bssdesc { * Adhoc join command and will cause a binary layout mismatch with * the firmware */ -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_ad_hoc_join { struct cmd_header hdr; @@ -754,18 +754,18 @@ struct cmd_ds_802_11_ad_hoc_join { struct adhoc_bssdesc bss; __le16 failtimeout; /* Reserved on v9 and later */ __le16 probedelay; /* Reserved on v9 and later */ -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_ad_hoc_stop { struct cmd_header hdr; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_enable_rsn { struct cmd_header hdr; __le16 action; __le16 enable; -} __attribute__ ((packed)); +} __packed; struct MrvlIEtype_keyParamSet { /* type ID */ @@ -785,7 +785,7 @@ struct MrvlIEtype_keyParamSet { /* key material of size keylen */ u8 key[32]; -} __attribute__ ((packed)); +} __packed; #define MAX_WOL_RULES 16 @@ -797,7 +797,7 @@ struct host_wol_rule { __le16 reserve; __be32 sig_mask; __be32 signature; -} __attribute__ ((packed)); +} __packed; struct wol_config { uint8_t action; @@ -805,7 +805,7 @@ struct wol_config { uint8_t no_rules_in_cmd; uint8_t result; struct host_wol_rule rule[MAX_WOL_RULES]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_host_sleep { struct cmd_header hdr; @@ -813,7 +813,7 @@ struct cmd_ds_host_sleep { uint8_t gpio; uint16_t gap; struct wol_config wol_conf; -} __attribute__ ((packed)); +} __packed; @@ -822,7 +822,7 @@ struct cmd_ds_802_11_key_material { __le16 action; struct MrvlIEtype_keyParamSet keyParamSet[2]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_eeprom_access { struct cmd_header hdr; @@ -832,7 +832,7 @@ struct cmd_ds_802_11_eeprom_access { /* firmware says it returns a maximum of 20 bytes */ #define LBS_EEPROM_READ_LEN 20 u8 value[LBS_EEPROM_READ_LEN]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_tpc_cfg { struct cmd_header hdr; @@ -843,7 +843,7 @@ struct cmd_ds_802_11_tpc_cfg { int8_t P1; int8_t P2; uint8_t usesnr; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_pa_cfg { @@ -854,14 +854,14 @@ struct cmd_ds_802_11_pa_cfg { int8_t P0; int8_t P1; int8_t P2; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_led_ctrl { __le16 action; __le16 numled; u8 data[256]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_802_11_afc { __le16 afc_auto; @@ -875,22 +875,22 @@ struct cmd_ds_802_11_afc { __le16 carrier_offset; /* signed */ }; }; -} __attribute__ ((packed)); +} __packed; struct cmd_tx_rate_query { __le16 txrate; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_get_tsf { __le64 tsfvalue; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_bt_access { __le16 action; __le32 id; u8 addr1[ETH_ALEN]; u8 addr2[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_fwt_access { __le16 action; @@ -910,7 +910,7 @@ struct cmd_ds_fwt_access { __le32 snr; __le32 references; u8 prec[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mesh_config { struct cmd_header hdr; @@ -920,14 +920,14 @@ struct cmd_ds_mesh_config { __le16 type; __le16 length; u8 data[128]; /* last position reserved */ -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mesh_access { struct cmd_header hdr; __le16 action; __le32 data[32]; /* last position reserved */ -} __attribute__ ((packed)); +} __packed; /* Number of stats counters returned by the firmware */ #define MESH_STATS_NUM 8 @@ -957,6 +957,6 @@ struct cmd_ds_command { struct cmd_ds_fwt_access fwt; struct cmd_ds_802_11_beacon_control bcn_ctrl; } params; -} __attribute__ ((packed)); +} __packed; #endif diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 64dd345d30f5..6e71346a7550 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func) lbs_deb_leave(LBS_DEB_SDIO); } +static int if_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int ret; + struct if_sdio_card *card = sdio_get_drvdata(func); + + mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); + + lbs_pr_info("%s: suspend: PM flags = 0x%x\n", + sdio_func_id(func), flags); + + /* If we aren't being asked to wake on anything, we should bail out + * and let the SD stack power down the card. + */ + if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { + lbs_pr_info("Suspend without wake params -- " + "powering down card."); + return -ENOSYS; + } + + if (!(flags & MMC_PM_KEEP_POWER)) { + lbs_pr_err("%s: cannot remain alive while host is suspended\n", + sdio_func_id(func)); + return -ENOSYS; + } + + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) + return ret; + + ret = lbs_suspend(card->priv); + if (ret) + return ret; + + return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); +} + +static int if_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct if_sdio_card *card = sdio_get_drvdata(func); + int ret; + + lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func)); + + ret = lbs_resume(card->priv); + + return ret; +} + +static const struct dev_pm_ops if_sdio_pm_ops = { + .suspend = if_sdio_suspend, + .resume = if_sdio_resume, +}; + static struct sdio_driver if_sdio_driver = { .name = "libertas_sdio", .id_table = if_sdio_ids, .probe = if_sdio_probe, .remove = if_sdio_remove, + .drv = { + .pm = &if_sdio_pm_ops, + }, }; /*******************************************************************/ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index f41594c7ac16..3678e532874f 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb) return; } - syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); + syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET, + sizeof(struct fwsyncheader), GFP_ATOMIC); if (!syncfwheader) { lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); kfree_skb(skb); return; } - memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET, - sizeof(struct fwsyncheader)); - if (!syncfwheader->cmd) { lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", @@ -1043,6 +1041,12 @@ 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 d9b8ee130c45..abfecc4814b4 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -625,16 +625,13 @@ static int lbs_thread(void *data) return 0; } -static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy, - struct cmd_header *cmd) +static int lbs_ret_host_sleep_activate(struct lbs_private *priv, + unsigned long dummy, + struct cmd_header *cmd) { lbs_deb_enter(LBS_DEB_FW); - - netif_device_detach(priv->dev); - if (priv->mesh_dev) - netif_device_detach(priv->mesh_dev); - - priv->fw_ready = 0; + priv->is_host_sleep_activated = 1; + wake_up_interruptible(&priv->host_sleep_q); lbs_deb_leave(LBS_DEB_FW); return 0; } @@ -646,39 +643,65 @@ int lbs_suspend(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_FW); - if (priv->wol_criteria == 0xffffffff) { - lbs_pr_info("Suspend attempt without configuring wake params!\n"); - return -EINVAL; + if (priv->is_deep_sleep) { + ret = lbs_set_deep_sleep(priv, 0); + if (ret) { + lbs_pr_err("deep sleep cancellation failed: %d\n", ret); + return ret; + } + priv->deep_sleep_required = 1; } memset(&cmd, 0, sizeof(cmd)); + ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, + (struct wol_config *)NULL); + if (ret) { + lbs_pr_info("Host sleep configuration failed: %d\n", ret); + return ret; + } + if (priv->psstate == PS_STATE_FULL_POWER) { + ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, + sizeof(cmd), lbs_ret_host_sleep_activate, 0); + if (ret) + lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); + } - ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, - sizeof(cmd), lbs_suspend_callback, 0); - if (ret) - lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); + if (!wait_event_interruptible_timeout(priv->host_sleep_q, + priv->is_host_sleep_activated, (10 * HZ))) { + lbs_pr_err("host_sleep_q: timer expired\n"); + ret = -1; + } + netif_device_detach(priv->dev); + if (priv->mesh_dev) + netif_device_detach(priv->mesh_dev); lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); return ret; } EXPORT_SYMBOL_GPL(lbs_suspend); -void lbs_resume(struct lbs_private *priv) +int lbs_resume(struct lbs_private *priv) { - lbs_deb_enter(LBS_DEB_FW); + int ret; + uint32_t criteria = EHS_REMOVE_WAKEUP; - priv->fw_ready = 1; + lbs_deb_enter(LBS_DEB_FW); - /* Firmware doesn't seem to give us RX packets any more - until we send it some command. Might as well update */ - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - 0, 0, NULL); + ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); netif_device_attach(priv->dev); if (priv->mesh_dev) netif_device_attach(priv->mesh_dev); - lbs_deb_leave(LBS_DEB_FW); + if (priv->deep_sleep_required) { + priv->deep_sleep_required = 0; + ret = lbs_set_deep_sleep(priv, 1); + if (ret) + lbs_pr_err("deep sleep activation failed: %d\n", ret); + } + + lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); + return ret; } EXPORT_SYMBOL_GPL(lbs_resume); @@ -834,10 +857,13 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->psstate = PS_STATE_FULL_POWER; priv->is_deep_sleep = 0; priv->is_auto_deep_sleep_enabled = 0; + priv->deep_sleep_required = 0; priv->wakeup_dev_required = 0; init_waitqueue_head(&priv->ds_awake_q); priv->authtype_auto = 1; - + priv->is_host_sleep_configured = 0; + priv->is_host_sleep_activated = 0; + init_waitqueue_head(&priv->host_sleep_q); mutex_init(&priv->lock); setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, @@ -976,6 +1002,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->wol_criteria = 0xffffffff; priv->wol_gpio = 0xff; + priv->wol_gap = 20; goto done; @@ -1031,6 +1058,10 @@ void lbs_remove_card(struct lbs_private *priv) wake_up_interruptible(&priv->ds_awake_q); } + priv->is_host_sleep_configured = 0; + priv->is_host_sleep_activated = 0; + wake_up_interruptible(&priv->host_sleep_q); + /* Stop the thread servicing the interrupts */ priv->surpriseremoved = 1; kthread_stop(priv->main_thread); diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h index d16b26416e82..b3c8ea6d610e 100644 --- a/drivers/net/wireless/libertas/radiotap.h +++ b/drivers/net/wireless/libertas/radiotap.h @@ -6,7 +6,7 @@ struct tx_radiotap_hdr { u8 txpower; u8 rts_retries; u8 data_retries; -} __attribute__ ((packed)); +} __packed; #define TX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_RATE) | \ @@ -34,7 +34,7 @@ struct rx_radiotap_hdr { u8 flags; u8 rate; u8 antsignal; -} __attribute__ ((packed)); +} __packed; #define RX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 7a377f5b7662..1c63f8ce7349 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -15,7 +15,7 @@ struct eth803hdr { u8 dest_addr[6]; u8 src_addr[6]; u16 h803_len; -} __attribute__ ((packed)); +} __packed; struct rfc1042hdr { u8 llc_dsap; @@ -23,17 +23,17 @@ struct rfc1042hdr { u8 llc_ctrl; u8 snap_oui[3]; u16 snap_type; -} __attribute__ ((packed)); +} __packed; struct rxpackethdr { struct eth803hdr eth803_hdr; struct rfc1042hdr rfc1042_hdr; -} __attribute__ ((packed)); +} __packed; struct rx80211packethdr { struct rxpd rx_pd; void *eth80211_hdr; -} __attribute__ ((packed)); +} __packed; static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 24cd54b3a806..7d82f13bdf1d 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -666,7 +666,7 @@ void lbs_scan_worker(struct work_struct *work) /** * @brief Interpret a BSS scan response returned from the firmware * - * Parse the various fixed fields and IEs passed back for a a BSS probe + * Parse the various fixed fields and IEs passed back for a BSS probe * response or beacon from the scan command. Record information as needed * in the scan table struct bss_descriptor for that entry. * diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 3e72c86ceca8..462fbb4cb743 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -11,7 +11,7 @@ struct ieee_ie_header { u8 id; u8 len; -} __attribute__ ((packed)); +} __packed; struct ieee_ie_cf_param_set { struct ieee_ie_header header; @@ -20,19 +20,19 @@ struct ieee_ie_cf_param_set { u8 cfpperiod; __le16 cfpmaxduration; __le16 cfpdurationremaining; -} __attribute__ ((packed)); +} __packed; struct ieee_ie_ibss_param_set { struct ieee_ie_header header; __le16 atimwindow; -} __attribute__ ((packed)); +} __packed; union ieee_ss_param_set { struct ieee_ie_cf_param_set cf; struct ieee_ie_ibss_param_set ibss; -} __attribute__ ((packed)); +} __packed; struct ieee_ie_fh_param_set { struct ieee_ie_header header; @@ -41,18 +41,18 @@ struct ieee_ie_fh_param_set { u8 hopset; u8 hoppattern; u8 hopindex; -} __attribute__ ((packed)); +} __packed; struct ieee_ie_ds_param_set { struct ieee_ie_header header; u8 channel; -} __attribute__ ((packed)); +} __packed; union ieee_phy_param_set { struct ieee_ie_fh_param_set fh; struct ieee_ie_ds_param_set ds; -} __attribute__ ((packed)); +} __packed; /** TLV type ID definition */ #define PROPRIETARY_TLV_BASE_ID 0x0100 @@ -100,28 +100,28 @@ union ieee_phy_param_set { struct mrvl_ie_header { __le16 type; __le16 len; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_data { struct mrvl_ie_header header; u8 Data[1]; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_rates_param_set { struct mrvl_ie_header header; u8 rates[1]; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_ssid_param_set { struct mrvl_ie_header header; u8 ssid[1]; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_wildcard_ssid_param_set { struct mrvl_ie_header header; u8 MaxSsidlength; u8 ssid[1]; -} __attribute__ ((packed)); +} __packed; struct chanscanmode { #ifdef __BIG_ENDIAN_BITFIELD @@ -133,7 +133,7 @@ struct chanscanmode { u8 disablechanfilt:1; u8 reserved_2_7:6; #endif -} __attribute__ ((packed)); +} __packed; struct chanscanparamset { u8 radiotype; @@ -141,12 +141,12 @@ struct chanscanparamset { struct chanscanmode chanscanmode; __le16 minscantime; __le16 maxscantime; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_chanlist_param_set { struct mrvl_ie_header header; struct chanscanparamset chanscanparam[1]; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_cf_param_set { struct mrvl_ie_header header; @@ -154,86 +154,86 @@ struct mrvl_ie_cf_param_set { u8 cfpperiod; __le16 cfpmaxduration; __le16 cfpdurationremaining; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_ds_param_set { struct mrvl_ie_header header; u8 channel; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_rsn_param_set { struct mrvl_ie_header header; u8 rsnie[1]; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_tsf_timestamp { struct mrvl_ie_header header; __le64 tsftable[1]; -} __attribute__ ((packed)); +} __packed; /* v9 and later firmware only */ struct mrvl_ie_auth_type { struct mrvl_ie_header header; __le16 auth; -} __attribute__ ((packed)); +} __packed; /** Local Power capability */ struct mrvl_ie_power_capability { struct mrvl_ie_header header; s8 minpower; s8 maxpower; -} __attribute__ ((packed)); +} __packed; /* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */ struct mrvl_ie_thresholds { struct mrvl_ie_header header; u8 value; u8 freq; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_beacons_missed { struct mrvl_ie_header header; u8 beaconmissed; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_num_probes { struct mrvl_ie_header header; __le16 numprobes; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_bcast_probe { struct mrvl_ie_header header; __le16 bcastprobe; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_num_ssid_probe { struct mrvl_ie_header header; __le16 numssidprobe; -} __attribute__ ((packed)); +} __packed; struct led_pin { u8 led; u8 pin; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_ledgpio { struct mrvl_ie_header header; struct led_pin ledpin[1]; -} __attribute__ ((packed)); +} __packed; struct led_bhv { uint8_t firmwarestate; uint8_t led; uint8_t ledstate; uint8_t ledarg; -} __attribute__ ((packed)); +} __packed; struct mrvl_ie_ledbhv { struct mrvl_ie_header header; struct led_bhv ledbhv[1]; -} __attribute__ ((packed)); +} __packed; /* Meant to be packed as the value member of a struct ieee80211_info_element. * Note that the len member of the ieee80211_info_element varies depending on @@ -248,12 +248,12 @@ struct mrvl_meshie_val { uint8_t mesh_capability; uint8_t mesh_id_len; uint8_t mesh_id[IEEE80211_MAX_SSID_LEN]; -} __attribute__ ((packed)); +} __packed; struct mrvl_meshie { u8 id, len; struct mrvl_meshie_val val; -} __attribute__ ((packed)); +} __packed; struct mrvl_mesh_defaults { __le32 bootflag; @@ -261,6 +261,6 @@ struct mrvl_mesh_defaults { uint8_t reserved; __le16 channel; struct mrvl_meshie meshie; -} __attribute__ ((packed)); +} __packed; #endif diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index c445500ffc61..b172f5d87a3b 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -538,7 +538,8 @@ static void if_usb_receive_fwload(struct urb *urb) return; } - syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); + syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), + GFP_ATOMIC); if (!syncfwheader) { lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); kfree_skb(skb); @@ -546,8 +547,6 @@ static void if_usb_receive_fwload(struct urb *urb) return; } - memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader)); - if (!syncfwheader->cmd) { lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h index fbbaaae7a1ae..737eac92ef72 100644 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/libertas_tf/libertas_tf.h @@ -316,7 +316,7 @@ struct cmd_header { __le16 size; __le16 seqnum; __le16 result; -} __attribute__ ((packed)); +} __packed; struct cmd_ctrl_node { struct list_head list; @@ -369,7 +369,7 @@ struct cmd_ds_get_hw_spec { /*FW/HW capability */ __le32 fwcapinfo; -} __attribute__ ((packed)); +} __packed; struct cmd_ds_mac_control { struct cmd_header hdr; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6f8cb3ee6fed..49a7dfb4809a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -317,7 +317,7 @@ struct hwsim_radiotap_hdr { u8 rt_rate; __le16 rt_channel; __le16 rt_chbitmask; -} __attribute__ ((packed)); +} __packed; static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 808adb909095..c019fdc131c0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -109,7 +109,7 @@ struct mwl8k_rx_queue { dma_addr_t rxd_dma; struct { struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(dma) + DEFINE_DMA_UNMAP_ADDR(dma); } *buf; }; @@ -426,7 +426,7 @@ struct mwl8k_cmd_pkt { __u8 macid; __le16 result; char payload[0]; -} __attribute__((packed)); +} __packed; /* * Firmware loading. @@ -632,7 +632,7 @@ struct mwl8k_dma_data { __le16 fwlen; struct ieee80211_hdr wh; char data[0]; -} __attribute__((packed)); +} __packed; /* Routines to add/remove DMA header from skb. */ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) @@ -711,7 +711,7 @@ struct mwl8k_rxd_8366_ap { __u8 rx_status; __u8 channel; __u8 rx_ctrl; -} __attribute__((packed)); +} __packed; #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 @@ -806,7 +806,7 @@ struct mwl8k_rxd_sta { __u8 rx_ctrl; __u8 rx_status; __u8 pad2[2]; -} __attribute__((packed)); +} __packed; #define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 #define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) @@ -963,7 +963,7 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) if (rxq->tail == MWL8K_RX_DESCS) rxq->tail = 0; rxq->buf[rx].skb = skb; - pci_unmap_addr_set(&rxq->buf[rx], dma, addr); + dma_unmap_addr_set(&rxq->buf[rx], dma, addr); rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size); priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ); @@ -984,9 +984,9 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) for (i = 0; i < MWL8K_RX_DESCS; i++) { if (rxq->buf[i].skb != NULL) { pci_unmap_single(priv->pdev, - pci_unmap_addr(&rxq->buf[i], dma), + dma_unmap_addr(&rxq->buf[i], dma), MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - pci_unmap_addr_set(&rxq->buf[i], dma, 0); + dma_unmap_addr_set(&rxq->buf[i], dma, 0); kfree_skb(rxq->buf[i].skb); rxq->buf[i].skb = NULL; @@ -1060,9 +1060,9 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rxq->buf[rxq->head].skb = NULL; pci_unmap_single(priv->pdev, - pci_unmap_addr(&rxq->buf[rxq->head], dma), + dma_unmap_addr(&rxq->buf[rxq->head], dma), MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); + dma_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); rxq->head++; if (rxq->head == MWL8K_RX_DESCS) @@ -1120,7 +1120,7 @@ struct mwl8k_tx_desc { __le16 rate_info; __u8 peer_id; __u8 tx_frag_cnt; -} __attribute__((packed)); +} __packed; #define MWL8K_TX_DESCS 128 @@ -1666,7 +1666,7 @@ struct mwl8k_cmd_get_hw_spec_sta { __le32 caps2; __le32 num_tx_desc_per_queue; __le32 total_rxd; -} __attribute__((packed)); +} __packed; #define MWL8K_CAP_MAX_AMSDU 0x20000000 #define MWL8K_CAP_GREENFIELD 0x08000000 @@ -1810,7 +1810,7 @@ struct mwl8k_cmd_get_hw_spec_ap { __le32 wcbbase1; __le32 wcbbase2; __le32 wcbbase3; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) { @@ -1883,7 +1883,7 @@ struct mwl8k_cmd_set_hw_spec { __le32 flags; __le32 num_tx_desc_per_queue; __le32 total_rxd; -} __attribute__((packed)); +} __packed; #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 @@ -1985,7 +1985,7 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, struct mwl8k_cmd_get_stat { struct mwl8k_cmd_pkt header; __le32 stats[64]; -} __attribute__((packed)); +} __packed; #define MWL8K_STAT_ACK_FAILURE 9 #define MWL8K_STAT_RTS_FAILURE 12 @@ -2029,7 +2029,7 @@ struct mwl8k_cmd_radio_control { __le16 action; __le16 control; __le16 radio_on; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) @@ -2092,7 +2092,7 @@ struct mwl8k_cmd_rf_tx_power { __le16 current_level; __le16 reserved; __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) { @@ -2121,7 +2121,7 @@ struct mwl8k_cmd_rf_antenna { struct mwl8k_cmd_pkt header; __le16 antenna; __le16 mode; -} __attribute__((packed)); +} __packed; #define MWL8K_RF_ANTENNA_RX 1 #define MWL8K_RF_ANTENNA_TX 2 @@ -2182,7 +2182,7 @@ static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, */ struct mwl8k_cmd_set_pre_scan { struct mwl8k_cmd_pkt header; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) { @@ -2209,7 +2209,7 @@ struct mwl8k_cmd_set_post_scan { struct mwl8k_cmd_pkt header; __le32 isibss; __u8 bssid[ETH_ALEN]; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac) @@ -2240,7 +2240,7 @@ struct mwl8k_cmd_set_rf_channel { __le16 action; __u8 current_channel; __le32 channel_flags; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, struct ieee80211_conf *conf) @@ -2293,7 +2293,7 @@ struct mwl8k_cmd_update_set_aid { __u8 bssid[ETH_ALEN]; __le16 protection_mode; __u8 supp_rates[14]; -} __attribute__((packed)); +} __packed; static void legacy_rate_mask_to_array(u8 *rates, u32 mask) { @@ -2364,7 +2364,7 @@ struct mwl8k_cmd_set_rate { /* Bitmap for supported MCS codes. */ __u8 mcs_set[16]; __u8 reserved[16]; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2397,7 +2397,7 @@ struct mwl8k_cmd_finalize_join { struct mwl8k_cmd_pkt header; __le32 sleep_interval; /* Number of beacon periods to sleep */ __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, int framelen, int dtim) @@ -2436,7 +2436,7 @@ struct mwl8k_cmd_set_rts_threshold { struct mwl8k_cmd_pkt header; __le16 action; __le16 threshold; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh) @@ -2466,7 +2466,7 @@ struct mwl8k_cmd_set_slot { struct mwl8k_cmd_pkt header; __le16 action; __u8 short_slot; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) { @@ -2528,7 +2528,7 @@ struct mwl8k_cmd_set_edca_params { __u8 txq; } sta; }; -} __attribute__((packed)); +} __packed; #define MWL8K_SET_EDCA_CW 0x01 #define MWL8K_SET_EDCA_TXOP 0x02 @@ -2579,7 +2579,7 @@ mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, struct mwl8k_cmd_set_wmm_mode { struct mwl8k_cmd_pkt header; __le16 action; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) { @@ -2612,7 +2612,7 @@ struct mwl8k_cmd_mimo_config { __le32 action; __u8 rx_antenna_map; __u8 tx_antenna_map; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) { @@ -2652,7 +2652,7 @@ struct mwl8k_cmd_use_fixed_rate_sta { __le32 rate_type; __le32 reserved1; __le32 reserved2; -} __attribute__((packed)); +} __packed; #define MWL8K_USE_AUTO_RATE 0x0002 #define MWL8K_UCAST_RATE 0 @@ -2694,7 +2694,7 @@ struct mwl8k_cmd_use_fixed_rate_ap { u8 multicast_rate; u8 multicast_rate_type; u8 management_rate; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt) @@ -2724,7 +2724,7 @@ mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt) struct mwl8k_cmd_enable_sniffer { struct mwl8k_cmd_pkt header; __le32 action; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) { @@ -2757,7 +2757,7 @@ struct mwl8k_cmd_set_mac_addr { } mbss; __u8 mac_addr[ETH_ALEN]; }; -} __attribute__((packed)); +} __packed; #define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 #define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1 @@ -2812,7 +2812,7 @@ struct mwl8k_cmd_set_rate_adapt_mode { struct mwl8k_cmd_pkt header; __le16 action; __le16 mode; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) { @@ -2840,7 +2840,7 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) struct mwl8k_cmd_bss_start { struct mwl8k_cmd_pkt header; __le32 enable; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int enable) @@ -2885,7 +2885,7 @@ struct mwl8k_cmd_set_new_stn { __u8 add_qos_info; __u8 is_qos_sta; __le32 fw_sta_ptr; -} __attribute__((packed)); +} __packed; #define MWL8K_STA_ACTION_ADD 0 #define MWL8K_STA_ACTION_REMOVE 2 @@ -2978,7 +2978,7 @@ struct ewc_ht_info { __le16 control1; __le16 control2; __le16 control3; -} __attribute__((packed)); +} __packed; struct peer_capability_info { /* Peer type - AP vs. STA. */ @@ -3007,7 +3007,7 @@ struct peer_capability_info { __u8 pad2; __u8 station_id; __le16 amsdu_enabled; -} __attribute__((packed)); +} __packed; struct mwl8k_cmd_update_stadb { struct mwl8k_cmd_pkt header; @@ -3022,7 +3022,7 @@ struct mwl8k_cmd_update_stadb { /* Peer info - valid during add/update. */ struct peer_capability_info peer_info; -} __attribute__((packed)); +} __packed; #define MWL8K_STA_DB_MODIFY_ENTRY 1 #define MWL8K_STA_DB_DEL_ENTRY 2 diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 3e1947d097ca..259d75853984 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -49,7 +49,7 @@ struct orinoco_fw_header { __le32 pri_offset; /* Offset to primary plug data */ __le32 compat_offset; /* Offset to compatibility data*/ char signature[0]; /* FW signature length headersize-20 */ -} __attribute__ ((packed)); +} __packed; /* Check the range of various header entries. Return a pointer to a * description of the problem, or NULL if everything checks out. */ diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 9ca34e722b45..d9f18c11682a 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -205,7 +205,7 @@ struct hermes_tx_descriptor { u8 retry_count; u8 tx_rate; __le16 tx_control; -} __attribute__ ((packed)); +} __packed; #define HERMES_TXSTAT_RETRYERR (0x0001) #define HERMES_TXSTAT_AGEDERR (0x0002) @@ -254,7 +254,7 @@ struct hermes_tallies_frame { /* Those last are probably not available in very old firmwares */ __le16 RxDiscards_WEPICVError; __le16 RxDiscards_WEPExcluded; -} __attribute__ ((packed)); +} __packed; /* Grabbed from wlan-ng - Thanks Mark... - Jean II * This is the result of a scan inquiry command */ @@ -271,7 +271,7 @@ struct prism2_scan_apinfo { u8 rates[10]; /* Bit rate supported */ __le16 proberesp_rate; /* Data rate of the response frame */ __le16 atim; /* ATIM window time, Kus (hostscan only) */ -} __attribute__ ((packed)); +} __packed; /* Same stuff for the Lucent/Agere card. * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */ @@ -285,7 +285,7 @@ struct agere_scan_apinfo { /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ __le16 essid_len; /* ESSID length */ u8 essid[32]; /* ESSID of the network */ -} __attribute__ ((packed)); +} __packed; /* Moustafa: Scan structure for Symbol cards */ struct symbol_scan_apinfo { @@ -303,7 +303,7 @@ struct symbol_scan_apinfo { __le16 basic_rates; /* Basic rates bitmask */ u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */ u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */ -} __attribute__ ((packed)); +} __packed; union hermes_scan_info { struct agere_scan_apinfo a; @@ -343,7 +343,7 @@ struct agere_ext_scan_info { __le16 beacon_interval; __le16 capabilities; u8 data[0]; -} __attribute__ ((packed)); +} __packed; #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) #define HERMES_LINKSTATUS_CONNECTED (0x0001) @@ -355,7 +355,7 @@ struct agere_ext_scan_info { struct hermes_linkstatus { __le16 linkstatus; /* Link status */ -} __attribute__ ((packed)); +} __packed; struct hermes_response { u16 status, resp0, resp1, resp2; @@ -365,11 +365,11 @@ struct hermes_response { struct hermes_idstring { __le16 len; __le16 val[16]; -} __attribute__ ((packed)); +} __packed; struct hermes_multicast { u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; /* Timeouts */ #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index 6da85e75fce0..2b2b9a1a979c 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -65,10 +65,10 @@ struct dblock { __le32 addr; /* adapter address where to write the block */ __le16 len; /* length of the data only, in bytes */ char data[0]; /* data to be written */ -} __attribute__ ((packed)); +} __packed; /* - * Plug Data References are located in in the image after the last data + * Plug Data References are located in the image after the last data * block. They refer to areas in the adapter memory where the plug data * items with matching ID should be written. */ @@ -77,7 +77,7 @@ struct pdr { __le32 addr; /* adapter address where to write the data */ __le32 len; /* expected length of the data, in bytes */ char next[0]; /* next PDR starts here */ -} __attribute__ ((packed)); +} __packed; /* * Plug Data Items are located in the EEPROM read from the adapter by @@ -88,7 +88,7 @@ struct pdi { __le16 len; /* length of ID and data, in words */ __le16 id; /* record ID */ char data[0]; /* plug data */ -} __attribute__ ((packed)); +} __packed; /*** FW data block access functions ***/ @@ -317,7 +317,7 @@ static const struct { \ __le16 len; \ __le16 id; \ u8 val[length]; \ -} __attribute__ ((packed)) default_pdr_data_##pid = { \ +} __packed default_pdr_data_##pid = { \ cpu_to_le16((sizeof(default_pdr_data_##pid)/ \ sizeof(__le16)) - 1), \ cpu_to_le16(pid), \ diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 6fbd78850123..077baa86756b 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -45,7 +45,7 @@ static const struct { /* Firmware version encoding */ struct comp_id { u16 id, variant, major, minor; -} __attribute__ ((packed)); +} __packed; static inline fwtype_t determine_firmware_type(struct comp_id *nic_id) { @@ -995,7 +995,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, u8 tx_mic[MIC_KEYLEN]; u8 rx_mic[MIC_KEYLEN]; u8 tsc[ORINOCO_SEQ_LEN]; - } __attribute__ ((packed)) buf; + } __packed buf; hermes_t *hw = &priv->hw; int ret; int err; @@ -1326,7 +1326,7 @@ int orinoco_hw_disassociate(struct orinoco_private *priv, struct { u8 addr[ETH_ALEN]; __le16 reason_code; - } __attribute__ ((packed)) buf; + } __packed buf; /* Currently only supported by WPA enabled Agere fw */ if (!priv->has_wpa) diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index ca71f08709bc..e8e2d0f4763d 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -172,7 +172,7 @@ struct hermes_txexc_data { __le16 frame_ctl; __le16 duration_id; u8 addr1[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; /* Rx frame header except compatibility 802.3 header */ struct hermes_rx_descriptor { @@ -196,7 +196,7 @@ struct hermes_rx_descriptor { /* Data length */ __le16 data_len; -} __attribute__ ((packed)); +} __packed; struct orinoco_rx_data { struct hermes_rx_descriptor *desc; @@ -390,7 +390,7 @@ int orinoco_process_xmit_skb(struct sk_buff *skb, struct header_struct { struct ethhdr eth; /* 802.3 header */ u8 encap[6]; /* 802.2 header */ - } __attribute__ ((packed)) hdr; + } __packed hdr; int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN); if (skb_headroom(skb) < ENCAPS_OVERHEAD) { @@ -1170,7 +1170,7 @@ static void orinoco_join_ap(struct work_struct *work) struct join_req { u8 bssid[ETH_ALEN]; __le16 channel; - } __attribute__ ((packed)) req; + } __packed req; const int atom_len = offsetof(struct prism2_scan_apinfo, atim); struct prism2_scan_apinfo *atom = NULL; int offset = 4; @@ -1410,7 +1410,7 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) struct { __le16 len; __le16 type; - } __attribute__ ((packed)) info; + } __packed info; int len, type; int err; diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index a6da86e0a70f..255710ef082a 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -32,7 +32,7 @@ struct orinoco_key { __le16 len; /* always stored as little-endian */ char data[ORINOCO_MAX_KEY_SIZE]; -} __attribute__ ((packed)); +} __packed; #define TKIP_KEYLEN 16 #define MIC_KEYLEN 8 diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 78f089baa8c9..1558381998ee 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -90,7 +90,7 @@ struct header_struct { /* SNAP */ u8 oui[3]; __be16 ethertype; -} __attribute__ ((packed)); +} __packed; struct ez_usb_fw { u16 size; @@ -222,7 +222,7 @@ struct ezusb_packet { __le16 hermes_len; __le16 hermes_rid; u8 data[0]; -} __attribute__ ((packed)); +} __packed; /* Table of devices that work or may work with this driver */ static struct usb_device_id ezusb_table[] = { @@ -356,12 +356,10 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv, { struct request_context *ctx; - ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); + ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC); if (!ctx) return NULL; - memset(ctx, 0, sizeof(*ctx)); - ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC); if (!ctx->buf) { kfree(ctx); diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 5775124e2aee..cf7be1eb6124 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -128,7 +128,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) } else { struct { __le16 qual, signal, noise, unused; - } __attribute__ ((packed)) cq; + } __packed cq; err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_COMMSQUALITY, &cq); @@ -993,11 +993,9 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, return -EINVAL; if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - - memcpy(buf, extra, wrqu->data.length); } else buf = NULL; diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 187e263b045a..e51650ed49f2 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -599,13 +599,13 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } break; case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: - priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); + priv->iq_autocal = kmemdup(entry->data, data_len, + GFP_KERNEL); if (!priv->iq_autocal) { err = -ENOMEM; goto err; } - memcpy(priv->iq_autocal, entry->data, data_len); priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); break; case PDR_DEFAULT_COUNTRY: diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h index 4915d9d54203..e3ed893b5aaf 100644 --- a/drivers/net/wireless/p54/net2280.h +++ b/drivers/net/wireless/p54/net2280.h @@ -232,7 +232,7 @@ struct net2280_regs { #define GPIO2_INTERRUPT 2 #define GPIO1_INTERRUPT 1 #define GPIO0_INTERRUPT 0 -} __attribute__ ((packed)); +} __packed; /* usb control, BAR0 + 0x0080 */ struct net2280_usb_regs { @@ -296,7 +296,7 @@ struct net2280_usb_regs { #define FORCE_IMMEDIATE 7 #define OUR_USB_ADDRESS 0 __le32 ourconfig; -} __attribute__ ((packed)); +} __packed; /* pci control, BAR0 + 0x0100 */ struct net2280_pci_regs { @@ -323,7 +323,7 @@ struct net2280_pci_regs { #define PCI_ARBITER_CLEAR 2 #define PCI_EXTERNAL_ARBITER 1 #define PCI_HOST_MODE 0 -} __attribute__ ((packed)); +} __packed; /* dma control, BAR0 + 0x0180 ... array of four structs like this, * for channels 0..3. see also struct net2280_dma: descriptor @@ -364,7 +364,7 @@ struct net2280_dma_regs { /* [11.7] */ __le32 dmaaddr; __le32 dmadesc; u32 _unused1; -} __attribute__ ((packed)); +} __packed; /* dedicated endpoint registers, BAR0 + 0x0200 */ @@ -374,7 +374,7 @@ struct net2280_dep_regs { /* [11.8] */ /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */ __le32 dep_rsp; u32 _unused[2]; -} __attribute__ ((packed)); +} __packed; /* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs * like this, for ep0 then the configurable endpoints A..F @@ -437,16 +437,16 @@ struct net2280_ep_regs { /* [11.9] */ __le32 ep_avail; __le32 ep_data; u32 _unused0[2]; -} __attribute__ ((packed)); +} __packed; struct net2280_reg_write { __le16 port; __le32 addr; __le32 val; -} __attribute__ ((packed)); +} __packed; struct net2280_reg_read { __le16 port; __le32 addr; -} __attribute__ ((packed)); +} __packed; #endif /* NET2280_H */ diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index 2feead617a3b..ee9bc62a4fa2 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h @@ -65,7 +65,7 @@ struct p54p_csr { u8 unused_6[1924]; u8 cardbus_cis[0x800]; u8 direct_mem_win[0x1000]; -} __attribute__ ((packed)); +} __packed; /* usb backend only needs the register defines above */ #ifndef P54USB_H @@ -74,7 +74,7 @@ struct p54p_desc { __le32 device_addr; __le16 len; __le16 flags; -} __attribute__ ((packed)); +} __packed; struct p54p_ring_control { __le32 host_idx[4]; @@ -83,7 +83,7 @@ struct p54p_ring_control { struct p54p_desc tx_data[32]; struct p54p_desc rx_mgmt[4]; struct p54p_desc tx_mgmt[4]; -} __attribute__ ((packed)); +} __packed; #define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r) #define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index c8f09da1f84d..087bf0698a5a 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -697,9 +697,7 @@ static int __devexit p54spi_remove(struct spi_device *spi) static struct spi_driver p54spi_driver = { .driver = { - /* use cx3110x name because board-n800.c uses that for the - * SPI port */ - .name = "cx3110x", + .name = "p54spi", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -733,3 +731,4 @@ module_exit(p54spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); MODULE_ALIAS("spi:cx3110x"); +MODULE_ALIAS("spi:p54spi"); diff --git a/drivers/net/wireless/p54/p54spi.h b/drivers/net/wireless/p54/p54spi.h index 7fbe8d8fc67c..dfaa62aaeb07 100644 --- a/drivers/net/wireless/p54/p54spi.h +++ b/drivers/net/wireless/p54/p54spi.h @@ -96,7 +96,7 @@ struct p54s_dma_regs { __le16 cmd; __le16 len; __le32 addr; -} __attribute__ ((packed)); +} __packed; struct p54s_tx_info { struct list_head tx_list; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 73073259f508..ad595958b7df 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -69,7 +69,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ + /* {USB_DEVICE(0x0cde, 0x0006)}, * Medion MD40900 already listed above, + * just noting it here for clarity */ {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ @@ -434,10 +435,9 @@ static int p54u_firmware_reset_3887(struct ieee80211_hw *dev) u8 *buf; int ret; - buf = kmalloc(4, GFP_KERNEL); + buf = kmemdup(p54u_romboot_3887, 4, GFP_KERNEL); if (!buf) return -ENOMEM; - memcpy(buf, p54u_romboot_3887, 4); ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4); kfree(buf); diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index e935b79f7f75..ed4034ade59a 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h @@ -70,12 +70,12 @@ struct net2280_tx_hdr { __le16 len; __le16 follower; /* ? */ u8 padding[8]; -} __attribute__((packed)); +} __packed; struct lm87_tx_hdr { __le32 device_addr; __le32 chksum; -} __attribute__((packed)); +} __packed; /* Some flags for the isl hardware registers controlling DMA inside the * chip */ @@ -103,7 +103,7 @@ struct x2_header { __le32 fw_load_addr; __le32 fw_length; __le32 crc; -} __attribute__((packed)); +} __packed; /* pipes 3 and 4 are not used by the driver */ #define P54U_PIPE_NUMBER 9 diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 8d1190c0f062..912fdc022d08 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -2101,7 +2101,7 @@ struct ieee80211_beacon_phdr { u8 timestamp[8]; u16 beacon_int; u16 capab_info; -} __attribute__ ((packed)); +} __packed; #define WLAN_EID_GENERIC 0xdd static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; @@ -2751,14 +2751,9 @@ prism54_hostapd(struct net_device *ndev, struct iw_point *p) p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - kfree(param); - return -EFAULT; - } + param = memdup_user(p->pointer, p->length); + if (IS_ERR(param)) + return PTR_ERR(param); switch (param->cmd) { case PRISM2_SET_ENCRYPTION: diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index b7534c2869c8..59e31258d450 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -29,20 +29,20 @@ struct obj_ssid { u8 length; char octets[33]; -} __attribute__ ((packed)); +} __packed; struct obj_key { u8 type; /* dot11_priv_t */ u8 length; char key[32]; -} __attribute__ ((packed)); +} __packed; struct obj_mlme { u8 address[6]; u16 id; u16 state; u16 code; -} __attribute__ ((packed)); +} __packed; struct obj_mlmeex { u8 address[6]; @@ -51,12 +51,12 @@ struct obj_mlmeex { u16 code; u16 size; u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct obj_buffer { u32 size; u32 addr; /* 32bit bus address */ -} __attribute__ ((packed)); +} __packed; struct obj_bss { u8 address[6]; @@ -77,17 +77,17 @@ struct obj_bss { short rates; short basic_rates; int:16; /* padding */ -} __attribute__ ((packed)); +} __packed; struct obj_bsslist { u32 nr; struct obj_bss bsslist[0]; -} __attribute__ ((packed)); +} __packed; struct obj_frequencies { u16 nr; u16 mhz[0]; -} __attribute__ ((packed)); +} __packed; struct obj_attachment { char type; @@ -95,7 +95,7 @@ struct obj_attachment { short id; short size; char data[0]; -} __attribute__((packed)); +} __packed; /* * in case everything's ok, the inlined function below will be diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h index 54f9a4b7bf9b..6ca30a5b7bfb 100644 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ b/drivers/net/wireless/prism54/islpci_eth.h @@ -34,13 +34,13 @@ struct rfmon_header { __le16 unk3; u8 rssi; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct rx_annex_header { u8 addr1[ETH_ALEN]; u8 addr2[ETH_ALEN]; struct rfmon_header rfmon; -} __attribute__ ((packed)); +} __packed; /* wlan-ng (and hopefully others) AVS header, version one. Fields in * network byte order. */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h index 0b27e50fe0d5..0db93db9b675 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ b/drivers/net/wireless/prism54/islpci_mgt.h @@ -101,7 +101,7 @@ typedef struct { u8 device_id; u8 flags; u32 length; -} __attribute__ ((packed)) +} __packed pimfor_header_t; /* A received and interrupt-processed management frame, either for diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 4bd61ee627c0..5e7f344b000d 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -238,19 +238,19 @@ struct ndis_80211_auth_request { u8 bssid[6]; u8 padding[2]; __le32 flags; -} __attribute__((packed)); +} __packed; struct ndis_80211_pmkid_candidate { u8 bssid[6]; u8 padding[2]; __le32 flags; -} __attribute__((packed)); +} __packed; struct ndis_80211_pmkid_cand_list { __le32 version; __le32 num_candidates; struct ndis_80211_pmkid_candidate candidate_list[0]; -} __attribute__((packed)); +} __packed; struct ndis_80211_status_indication { __le32 status_type; @@ -260,19 +260,19 @@ struct ndis_80211_status_indication { struct ndis_80211_auth_request auth_request[0]; struct ndis_80211_pmkid_cand_list cand_list; } u; -} __attribute__((packed)); +} __packed; struct ndis_80211_ssid { __le32 length; u8 essid[NDIS_802_11_LENGTH_SSID]; -} __attribute__((packed)); +} __packed; struct ndis_80211_conf_freq_hop { __le32 length; __le32 hop_pattern; __le32 hop_set; __le32 dwell_time; -} __attribute__((packed)); +} __packed; struct ndis_80211_conf { __le32 length; @@ -280,7 +280,7 @@ struct ndis_80211_conf { __le32 atim_window; __le32 ds_config; struct ndis_80211_conf_freq_hop fh_config; -} __attribute__((packed)); +} __packed; struct ndis_80211_bssid_ex { __le32 length; @@ -295,25 +295,25 @@ struct ndis_80211_bssid_ex { u8 rates[NDIS_802_11_LENGTH_RATES_EX]; __le32 ie_length; u8 ies[0]; -} __attribute__((packed)); +} __packed; struct ndis_80211_bssid_list_ex { __le32 num_items; struct ndis_80211_bssid_ex bssid[0]; -} __attribute__((packed)); +} __packed; struct ndis_80211_fixed_ies { u8 timestamp[8]; __le16 beacon_interval; __le16 capabilities; -} __attribute__((packed)); +} __packed; struct ndis_80211_wep_key { __le32 size; __le32 index; __le32 length; u8 material[32]; -} __attribute__((packed)); +} __packed; struct ndis_80211_key { __le32 size; @@ -323,14 +323,14 @@ struct ndis_80211_key { u8 padding[6]; u8 rsc[8]; u8 material[32]; -} __attribute__((packed)); +} __packed; struct ndis_80211_remove_key { __le32 size; __le32 index; u8 bssid[6]; u8 padding[2]; -} __attribute__((packed)); +} __packed; struct ndis_config_param { __le32 name_offs; @@ -338,7 +338,7 @@ struct ndis_config_param { __le32 type; __le32 value_offs; __le32 value_length; -} __attribute__((packed)); +} __packed; struct ndis_80211_assoc_info { __le32 length; @@ -358,12 +358,12 @@ struct ndis_80211_assoc_info { } resp_ie; __le32 resp_ie_length; __le32 offset_resp_ies; -} __attribute__((packed)); +} __packed; struct ndis_80211_auth_encr_pair { __le32 auth_mode; __le32 encr_mode; -} __attribute__((packed)); +} __packed; struct ndis_80211_capability { __le32 length; @@ -371,7 +371,7 @@ struct ndis_80211_capability { __le32 num_pmkids; __le32 num_auth_encr_pair; struct ndis_80211_auth_encr_pair auth_encr_pair[0]; -} __attribute__((packed)); +} __packed; struct ndis_80211_bssid_info { u8 bssid[6]; @@ -2495,8 +2495,7 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_assoc_info *info; - u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32]; + struct ndis_80211_assoc_info *info = NULL; u8 bssid[ETH_ALEN]; int resp_ie_len, req_ie_len; u8 *req_ie, *resp_ie; @@ -2515,23 +2514,43 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) resp_ie = NULL; if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { - memset(assoc_buf, 0, sizeof(assoc_buf)); - info = (void *)assoc_buf; + info = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); + if (!info) { + /* No memory? Try resume work later */ + set_bit(WORK_LINK_UP, &priv->work_pending); + queue_work(priv->workqueue, &priv->work); + return; + } - /* Get association info IEs from device and send them back to - * userspace. */ - ret = get_association_info(usbdev, info, sizeof(assoc_buf)); + /* Get association info IEs from device. */ + ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); if (!ret) { req_ie_len = le32_to_cpu(info->req_ie_length); if (req_ie_len > 0) { offset = le32_to_cpu(info->offset_req_ies); + + if (offset > CONTROL_BUFFER_SIZE) + offset = CONTROL_BUFFER_SIZE; + req_ie = (u8 *)info + offset; + + if (offset + req_ie_len > CONTROL_BUFFER_SIZE) + req_ie_len = + CONTROL_BUFFER_SIZE - offset; } resp_ie_len = le32_to_cpu(info->resp_ie_length); if (resp_ie_len > 0) { offset = le32_to_cpu(info->offset_resp_ies); + + if (offset > CONTROL_BUFFER_SIZE) + offset = CONTROL_BUFFER_SIZE; + resp_ie = (u8 *)info + offset; + + if (offset + resp_ie_len > CONTROL_BUFFER_SIZE) + resp_ie_len = + CONTROL_BUFFER_SIZE - offset; } } } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) @@ -2563,6 +2582,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); + if (info != NULL) + kfree(info); + priv->connected = true; memcpy(priv->bssid, bssid, ETH_ALEN); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ad2c98af7e9d..1eb882e15fb4 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1076,9 +1076,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; u32 reg; /* @@ -1091,9 +1088,15 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00queue_map_txskb(rt2x00dev, entry->skb); - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); + /* + * Write the TX descriptor for the beacon. + */ + rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* * Enable beaconing again. @@ -1226,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, } txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(entry, &txdesc); } } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 41da3d218c65..a29cb212f89a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1233,9 +1233,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; u32 reg; /* @@ -1248,9 +1245,15 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00queue_map_txskb(rt2x00dev, entry->skb); - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); + /* + * Write the TX descriptor for the beacon. + */ + rt2500pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* * Enable beaconing again. @@ -1362,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, } txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(entry, &txdesc); } } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9ae96a626e6d..002db646ae0b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -345,7 +345,6 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key) { - int timeout; u32 mask; u16 reg; @@ -367,18 +366,8 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, key->hw_key_idx += reg ? ffz(reg) : 0; - /* - * The encryption key doesn't fit within the CSR cache, - * this means we should allocate it separately and use - * rt2x00usb_vendor_request() to send the key to the hardware. - */ - reg = KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(crypto->key)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - crypto->key, - sizeof(crypto->key), - timeout); + rt2500usb_register_multiwrite(rt2x00dev, reg, + crypto->key, sizeof(crypto->key)); /* * The driver does not support the IV/EIV generation @@ -1034,7 +1023,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); + __le32 *txd = (__le32 *) skb->data; u32 word; /* @@ -1080,6 +1069,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Register descriptor details in skb frame descriptor. */ + skbdesc->flags |= SKBDESC_DESC_IN_SKB; skbdesc->desc = txd; skbdesc->desc_len = TXD_DESC_SIZE; } @@ -1108,9 +1098,20 @@ static void rt2500usb_write_beacon(struct queue_entry *entry, rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); /* - * Take the descriptor in front of the skb into account. + * Add space for the descriptor in front of the skb. */ skb_push(entry->skb, TXD_DESC_SIZE); + memset(entry->skb->data, 0, TXD_DESC_SIZE); + + /* + * Write the TX descriptor for the beacon. + */ + rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* * USB devices cannot blindly pass the skb->len as the diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2aa03751c341..552f9f4c73d6 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -63,7 +63,6 @@ */ #define REV_RT2860C 0x0100 #define REV_RT2860D 0x0101 -#define REV_RT2870D 0x0101 #define REV_RT2872E 0x0200 #define REV_RT3070E 0x0200 #define REV_RT3070F 0x0201 @@ -99,6 +98,21 @@ */ /* + * E2PROM_CSR: PCI EEPROM control register. + * RELOAD: Write 1 to reload eeprom content. + * TYPE: 0: 93c46, 1:93c66. + * LOAD_STATUS: 1:loading, 0:done. + */ +#define E2PROM_CSR 0x0004 +#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) +#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) +#define E2PROM_CSR_DATA_IN FIELD32(0x00000004) +#define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) +#define E2PROM_CSR_TYPE FIELD32(0x00000030) +#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) +#define E2PROM_CSR_RELOAD FIELD32(0x00000080) + +/* * OPT_14: Unknown register used by rt3xxx devices. */ #define OPT_14_CSR 0x0114 @@ -322,6 +336,39 @@ #define RX_DRX_IDX 0x029c /* + * USB_DMA_CFG + * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. + * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. + * PHY_CLEAR: phy watch dog enable. + * TX_CLEAR: Clear USB DMA TX path. + * TXOP_HALT: Halt TXOP count down when TX buffer is full. + * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. + * RX_BULK_EN: Enable USB DMA Rx. + * TX_BULK_EN: Enable USB DMA Tx. + * EP_OUT_VALID: OUT endpoint data valid. + * RX_BUSY: USB DMA RX FSM busy. + * TX_BUSY: USB DMA TX FSM busy. + */ +#define USB_DMA_CFG 0x02a0 +#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) +#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) +#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) +#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) +#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) +#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) +#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) +#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) +#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) +#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) +#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) + +/* + * US_CYC_CNT + */ +#define US_CYC_CNT 0x02a4 +#define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) + +/* * PBF_SYS_CTRL * HOST_RAM_WRITE: enable Host program ram write selection */ @@ -1370,17 +1417,17 @@ struct mac_wcid_entry { u8 mac[6]; u8 reserved[2]; -} __attribute__ ((packed)); +} __packed; struct hw_key_entry { u8 key[16]; u8 tx_mic[8]; u8 rx_mic[8]; -} __attribute__ ((packed)); +} __packed; struct mac_iveiv_entry { u8 iv[8]; -} __attribute__ ((packed)); +} __packed; /* * MAC_WCID_ATTRIBUTE: @@ -1389,6 +1436,10 @@ struct mac_iveiv_entry { #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) +#define MAC_WCID_ATTRIBUTE_CIPHER_EXT FIELD32(0x00000400) +#define MAC_WCID_ATTRIBUTE_BSS_IDX_EXT FIELD32(0x00000800) +#define MAC_WCID_ATTRIBUTE_WAPI_MCBC FIELD32(0x00008000) +#define MAC_WCID_ATTRIBUTE_WAPI_KEY_IDX FIELD32(0xff000000) /* * SHARED_KEY_MODE: @@ -1510,7 +1561,9 @@ struct mac_iveiv_entry { */ /* - * BBP 1: TX Antenna + * BBP 1: TX Antenna & Power + * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm, + * 3 - increase tx power by 6dBm */ #define BBP1_TX_POWER FIELD8(0x07) #define BBP1_TX_ANTENNA FIELD8(0x18) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index db4250d1c8b3..14c361ae87be 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1,9 +1,9 @@ /* + Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> Based on the original rt2800pci.c and rt2800usb.c. - Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> @@ -38,16 +38,8 @@ #include <linux/slab.h> #include "rt2x00.h" -#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) -#include "rt2x00usb.h" -#endif #include "rt2800lib.h" #include "rt2800.h" -#include "rt2800usb.h" - -MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); -MODULE_DESCRIPTION("rt2800 library"); -MODULE_LICENSE("GPL"); /* * Register access. @@ -282,9 +274,8 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); -void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) +void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) { - __le32 *txwi = (__le32 *)(skb->data - TXWI_DESC_SIZE); u32 word; /* @@ -380,6 +371,67 @@ void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) } EXPORT_SYMBOL_GPL(rt2800_process_rxwi); +void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + /* + * Add space for the TXWI in front of the skb. + */ + skb_push(entry->skb, TXWI_DESC_SIZE); + memset(entry->skb, 0, TXWI_DESC_SIZE); + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->flags |= SKBDESC_DESC_IN_SKB; + skbdesc->desc = entry->skb->data; + skbdesc->desc_len = TXWI_DESC_SIZE; + + /* + * Add the TXWI for the beacon to the skb. + */ + rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); + + /* + * Write entire beacon with TXWI to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2800_register_multiwrite(rt2x00dev, beacon_base, + entry->skb->data, entry->skb->len); + + /* + * Enable beaconing again. + */ + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + /* + * Clean up beacon skb. + */ + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; +} +EXPORT_SYMBOL(rt2800_write_beacon); + #ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug rt2800_rt2x00debug = { .owner = THIS_MODULE, @@ -502,15 +554,28 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, - !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, - (crypto->cmd == SET_KEY) * crypto->cipher); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, - (crypto->cmd == SET_KEY) * crypto->bssidx); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); - rt2800_register_write(rt2x00dev, offset, reg); + if (crypto->cmd == SET_KEY) { + rt2800_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + /* + * Both the cipher as the BSS Idx numbers are split in a main + * value of 3 bits, and a extended field for adding one additional + * bit to the value. + */ + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, + (crypto->cipher & 0x7)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, + (crypto->cipher & 0x8) >> 3); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->bssidx & 0x7)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, + (crypto->bssidx & 0x8) >> 3); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2800_register_write(rt2x00dev, offset, reg); + } else { + rt2800_register_write(rt2x00dev, offset, 0); + } offset = MAC_IVEIV_ENTRY(key->hw_key_idx); @@ -1023,7 +1088,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, u8 r1; rt2800_bbp_read(rt2x00dev, 1, &r1); - rt2x00_set_field8(®, BBP1_TX_POWER, 0); + rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); rt2800_bbp_write(rt2x00dev, 1, r1); rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); @@ -1212,6 +1277,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) u32 reg; u16 eeprom; unsigned int i; + int ret; rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); @@ -1221,59 +1287,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - if (rt2x00_is_usb(rt2x00dev)) { - /* - * Wait until BBP and RF are ready. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, - reg & ~0x00002000); - } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { - /* - * Reset DMA indexes - */ - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); - - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - } - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - if (rt2x00_is_usb(rt2x00dev)) { - rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); -#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_RESET, REGISTER_TIMEOUT); -#endif - } - - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + ret = rt2800_drv_init_registers(rt2x00dev); + if (ret) + return ret; rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ @@ -1328,7 +1344,6 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) } else { rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); } - rt2800_register_write(rt2x00dev, TX_SW_CFG2, reg); } else if (rt2x00_rt(rt2x00dev, RT3070)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); @@ -1339,6 +1354,10 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); } + } else if (rt2800_is_305x_soc(rt2x00dev)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); } else { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -1560,9 +1579,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); if (rt2x00_is_usb(rt2x00dev)) { - rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); - rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); - rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); + rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); + rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); + rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); } rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); @@ -1706,8 +1725,7 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D) || - rt2x00_rt_rev(rt2x00dev, RT2870, REV_RT2870D)) + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) rt2800_bbp_write(rt2x00dev, 84, 0x19); else rt2800_bbp_write(rt2x00dev, 84, 0x99); @@ -2013,8 +2031,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); } rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); @@ -2147,7 +2164,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); } else if (rt2x00_rt(rt2x00dev, RT2860) || - rt2x00_rt(rt2x00dev, RT2870) || rt2x00_rt(rt2x00dev, RT2872)) { /* * There is a max of 2 RX streams for RT28x0 series @@ -2251,7 +2267,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); if (!rt2x00_rt(rt2x00dev, RT2860) && - !rt2x00_rt(rt2x00dev, RT2870) && !rt2x00_rt(rt2x00dev, RT2872) && !rt2x00_rt(rt2x00dev, RT2883) && !rt2x00_rt(rt2x00dev, RT3070) && @@ -2491,6 +2506,18 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); + /* + * As rt2800 has a global fallback table we cannot specify + * more then one tx rate per frame but since the hw will + * try several rates (based on the fallback table) we should + * still initialize max_rates to the maximum number of rates + * we are going to try. Otherwise mac80211 will truncate our + * reported tx rates and the rc algortihm will end up with + * incorrect data. + */ + rt2x00dev->hw->max_rates = 7; + rt2x00dev->hw->max_rate_tries = 1; + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); /* @@ -2528,16 +2555,16 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) else spec->ht.ht_supported = false; - /* - * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes - * reception problems with HT40 capable 11n APs - */ spec->ht.cap = + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_RX_STBC; + + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) + spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; + spec->ht.ampdu_factor = 3; spec->ht.ampdu_density = 4; spec->ht.mcs.tx_params = @@ -2743,3 +2770,8 @@ const struct ieee80211_ops rt2800_mac80211_ops = { .rfkill_poll = rt2x00mac_rfkill_poll, }; EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); + +MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink RT2800 library"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 94de999e2290..8313dbf441a5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -40,6 +40,8 @@ struct rt2800_ops { int (*regbusy_read)(struct rt2x00_dev *rt2x00dev, const unsigned int offset, const struct rt2x00_field32 field, u32 *reg); + + int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); }; static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, @@ -107,13 +109,22 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); } +static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) +{ + const struct rt2800_ops *rt2800ops = rt2x00dev->priv; + + return rt2800ops->drv_init_registers(rt2x00dev); +} + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); -void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); +void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); +void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); + extern const struct rt2x00debug rt2800_rt2x00debug; int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b2f23272c3aa..e5ea670a18db 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -51,7 +51,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 1; +static int modparam_nohwcrypt = 0; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -446,6 +446,38 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); } +static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + /* + * Reset DMA indexes + */ + rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); + rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); + rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + return 0; +} + static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -465,7 +497,7 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Send signal to firmware during boot time. */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); /* * Enable RX. @@ -613,18 +645,10 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, /* * TX descriptor initialization */ -static int rt2800pci_write_tx_data(struct queue_entry* entry, - struct txentry_desc *txdesc) +static void rt2800pci_write_tx_datadesc(struct queue_entry* entry, + struct txentry_desc *txdesc) { - int ret; - - ret = rt2x00pci_write_tx_data(entry, txdesc); - if (ret) - return ret; - - rt2800_write_txwi(entry->skb, txdesc); - - return 0; + rt2800_write_txwi((__le32 *) entry->skb->data, txdesc); } @@ -684,49 +708,6 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2800pci_write_beacon(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - unsigned int beacon_base; - u32 reg; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - /* - * Add the TXWI for the beacon to the skb. - */ - rt2800_write_txwi(entry->skb, txdesc); - skb_push(entry->skb, TXWI_DESC_SIZE); - - /* - * Write entire beacon with TXWI to register. - */ - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2800_register_multiwrite(rt2x00dev, beacon_base, - entry->skb->data, entry->skb->len); - - /* - * Enable beaconing again. - */ - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - /* - * Clean up beacon skb. - */ - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; -} - static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue_idx) { @@ -832,29 +813,24 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) struct txdone_entry_desc txdesc; u32 word; u32 reg; - u32 old_reg; int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; u16 mcs, real_mcs; + int i; /* - * During each loop we will compare the freshly read - * TX_STA_FIFO register value with the value read from - * the previous loop. If the 2 values are equal then - * we should stop processing because the chance it - * quite big that the device has been unplugged and - * we risk going into an endless loop. + * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO + * at most X times and also stop processing once the TX_STA_FIFO_VALID + * flag is not set anymore. + * + * The legacy drivers use X=TX_RING_SIZE but state in a comment + * that the TX_STA_FIFO stack has a size of 16. We stick to our + * tx ring size for now. */ - old_reg = 0; - - while (1) { + for (i = 0; i < TX_ENTRIES; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; - if (old_reg == reg) - break; - old_reg = reg; - wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); @@ -880,8 +856,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) /* Check if we got a match by looking at WCID/ACK/PID * fields */ - txwi = (__le32 *)(entry->skb->data - - rt2x00dev->ops->extra_tx_headroom); + txwi = (__le32 *) entry->skb->data; rt2x00_desc_read(txwi, 1, &word); tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); @@ -923,10 +898,14 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) txdesc.retry = 7; } - __set_bit(TXDONE_FALLBACK, &txdesc.flags); - + /* + * the frame was retried at least once + * -> hw used fallback rates + */ + if (txdesc.retry) + __set_bit(TXDONE_FALLBACK, &txdesc.flags); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(entry, &txdesc); } } @@ -996,6 +975,8 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { .register_multiwrite = rt2x00pci_register_multiwrite, .regbusy_read = rt2x00pci_regbusy_read, + + .drv_init_registers = rt2800pci_init_registers, }; static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) @@ -1063,8 +1044,9 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, .write_tx_desc = rt2800pci_write_tx_desc, - .write_tx_data = rt2800pci_write_tx_data, - .write_beacon = rt2800pci_write_beacon, + .write_tx_data = rt2x00pci_write_tx_data, + .write_tx_datadesc = rt2800pci_write_tx_datadesc, + .write_beacon = rt2800_write_beacon, .kick_tx_queue = rt2800pci_kick_tx_queue, .kill_tx_queue = rt2800pci_kill_tx_queue, .fill_rxdone = rt2800pci_fill_rxdone, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index afc8e7da27cb..5a8dda9b5b5a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -35,25 +35,6 @@ #define RT2800PCI_H /* - * PCI registers. - */ - -/* - * E2PROM_CSR: EEPROM control register. - * RELOAD: Write 1 to reload eeprom content. - * TYPE: 0: 93c46, 1:93c66. - * LOAD_STATUS: 1:loading, 0:done. - */ -#define E2PROM_CSR 0x0004 -#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) -#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) -#define E2PROM_CSR_DATA_IN FIELD32(0x00000004) -#define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) -#define E2PROM_CSR_TYPE FIELD32(0x00000030) -#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) -#define E2PROM_CSR_RELOAD FIELD32(0x00000080) - -/* * Queue register offset macros */ #define TX_QUEUE_REG_OFFSET 0x10 diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0f8b84b7224c..f18c12a19cc9 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 = 1; +static int modparam_nohwcrypt = 0; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -169,11 +169,8 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - FIRMWARE_IMAGE_BASE, - data + offset, length, - REGISTER_TIMEOUT32(length)); + rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data + offset, length); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); @@ -196,7 +193,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Send signal to firmware during boot time. */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || @@ -246,6 +243,44 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } +static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + int i; + + /* + * Wait until BBP and RF are ready. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_RESET, REGISTER_TIMEOUT); + + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + return 0; +} + static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -400,20 +435,21 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txi = (__le32 *)(skb->data - TXWI_DESC_SIZE - TXINFO_DESC_SIZE); + __le32 *txi = (__le32 *) skb->data; + __le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE); u32 word; /* * Initialize TXWI descriptor */ - rt2800_write_txwi(skb, txdesc); + rt2800_write_txwi(txwi, txdesc); /* * Initialize TXINFO descriptor */ rt2x00_desc_read(txi, 0, &word); rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - skb->len + TXWI_DESC_SIZE); + skb->len - TXINFO_DESC_SIZE); rt2x00_set_field32(&word, TXINFO_W0_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); @@ -426,6 +462,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Register descriptor details in skb frame descriptor. */ + skbdesc->flags |= SKBDESC_DESC_IN_SKB; skbdesc->desc = txi; skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; } @@ -433,51 +470,6 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2800usb_write_beacon(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - unsigned int beacon_base; - u32 reg; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - /* - * Add the TXWI for the beacon to the skb. - */ - rt2800_write_txwi(entry->skb, txdesc); - skb_push(entry->skb, TXWI_DESC_SIZE); - - /* - * Write entire beacon with descriptor to register. - */ - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, - entry->skb->data, entry->skb->len, - REGISTER_TIMEOUT32(entry->skb->len)); - - /* - * Enable beaconing again. - */ - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - /* - * Clean up the beacon skb. - */ - dev_kfree_skb(entry->skb); - entry->skb = NULL; -} - static int rt2800usb_get_tx_data_len(struct queue_entry *entry) { int length; @@ -595,6 +587,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { .register_multiwrite = rt2x00usb_register_multiwrite, .regbusy_read = rt2x00usb_regbusy_read, + + .drv_init_registers = rt2800usb_init_registers, }; static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) @@ -659,7 +653,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_tuner = rt2800_link_tuner, .write_tx_desc = rt2800usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, - .write_beacon = rt2800usb_write_beacon, + .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, .kick_tx_queue = rt2x00usb_kick_tx_queue, .kill_tx_queue = rt2x00usb_kill_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 2bca6a71a7f5..0722badccf86 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -32,43 +32,6 @@ #define RT2800USB_H /* - * USB registers. - */ - -/* - * USB_DMA_CFG - * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. - * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. - * PHY_CLEAR: phy watch dog enable. - * TX_CLEAR: Clear USB DMA TX path. - * TXOP_HALT: Halt TXOP count down when TX buffer is full. - * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. - * RX_BULK_EN: Enable USB DMA Rx. - * TX_BULK_EN: Enable USB DMA Tx. - * EP_OUT_VALID: OUT endpoint data valid. - * RX_BUSY: USB DMA RX FSM busy. - * TX_BUSY: USB DMA TX FSM busy. - */ -#define USB_DMA_CFG 0x02a0 -#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) -#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) -#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) -#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) -#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) -#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) -#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) -#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) -#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) -#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) -#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) - -/* - * USB_CYC_CFG - */ -#define USB_CYC_CFG 0x02a4 -#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) - -/* * 8051 firmware image. */ #define FIRMWARE_RT2870 "rt2870.bin" diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6c1ff4c15c84..e7acc6abfd89 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -39,6 +39,7 @@ #include <net/mac80211.h> #include "rt2x00debug.h" +#include "rt2x00dump.h" #include "rt2x00leds.h" #include "rt2x00reg.h" #include "rt2x00queue.h" @@ -159,6 +160,7 @@ struct avg_val { enum rt2x00_chip_intf { RT2X00_CHIP_INTF_PCI, + RT2X00_CHIP_INTF_PCIE, RT2X00_CHIP_INTF_USB, RT2X00_CHIP_INTF_SOC, }; @@ -175,8 +177,7 @@ struct rt2x00_chip { #define RT2570 0x2570 #define RT2661 0x2661 #define RT2573 0x2573 -#define RT2860 0x2860 /* 2.4GHz PCI/CB */ -#define RT2870 0x2870 +#define RT2860 0x2860 /* 2.4GHz */ #define RT2872 0x2872 /* WSOC */ #define RT2883 0x2883 /* WSOC */ #define RT3070 0x3070 @@ -551,6 +552,8 @@ struct rt2x00lib_ops { struct txentry_desc *txdesc); int (*write_tx_data) (struct queue_entry *entry, struct txentry_desc *txdesc); + void (*write_tx_datadesc) (struct queue_entry *entry, + struct txentry_desc *txdesc); void (*write_beacon) (struct queue_entry *entry, struct txentry_desc *txdesc); int (*get_tx_data_len) (struct queue_entry *entry); @@ -978,7 +981,13 @@ static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) { - return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI) || + rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); +} + +static inline bool rt2x00_is_pcie(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); } static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) @@ -999,6 +1008,13 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); /** + * rt2x00queue_unmap_skb - Unmap a skb from DMA. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @skb: The skb to unmap. + */ +void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); + +/** * rt2x00queue_get_queue - Convert queue index to queue pointer * @rt2x00dev: Pointer to &struct rt2x00_dev. * @queue: rt2x00 queue index (see &enum data_queue_qid). @@ -1015,6 +1031,26 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index); /* + * Debugfs handlers. + */ +/** + * rt2x00debug_dump_frame - Dump a frame to userspace through debugfs. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @type: The type of frame that is being dumped. + * @skb: The skb containing the frame to be dumped. + */ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + enum rt2x00_dump_type type, struct sk_buff *skb); +#else +static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + enum rt2x00_dump_type type, + struct sk_buff *skb) +{ +} +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +/* * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 098315a271ca..8dbd634dae27 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -170,23 +170,27 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, unsigned int ieee80211_flags) { struct rt2x00lib_conf libconf; + u16 hw_value; memset(&libconf, 0, sizeof(libconf)); libconf.conf = conf; if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { - if (conf_is_ht40(conf)) + if (conf_is_ht40(conf)) { __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); - else + hw_value = rt2x00ht_center_channel(rt2x00dev, conf); + } else { __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + hw_value = conf->channel->hw_value; + } memcpy(&libconf.rf, - &rt2x00dev->spec.channels[conf->channel->hw_value], + &rt2x00dev->spec.channels[hw_value], sizeof(libconf.rf)); memcpy(&libconf.channel, - &rt2x00dev->spec.channels_info[conf->channel->hw_value], + &rt2x00dev->spec.channels_info[hw_value], sizeof(libconf.channel)); } diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index e9fe93fd8042..b0498e7e7aae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -211,6 +211,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) skb_queue_purge(&intf->frame_dump_skbqueue); } +EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame); static int rt2x00debug_file_open(struct inode *inode, struct file *file) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 3ae468c4d760..339cc84bf4fb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -211,11 +211,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, bool success; /* - * Unmap the skb. - */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); - - /* * Remove L2 padding which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) @@ -224,7 +219,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * If the IV/EIV data was stripped from the frame before it was * passed to the hardware, we should now reinsert it again because - * mac80211 will expect the the same data to be present it the + * mac80211 will expect the same data to be present it the * frame as it was passed to us. */ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) @@ -241,8 +236,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, */ success = test_bit(TXDONE_SUCCESS, &txdesc->flags) || - test_bit(TXDONE_UNKNOWN, &txdesc->flags) || - test_bit(TXDONE_FALLBACK, &txdesc->flags); + test_bit(TXDONE_UNKNOWN, &txdesc->flags); /* * Update TX statistics. @@ -264,11 +258,22 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * Frame was send with retries, hardware tried * different rates to send out the frame, at each - * retry it lowered the rate 1 step. + * retry it lowered the rate 1 step except when the + * lowest rate was used. */ for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { tx_info->status.rates[i].idx = rate_idx - i; tx_info->status.rates[i].flags = rate_flags; + + if (rate_idx - i == 0) { + /* + * The lowest rate (index 0) was used until the + * number of max retries was reached. + */ + tx_info->status.rates[i].count = retry_rates - i; + i++; + break; + } tx_info->status.rates[i].count = 1; } if (i < (IEEE80211_TX_MAX_RATES - 1)) diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index ed303b423e41..6df2e0b746b8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -20,7 +20,12 @@ /* Module: rt2x00dump - Abstract: Data structures for the rt2x00debug & userspace. + Abstract: + Data structures for the rt2x00debug & userspace. + + The declarations in this file can be used by both rt2x00 + and userspace and therefore should be kept together in + this file. */ #ifndef RT2X00DUMP_H diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index 5a407602ce3e..c004cd3a8847 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -44,11 +44,22 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, txdesc->mpdu_density = 0; txdesc->ba_size = 7; /* FIXME: What value is needed? */ - txdesc->stbc = 0; /* FIXME: What value is needed? */ - txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->mcs |= 0x08; + txdesc->stbc = + (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; + + /* + * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the + * mcs rate to be used + */ + if (txrate->flags & IEEE80211_TX_RC_MCS) { + txdesc->mcs = txrate->idx; + } else { + txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->mcs |= 0x08; + } + /* * Convert flags @@ -84,3 +95,31 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, else txdesc->txop = TXOP_HTTXOP; } + +u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf) +{ + struct hw_mode_spec *spec = &rt2x00dev->spec; + int center_channel; + u16 i; + + /* + * Initialize center channel to current channel. + */ + center_channel = spec->channels[conf->channel->hw_value].channel; + + /* + * Adjust center channel to HT40+ and HT40- operation. + */ + if (conf_is_ht40_plus(conf)) + center_channel += 2; + else if (conf_is_ht40_minus(conf)) + center_channel -= (center_channel == 14) ? 1 : 2; + + for (i = 0; i < spec->num_channels; i++) + if (spec->channels[i].channel == center_channel) + return i; + + WARN_ON(1); + return conf->channel->hw_value; +} diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index be2e37fb4071..ed27de1de57b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -27,8 +27,6 @@ #ifndef RT2X00LIB_H #define RT2X00LIB_H -#include "rt2x00dump.h" - /* * Interval defines */ @@ -107,13 +105,6 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry); /** - * rt2x00queue_unmap_skb - Unmap a skb from DMA. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to unmap. - */ -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** * rt2x00queue_free_skb - free a skb * @rt2x00dev: Pointer to &struct rt2x00_dev. * @skb: The skb to free. @@ -296,8 +287,6 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2X00_LIB_DEBUGFS void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); -void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, - enum rt2x00_dump_type type, struct sk_buff *skb); void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, struct rxdone_entry_desc *rxdesc); #else @@ -309,12 +298,6 @@ static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) { } -static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, - enum rt2x00_dump_type type, - struct sk_buff *skb) -{ -} - static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, struct rxdone_entry_desc *rxdesc) { @@ -384,12 +367,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc, const struct rt2x00_rate *hwrate); + +u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf); #else static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc, const struct rt2x00_rate *hwrate) { } + +static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf) +{ + return conf->channel->hw_value; +} #endif /* CONFIG_RT2X00_LIB_HT */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index f71eee67f977..10eaffd12b1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -81,6 +81,24 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry, return -EINVAL; } + /* + * Add the requested extra tx headroom in front of the skb. + */ + skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom); + memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom); + + /* + * Call the driver's write_tx_datadesc function, if it exists. + */ + if (rt2x00dev->ops->lib->write_tx_datadesc) + rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc); + + /* + * Map the skb to DMA. + */ + if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) + rt2x00queue_map_txskb(rt2x00dev, entry->skb); + return 0; } EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); @@ -88,6 +106,34 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); /* * TX/RX data handlers. */ +void rt2x00pci_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + + /* + * Unmap the skb. + */ + rt2x00queue_unmap_skb(rt2x00dev, entry->skb); + + /* + * Remove the extra tx headroom from the skb. + */ + skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom); + + /* + * Signal that the TX descriptor is no longer in the skb. + */ + skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; + + /* + * Pass on to rt2x00lib. + */ + rt2x00lib_txdone(entry, txdesc); +} +EXPORT_SYMBOL_GPL(rt2x00pci_txdone); + void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue = rt2x00dev->rx; @@ -305,7 +351,10 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00dev->irq = pci_dev->irq; rt2x00dev->name = pci_name(pci_dev); - rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); + if (pci_dev->is_pcie) + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); + else + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); retval = rt2x00pci_alloc_reg(rt2x00dev); if (retval) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 51bcef3839ce..00528b8a754d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -109,6 +109,14 @@ struct queue_entry_priv_pci { }; /** + * rt2x00pci_txdone - Handle TX done events. + * @entry: The queue entry for which a TX done event was received. + * @txdesc: The TX done descriptor for the entry. + */ +void rt2x00pci_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc); + +/** * rt2x00pci_rxdone - Handle RX done events * @rt2x00dev: Device pointer, see &struct rt2x00_dev. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 20dbdd6fb904..f91637147116 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -100,21 +100,8 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - /* - * If device has requested headroom, we should make sure that - * is also mapped to the DMA so it can be used for transfering - * additional descriptor information to the hardware. - */ - skb_push(skb, rt2x00dev->ops->extra_tx_headroom); - skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); - - /* - * Restore data pointer to original location again. - */ - skb_pull(skb, rt2x00dev->ops->extra_tx_headroom); - skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; } EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); @@ -130,16 +117,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) } if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { - /* - * Add headroom to the skb length, it has been removed - * by the driver, but it was actually mapped to DMA. - */ - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, - skb->len + rt2x00dev->ops->extra_tx_headroom, + dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, DMA_TO_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; } } +EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb); void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { @@ -370,13 +353,18 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Check if more fragments are pending */ - if (ieee80211_has_morefrags(hdr->frame_control) || - (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) { + if (ieee80211_has_morefrags(hdr->frame_control)) { __set_bit(ENTRY_TXD_BURST, &txdesc->flags); __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); } /* + * Check if more frames (!= fragments) are pending + */ + if (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES) + __set_bit(ENTRY_TXD_BURST, &txdesc->flags); + + /* * Beacons and probe responses require the tsf timestamp * to be inserted into the frame, except for a frame that has been injected * through a monitor interface. This latter is needed for testing a @@ -421,7 +409,6 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, { struct data_queue *queue = entry->queue; struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - enum rt2x00_dump_type dump_type; rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); @@ -429,9 +416,7 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, * All processing on the frame has been completed, this means * it is now ready to be dumped to userspace through debugfs. */ - dump_type = (txdesc->queue == QID_BEACON) ? - DUMP_FRAME_BEACON : DUMP_FRAME_TX; - rt2x00debug_dump_frame(rt2x00dev, dump_type, entry->skb); + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); } static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, @@ -537,9 +522,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, return -EIO; } - if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) - rt2x00queue_map_txskb(queue->rt2x00dev, skb); - set_bit(ENTRY_DATA_PENDING, &entry->flags); rt2x00queue_index_inc(queue, Q_INDEX); @@ -595,11 +577,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, skbdesc->entry = intf->beacon; /* - * Write TX descriptor into reserved room in front of the beacon. - */ - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - - /* * Send beacon to hardware and enable beacon genaration.. */ rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index f79170849add..bd54f55a8cb9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -213,9 +213,16 @@ struct rxdone_entry_desc { /** * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc * + * Every txdone report has to contain the basic result of the + * transmission, either &TXDONE_UNKNOWN, &TXDONE_SUCCESS or + * &TXDONE_FAILURE. The flag &TXDONE_FALLBACK can be used in + * conjunction with all of these flags but should only be set + * if retires > 0. The flag &TXDONE_EXCESSIVE_RETRY can only be used + * in conjunction with &TXDONE_FAILURE. + * * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. * @TXDONE_SUCCESS: Frame was successfully send - * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. + * @TXDONE_FALLBACK: Hardware used fallback rates for retries * @TXDONE_FAILURE: Frame was not successfully send * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the * frame transmission failed due to excessive retries. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index bd1546ba7ad2..b45bc24c3dae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -113,26 +113,6 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u16 offset, void *buffer, const u16 buffer_length, const int timeout) { - int status; - - mutex_lock(&rt2x00dev->csr_mutex); - - status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, - requesttype, offset, buffer, - buffer_length, timeout); - - mutex_unlock(&rt2x00dev->csr_mutex); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); - -int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const void *buffer, - const u16 buffer_length, - const int timeout) -{ int status = 0; unsigned char *tb; u16 off, len, bsize; @@ -157,7 +137,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, return status; } -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); +EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, const unsigned int offset, @@ -198,6 +178,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) return; /* + * Remove the descriptor from the front of the skb. + */ + skb_pull(entry->skb, entry->queue->desc_size); + + /* * Obtain the status about this packet. * Note that when the status is 0 it does not mean the * frame was send out correctly. It only means the frame @@ -243,10 +228,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry, rt2x00usb_interrupt_txdone, entry); /* - * Make sure the skb->data pointer points to the frame, not the - * descriptor. + * Call the driver's write_tx_datadesc function, if it exists. */ - skb_pull(entry->skb, entry->queue->desc_size); + if (rt2x00dev->ops->lib->write_tx_datadesc) + rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 621d0f829251..255b81ef9530 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -167,25 +167,6 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, const u16 buffer_length, const int timeout); /** - * rt2x00usb_vendor_request_large_buff - Send register command to device (buffered) - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @requesttype: Request type &USB_VENDOR_REQUEST_* - * @offset: Register start offset to perform action on - * @buffer: Buffer where information will be read/written to by device - * @buffer_length: Size of &buffer - * @timeout: Operation timeout - * - * This function is used to transfer register data in blocks larger - * then CSR_CACHE_SIZE. Use for firmware upload, keys and beacons. - */ -int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const void *buffer, - const u16 buffer_length, - const int timeout); - -/** * rt2x00usb_vendor_request_sw - Send single register command to device * @rt2x00dev: Pointer to &struct rt2x00_dev * @request: USB vendor command (See &enum rt2x00usb_vendor_request) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6a74baf4e934..7ca383478eeb 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -931,6 +931,9 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, u32 reg; rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, libconf->conf->long_frame_max_tx_count); rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, @@ -1874,6 +1877,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); /* + * Write the TX descriptor for the beacon. + */ + rt61pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); + + /* * Write entire beacon with descriptor to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); @@ -2039,29 +2052,24 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) struct txdone_entry_desc txdesc; u32 word; u32 reg; - u32 old_reg; int type; int index; + int i; /* - * During each loop we will compare the freshly read - * STA_CSR4 register value with the value read from - * the previous loop. If the 2 values are equal then - * we should stop processing because the chance is - * quite big that the device has been unplugged and - * we risk going into an endless loop. + * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO + * at most X times and also stop processing once the TX_STA_FIFO_VALID + * flag is not set anymore. + * + * The legacy drivers use X=TX_RING_SIZE but state in a comment + * that the TX_STA_FIFO stack has a size of 16. We stick to our + * tx ring size for now. */ - old_reg = 0; - - while (1) { + for (i = 0; i < TX_ENTRIES; i++) { rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; - if (old_reg == reg) - break; - old_reg = reg; - /* * Skip this entry when it contains an invalid * queue identication number. @@ -2100,7 +2108,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) __set_bit(TXDONE_UNKNOWN, &txdesc.flags); txdesc.retry = 0; - rt2x00lib_txdone(entry_done, &txdesc); + rt2x00pci_txdone(entry_done, &txdesc); entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); } @@ -2120,7 +2128,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) } txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + /* + * the frame was retried at least once + * -> hw used fallback rates + */ + if (txdesc.retry) + __set_bit(TXDONE_FALLBACK, &txdesc.flags); + + rt2x00pci_txdone(entry, &txdesc); } } @@ -2577,6 +2592,18 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) EEPROM_MAC_ADDR_0)); /* + * As rt61 has a global fallback table we cannot specify + * more then one tx rate per frame but since the hw will + * try several rates (based on the fallback table) we should + * still initialize max_rates to the maximum number of rates + * we are going to try. Otherwise mac80211 will truncate our + * reported tx rates and the rc algortihm will end up with + * incorrect data. + */ + rt2x00dev->hw->max_rates = 7; + rt2x00dev->hw->max_rate_tries = 1; + + /* * Initialize hw_mode information. */ spec->supported_bands = SUPPORT_BAND_2GHZ; diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index df80f1af22a4..e2e728ab0b2e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -153,13 +153,13 @@ struct hw_key_entry { u8 key[16]; u8 tx_mic[8]; u8 rx_mic[8]; -} __attribute__ ((packed)); +} __packed; struct hw_pairwise_ta_entry { u8 address[6]; u8 cipher; u8 reserved; -} __attribute__ ((packed)); +} __packed; /* * Other on-chip shared memory space. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6e0d82efe924..d06d90f003e7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -270,7 +270,6 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, { struct hw_key_entry key_entry; struct rt2x00_field32 field; - int timeout; u32 mask; u32 reg; @@ -306,12 +305,8 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, sizeof(key_entry.rx_mic)); reg = SHARED_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - &key_entry, - sizeof(key_entry), - timeout); + rt2x00usb_register_multiwrite(rt2x00dev, reg, + &key_entry, sizeof(key_entry)); /* * The cipher types are stored over 2 registers. @@ -372,7 +367,6 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, { struct hw_pairwise_ta_entry addr_entry; struct hw_key_entry key_entry; - int timeout; u32 mask; u32 reg; @@ -407,17 +401,11 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, sizeof(key_entry.rx_mic)); reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - &key_entry, - sizeof(key_entry), - timeout); + rt2x00usb_register_multiwrite(rt2x00dev, reg, + &key_entry, sizeof(key_entry)); /* * Send the address and cipher type to the hardware register. - * This data fits within the CSR cache size, so we can use - * rt2x00usb_register_multiwrite() directly. */ memset(&addr_entry, 0, sizeof(addr_entry)); memcpy(&addr_entry, crypto->address, ETH_ALEN); @@ -828,6 +816,9 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, u32 reg; rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); + rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, libconf->conf->long_frame_max_tx_count); rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, @@ -1092,11 +1083,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - FIRMWARE_IMAGE_BASE, - data, len, - REGISTER_TIMEOUT32(len)); + rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); /* * Send firmware request to device to load firmware, @@ -1442,7 +1429,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); + __le32 *txd = (__le32 *) skb->data; u32 word; /* @@ -1505,6 +1492,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Register descriptor details in skb frame descriptor. */ + skbdesc->flags |= SKBDESC_DESC_IN_SKB; skbdesc->desc = txd; skbdesc->desc_len = TXD_DESC_SIZE; } @@ -1528,18 +1516,27 @@ static void rt73usb_write_beacon(struct queue_entry *entry, rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); /* - * Take the descriptor in front of the skb into account. + * Add space for the descriptor in front of the skb. */ skb_push(entry->skb, TXD_DESC_SIZE); + memset(entry->skb->data, 0, TXD_DESC_SIZE); + + /* + * Write the TX descriptor for the beacon. + */ + rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); + + /* + * Dump beacon to userspace through debugfs. + */ + rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* * Write entire beacon with descriptor to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, - entry->skb->data, entry->skb->len, - REGISTER_TIMEOUT32(entry->skb->len)); + rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, + entry->skb->data, entry->skb->len); /* * Enable beaconing again. diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 7abe7eb14555..44d5b2bebd39 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -108,13 +108,13 @@ struct hw_key_entry { u8 key[16]; u8 tx_mic[8]; u8 rx_mic[8]; -} __attribute__ ((packed)); +} __packed; struct hw_pairwise_ta_entry { u8 address[6]; u8 cipher; u8 reserved; -} __attribute__ ((packed)); +} __packed; /* * Since NULL frame won't be that long (256 byte), diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 4baf0cf0826f..30523314da43 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h @@ -36,7 +36,7 @@ struct rtl8180_tx_desc { u8 agc; u8 flags2; u32 reserved[2]; -} __attribute__ ((packed)); +} __packed; struct rtl8180_rx_desc { __le32 flags; @@ -45,7 +45,7 @@ struct rtl8180_rx_desc { __le32 rx_buf; __le64 tsft; }; -} __attribute__ ((packed)); +} __packed; struct rtl8180_tx_ring { struct rtl8180_tx_desc *desc; diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 6bb32112e65c..98878160a65a 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -47,7 +47,7 @@ struct rtl8187_rx_hdr { u8 agc; u8 reserved; __le64 mac_time; -} __attribute__((packed)); +} __packed; struct rtl8187b_rx_hdr { __le32 flags; @@ -59,7 +59,7 @@ struct rtl8187b_rx_hdr { __le16 snr_long2end; s8 pwdb_g12; u8 fot; -} __attribute__((packed)); +} __packed; /* {rtl8187,rtl8187b}_tx_info is in skb */ @@ -68,7 +68,7 @@ struct rtl8187_tx_hdr { __le16 rts_duration; __le16 len; __le32 retry; -} __attribute__((packed)); +} __packed; struct rtl8187b_tx_hdr { __le32 flags; @@ -80,7 +80,7 @@ struct rtl8187b_tx_hdr { __le32 unused_3; __le32 retry; __le32 unused_4[2]; -} __attribute__((packed)); +} __packed; enum { DEVICE_RTL8187, diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index 8522490d2e29..978519d1ff4c 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h @@ -185,7 +185,7 @@ struct rtl818x_csr { u8 reserved_22[4]; __le16 TALLY_CNT; u8 TALLY_SEL; -} __attribute__((packed)); +} __packed; struct rtl818x_rf_ops { char *name; diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 337fc7bec5a5..2f98058be451 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -41,7 +41,7 @@ config WL1251_SDIO config WL1271 tristate "TI wl1271 support" - depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS + depends on WL12XX && GENERIC_HARDIRQS depends on INET select FW_LOADER select CRC7 @@ -65,7 +65,7 @@ config WL1271_SPI config WL1271_SDIO tristate "TI wl1271 SDIO support" - depends on WL1271 && MMC && ARM + depends on WL1271 && MMC ---help--- This module adds support for the SDIO interface of adapters using TI wl1271 chipset. Select this if your platform is using diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 26160c45784c..842df310d92a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -60,7 +60,7 @@ struct acx_error_counter { /* the number of missed sequence numbers in the squentially */ /* values of frames seq numbers */ u32 seq_num_miss; -} __attribute__ ((packed)); +} __packed; struct acx_revision { struct acx_header header; @@ -89,7 +89,7 @@ struct acx_revision { * bits 24 - 31: Chip ID - The WiLink chip ID. */ u32 hw_version; -} __attribute__ ((packed)); +} __packed; enum wl1251_psm_mode { /* Active mode */ @@ -111,7 +111,7 @@ struct acx_sleep_auth { /* 2 - ELP mode: Deep / Max sleep*/ u8 sleep_auth; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum { HOSTIF_PCI_MASTER_HOST_INDIRECT, @@ -159,7 +159,7 @@ struct acx_data_path_params { * complete ring until an interrupt is generated. */ u32 tx_complete_timeout; -} __attribute__ ((packed)); +} __packed; struct acx_data_path_params_resp { @@ -180,7 +180,7 @@ struct acx_data_path_params_resp { u32 tx_control_addr; u32 tx_complete_addr; -} __attribute__ ((packed)); +} __packed; #define TX_MSDU_LIFETIME_MIN 0 #define TX_MSDU_LIFETIME_MAX 3000 @@ -197,7 +197,7 @@ struct acx_rx_msdu_lifetime { * firmware discards the MSDU. */ u32 lifetime; -} __attribute__ ((packed)); +} __packed; /* * RX Config Options Table @@ -285,7 +285,7 @@ struct acx_rx_config { u32 config_options; u32 filter_options; -} __attribute__ ((packed)); +} __packed; enum { QOS_AC_BE = 0, @@ -325,13 +325,13 @@ struct acx_tx_queue_qos_config { /* Lowest memory blocks guaranteed for this queue */ u16 low_threshold; -} __attribute__ ((packed)); +} __packed; struct acx_packet_detection { struct acx_header header; u32 threshold; -} __attribute__ ((packed)); +} __packed; enum acx_slot_type { @@ -349,7 +349,7 @@ struct acx_slot { u8 wone_index; /* Reserved */ u8 slot_time; u8 reserved[6]; -} __attribute__ ((packed)); +} __packed; #define ADDRESS_GROUP_MAX (8) @@ -362,7 +362,7 @@ struct acx_dot11_grp_addr_tbl { u8 num_groups; u8 pad[2]; u8 mac_table[ADDRESS_GROUP_MAX_LEN]; -} __attribute__ ((packed)); +} __packed; #define RX_TIMEOUT_PS_POLL_MIN 0 @@ -388,7 +388,7 @@ struct acx_rx_timeout { * from an UPSD enabled queue. */ u16 upsd_timeout; -} __attribute__ ((packed)); +} __packed; #define RTS_THRESHOLD_MIN 0 #define RTS_THRESHOLD_MAX 4096 @@ -399,7 +399,7 @@ struct acx_rts_threshold { u16 threshold; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_beacon_filter_option { struct acx_header header; @@ -415,7 +415,7 @@ struct acx_beacon_filter_option { */ u8 max_num_beacons; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; /* * ACXBeaconFilterEntry (not 221) @@ -461,7 +461,7 @@ struct acx_beacon_filter_ie_table { u8 num_ie; u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ #define NO_BEACON_DEFAULT_TIMEOUT (500) /* in microseconds */ @@ -494,7 +494,7 @@ struct acx_bt_wlan_coex { */ u8 enable; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; #define PTA_ANTENNA_TYPE_DEF (0) #define PTA_BT_HP_MAXTIME_DEF (2000) @@ -648,7 +648,7 @@ struct acx_bt_wlan_coex_param { /* range: 0 - 20 default: 1 */ u8 bt_hp_respected_num; -} __attribute__ ((packed)); +} __packed; #define CCA_THRSH_ENABLE_ENERGY_D 0x140A #define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF @@ -660,7 +660,7 @@ struct acx_energy_detection { u16 rx_cca_threshold; u8 tx_energy_detection; u8 pad; -} __attribute__ ((packed)); +} __packed; #define BCN_RX_TIMEOUT_DEF_VALUE 10000 #define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 @@ -679,14 +679,14 @@ struct acx_beacon_broadcast { /* Consecutive PS Poll failures before updating the host */ u8 ps_poll_threshold; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_event_mask { struct acx_header header; u32 event_mask; u32 high_event_mask; /* Unused */ -} __attribute__ ((packed)); +} __packed; #define CFG_RX_FCS BIT(2) #define CFG_RX_ALL_GOOD BIT(3) @@ -729,7 +729,7 @@ struct acx_fw_gen_frame_rates { u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */ u8 tx_mgt_frame_rate; u8 tx_mgt_frame_mod; -} __attribute__ ((packed)); +} __packed; /* STA MAC */ struct acx_dot11_station_id { @@ -737,28 +737,28 @@ struct acx_dot11_station_id { u8 mac[ETH_ALEN]; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_feature_config { struct acx_header header; u32 options; u32 data_flow_options; -} __attribute__ ((packed)); +} __packed; struct acx_current_tx_power { struct acx_header header; u8 current_tx_power; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct acx_dot11_default_key { struct acx_header header; u8 id; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; struct acx_tsf_info { struct acx_header header; @@ -769,7 +769,7 @@ struct acx_tsf_info { u32 last_TBTT_lsb; u8 last_dtim_count; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; enum acx_wake_up_event { WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ @@ -785,7 +785,7 @@ struct acx_wake_up_condition { u8 wake_up_event; /* Only one bit can be set */ u8 listen_interval; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_aid { struct acx_header header; @@ -795,7 +795,7 @@ struct acx_aid { */ u16 aid; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; enum acx_preamble_type { ACX_PREAMBLE_LONG = 0, @@ -811,7 +811,7 @@ struct acx_preamble { */ u8 preamble; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum acx_ctsprotect_type { CTSPROTECT_DISABLE = 0, @@ -822,11 +822,11 @@ struct acx_ctsprotect { struct acx_header header; u8 ctsprotect; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct acx_tx_statistics { u32 internal_desc_overflow; -} __attribute__ ((packed)); +} __packed; struct acx_rx_statistics { u32 out_of_mem; @@ -837,14 +837,14 @@ struct acx_rx_statistics { u32 xfr_hint_trig; u32 path_reset; u32 reset_counter; -} __attribute__ ((packed)); +} __packed; struct acx_dma_statistics { u32 rx_requested; u32 rx_errors; u32 tx_requested; u32 tx_errors; -} __attribute__ ((packed)); +} __packed; struct acx_isr_statistics { /* host command complete */ @@ -903,7 +903,7 @@ struct acx_isr_statistics { /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ u32 low_rssi; -} __attribute__ ((packed)); +} __packed; struct acx_wep_statistics { /* WEP address keys configured */ @@ -925,7 +925,7 @@ struct acx_wep_statistics { /* WEP decrypt interrupts */ u32 interrupt; -} __attribute__ ((packed)); +} __packed; #define ACX_MISSED_BEACONS_SPREAD 10 @@ -985,12 +985,12 @@ struct acx_pwr_statistics { /* the number of beacons in awake mode */ u32 rcvd_awake_beacons; -} __attribute__ ((packed)); +} __packed; struct acx_mic_statistics { u32 rx_pkts; u32 calc_failure; -} __attribute__ ((packed)); +} __packed; struct acx_aes_statistics { u32 encrypt_fail; @@ -999,7 +999,7 @@ struct acx_aes_statistics { u32 decrypt_packets; u32 encrypt_interrupt; u32 decrypt_interrupt; -} __attribute__ ((packed)); +} __packed; struct acx_event_statistics { u32 heart_beat; @@ -1010,7 +1010,7 @@ struct acx_event_statistics { u32 oom_late; u32 phy_transmit_error; u32 tx_stuck; -} __attribute__ ((packed)); +} __packed; struct acx_ps_statistics { u32 pspoll_timeouts; @@ -1020,7 +1020,7 @@ struct acx_ps_statistics { u32 pspoll_max_apturn; u32 pspoll_utilization; u32 upsd_utilization; -} __attribute__ ((packed)); +} __packed; struct acx_rxpipe_statistics { u32 rx_prep_beacon_drop; @@ -1028,7 +1028,7 @@ struct acx_rxpipe_statistics { u32 beacon_buffer_thres_host_int_trig_rx_data; u32 missed_beacon_host_int_trig_rx_data; u32 tx_xfr_host_int_trig_rx_data; -} __attribute__ ((packed)); +} __packed; struct acx_statistics { struct acx_header header; @@ -1044,7 +1044,7 @@ struct acx_statistics { struct acx_event_statistics event; struct acx_ps_statistics ps; struct acx_rxpipe_statistics rxpipe; -} __attribute__ ((packed)); +} __packed; #define ACX_MAX_RATE_CLASSES 8 #define ACX_RATE_MASK_UNSPECIFIED 0 @@ -1063,7 +1063,7 @@ struct acx_rate_policy { u32 rate_class_cnt; struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES]; -} __attribute__ ((packed)); +} __packed; struct wl1251_acx_memory { __le16 num_stations; /* number of STAs to be supported. */ @@ -1082,7 +1082,7 @@ struct wl1251_acx_memory { u8 tx_min_mem_block_num; u8 num_ssid_profiles; __le16 debug_buffer_size; -} __attribute__ ((packed)); +} __packed; #define ACX_RX_DESC_MIN 1 @@ -1094,7 +1094,7 @@ struct wl1251_acx_rx_queue_config { u8 type; u8 priority; __le32 dma_address; -} __attribute__ ((packed)); +} __packed; #define ACX_TX_DESC_MIN 1 #define ACX_TX_DESC_MAX 127 @@ -1103,7 +1103,7 @@ struct wl1251_acx_tx_queue_config { u8 num_descs; u8 pad[2]; u8 attributes; -} __attribute__ ((packed)); +} __packed; #define MAX_TX_QUEUE_CONFIGS 5 #define MAX_TX_QUEUES 4 @@ -1113,7 +1113,7 @@ struct wl1251_acx_config_memory { struct wl1251_acx_memory mem_config; struct wl1251_acx_rx_queue_config rx_queue_config; struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS]; -} __attribute__ ((packed)); +} __packed; struct wl1251_acx_mem_map { struct acx_header header; @@ -1147,7 +1147,7 @@ struct wl1251_acx_mem_map { /* Number of blocks FW allocated for RX packets */ u32 num_rx_mem_blocks; -} __attribute__ ((packed)); +} __packed; struct wl1251_acx_wr_tbtt_and_dtim { @@ -1164,7 +1164,7 @@ struct wl1251_acx_wr_tbtt_and_dtim { */ u8 dtim; u8 padding; -} __attribute__ ((packed)); +} __packed; struct wl1251_acx_ac_cfg { struct acx_header header; @@ -1194,7 +1194,7 @@ struct wl1251_acx_ac_cfg { /* The TX Op Limit (in microseconds) for the access class. */ u16 txop_limit; -} __attribute__ ((packed)); +} __packed; enum wl1251_acx_channel_type { @@ -1245,7 +1245,7 @@ struct wl1251_acx_tid_cfg { /* not supported */ u32 apsdconf[2]; -} __attribute__ ((packed)); +} __packed; /************************************************************************* diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index 4ad67cae94d2..7e70dd5a21b8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -106,7 +106,7 @@ struct wl1251_cmd_header { u16 status; /* payload */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct wl1251_command { struct wl1251_cmd_header header; @@ -201,7 +201,7 @@ struct wl1251_scan_parameters { u8 ssid_len; u8 ssid[32]; -} __attribute__ ((packed)); +} __packed; struct wl1251_scan_ch_parameters { u32 min_duration; /* in TU */ @@ -218,7 +218,7 @@ struct wl1251_scan_ch_parameters { u8 tx_power_att; u8 channel; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; /* SCAN parameters */ #define SCAN_MAX_NUM_OF_CHANNELS 16 @@ -228,7 +228,7 @@ struct wl1251_cmd_scan { struct wl1251_scan_parameters params; struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; -} __attribute__ ((packed)); +} __packed; enum { BSS_TYPE_IBSS = 0, @@ -276,14 +276,14 @@ struct cmd_join { u8 tx_mgt_frame_rate; /* OBSOLETE */ u8 tx_mgt_frame_mod; /* OBSOLETE */ u8 reserved; -} __attribute__ ((packed)); +} __packed; struct cmd_enabledisable_path { struct wl1251_cmd_header header; u8 channel; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; #define WL1251_MAX_TEMPLATE_SIZE 300 @@ -292,7 +292,7 @@ struct wl1251_cmd_packet_template { __le16 size; u8 data[0]; -} __attribute__ ((packed)); +} __packed; #define TIM_ELE_ID 5 #define PARTIAL_VBM_MAX 251 @@ -304,7 +304,7 @@ struct wl1251_tim { u8 dtim_period; u8 bitmap_ctrl; u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ -} __attribute__ ((packed)); +} __packed; /* Virtual Bit Map update */ struct wl1251_cmd_vbm_update { @@ -312,7 +312,7 @@ struct wl1251_cmd_vbm_update { __le16 len; u8 padding[2]; struct wl1251_tim tim; -} __attribute__ ((packed)); +} __packed; enum wl1251_cmd_ps_mode { STATION_ACTIVE_MODE, @@ -333,7 +333,7 @@ struct wl1251_cmd_ps_params { u8 hang_over_period; u16 null_data_rate; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct wl1251_cmd_trigger_scan_to { struct wl1251_cmd_header header; @@ -411,7 +411,7 @@ struct wl1251_cmd_set_keys { u8 key[MAX_KEY_SIZE]; u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; -} __attribute__ ((packed)); +} __packed; #endif /* __WL1251_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h index be0ac54d6246..f48a2b66bc5a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ b/drivers/net/wireless/wl12xx/wl1251_event.h @@ -82,7 +82,7 @@ struct event_debug_report { u32 report_1; u32 report_2; u32 report_3; -} __attribute__ ((packed)); +} __packed; struct event_mailbox { u32 events_vector; @@ -112,7 +112,7 @@ struct event_mailbox { struct event_debug_report report; u8 average_snr_level; u8 padding[19]; -} __attribute__ ((packed)); +} __packed; int wl1251_event_unmask(struct wl1251 *wl); void wl1251_event_mbox_config(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 00b24282fc73..c8f268951e10 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -124,7 +124,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) } wl->nvs_len = fw->size; - wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); + wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL); if (!wl->nvs) { wl1251_error("could not allocate memory for the nvs file"); @@ -132,8 +132,6 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) goto out; } - memcpy(wl->nvs, fw->data, wl->nvs_len); - ret = 0; out: diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h index 563a3fde40fb..da4e53406a0e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ b/drivers/net/wireless/wl12xx/wl1251_rx.h @@ -117,7 +117,7 @@ struct wl1251_rx_descriptor { s8 rssi; /* in dB */ u8 rcpi; /* in dB */ u8 snr; /* in dB */ -} __attribute__ ((packed)); +} __packed; void wl1251_rx(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index c561332e7009..b901b6135654 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -37,11 +37,17 @@ #define SDIO_DEVICE_ID_TI_WL1251 0x9066 #endif +struct wl1251_sdio { + struct sdio_func *func; + u32 elp_val; +}; + static struct wl12xx_platform_data *wl12xx_board_data; static struct sdio_func *wl_to_func(struct wl1251 *wl) { - return wl->if_priv; + struct wl1251_sdio *wl_sdio = wl->if_priv; + return wl_sdio->func; } static void wl1251_sdio_interrupt(struct sdio_func *func) @@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr, static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) { int ret = 0; - struct sdio_func *func = wl_to_func(wl); - + struct wl1251_sdio *wl_sdio = wl->if_priv; + struct sdio_func *func = wl_sdio->func; + + /* + * The hardware only supports RAW (read after write) access for + * reading, regular sdio_readb won't work here (it interprets + * the unused bits of CMD52 as write data even if we send read + * request). + */ sdio_claim_host(func); - *val = sdio_readb(func, addr, &ret); + *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret); sdio_release_host(func); if (ret) @@ -103,7 +116,8 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) { int ret = 0; - struct sdio_func *func = wl_to_func(wl); + struct wl1251_sdio *wl_sdio = wl->if_priv; + struct sdio_func *func = wl_sdio->func; sdio_claim_host(func); sdio_writeb(func, val, addr, &ret); @@ -111,6 +125,8 @@ static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) if (ret) wl1251_error("sdio_writeb failed (%d)", ret); + else + wl_sdio->elp_val = val; } static void wl1251_sdio_reset(struct wl1251 *wl) @@ -197,6 +213,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, int ret; struct wl1251 *wl; struct ieee80211_hw *hw; + struct wl1251_sdio *wl_sdio; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) @@ -204,6 +221,12 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl = hw->priv; + wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL); + if (wl_sdio == NULL) { + ret = -ENOMEM; + goto out_free_hw; + } + sdio_claim_host(func); ret = sdio_enable_func(func); if (ret) @@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func, sdio_release_host(func); SET_IEEE80211_DEV(hw, &func->dev); - wl->if_priv = func; + wl_sdio->func = func; + wl->if_priv = wl_sdio; wl->if_ops = &wl1251_sdio_ops; wl->set_power = wl1251_sdio_set_power; @@ -259,6 +283,8 @@ disable: sdio_disable_func(func); release: sdio_release_host(func); + kfree(wl_sdio); +out_free_hw: wl1251_free_hw(wl); return ret; } @@ -266,9 +292,11 @@ release: 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; if (wl->irq) free_irq(wl->irq, wl); + kfree(wl_sdio); wl1251_free_hw(wl); sdio_claim_host(func); diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 55856c6bb97a..65c4be8c2e80 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h @@ -109,7 +109,7 @@ struct tx_control { unsigned xfer_pad:1; unsigned reserved:7; -} __attribute__ ((packed)); +} __packed; struct tx_double_buffer_desc { @@ -156,7 +156,7 @@ struct tx_double_buffer_desc { u8 num_mem_blocks; u8 reserved; -} __attribute__ ((packed)); +} __packed; enum { TX_SUCCESS = 0, @@ -208,7 +208,7 @@ struct tx_result { /* See done_1 */ u8 done_2; -} __attribute__ ((packed)); +} __packed; static inline int wl1251_tx_get_queue(int queue) { diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 6f1b6b5640c0..ec09f0d40ca2 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -33,6 +33,7 @@ #include <net/mac80211.h> #include "wl1271_conf.h" +#include "wl1271_ini.h" #define DRIVER_NAME "wl1271" #define DRIVER_PREFIX DRIVER_NAME ": " @@ -116,33 +117,6 @@ enum { #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) -/* NVS data structure */ -#define WL1271_NVS_SECTION_SIZE 468 - -#define WL1271_NVS_GENERAL_PARAMS_SIZE 57 -#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \ - (WL1271_NVS_GENERAL_PARAMS_SIZE + 1) -#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17 -#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \ - (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1) -#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65 -#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \ - (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1) -#define WL1271_NVS_FEM_COUNT 2 -#define WL1271_NVS_INI_SPARE_SIZE 124 - -struct wl1271_nvs_file { - /* NVS section */ - u8 nvs[WL1271_NVS_SECTION_SIZE]; - - /* INI section */ - u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED]; - u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED]; - u8 dyn_radio_params[WL1271_NVS_FEM_COUNT] - [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED]; - u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE]; -} __attribute__ ((packed)); - /* * Enable/disable 802.11a support for WL1273 */ @@ -317,7 +291,7 @@ struct wl1271_fw_status { __le32 tx_released_blks[NUM_TX_QUEUES]; __le32 fw_localtime; __le32 padding[2]; -} __attribute__ ((packed)); +} __packed; struct wl1271_rx_mem_pool_addr { u32 addr; @@ -325,6 +299,7 @@ struct wl1271_rx_mem_pool_addr { }; struct wl1271_scan { + struct cfg80211_scan_request *req; u8 state; u8 ssid[IW_ESSID_MAX_SIZE+1]; size_t ssid_len; @@ -375,6 +350,7 @@ struct wl1271 { #define WL1271_FLAG_IRQ_PENDING (9) #define WL1271_FLAG_IRQ_RUNNING (10) #define WL1271_FLAG_IDLE (11) +#define WL1271_FLAG_IDLE_REQUESTED (12) unsigned long flags; struct wl1271_partition_set part; @@ -421,6 +397,7 @@ struct wl1271 { /* Pending TX frames */ struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; + int tx_frames_cnt; /* Security sequence number counters */ u8 tx_security_last_seq; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 420e7e2fc021..4c87e601df2f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -75,7 +75,7 @@ struct acx_header { /* payload length (not including headers */ __le16 len; -} __attribute__ ((packed)); +} __packed; struct acx_error_counter { struct acx_header header; @@ -98,7 +98,7 @@ struct acx_error_counter { /* the number of missed sequence numbers in the squentially */ /* values of frames seq numbers */ __le32 seq_num_miss; -} __attribute__ ((packed)); +} __packed; struct acx_revision { struct acx_header header; @@ -127,7 +127,7 @@ struct acx_revision { * bits 24 - 31: Chip ID - The WiLink chip ID. */ __le32 hw_version; -} __attribute__ ((packed)); +} __packed; enum wl1271_psm_mode { /* Active mode */ @@ -149,7 +149,7 @@ struct acx_sleep_auth { /* 2 - ELP mode: Deep / Max sleep*/ u8 sleep_auth; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum { HOSTIF_PCI_MASTER_HOST_INDIRECT, @@ -187,7 +187,7 @@ struct acx_rx_msdu_lifetime { * firmware discards the MSDU. */ __le32 lifetime; -} __attribute__ ((packed)); +} __packed; /* * RX Config Options Table @@ -275,13 +275,13 @@ struct acx_rx_config { __le32 config_options; __le32 filter_options; -} __attribute__ ((packed)); +} __packed; struct acx_packet_detection { struct acx_header header; __le32 threshold; -} __attribute__ ((packed)); +} __packed; enum acx_slot_type { @@ -299,7 +299,7 @@ struct acx_slot { u8 wone_index; /* Reserved */ u8 slot_time; u8 reserved[6]; -} __attribute__ ((packed)); +} __packed; #define ACX_MC_ADDRESS_GROUP_MAX (8) @@ -312,21 +312,21 @@ struct acx_dot11_grp_addr_tbl { u8 num_groups; u8 pad[2]; u8 mac_table[ADDRESS_GROUP_MAX_LEN]; -} __attribute__ ((packed)); +} __packed; struct acx_rx_timeout { struct acx_header header; __le16 ps_poll_timeout; __le16 upsd_timeout; -} __attribute__ ((packed)); +} __packed; struct acx_rts_threshold { struct acx_header header; __le16 threshold; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_beacon_filter_option { struct acx_header header; @@ -342,7 +342,7 @@ struct acx_beacon_filter_option { */ u8 max_num_beacons; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; /* * ACXBeaconFilterEntry (not 221) @@ -383,21 +383,21 @@ struct acx_beacon_filter_ie_table { u8 num_ie; u8 pad[3]; u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; -} __attribute__ ((packed)); +} __packed; struct acx_conn_monit_params { struct acx_header header; __le32 synch_fail_thold; /* number of beacons missed */ __le32 bss_lose_timeout; /* number of TU's from synch fail */ -} __attribute__ ((packed)); +} __packed; struct acx_bt_wlan_coex { struct acx_header header; u8 enable; u8 pad[3]; -} __attribute__ ((packed)); +} __packed; struct acx_bt_wlan_coex_param { struct acx_header header; @@ -405,7 +405,7 @@ struct acx_bt_wlan_coex_param { __le32 params[CONF_SG_PARAMS_MAX]; u8 param_idx; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct acx_dco_itrim_params { struct acx_header header; @@ -413,7 +413,7 @@ struct acx_dco_itrim_params { u8 enable; u8 padding[3]; __le32 timeout; -} __attribute__ ((packed)); +} __packed; struct acx_energy_detection { struct acx_header header; @@ -422,7 +422,7 @@ struct acx_energy_detection { __le16 rx_cca_threshold; u8 tx_energy_detection; u8 pad; -} __attribute__ ((packed)); +} __packed; struct acx_beacon_broadcast { struct acx_header header; @@ -436,14 +436,14 @@ struct acx_beacon_broadcast { /* Consecutive PS Poll failures before updating the host */ u8 ps_poll_threshold; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_event_mask { struct acx_header header; __le32 event_mask; __le32 high_event_mask; /* Unused */ -} __attribute__ ((packed)); +} __packed; #define CFG_RX_FCS BIT(2) #define CFG_RX_ALL_GOOD BIT(3) @@ -488,14 +488,14 @@ struct acx_feature_config { __le32 options; __le32 data_flow_options; -} __attribute__ ((packed)); +} __packed; struct acx_current_tx_power { struct acx_header header; u8 current_tx_power; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct acx_wake_up_condition { struct acx_header header; @@ -503,7 +503,7 @@ struct acx_wake_up_condition { u8 wake_up_event; /* Only one bit can be set */ u8 listen_interval; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; struct acx_aid { struct acx_header header; @@ -513,7 +513,7 @@ struct acx_aid { */ __le16 aid; u8 pad[2]; -} __attribute__ ((packed)); +} __packed; enum acx_preamble_type { ACX_PREAMBLE_LONG = 0, @@ -529,7 +529,7 @@ struct acx_preamble { */ u8 preamble; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum acx_ctsprotect_type { CTSPROTECT_DISABLE = 0, @@ -540,11 +540,11 @@ struct acx_ctsprotect { struct acx_header header; u8 ctsprotect; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct acx_tx_statistics { __le32 internal_desc_overflow; -} __attribute__ ((packed)); +} __packed; struct acx_rx_statistics { __le32 out_of_mem; @@ -555,14 +555,14 @@ struct acx_rx_statistics { __le32 xfr_hint_trig; __le32 path_reset; __le32 reset_counter; -} __attribute__ ((packed)); +} __packed; struct acx_dma_statistics { __le32 rx_requested; __le32 rx_errors; __le32 tx_requested; __le32 tx_errors; -} __attribute__ ((packed)); +} __packed; struct acx_isr_statistics { /* host command complete */ @@ -621,7 +621,7 @@ struct acx_isr_statistics { /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ __le32 low_rssi; -} __attribute__ ((packed)); +} __packed; struct acx_wep_statistics { /* WEP address keys configured */ @@ -643,7 +643,7 @@ struct acx_wep_statistics { /* WEP decrypt interrupts */ __le32 interrupt; -} __attribute__ ((packed)); +} __packed; #define ACX_MISSED_BEACONS_SPREAD 10 @@ -703,12 +703,12 @@ struct acx_pwr_statistics { /* the number of beacons in awake mode */ __le32 rcvd_awake_beacons; -} __attribute__ ((packed)); +} __packed; struct acx_mic_statistics { __le32 rx_pkts; __le32 calc_failure; -} __attribute__ ((packed)); +} __packed; struct acx_aes_statistics { __le32 encrypt_fail; @@ -717,7 +717,7 @@ struct acx_aes_statistics { __le32 decrypt_packets; __le32 encrypt_interrupt; __le32 decrypt_interrupt; -} __attribute__ ((packed)); +} __packed; struct acx_event_statistics { __le32 heart_beat; @@ -728,7 +728,7 @@ struct acx_event_statistics { __le32 oom_late; __le32 phy_transmit_error; __le32 tx_stuck; -} __attribute__ ((packed)); +} __packed; struct acx_ps_statistics { __le32 pspoll_timeouts; @@ -738,7 +738,7 @@ struct acx_ps_statistics { __le32 pspoll_max_apturn; __le32 pspoll_utilization; __le32 upsd_utilization; -} __attribute__ ((packed)); +} __packed; struct acx_rxpipe_statistics { __le32 rx_prep_beacon_drop; @@ -746,7 +746,7 @@ struct acx_rxpipe_statistics { __le32 beacon_buffer_thres_host_int_trig_rx_data; __le32 missed_beacon_host_int_trig_rx_data; __le32 tx_xfr_host_int_trig_rx_data; -} __attribute__ ((packed)); +} __packed; struct acx_statistics { struct acx_header header; @@ -762,7 +762,7 @@ struct acx_statistics { struct acx_event_statistics event; struct acx_ps_statistics ps; struct acx_rxpipe_statistics rxpipe; -} __attribute__ ((packed)); +} __packed; struct acx_rate_class { __le32 enabled_rates; @@ -780,7 +780,7 @@ struct acx_rate_policy { __le32 rate_class_cnt; struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; -} __attribute__ ((packed)); +} __packed; struct acx_ac_cfg { struct acx_header header; @@ -790,7 +790,7 @@ struct acx_ac_cfg { u8 aifsn; u8 reserved; __le16 tx_op_limit; -} __attribute__ ((packed)); +} __packed; struct acx_tid_config { struct acx_header header; @@ -801,19 +801,19 @@ struct acx_tid_config { u8 ack_policy; u8 padding[3]; __le32 apsd_conf[2]; -} __attribute__ ((packed)); +} __packed; struct acx_frag_threshold { struct acx_header header; __le16 frag_threshold; u8 padding[2]; -} __attribute__ ((packed)); +} __packed; struct acx_tx_config_options { struct acx_header header; __le16 tx_compl_timeout; /* msec */ __le16 tx_compl_threshold; /* number of packets */ -} __attribute__ ((packed)); +} __packed; #define ACX_RX_MEM_BLOCKS 70 #define ACX_TX_MIN_MEM_BLOCKS 40 @@ -828,7 +828,7 @@ struct wl1271_acx_config_memory { u8 num_stations; u8 num_ssid_profiles; __le32 total_tx_descriptors; -} __attribute__ ((packed)); +} __packed; struct wl1271_acx_mem_map { struct acx_header header; @@ -872,7 +872,7 @@ struct wl1271_acx_mem_map { u8 *rx_cbuf; __le32 rx_ctrl; __le32 tx_ctrl; -} __attribute__ ((packed)); +} __packed; struct wl1271_acx_rx_config_opt { struct acx_header header; @@ -882,7 +882,7 @@ struct wl1271_acx_rx_config_opt { __le16 timeout; u8 queue_type; u8 reserved; -} __attribute__ ((packed)); +} __packed; struct wl1271_acx_bet_enable { @@ -891,7 +891,7 @@ struct wl1271_acx_bet_enable { u8 enable; u8 max_consecutive; u8 padding[2]; -} __attribute__ ((packed)); +} __packed; #define ACX_IPV4_VERSION 4 #define ACX_IPV6_VERSION 6 @@ -905,7 +905,7 @@ struct wl1271_acx_arp_filter { requests directed to this IP address will pass through. For IPv4, the first four bytes are used. */ -} __attribute__((packed)); +} __packed; struct wl1271_acx_pm_config { struct acx_header header; @@ -913,14 +913,14 @@ struct wl1271_acx_pm_config { __le32 host_clk_settling_time; u8 host_fast_wakeup_support; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; struct wl1271_acx_keep_alive_mode { struct acx_header header; u8 enabled; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum { ACX_KEEP_ALIVE_NO_TX = 0, @@ -940,7 +940,7 @@ struct wl1271_acx_keep_alive_config { u8 tpl_validation; u8 trigger; u8 padding; -} __attribute__ ((packed)); +} __packed; enum { WL1271_ACX_TRIG_TYPE_LEVEL = 0, diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 19393e236e2c..530678e45a13 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -212,8 +212,8 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; - memcpy(gen_parms->params, wl->nvs->general_params, - WL1271_NVS_GENERAL_PARAMS_SIZE); + memcpy(&gen_parms->general_params, &wl->nvs->general_params, + sizeof(struct wl1271_ini_general_params)); ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); if (ret < 0) @@ -238,13 +238,20 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, - WL1271_NVS_STAT_RADIO_PARAMS_SIZE); - memcpy(radio_parms->dyn_radio_params, - wl->nvs->dyn_radio_params[rparam->fem], - WL1271_NVS_DYN_RADIO_PARAMS_SIZE); - - /* FIXME: current NVS is missing 5GHz parameters */ + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, + sizeof(struct wl1271_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &wl->nvs->dyn_radio_params_2[rparam->fem].params, + sizeof(struct wl1271_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &wl->nvs->stat_radio_params_5, + sizeof(struct wl1271_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &wl->nvs->dyn_radio_params_5[rparam->fem].params, + sizeof(struct wl1271_ini_fem_params_5)); wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", radio_parms, sizeof(*radio_parms)); @@ -329,12 +336,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) join->channel = wl->channel; join->ssid_len = wl->ssid_len; memcpy(join->ssid, wl->ssid, wl->ssid_len); - join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH; - - /* increment the session counter */ - wl->session_counter++; - if (wl->session_counter >= SESSION_COUNTER_MAX) - wl->session_counter = 0; join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; @@ -517,7 +518,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) ps_params->send_null_data = send; ps_params->retries = 5; ps_params->hang_over_period = 1; - ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ + ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set); ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params), 0); @@ -567,7 +568,7 @@ out: } int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len, u8 active_scan, + struct cfg80211_scan_request *req, u8 active_scan, u8 high_prio, u8 band, u8 probe_requests) { @@ -648,7 +649,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, } ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, - ie, ie_len, ieee_band); + req->ie, req->ie_len, ieee_band); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; @@ -684,7 +685,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, memcpy(wl->scan.ssid, ssid, ssid_len); } else wl->scan.ssid_len = 0; - } + wl->scan.req = req; + } else + wl->scan.req = NULL; } ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index f2820b42a943..f5745d829c9b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -42,7 +42,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len, u8 active_scan, + struct cfg80211_scan_request *req, u8 active_scan, u8 high_prio, u8 band, u8 probe_requests); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, void *buf, size_t buf_len, int index, u32 rates); @@ -136,14 +136,14 @@ struct wl1271_cmd_header { __le16 status; /* payload */ u8 data[0]; -} __attribute__ ((packed)); +} __packed; #define WL1271_CMD_MAX_PARAMS 572 struct wl1271_command { struct wl1271_cmd_header header; u8 parameters[WL1271_CMD_MAX_PARAMS]; -} __attribute__ ((packed)); +} __packed; enum { CMD_MAILBOX_IDLE = 0, @@ -196,7 +196,7 @@ struct cmd_read_write_memory { of this field is the Host in WRITE command or the Wilink in READ command. */ u8 value[MAX_READ_SIZE]; -} __attribute__ ((packed)); +} __packed; #define CMDMBOX_HEADER_LEN 4 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 @@ -243,14 +243,14 @@ struct wl1271_cmd_join { u8 ssid[IW_ESSID_MAX_SIZE]; u8 ctrl; /* JOIN_CMD_CTRL_* */ u8 reserved[3]; -} __attribute__ ((packed)); +} __packed; struct cmd_enabledisable_path { struct wl1271_cmd_header header; u8 channel; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; #define WL1271_RATE_AUTOMATIC 0 @@ -266,7 +266,7 @@ struct wl1271_cmd_template_set { u8 aflags; u8 reserved; u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE]; -} __attribute__ ((packed)); +} __packed; #define TIM_ELE_ID 5 #define PARTIAL_VBM_MAX 251 @@ -278,7 +278,7 @@ struct wl1271_tim { u8 dtim_period; u8 bitmap_ctrl; u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ -} __attribute__ ((packed)); +} __packed; enum wl1271_cmd_ps_mode { STATION_ACTIVE_MODE, @@ -298,7 +298,7 @@ struct wl1271_cmd_ps_params { */ u8 hang_over_period; __le32 null_data_rate; -} __attribute__ ((packed)); +} __packed; /* HW encryption keys */ #define NUM_ACCESS_CATEGORIES_COPY 4 @@ -348,7 +348,7 @@ struct wl1271_cmd_set_keys { u8 key[MAX_KEY_SIZE]; __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; -} __attribute__ ((packed)); +} __packed; #define WL1271_SCAN_MAX_CHANNELS 24 @@ -385,7 +385,7 @@ struct basic_scan_params { u8 use_ssid_list; u8 scan_tag; u8 padding2; -} __attribute__ ((packed)); +} __packed; struct basic_scan_channel_params { /* Duration in TU to wait for frames on a channel for active scan */ @@ -400,25 +400,25 @@ struct basic_scan_channel_params { u8 dfs_candidate; u8 activity_detected; u8 pad; -} __attribute__ ((packed)); +} __packed; struct wl1271_cmd_scan { struct wl1271_cmd_header header; struct basic_scan_params params; struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; -} __attribute__ ((packed)); +} __packed; struct wl1271_cmd_trigger_scan_to { struct wl1271_cmd_header header; __le32 timeout; -} __attribute__ ((packed)); +} __packed; struct wl1271_cmd_test_header { u8 id; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; enum wl1271_channel_tune_bands { WL1271_CHANNEL_TUNE_BAND_2_4, @@ -439,25 +439,31 @@ struct wl1271_general_parms_cmd { struct wl1271_cmd_test_header test; - u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE]; - s8 reserved[23]; -} __attribute__ ((packed)); + struct wl1271_ini_general_params general_params; -#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29 -#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104 + u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; + u8 padding[3]; +} __packed; struct wl1271_radio_parms_cmd { struct wl1271_cmd_header header; struct wl1271_cmd_test_header test; - u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE]; - u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE]; + /* Static radio parameters */ + struct wl1271_ini_band_params_2 static_params_2; + struct wl1271_ini_band_params_5 static_params_5; - u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE]; - u8 reserved; - u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE]; -} __attribute__ ((packed)); + /* Dynamic radio parameters */ + struct wl1271_ini_fem_params_2 dyn_params_2; + u8 padding2; + struct wl1271_ini_fem_params_5 dyn_params_5; + u8 padding3[2]; +} __packed; struct wl1271_cmd_cal_channel_tune { struct wl1271_cmd_header header; @@ -468,7 +474,7 @@ struct wl1271_cmd_cal_channel_tune { u8 channel; __le16 radio_status; -} __attribute__ ((packed)); +} __packed; struct wl1271_cmd_cal_update_ref_point { struct wl1271_cmd_header header; @@ -479,7 +485,7 @@ struct wl1271_cmd_cal_update_ref_point { __le32 ref_detector; u8 sub_band; u8 padding[3]; -} __attribute__ ((packed)); +} __packed; #define MAX_TLV_LENGTH 400 #define MAX_NVS_VERSION_LENGTH 12 @@ -501,7 +507,7 @@ struct wl1271_cmd_cal_p2g { u8 sub_band_mask; u8 padding2; -} __attribute__ ((packed)); +} __packed; /* @@ -529,6 +535,6 @@ struct wl1271_cmd_disconnect { u8 type; u8 padding; -} __attribute__ ((packed)); +} __packed; #endif /* __WL1271_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index cf37aa6eb137..ca52cdec7a8f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -43,11 +43,11 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, clear_bit(WL1271_FLAG_SCANNING, &wl->flags); /* FIXME: ie missing! */ wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, - NULL, 0, - wl->scan.active, - wl->scan.high_prio, - WL1271_SCAN_BAND_5_GHZ, - wl->scan.probe_requests); + wl->scan.req, + wl->scan.active, + wl->scan.high_prio, + WL1271_SCAN_BAND_5_GHZ, + wl->scan.probe_requests); } else { mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 58371008f270..43d5aeae1783 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h @@ -85,7 +85,7 @@ struct event_debug_report { __le32 report_1; __le32 report_2; __le32 report_3; -} __attribute__ ((packed)); +} __packed; #define NUM_OF_RSSI_SNR_TRIGGERS 8 @@ -116,7 +116,7 @@ struct event_mailbox { u8 ps_status; u8 reserved_5[29]; -} __attribute__ ((packed)); +} __packed; int wl1271_event_unmask(struct wl1271 *wl); void wl1271_event_mbox_config(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_ini.h b/drivers/net/wireless/wl12xx/wl1271_ini.h new file mode 100644 index 000000000000..2313047d4015 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_ini.h @@ -0,0 +1,123 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Luciano Coelho <luciano.coelho@nokia.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL1271_INI_H__ +#define __WL1271_INI_H__ + +#define WL1271_INI_MAX_SMART_REFLEX_PARAM 16 + +struct wl1271_ini_general_params { + u8 ref_clock; + u8 settling_time; + u8 clk_valid_on_wakeup; + u8 dc2dc_mode; + u8 dual_mode_select; + u8 tx_bip_fem_auto_detect; + u8 tx_bip_fem_manufacturer; + u8 general_settings; + u8 sr_state; + u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; +} __packed; + +#define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15 + +struct wl1271_ini_band_params_2 { + u8 rx_trace_insertion_loss; + u8 tx_trace_loss; + u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; +} __packed; + +#define WL1271_INI_RATE_GROUP_COUNT 6 +#define WL1271_INI_CHANNEL_COUNT_2 14 + +struct wl1271_ini_fem_params_2 { + __le16 tx_bip_ref_pd_voltage; + u8 tx_bip_ref_power; + u8 tx_bip_ref_offset; + u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2]; + u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2]; + u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT]; + u8 rx_fem_insertion_loss; + u8 degraded_low_to_normal_thr; + u8 normal_to_degraded_high_thr; +} __packed; + +#define WL1271_INI_CHANNEL_COUNT_5 35 +#define WL1271_INI_SUB_BAND_COUNT_5 7 + +struct wl1271_ini_band_params_5 { + u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_trace_loss[WL1271_INI_SUB_BAND_COUNT_5]; + u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; +} __packed; + +struct wl1271_ini_fem_params_5 { + __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5]; + u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT]; + u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT]; + u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; + u8 degraded_low_to_normal_thr; + u8 normal_to_degraded_high_thr; +} __packed; + + +/* NVS data structure */ +#define WL1271_INI_NVS_SECTION_SIZE 468 +#define WL1271_INI_FEM_MODULE_COUNT 2 + +#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 + +struct wl1271_nvs_file { + /* NVS section */ + u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; + + /* INI section */ + struct wl1271_ini_general_params general_params; + u8 padding1; + struct wl1271_ini_band_params_2 stat_radio_params_2; + u8 padding2; + struct { + struct wl1271_ini_fem_params_2 params; + u8 padding; + } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; + struct wl1271_ini_band_params_5 stat_radio_params_5; + u8 padding3; + struct { + struct wl1271_ini_fem_params_5 params; + u8 padding; + } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; +} __packed; + +#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b7d9137851ac..7a14da506d78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -566,14 +566,21 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) return ret; } - if (fw->size != sizeof(struct wl1271_nvs_file)) { + /* + * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band + * configurations) can be removed when those NVS files stop floating + * around. + */ + if (fw->size != sizeof(struct wl1271_nvs_file) && + (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE || + wl1271_11a_enabled())) { wl1271_error("nvs size is not as expected: %zu != %zu", fw->size, sizeof(struct wl1271_nvs_file)); ret = -EILSEQ; goto out; } - wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); + wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -581,7 +588,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) goto out; } - memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); + memcpy(wl->nvs, fw->data, fw->size); out: release_firmware(fw); @@ -1044,7 +1051,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); /* let's notify MAC80211 about the remaining pending TX frames */ - wl1271_tx_flush(wl); + wl1271_tx_reset(wl); wl1271_power_off(wl); memset(wl->bssid, 0, ETH_ALEN); @@ -1241,6 +1248,42 @@ static u32 wl1271_min_rate_get(struct wl1271 *wl) return rate; } +static int wl1271_handle_idle(struct wl1271 *wl, bool idle) +{ + int ret; + + if (idle) { + if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { + ret = wl1271_unjoin(wl); + if (ret < 0) + goto out; + } + wl->rate_set = wl1271_min_rate_get(wl); + wl->sta_rate_set = 0; + ret = wl1271_acx_rate_policies(wl); + if (ret < 0) + goto out; + ret = wl1271_acx_keep_alive_config( + wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_INVALID); + if (ret < 0) + goto out; + set_bit(WL1271_FLAG_IDLE, &wl->flags); + } else { + /* increment the session counter */ + wl->session_counter++; + if (wl->session_counter >= SESSION_COUNTER_MAX) + wl->session_counter = 0; + ret = wl1271_dummy_join(wl); + if (ret < 0) + goto out; + clear_bit(WL1271_FLAG_IDLE, &wl->flags); + } + +out: + return ret; +} + static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; @@ -1255,6 +1298,15 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) conf->power_level, conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); + /* + * mac80211 will go to idle nearly immediately after transmitting some + * frames, such as the deauth. To make sure those frames reach the air, + * wait here until the TX queue is fully flushed. + */ + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (conf->flags & IEEE80211_CONF_IDLE)) + wl1271_tx_flush(wl); + mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) @@ -1295,22 +1347,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (conf->flags & IEEE80211_CONF_IDLE && - test_bit(WL1271_FLAG_JOINED, &wl->flags)) - wl1271_unjoin(wl); - else if (!(conf->flags & IEEE80211_CONF_IDLE)) - wl1271_dummy_join(wl); - - if (conf->flags & IEEE80211_CONF_IDLE) { - wl->rate_set = wl1271_min_rate_get(wl); - wl->sta_rate_set = 0; - wl1271_acx_rate_policies(wl); - wl1271_acx_keep_alive_config( - wl, CMD_TEMPL_KLV_IDX_NULL_DATA, - ACX_KEEP_ALIVE_TPL_INVALID); - set_bit(WL1271_FLAG_IDLE, &wl->flags); - } else - clear_bit(WL1271_FLAG_IDLE, &wl->flags); + ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE); + if (ret < 0) + wl1271_warning("idle mode change failed %d", ret); } if (conf->flags & IEEE80211_CONF_PS && @@ -1595,13 +1634,11 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, goto out; if (wl1271_11a_enabled()) - ret = wl1271_cmd_scan(hw->priv, ssid, len, - req->ie, req->ie_len, 1, 0, - WL1271_SCAN_BAND_DUAL, 3); + ret = wl1271_cmd_scan(hw->priv, ssid, len, req, + 1, 0, WL1271_SCAN_BAND_DUAL, 3); else - ret = wl1271_cmd_scan(hw->priv, ssid, len, - req->ie, req->ie_len, 1, 0, - WL1271_SCAN_BAND_2_4_GHZ, 3); + ret = wl1271_cmd_scan(hw->priv, ssid, len, req, + 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); wl1271_ps_elp_sleep(wl); @@ -1991,7 +2028,7 @@ static struct ieee80211_channel wl1271_channels[] = { }; /* mapping to indexes for wl1271_rates */ -const static u8 wl1271_rate_to_idx_2ghz[] = { +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 */ @@ -2103,7 +2140,7 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { }; /* mapping to indexes for wl1271_rates_5ghz */ -const static u8 wl1271_rate_to_idx_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 */ @@ -2139,7 +2176,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), }; -const static u8 *wl1271_band_rate_to_idx[] = { +static const u8 *wl1271_band_rate_to_idx[] = { [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz }; diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index b89be4758e78..13a232333b13 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h @@ -113,7 +113,7 @@ struct wl1271_rx_descriptor { u8 process_id; u8 pad_len; u8 reserved; -} __attribute__ ((packed)); +} __packed; void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index d3d6f302f705..7059b5cccf0f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -28,7 +28,7 @@ #include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_ids.h> #include <linux/mmc/card.h> -#include <plat/gpio.h> +#include <linux/gpio.h> #include "wl1271.h" #include "wl12xx_80211.h" diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 554deb4d024e..6e0952f79e9a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c @@ -199,7 +199,14 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) buf = nla_data(tb[WL1271_TM_ATTR_DATA]); len = nla_len(tb[WL1271_TM_ATTR_DATA]); - if (len != sizeof(struct wl1271_nvs_file)) { + /* + * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band + * configurations) can be removed when those NVS files stop floating + * around. + */ + if (len != sizeof(struct wl1271_nvs_file) && + (len != WL1271_INI_LEGACY_NVS_FILE_SIZE || + wl1271_11a_enabled())) { wl1271_error("nvs size is not as expected: %zu != %zu", len, sizeof(struct wl1271_nvs_file)); return -EMSGSIZE; @@ -209,7 +216,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) kfree(wl->nvs); - wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); + wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); ret = -ENOMEM; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 62db79508ddf..c592cc2e9fe8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -36,6 +36,7 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) 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; } @@ -73,8 +74,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) wl1271_debug(DEBUG_TX, "tx_allocate: size: %d, blocks: %d, id: %d", total_len, total_blocks, id); - } else + } else { wl->tx_frames[id] = NULL; + wl->tx_frames_cnt--; + } return ret; } @@ -358,6 +361,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--; } /* Called upon reception of a TX complete interrupt */ @@ -412,7 +416,7 @@ void wl1271_tx_complete(struct wl1271 *wl) } /* caller must hold wl->mutex */ -void wl1271_tx_flush(struct wl1271 *wl) +void wl1271_tx_reset(struct wl1271 *wl) { int i; struct sk_buff *skb; @@ -421,7 +425,7 @@ void wl1271_tx_flush(struct wl1271 *wl) /* control->flags = 0; FIXME */ while ((skb = skb_dequeue(&wl->tx_queue))) { - wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); + wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); ieee80211_tx_status(wl->hw, skb); } @@ -429,6 +433,32 @@ void wl1271_tx_flush(struct wl1271 *wl) if (wl->tx_frames[i] != NULL) { skb = wl->tx_frames[i]; wl->tx_frames[i] = NULL; + 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 + +/* caller must *NOT* hold wl->mutex */ +void wl1271_tx_flush(struct wl1271 *wl) +{ + unsigned long timeout; + timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); + + while (!time_after(jiffies, timeout)) { + mutex_lock(&wl->mutex); + wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", + wl->tx_frames_cnt); + if ((wl->tx_frames_cnt == 0) && + skb_queue_empty(&wl->tx_queue)) { + mutex_unlock(&wl->mutex); + return; + } + mutex_unlock(&wl->mutex); + msleep(1); + } + + wl1271_warning("Unable to flush all TX buffers, timed out."); } diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 3b8b7ac253fd..48bf92621c03 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -80,7 +80,7 @@ struct wl1271_tx_hw_descr { /* Identifier of the remote STA in IBSS, 1 in infra-BSS */ u8 aid; u8 reserved; -} __attribute__ ((packed)); +} __packed; enum wl1271_tx_hw_res_status { TX_SUCCESS = 0, @@ -115,13 +115,13 @@ struct wl1271_tx_hw_res_descr { u8 rate_class_index; /* for 4-byte alignment. */ u8 spare; -} __attribute__ ((packed)); +} __packed; struct wl1271_tx_hw_res_if { __le32 tx_result_fw_counter; __le32 tx_result_host_counter; struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; -} __attribute__ ((packed)); +} __packed; static inline int wl1271_tx_get_queue(int queue) { @@ -158,6 +158,7 @@ static inline int wl1271_tx_ac_to_tid(int ac) void wl1271_tx_work(struct work_struct *work); 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); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index 055d7bc6f592..184628027213 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -66,41 +66,41 @@ struct ieee80211_header { u8 bssid[ETH_ALEN]; __le16 seq_ctl; u8 payload[0]; -} __attribute__ ((packed)); +} __packed; struct wl12xx_ie_header { u8 id; u8 len; -} __attribute__ ((packed)); +} __packed; /* IEs */ struct wl12xx_ie_ssid { struct wl12xx_ie_header header; char ssid[IW_ESSID_MAX_SIZE]; -} __attribute__ ((packed)); +} __packed; struct wl12xx_ie_rates { struct wl12xx_ie_header header; u8 rates[MAX_SUPPORTED_RATES]; -} __attribute__ ((packed)); +} __packed; struct wl12xx_ie_ds_params { struct wl12xx_ie_header header; u8 channel; -} __attribute__ ((packed)); +} __packed; struct country_triplet { u8 channel; u8 num_channels; u8 max_tx_power; -} __attribute__ ((packed)); +} __packed; struct wl12xx_ie_country { struct wl12xx_ie_header header; u8 country_string[COUNTRY_STRING_LEN]; struct country_triplet triplets[MAX_COUNTRY_TRIPLETS]; -} __attribute__ ((packed)); +} __packed; /* Templates */ @@ -115,30 +115,30 @@ struct wl12xx_beacon_template { struct wl12xx_ie_rates ext_rates; struct wl12xx_ie_ds_params ds_params; struct wl12xx_ie_country country; -} __attribute__ ((packed)); +} __packed; struct wl12xx_null_data_template { struct ieee80211_header header; -} __attribute__ ((packed)); +} __packed; struct wl12xx_ps_poll_template { __le16 fc; __le16 aid; u8 bssid[ETH_ALEN]; u8 ta[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct wl12xx_qos_null_data_template { struct ieee80211_header header; __le16 qos_ctl; -} __attribute__ ((packed)); +} __packed; struct wl12xx_probe_req_template { struct ieee80211_header header; struct wl12xx_ie_ssid ssid; struct wl12xx_ie_rates rates; struct wl12xx_ie_rates ext_rates; -} __attribute__ ((packed)); +} __packed; struct wl12xx_probe_resp_template { @@ -151,6 +151,6 @@ struct wl12xx_probe_resp_template { struct wl12xx_ie_rates ext_rates; struct wl12xx_ie_ds_params ds_params; struct wl12xx_ie_country country; -} __attribute__ ((packed)); +} __packed; #endif diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index 8816e371fd0e..3fbfd19818f1 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -231,12 +231,12 @@ struct iw_mgmt_info_element { but sizeof(enum) > sizeof(u8) :-( */ u8 len; u8 data[0]; -} __attribute__ ((packed)); +} __packed; struct iw_mgmt_essid_pset { struct iw_mgmt_info_element el; u8 essid[IW_ESSID_MAX_SIZE]; -} __attribute__ ((packed)); +} __packed; /* * According to 802.11 Wireless Netowors, the definitive guide - O'Reilly @@ -247,12 +247,12 @@ struct iw_mgmt_essid_pset { struct iw_mgmt_data_rset { struct iw_mgmt_info_element el; u8 data_rate_labels[IW_DATA_RATE_MAX_LABELS]; -} __attribute__ ((packed)); +} __packed; struct iw_mgmt_ds_pset { struct iw_mgmt_info_element el; u8 chan; -} __attribute__ ((packed)); +} __packed; struct iw_mgmt_cf_pset { struct iw_mgmt_info_element el; @@ -260,12 +260,12 @@ struct iw_mgmt_cf_pset { u8 cfp_period; u16 cfp_max_duration; u16 cfp_dur_remaining; -} __attribute__ ((packed)); +} __packed; struct iw_mgmt_ibss_pset { struct iw_mgmt_info_element el; u16 atim_window; -} __attribute__ ((packed)); +} __packed; struct wl3501_tx_hdr { u16 tx_cnt; @@ -544,12 +544,12 @@ struct wl3501_80211_tx_plcp_hdr { u8 service; u16 len; u16 crc16; -} __attribute__ ((packed)); +} __packed; struct wl3501_80211_tx_hdr { struct wl3501_80211_tx_plcp_hdr pclp_hdr; struct ieee80211_hdr mac_hdr; -} __attribute__ ((packed)); +} __packed; /* Reserve the beginning Tx space for descriptor use. diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index b0b666019a93..43307bd42a69 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -42,7 +42,8 @@ static struct zd_reg_alpha2_map reg_alpha2_map[] = { { ZD_REGDOMAIN_IC, "CA" }, { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ { ZD_REGDOMAIN_JAPAN, "JP" }, - { ZD_REGDOMAIN_JAPAN_ADD, "JP" }, + { ZD_REGDOMAIN_JAPAN_2, "JP" }, + { ZD_REGDOMAIN_JAPAN_3, "JP" }, { ZD_REGDOMAIN_SPAIN, "ES" }, { ZD_REGDOMAIN_FRANCE, "FR" }, }; @@ -855,7 +856,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) if (skb == NULL) return -ENOMEM; if (need_padding) { - /* Make sure the the payload data is 4 byte aligned. */ + /* Make sure the payload data is 4 byte aligned. */ skb_reserve(skb, 2); } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 630c298a730e..a6d86b996c79 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -35,7 +35,7 @@ struct zd_ctrlset { __le16 current_length; u8 service; __le16 next_frame_length; -} __attribute__((packed)); +} __packed; #define ZD_CS_RESERVED_SIZE 25 @@ -106,7 +106,7 @@ struct zd_ctrlset { struct rx_length_info { __le16 length[3]; __le16 tag; -} __attribute__((packed)); +} __packed; #define RX_LENGTH_INFO_TAG 0x697e @@ -117,7 +117,7 @@ struct rx_status { u8 signal_quality_ofdm; u8 decryption_type; u8 frame_status; -} __attribute__((packed)); +} __packed; /* rx_status field decryption_type */ #define ZD_RX_NO_WEP 0 @@ -153,7 +153,7 @@ struct tx_status { u8 mac[ETH_ALEN]; u8 retry; u8 failure; -} __attribute__((packed)); +} __packed; enum mac_flags { MAC_FIXED_CHANNEL = 0x01, @@ -212,8 +212,9 @@ struct zd_mac { #define ZD_REGDOMAIN_ETSI 0x30 #define ZD_REGDOMAIN_SPAIN 0x31 #define ZD_REGDOMAIN_FRANCE 0x32 -#define ZD_REGDOMAIN_JAPAN_ADD 0x40 +#define ZD_REGDOMAIN_JAPAN_2 0x40 #define ZD_REGDOMAIN_JAPAN 0x41 +#define ZD_REGDOMAIN_JAPAN_3 0x49 enum { MIN_CHANNEL24 = 1, @@ -225,7 +226,7 @@ enum { struct ofdm_plcp_header { u8 prefix[3]; __le16 service; -} __attribute__((packed)); +} __packed; static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header) { @@ -252,7 +253,7 @@ struct cck_plcp_header { u8 service; __le16 length; __le16 crc16; -} __attribute__((packed)); +} __packed; static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header) { diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index c257940b71b6..818e1480ca93 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -844,7 +844,7 @@ out: * @usb: a &struct zd_usb pointer * @urb: URB to be freed * - * Frees the the transmission URB, which means to put it on the free URB + * Frees the transmission URB, which means to put it on the free URB * list. */ static void free_tx_urb(struct zd_usb *usb, struct urb *urb) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index 049f8b91f020..1b1655cb7cb4 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -79,17 +79,17 @@ enum control_requests { struct usb_req_read_regs { __le16 id; __le16 addr[0]; -} __attribute__((packed)); +} __packed; struct reg_data { __le16 addr; __le16 value; -} __attribute__((packed)); +} __packed; struct usb_req_write_regs { __le16 id; struct reg_data reg_writes[0]; -} __attribute__((packed)); +} __packed; enum { RF_IF_LE = 0x02, @@ -106,7 +106,7 @@ struct usb_req_rfwrite { /* RF2595: 24 */ __le16 bit_values[0]; /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ -} __attribute__((packed)); +} __packed; /* USB interrupt */ @@ -123,12 +123,12 @@ enum usb_int_flags { struct usb_int_header { u8 type; /* must always be 1 */ u8 id; -} __attribute__((packed)); +} __packed; struct usb_int_regs { struct usb_int_header hdr; struct reg_data regs[0]; -} __attribute__((packed)); +} __packed; struct usb_int_retry_fail { struct usb_int_header hdr; @@ -136,7 +136,7 @@ struct usb_int_retry_fail { u8 _dummy; u8 addr[ETH_ALEN]; u8 ibss_wakeup_dest; -} __attribute__((packed)); +} __packed; struct read_regs_int { struct completion completion; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index d504e2b60257..b50fedcef8ac 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1621,6 +1621,7 @@ static void backend_changed(struct xenbus_device *dev, if (xennet_connect(netdev) != 0) break; xenbus_switch_state(dev, XenbusStateConnected); + netif_notify_peers(netdev); break; case XenbusStateClosing: |