diff options
author | Arve Hjønnevåg <arve@android.com> | 2010-03-10 16:38:33 -0800 |
---|---|---|
committer | Arve Hjønnevåg <arve@android.com> | 2010-03-10 16:38:33 -0800 |
commit | 67078ecae3edb5b4657dcb9f67f744ecccd18a97 (patch) | |
tree | 90333318a7229fd977881577e0d19fd8e7e26423 /drivers/net | |
parent | dc136618cb23810dd3d4adfcb836b289cd528b4f (diff) | |
parent | 7f5e918e62cbc9ac27c2f47d3c3dd4b86f67ff0e (diff) |
Merge commit 'v2.6.32.9' into android-2.6.32
Diffstat (limited to 'drivers/net')
55 files changed, 389 insertions, 244 deletions
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index 2a1120ad2e74..790e55bf3fa2 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -534,6 +534,9 @@ struct atl1c_adapter { #define __AT_TESTING 0x0001 #define __AT_RESETTING 0x0002 #define __AT_DOWN 0x0003 + u8 work_event; +#define ATL1C_WORK_EVENT_RESET 0x01 +#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02 u32 msg_enable; bool have_msi; @@ -545,8 +548,7 @@ struct atl1c_adapter { spinlock_t tx_lock; atomic_t irq_sem; - struct work_struct reset_task; - struct work_struct link_chg_task; + struct work_struct common_task; struct timer_list watchdog_timer; struct timer_list phy_config_timer; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 1372e9a99f5b..be00ee973546 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -198,27 +198,12 @@ static void atl1c_phy_config(unsigned long data) void atl1c_reinit_locked(struct atl1c_adapter *adapter) { - WARN_ON(in_interrupt()); atl1c_down(adapter); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); } -static void atl1c_reset_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - struct net_device *netdev; - - adapter = container_of(work, struct atl1c_adapter, reset_task); - netdev = adapter->netdev; - - netif_device_detach(netdev); - atl1c_down(adapter); - atl1c_up(adapter); - netif_device_attach(netdev); -} - static void atl1c_check_link_status(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; @@ -275,18 +260,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) } } -/* - * atl1c_link_chg_task - deal with link change event Out of interrupt context - * @netdev: network interface device structure - */ -static void atl1c_link_chg_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - - adapter = container_of(work, struct atl1c_adapter, link_chg_task); - atl1c_check_link_status(adapter); -} - static void atl1c_link_chg_event(struct atl1c_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -311,20 +284,40 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter) adapter->link_speed = SPEED_0; } } - schedule_work(&adapter->link_chg_task); + + adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE; + schedule_work(&adapter->common_task); } -static void atl1c_del_timer(struct atl1c_adapter *adapter) +static void atl1c_common_task(struct work_struct *work) { - del_timer_sync(&adapter->phy_config_timer); + struct atl1c_adapter *adapter; + struct net_device *netdev; + + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + + if (adapter->work_event & ATL1C_WORK_EVENT_RESET) { + netif_device_detach(netdev); + atl1c_down(adapter); + atl1c_up(adapter); + netif_device_attach(netdev); + return; + } + + if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) + atl1c_check_link_status(adapter); + + return; } -static void atl1c_cancel_work(struct atl1c_adapter *adapter) + +static void atl1c_del_timer(struct atl1c_adapter *adapter) { - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->link_chg_task); + del_timer_sync(&adapter->phy_config_timer); } + /* * atl1c_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure @@ -334,7 +327,8 @@ static void atl1c_tx_timeout(struct net_device *netdev) struct atl1c_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); } /* @@ -1536,7 +1530,8 @@ static irqreturn_t atl1c_intr(int irq, void *data) /* reset MAC */ hw->intr_mask &= ~ISR_ERROR; AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); break; } @@ -2200,8 +2195,7 @@ void atl1c_down(struct atl1c_adapter *adapter) struct net_device *netdev = adapter->netdev; atl1c_del_timer(adapter); - atl1c_cancel_work(adapter); - + adapter->work_event = 0; /* clear all event */ /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__AT_DOWN, &adapter->flags); @@ -2601,8 +2595,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); atl1c_hw_set_mac_addr(&adapter->hw); - INIT_WORK(&adapter->reset_task, atl1c_reset_task); - INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); + INIT_WORK(&adapter->common_task, atl1c_common_task); + adapter->work_event = 0; err = register_netdev(netdev); if (err) { dev_err(&pdev->dev, "register netdevice failed\n"); diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 955da733c2ad..1b5facfcdc08 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1666,41 +1666,6 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, } return 0; } - - if (offload_type & SKB_GSO_TCPV6) { - real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data) - + ntohs(ipv6_hdr(skb)->payload_len)); - if (real_len < skb->len) - pskb_trim(skb, real_len); - - /* check payload == 0 byte ? */ - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - dev_warn(&pdev->dev, - "IPV6 tso with zero data??\n"); - goto check_sum; - } else { - tcp_hdr(skb)->check = ~csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT; - hdr_len >>= 1; - tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) << - TPD_V6_IPHLLO_SHIFT; - tpd->word3 |= ((hdr_len >> 3) & - TPD_V6_IPHLHI_MASK) << - TPD_V6_IPHLHI_SHIFT; - tpd->word3 |= (tcp_hdrlen(skb) >> 2 & - TPD_TCPHDRLEN_MASK) << - TPD_TCPHDRLEN_SHIFT; - tpd->word3 |= ((skb_shinfo(skb)->gso_size) & - TPD_MSS_MASK) << TPD_MSS_SHIFT; - tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT; - } - } - return 0; } check_sum: @@ -2289,7 +2254,6 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->features |= NETIF_F_LLTX; netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; return 0; } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2a9132343b66..4869adb69586 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1505,8 +1505,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) for (k = 0; k< ethaddr_bytes; k++) { ppattern[offset + magicsync + (j * ETH_ALEN) + k] = macaddr[k]; - len++; - set_bit(len, (unsigned long *) pmask); + set_bit(len++, (unsigned long *) pmask); } } return len - 1; diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index ba29dc319b34..d110c1b978a5 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -1248,9 +1248,15 @@ static void bcm_enet_get_drvinfo(struct net_device *netdev, drvinfo->n_stats = BCM_ENET_STATS_LEN; } -static int bcm_enet_get_stats_count(struct net_device *netdev) +static int bcm_enet_get_sset_count(struct net_device *netdev, + int string_set) { - return BCM_ENET_STATS_LEN; + switch (string_set) { + case ETH_SS_STATS: + return BCM_ENET_STATS_LEN; + default: + return -EINVAL; + } } static void bcm_enet_get_strings(struct net_device *netdev, @@ -1476,7 +1482,7 @@ static int bcm_enet_set_pauseparam(struct net_device *dev, static struct ethtool_ops bcm_enet_ethtool_ops = { .get_strings = bcm_enet_get_strings, - .get_stats_count = bcm_enet_get_stats_count, + .get_sset_count = bcm_enet_get_sset_count, .get_ethtool_stats = bcm_enet_get_ethtool_stats, .get_settings = bcm_enet_get_settings, .set_settings = bcm_enet_set_settings, diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 3b79a225628a..511b92237ad0 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -35,20 +35,31 @@ #define DRV_VER "2.101.205" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" +#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" #define OC_NAME "Emulex OneConnect 10Gbps NIC" +#define OC_NAME1 "Emulex OneConnect 10Gbps NIC (be3)" #define DRV_DESC BE_NAME "Driver" #define BE_VENDOR_ID 0x19a2 #define BE_DEVICE_ID1 0x211 +#define BE_DEVICE_ID2 0x221 #define OC_DEVICE_ID1 0x700 #define OC_DEVICE_ID2 0x701 +#define OC_DEVICE_ID3 0x710 static inline char *nic_name(struct pci_dev *pdev) { - if (pdev->device == OC_DEVICE_ID1 || pdev->device == OC_DEVICE_ID2) + switch (pdev->device) { + case OC_DEVICE_ID1: + case OC_DEVICE_ID2: return OC_NAME; - else + case OC_DEVICE_ID3: + return OC_NAME1; + case BE_DEVICE_ID2: + return BE3_NAME; + default: return BE_NAME; + } } /* Number of bytes of an RX frame that are copied to skb->data */ @@ -261,8 +272,13 @@ struct be_adapter { u32 cap; u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ + u8 generation; /* BladeEngine ASIC generation */ }; +/* BladeEngine Generation numbers */ +#define BE_GEN2 2 +#define BE_GEN3 3 + extern const struct ethtool_ops be_ethtool_ops; #define drvr_stats(adapter) (&adapter->stats.drvr_stats) diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index e5f9676cf1bc..ad33d5508f54 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -154,7 +154,8 @@ struct be_cmd_req_hdr { u8 domain; /* dword 0 */ u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ - u32 rsvd; /* dword 3 */ + u8 version; /* dword 3 */ + u8 rsvd[3]; /* dword 3 */ }; #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 876b357101fa..ec983cb67d1f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -31,8 +31,10 @@ MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, + { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -1942,6 +1944,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; + int pcicfg_reg; addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), pci_resource_len(adapter->pdev, 2)); @@ -1955,8 +1958,13 @@ static int be_map_pci_bars(struct be_adapter *adapter) goto pci_map_err; adapter->db = addr; - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), - pci_resource_len(adapter->pdev, 1)); + if (adapter->generation == BE_GEN2) + pcicfg_reg = 1; + else + pcicfg_reg = 0; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg), + pci_resource_len(adapter->pdev, pcicfg_reg)); if (addr == NULL) goto pci_map_err; adapter->pcicfg = addr; @@ -2026,6 +2034,7 @@ static int be_stats_init(struct be_adapter *adapter) cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); if (cmd->va == NULL) return -1; + memset(cmd->va, 0, cmd->size); return 0; } @@ -2099,6 +2108,20 @@ static int __devinit be_probe(struct pci_dev *pdev, goto rel_reg; } adapter = netdev_priv(netdev); + + switch (pdev->device) { + case BE_DEVICE_ID1: + case OC_DEVICE_ID1: + adapter->generation = BE_GEN2; + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: + adapter->generation = BE_GEN3; + break; + default: + adapter->generation = 0; + } + adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index d269a68ce354..0c53c9295ff6 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1817,6 +1817,7 @@ static int e100_alloc_cbs(struct nic *nic) &nic->cbs_dma_addr); if (!nic->cbs) return -ENOMEM; + memset(nic->cbs, 0, count * sizeof(struct cb)); for (cb = nic->cbs, i = 0; i < count; cb++, i++) { cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; @@ -1825,7 +1826,6 @@ static int e100_alloc_cbs(struct nic *nic) cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); cb->link = cpu_to_le32(nic->cbs_dma_addr + ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; } nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 42e2b7e21c29..4a2ee85d49a4 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -326,6 +326,8 @@ struct e1000_adapter { /* for ioport free */ int bars; int need_ioport; + + bool discarding; }; enum e1000_state_t { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index bcd192ca47b0..1a23f168bebd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case E1000_RXBUFFER_2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -3154,13 +3142,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * however with the new *_jumbo_rx* routines, jumbo receives will use * fragmented skbs */ - if (max_frame <= E1000_RXBUFFER_256) - adapter->rx_buffer_len = E1000_RXBUFFER_256; - else if (max_frame <= E1000_RXBUFFER_512) - adapter->rx_buffer_len = E1000_RXBUFFER_512; - else if (max_frame <= E1000_RXBUFFER_1024) - adapter->rx_buffer_len = E1000_RXBUFFER_1024; - else if (max_frame <= E1000_RXBUFFER_2048) + if (max_frame <= E1000_RXBUFFER_2048) adapter->rx_buffer_len = E1000_RXBUFFER_2048; else #if (PAGE_SIZE >= E1000_RXBUFFER_16384) @@ -3827,13 +3809,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) { + * packet, if thats the case we need to toss it. In fact, we + * to toss every packet with the EOP bit clear and the next + * frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->discarding = true; + + if (adapter->discarding) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" " buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->discarding = false; goto next_desc; } diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 3e187b0e4203..47db9bd47199 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -417,6 +417,7 @@ struct e1000_info { /* CRC Stripping defines */ #define FLAG2_CRC_STRIPPING (1 << 0) #define FLAG2_HAS_PHY_WAKEUP (1 << 1) +#define FLAG2_IS_DISCARDING (1 << 2) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index fad8f9ea0043..21545306bc1d 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -482,14 +482,24 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { + /* + * !EOP means multiple descriptors were used to store a single + * packet, if that's the case we need to toss it. In fact, we + * need to toss every packet with the EOP bit clear and the + * next frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { /* All receives must fit into a single buffer */ e_dbg("%s: Receive packet consumed multiple buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -747,10 +757,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, PCI_DMA_FROMDEVICE); buffer_info->dma = 0; - if (!(staterr & E1000_RXD_STAT_EOP)) { + /* see !EOP comment in other rx routine */ + if (!(staterr & E1000_RXD_STAT_EOP)) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { e_dbg("%s: Packet Split buffers didn't pick up the " "full packet\n", netdev->name); dev_kfree_skb_irq(skb); + if (staterr & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -1120,6 +1136,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; + adapter->flags2 &= ~FLAG2_IS_DISCARDING; writel(0, adapter->hw.hw_addr + rx_ring->head); writel(0, adapter->hw.hw_addr + rx_ring->tail); @@ -2330,18 +2347,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case 256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case 512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case 1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case 2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -4321,13 +4326,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * fragmented skbs */ - if (max_frame <= 256) - adapter->rx_buffer_len = 256; - else if (max_frame <= 512) - adapter->rx_buffer_len = 512; - else if (max_frame <= 1024) - adapter->rx_buffer_len = 1024; - else if (max_frame <= 2048) + if (max_frame <= 2048) adapter->rx_buffer_len = 2048; else adapter->rx_buffer_len = 4096; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index a2fc70a0d0cc..35d896b049fa 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3310,10 +3310,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Initialize the port and set the max framesize. */ status = qdev->nic_ops->port_initialize(qdev); - if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); - return status; - } + if (status) + QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); /* Set up the MAC address and frame routing filter. */ status = ql_cam_route_initialize(qdev); @@ -3714,9 +3712,6 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) struct sockaddr *addr = p; int status; - if (netif_running(ndev)) - return -EBUSY; - if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); @@ -3868,8 +3863,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, struct net_device *ndev, int cards_found) { struct ql_adapter *qdev = netdev_priv(ndev); - int pos, err = 0; - u16 val16; + int err = 0; memset((void *)qdev, 0, sizeof(*qdev)); err = pci_enable_device(pdev); @@ -3881,18 +3875,12 @@ static int __devinit ql_init_device(struct pci_dev *pdev, qdev->ndev = ndev; qdev->pdev = pdev; pci_set_drvdata(pdev, ndev); - pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (pos <= 0) { - dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, " - "aborting.\n"); - return pos; - } else { - pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16); - val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; - val16 |= (PCI_EXP_DEVCTL_CERE | - PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); - pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16); + + /* Set PCIe read request size */ + err = pcie_set_readrq(pdev, 4096); + if (err) { + dev_err(&pdev->dev, "Set readrq failed.\n"); + goto err_out; } err = pci_request_regions(pdev, DRV_NAME); diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index aec05f266107..32b1e1f41497 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -446,6 +446,9 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) ql_aen_lost(qdev, mbcp); break; + case AEN_DCBX_CHG: + /* Need to support AEN 8110 */ + break; default: QPRINTK(qdev, DRV, ERR, "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 489c4de31447..d443ad7d8064 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -821,8 +821,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) tx_queue->efx->type->txd_ring_mask]; efx_tsoh_free(tx_queue, buffer); EFX_BUG_ON_PARANOID(buffer->skb); - buffer->len = 0; - buffer->continuation = true; if (buffer->unmap_len) { unmap_addr = (buffer->dma_addr + buffer->len - buffer->unmap_len); @@ -836,6 +834,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) PCI_DMA_TODEVICE); buffer->unmap_len = 0; } + buffer->len = 0; + buffer->continuation = true; } } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6a10d7ba5877..f3600b3eb8c5 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1806,7 +1806,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) sky2->tx_cons = idx; smp_mb(); - if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) + /* Wake unless it's detached, and called e.g. from sky2_down() */ + if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev)) netif_wake_queue(dev); } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index a36e2b51e88c..e65ee4dcd518 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1063,7 +1063,7 @@ static int netdev_open(struct net_device *dev) if (retval) { printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", FIRMWARE_RX); - return retval; + goto out_init; } if (fw_rx->size % 4) { printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", @@ -1108,6 +1108,9 @@ out_tx: release_firmware(fw_tx); out_rx: release_firmware(fw_rx); +out_init: + if (retval) + netdev_close(dev); return retval; } diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index b091e20ca167..f14d225404da 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -324,7 +324,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p) dbg("%02X:", netdev->dev_addr[i]); dbg("%02X\n", netdev->dev_addr[i]); /* Set the IDR registers. */ - set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr); + set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr); #ifdef EEPROM_WRITE { u8 cr; diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..f141a4f711a1 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -68,8 +68,10 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x1002) }, /* Cace Airpcap NX */ { USB_DEVICE(0xcace, 0x0300) }, - /* D-Link DWA 160A */ + /* D-Link DWA 160 A1 */ { USB_DEVICE(0x07d1, 0x3c10) }, + /* D-Link DWA 160 A2 */ + { USB_DEVICE(0x07d1, 0x3a09) }, /* Netgear WNDA3100 */ { USB_DEVICE(0x0846, 0x9010) }, /* Netgear WN111 v2 */ diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e232b58f..8a82c757ea63 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2349,6 +2349,9 @@ ath5k_init(struct ath5k_softc *sc) */ ath5k_stop_locked(sc); + /* Set PHY calibration interval */ + ah->ah_cal_intval = ath5k_calinterval; + /* * The basic interface to setting the hardware in a good * state is ``reset''. On return the hardware is known to @@ -2376,10 +2379,6 @@ ath5k_init(struct ath5k_softc *sc) /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); - - /* Set PHY calibration inteval */ - ah->ah_cal_intval = ath5k_calinterval; - ret = 0; done: mmiowb(); diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 644962adda97..9a96550006ad 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -97,6 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int ret; u16 val; + u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; /* * Read values from EEPROM and store them in the capability structure @@ -111,20 +112,44 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) return 0; -#ifdef notyet /* * Validate the checksum of the EEPROM date. There are some * devices with invalid EEPROMs. */ - for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); + if (val) { + eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << + AR5K_EEPROM_SIZE_ENDLOC_SHIFT; + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); + eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; + + /* + * Fail safe check to prevent stupid loops due + * to busted EEPROMs. XXX: This value is likely too + * big still, waiting on a better value. + */ + if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { + ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " + "%d (0x%04x) max expected: %d (0x%04x)\n", + eep_max, eep_max, + 3 * AR5K_EEPROM_INFO_MAX, + 3 * AR5K_EEPROM_INFO_MAX); + return -EIO; + } + } + + for (cksum = 0, offset = 0; offset < eep_max; offset++) { AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); cksum ^= val; } if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); + ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " + "checksum: 0x%04x eep_max: 0x%04x (%s)\n", + cksum, eep_max, + eep_max == AR5K_EEPROM_INFO_MAX ? + "default size" : "custom size"); return -EIO; } -#endif AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), ee_ant_gain); diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 0123f3521a0b..473a483bb9c3 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -37,6 +37,14 @@ #define AR5K_EEPROM_RFKILL_POLARITY_S 1 #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ + +/* FLASH(EEPROM) Defines for AR531X chips */ +#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ +#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ +#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 +#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 +#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 + #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd732..9d676474839d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2954,8 +2954,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); return -EINVAL; } - if (txpower == 0) - txpower = AR5K_TUNE_DEFAULT_TXPOWER; /* Reset TX power values */ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1d59f10f68da..cdb90c5bf39b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -139,6 +139,7 @@ struct ath_buf { 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; u16 bf_flags; struct ath_buf_state bf_state; dma_addr_t bf_dmacontext; @@ -524,6 +525,8 @@ struct ath_led { #define SC_OP_BEACON_SYNC BIT(19) #define SC_OP_BTCOEX_ENABLED BIT(20) #define SC_OP_BT_PRIORITY_DETECTED BIT(21) +#define SC_OP_NULLFUNC_COMPLETED BIT(22) +#define SC_OP_PS_ENABLED BIT(23) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca7694caf364..0905b38f7b62 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -880,12 +880,11 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) } } -static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah) +static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) { u32 i, j; - if ((ah->hw_version.devid == AR9280_DEVID_PCI) && - test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { + if (ah->hw_version.devid == AR9280_DEVID_PCI) { /* EEPROM Fixup */ for (i = 0; i < ah->iniModes.ia_rows; i++) { @@ -937,6 +936,11 @@ int ath9k_hw_init(struct ath_hw *ah) DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", ah->config.serialize_regmode); + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; + else + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; + if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Mac Chip Rev 0x%02x.%x is not supported by " @@ -975,7 +979,7 @@ int ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_gain_regs(ah); ath9k_hw_fill_cap_info(ah); - ath9k_hw_init_11a_eeprom_fix(ah); + ath9k_hw_init_eeprom_fix(ah); r = ath9k_hw_init_macaddr(ah); if (r) { @@ -3670,7 +3674,11 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->keycache_size = AR_KEYTABLE_SIZE; pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; + else + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; if (AR_SREV_9285_10_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b89234571829..ff4383bb3ac3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -218,6 +218,7 @@ struct ath9k_ops_config { #define AR_SPUR_FEEQ_BOUND_HT20 10 int spurmode; u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; + u8 max_txtrig_level; }; enum ath9k_int { @@ -407,7 +408,7 @@ struct ath9k_hw_version { * Using de Bruijin sequence to to look up 1's index in a 32 bit number * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 */ -#define debruijn32 0x077CB531UL +#define debruijn32 0x077CB531U struct ath_gen_timer_configuration { u32 next_addr; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 800bfab94635..110c16dd465c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -70,7 +70,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) u32 txcfg, curLevel, newLevel; enum ath9k_int omask; - if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) + if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); @@ -79,7 +79,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) curLevel = MS(txcfg, AR_FTRIG); newLevel = curLevel; if (bIncTrigLevel) { - if (curLevel < MAX_TX_FIFO_THRESHOLD) + if (curLevel < ah->config.max_txtrig_level) newLevel++; } else if (curLevel > MIN_TX_FIFO_THRESHOLD) newLevel--; @@ -155,7 +155,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Failed to stop TX DMA in 100 " "msec after killing last frame\n"); break; @@ -222,6 +222,8 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) ds->ds_txstat.ts_status = 0; ds->ds_txstat.ts_flags = 0; + if (ads->ds_txstatus1 & AR_FrmXmitOK) + ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; if (ads->ds_txstatus1 & AR_ExcessiveRetries) ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; if (ads->ds_txstatus1 & AR_Filtered) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index f56e77da6c3e..9720c4dc9599 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -76,6 +76,10 @@ #define ATH9K_TXERR_FIFO 0x04 #define ATH9K_TXERR_XTXOP 0x08 #define ATH9K_TXERR_TIMER_EXPIRED 0x10 +#define ATH9K_TX_ACKED 0x20 +#define ATH9K_TXERR_MASK \ + (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ + ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) #define ATH9K_TX_BA 0x01 #define ATH9K_TX_PWRMGMT 0x02 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 43d2be9867fc..5864eaa53cfc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2147,6 +2147,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) return; /* another wiphy still in use */ } + /* Ensure HW is awake when we try to shut it down. */ + ath9k_ps_wakeup(sc); + if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { ath9k_hw_btcoex_disable(sc->sc_ah); if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) @@ -2167,6 +2170,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); + ath9k_ps_restore(sc); + + /* Finally, put the chip in FULL SLEEP mode */ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); sc->sc_flags |= SC_OP_INVALID; @@ -2277,10 +2283,12 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { + ath9k_ps_wakeup(sc); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - ath_beacon_return(sc, avp); + ath9k_ps_restore(sc); } + ath_beacon_return(sc, avp); sc->sc_flags &= ~SC_OP_BEACONS; for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { @@ -2327,6 +2335,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { + sc->sc_flags |= SC_OP_PS_ENABLED; if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { @@ -2334,11 +2343,17 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); } - ath9k_hw_setrxabort(sc->sc_ah, 1); } sc->ps_enabled = true; + if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) { + sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + sc->ps_enabled = true; + ath9k_hw_setrxabort(sc->sc_ah, 1); + } } else { sc->ps_enabled = false; + sc->sc_flags &= ~(SC_OP_PS_ENABLED | + SC_OP_NULLFUNC_COMPLETED); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { @@ -2717,15 +2732,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + ath9k_ps_wakeup(sc); ath_tx_aggr_start(sc, sta, tid, ssn); ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_STOP: + ath9k_ps_wakeup(sc); ath_tx_aggr_stop(sc, sta, tid); ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_OPERATIONAL: + ath9k_ps_wakeup(sc); ath_tx_aggr_resume(sc, sta, tid); + ath9k_ps_restore(sc); break; default: DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d83b77f821e9..c0d7e65bf6d4 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -969,10 +969,10 @@ enum { #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00001000 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 1 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 42551a48c8ac..9009bac9207d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1076,10 +1076,10 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) if (npend) { int r; - DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Unable to stop TxDMA. Reset HAL!\n"); spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); if (r) DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d\n", @@ -1563,7 +1563,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) + if (conf_is_ht(&sc->hw->conf)) bf->bf_state.bf_type |= BUF_HT; bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); @@ -1592,6 +1592,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, } bf->bf_buf_addr = bf->bf_dmacontext; + + if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { + bf->bf_isnullfunc = true; + sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + } else + bf->bf_isnullfunc = false; + return 0; } @@ -1641,7 +1648,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, goto tx_done; } - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && !is_pae(skb)) { /* * Try aggregation if it's a unicast data frame * and the destination is HT capable. @@ -1989,6 +1996,15 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (ds == txq->axq_gatingds) txq->axq_gatingds = NULL; + if (bf->bf_isnullfunc && + (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { + if ((sc->sc_flags & SC_OP_PS_ENABLED)) { + sc->ps_enabled = true; + ath9k_hw_setrxabort(sc->sc_ah, 1); + } else + sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED; + } + /* * Remove ath_buf's of the same transmit unit from txq, * however leave the last descriptor back as the holding @@ -2004,7 +2020,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf_isaggr(bf)) txq->axq_aggr_depth--; - txok = (ds->ds_txstat.ts_status == 0); + txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); @@ -2065,7 +2081,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) if (needreset) { DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); + ath9k_ps_wakeup(sc); ath_reset(sc, false); + ath9k_ps_restore(sc); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 660716214d49..0e6b15454d39 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -117,6 +117,7 @@ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ #define B43_MMIO_RNG 0x65A +#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 #define B43_MMIO_POWERUP_DELAY 0x6A8 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 098dda1a67c1..9ca253e40bd5 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -628,10 +628,17 @@ static void b43_upload_card_macaddress(struct b43_wldev *dev) static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) { /* slot_time is in usec. */ - if (dev->phy.type != B43_PHYTYPE_G) + /* This test used to exit for all but a G PHY. */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) return; - b43_write16(dev, 0x684, 510 + slot_time); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time); + /* Shared memory location 0x0010 is the slot time and should be + * set to slot_time; however, this register is initially 0 and changing + * the value adversely affects the transmit rate for BCM4311 + * devices. Until this behavior is unterstood, delete this step + * + * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + */ } static void b43_short_slot_timing_enable(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index ffdce6f3c909..78016ae21c50 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -33,8 +33,14 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) & B43_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { - if (b43_status(dev) >= B43_STAT_STARTED && - b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) + /* To prevent CPU fault on PPC, do not read a register + * unless the interface is started; however, on resume + * for hibernation, this routine is entered early. When + * that happens, unconditionally return TRUE. + */ + if (b43_status(dev) < B43_STAT_STARTED) + return 1; + if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) & B43_MMIO_RADIO_HWENABLED_LO_MASK) return 1; } diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 8783022db11e..d579df72b783 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -34,6 +34,13 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { + /* To prevent CPU fault on PPC, do not read a register + * unless the interface is started; however, on resume + * for hibernation, this routine is entered early. When + * that happens, unconditionally return TRUE. + */ + if (b43legacy_status(dev) < B43legacy_STAT_STARTED) + return 1; if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) return 1; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 6e2fc0cb6f8a..43102bff8dee 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6487,6 +6487,16 @@ static int ipw2100_resume(struct pci_dev *pci_dev) } #endif +static void ipw2100_shutdown(struct pci_dev *pci_dev) +{ + struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); + + /* Take down the device; powers it off, etc. */ + ipw2100_down(priv); + + pci_disable_device(pci_dev); +} + #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { @@ -6550,6 +6560,7 @@ static struct pci_driver ipw2100_pci_driver = { .suspend = ipw2100_suspend, .resume = ipw2100_resume, #endif + .shutdown = ipw2100_shutdown, }; /** diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f059b49dc691..9d60f6cfa1d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2895,6 +2895,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .mod_params = &iwl3945_mod_params, .use_isr_legacy = true, .ht_greenfield_support = false, + .broken_powersave = true, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2909,6 +2910,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .mod_params = &iwl3945_mod_params, .use_isr_legacy = true, .ht_greenfield_support = false, + .broken_powersave = true, }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6f703a041847..99331edd9d75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1337,7 +1337,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); /* calculate tx gain adjustment based on power supply voltage */ - voltage = priv->calib_info->voltage; + voltage = le16_to_cpu(priv->calib_info->voltage); init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); voltage_compensation = iwl4965_get_voltage_compensation(voltage, init_voltage); @@ -2087,7 +2087,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT; + int tid = MAX_TID_COUNT - 1; int sta_id; int freed; u8 *qc = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4ef6804a455a..bc056e9ab85f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -92,11 +92,15 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) { - u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, - EEPROM_5000_TEMPERATURE); - /* offset = temperature - voltage / coef */ - s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); - return offset; + u16 temperature, voltage; + __le16 *temp_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); + + temperature = le16_to_cpu(temp_calib[0]); + voltage = le16_to_cpu(temp_calib[1]); + + /* offset = temp - volt / coeff */ + return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); } /* Fixed (non-configurable) rx data from phy */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6e6f516ba404..133df70bc609 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -460,14 +460,15 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; - u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); + __le16 *xtal_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; - cmd.cap_pin1 = (u8)xtal_calib[0]; - cmd.cap_pin2 = (u8)xtal_calib[1]; + cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); + cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], (u8 *)&cmd, sizeof(cmd)); } @@ -1665,6 +1666,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5100_bg_cfg = { @@ -1716,6 +1718,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1733,6 +1736,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1750,6 +1754,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 81726ee32858..0eb25916f81d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2808,7 +2808,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, repeat_rate--; } - lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; + lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; lq_cmd->agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2dc928755454..0cd4ec40a7d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2645,6 +2645,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; + iwl_set_rxon_ht(priv, ht_conf); iwl_set_rxon_channel(priv, conf->channel); iwl_set_flags_for_band(priv, conf->channel->band); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 028d50599550..cea2ee25722c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -703,7 +703,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { - return q->write_ptr > q->read_ptr ? + return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } @@ -1149,7 +1149,7 @@ struct iwl_priv { u32 last_beacon_time; u64 last_tsf; - /* eeprom */ + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; struct iwl_eeprom_calib_info *calib_info; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e14c9952a935..18dc3a4b7948 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -337,7 +337,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) return ret; } -static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) +static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data) { int ret = 0; u32 r; @@ -370,7 +370,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } - *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); + *eeprom_data = cpu_to_le16(r >> 16); return 0; } @@ -379,7 +379,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) */ static bool iwl_is_otp_empty(struct iwl_priv *priv) { - u16 next_link_addr = 0, link_value; + u16 next_link_addr = 0; + __le16 link_value; bool is_empty = false; /* locate the beginning of OTP link list */ @@ -409,7 +410,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv) static int iwl_find_otp_image(struct iwl_priv *priv, u16 *validblockaddr) { - u16 next_link_addr = 0, link_value = 0, valid_addr; + u16 next_link_addr = 0, valid_addr; + __le16 link_value = 0; int usedblocks = 0; /* set addressing mode to absolute to traverse the link list */ @@ -429,7 +431,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, * check for more block on the link list */ valid_addr = next_link_addr; - next_link_addr = link_value * sizeof(u16); + next_link_addr = le16_to_cpu(link_value) * sizeof(u16); IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(priv, next_link_addr, &link_value)) @@ -463,7 +465,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, */ int iwl_eeprom_init(struct iwl_priv *priv) { - u16 *e; + __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; @@ -482,7 +484,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = -ENOMEM; goto alloc_err; } - e = (u16 *)priv->eeprom; + e = (__le16 *)priv->eeprom; ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { @@ -521,7 +523,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } for (addr = validblockaddr; addr < validblockaddr + sz; addr += sizeof(u16)) { - u16 eeprom_data; + __le16 eeprom_data; ret = iwl_read_otp_word(priv, addr, &eeprom_data); if (ret) @@ -545,7 +547,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) goto done; } r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + e[addr / 2] = cpu_to_le16(r >> 16); } } ret = 0; @@ -709,7 +711,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, ch_info->ht40_min_power = 0; ch_info->ht40_scan_power = eeprom_ch->max_power_avg; ch_info->ht40_flags = eeprom_ch->flags; - ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; + if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) + ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 80b9e45d9b9c..fc93f12853ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -133,7 +133,7 @@ struct iwl_eeprom_channel { * */ struct iwl_eeprom_enhanced_txpwr { - u16 reserved; + __le16 common; s8 chain_a_max; s8 chain_b_max; s8 chain_c_max; @@ -347,7 +347,7 @@ struct iwl_eeprom_calib_subband_info { struct iwl_eeprom_calib_info { u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ u8 saturation_power52; /* half-dBm */ - s16 voltage; /* signed */ + __le16 voltage; /* signed */ struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d00a80334095..5f26c93d3516 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -562,6 +562,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq = &priv->txq[txq_id]; q = &txq->q; + if ((iwl_queue_space(q) < q->high_mark)) + goto drop; + spin_lock_irqsave(&priv->lock, flags); idx = get_cmd_index(q, q->write_ptr, 0); @@ -3854,9 +3857,11 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + IEEE80211_HW_SPECTRUM_MGMT; + + if (!priv->cfg->broken_powersave) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 1b02a4e2a1ac..93c898990cce 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -258,7 +258,7 @@ struct iwm_priv { struct sk_buff_head rx_list; struct list_head rx_tickets; - struct list_head rx_packets[IWM_RX_ID_HASH]; + struct list_head rx_packets[IWM_RX_ID_HASH + 1]; struct workqueue_struct *rx_wq; struct work_struct rx_worker; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 6c95af3023cc..06d66a171396 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -399,11 +399,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) chan_count = lbs_scan_create_channel_list(priv, chan_list); netif_stop_queue(priv->dev); - netif_carrier_off(priv->dev); - if (priv->mesh_dev) { + if (priv->mesh_dev) netif_stop_queue(priv->mesh_dev); - netif_carrier_off(priv->mesh_dev); - } /* Prepare to continue an interrupted scan */ lbs_deb_scan("chan_count %d, scan_channel %d\n", @@ -467,16 +464,13 @@ out2: priv->scan_channel = 0; out: - if (priv->connect_status == LBS_CONNECTED) { - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - } - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { - netif_carrier_on(priv->mesh_dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - } + if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) + netif_wake_queue(priv->dev); + + if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && + !priv->tx_pending_len) + netif_wake_queue(priv->mesh_dev); + kfree(chan_list); lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index be837a0d2517..01c738b8e22c 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1953,10 +1953,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, if (priv->connect_status == LBS_CONNECTED) { memcpy(extra, priv->curbssparams.ssid, priv->curbssparams.ssid_len); - extra[priv->curbssparams.ssid_len] = '\0'; } else { memset(extra, 0, 32); - extra[priv->curbssparams.ssid_len] = '\0'; } /* * If none, we may want to get the one that was set diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 7698fdd6a3a2..31ca241f7753 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -23,7 +23,7 @@ #define MAX_RID_LEN 1024 /* Helper routine to record keys - * Do not call from interrupt context */ + * It is called under orinoco_lock so it may not sleep */ static int orinoco_set_key(struct orinoco_private *priv, int index, enum orinoco_alg alg, const u8 *key, int key_len, const u8 *seq, int seq_len) @@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, kzfree(priv->keys[index].seq); if (key_len) { - priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); + priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); if (!priv->keys[index].key) goto nomem; } else priv->keys[index].key = NULL; if (seq_len) { - priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); + priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); if (!priv->keys[index].seq) goto free_key; } else diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b20e3eac9d67..9a6ceb4e28d8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2538,6 +2538,11 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) unsigned int i; /* + * Disable powersaving as default. + */ + rt2x00dev->hw->wiphy->ps_default = false; + + /* * Initialize all hw fields. */ rt2x00dev->hw->flags = diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index bf9175a8c1f4..99406bf381ca 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -23,6 +23,7 @@ #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ +#define RTL8187_EEPROM_SELECT_GPIO 0x3B #define RTL8187_REQT_READ 0xC0 #define RTL8187_REQT_WRITE 0x40 @@ -31,6 +32,9 @@ #define RTL8187_MAX_RX 0x9C4 +#define RFKILL_MASK_8187_89_97 0x2 +#define RFKILL_MASK_8198 0x4 + struct rtl8187_rx_info { struct urb *urb; struct ieee80211_hw *dev; @@ -123,6 +127,7 @@ struct rtl8187_priv { u8 noise; u8 slot_time; u8 aifsn[4]; + u8 rfkill_mask; struct { __le64 buf; struct sk_buff_head queue; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 2017ccc00145..9921147edc29 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -65,6 +65,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, /* Sphairon Access Systems GmbH */ {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, /* Dick Smith Electronics */ @@ -1329,6 +1330,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, struct ieee80211_channel *channel; const char *chip_name; u16 txpwr, reg; + u16 product_id = le16_to_cpu(udev->descriptor.idProduct); int err, i; dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); @@ -1488,6 +1490,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } + /* Handle the differing rfkill GPIO bit in different models */ + priv->rfkill_mask = RFKILL_MASK_8187_89_97; + if (product_id == 0x8197 || product_id == 0x8198) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); + if (reg & 0xFF00) + priv->rfkill_mask = RFKILL_MASK_8198; + } /* * XXX: Once this driver supports anything that requires @@ -1516,9 +1525,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", + printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - chip_name, priv->asic_rev, priv->rf->name); + chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); #ifdef CONFIG_RTL8187_LEDS eeprom_93cx6_read(&eeprom, 0x3F, ®); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c index cad8037ab2af..03555e1e0cab 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c @@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) u8 gpio; gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02); + rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); - return gpio & 0x02; + return gpio & priv->rfkill_mask; } void rtl8187_rfkill_init(struct ieee80211_hw *hw) |