diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-03-11 16:06:31 +0530 |
---|---|---|
committer | Deepak Nibade <dnibade@nvidia.com> | 2014-03-13 11:01:40 +0530 |
commit | 50a3a706c880500ec305e7af51bd5f2363a8cc44 (patch) | |
tree | 5048357e0f00ac220b671942e210d41d0c739a5c /drivers/net | |
parent | 40a66a5c983a8bf93a8860bd9500bfea83411e08 (diff) | |
parent | 6969595f011b46b49c3f1b9e0bd7da27768c1fd9 (diff) |
Merge branch 'linux-3.10.33' into dev-kernel-3.10
Bug 1456092
Change-Id: I3021247ec68a3c2dddd9e98cde13d70a45191d53
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Diffstat (limited to 'drivers/net')
74 files changed, 574 insertions, 304 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 390061d09693..00c6c089b935 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1854,8 +1854,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) BOND_AD_INFO(bond).agg_select_timer = timeout; } -static u16 aggregator_identifier; - /** * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures * @bond: bonding struct to work on @@ -1869,7 +1867,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), bond->dev->dev_addr)) { - aggregator_identifier = 0; + BOND_AD_INFO(bond).aggregator_identifier = 0; BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); @@ -1940,7 +1938,7 @@ int bond_3ad_bind_slave(struct slave *slave) ad_initialize_agg(aggregator); aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); - aggregator->aggregator_identifier = (++aggregator_identifier); + aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier; aggregator->slave = slave; aggregator->is_active = 0; aggregator->num_of_ports = 0; diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 5d91ad0cc041..1f081c89753f 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -253,6 +253,7 @@ struct ad_system { struct ad_bond_info { struct ad_system system; /* 802.3ad system structure */ u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes + u16 aggregator_identifier; }; struct ad_slave_info { diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 1870c4731a57..539239d8e9ab 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -324,19 +324,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, } if (!priv->echo_skb[idx]) { - struct sock *srcsk = skb->sk; - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else - skb_orphan(skb); - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* make settings for echo to reduce code in irq context */ skb->protocol = htons(ETH_P_CAN); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index c4bc1d2e2033..b08383f485a5 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -19,6 +19,7 @@ #include <linux/netdevice.h> #include <linux/can.h> #include <linux/can/dev.h> +#include <linux/can/skb.h> #include <linux/can/error.h> #include <linux/mfd/janz.h> @@ -1134,20 +1135,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) */ static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) { - struct sock *srcsk = skb->sk; - - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else { - skb_orphan(skb); - } - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* save this skb for tx interrupt echo handling */ skb_queue_tail(&mod->echoq, skb); diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 4b2d5ed62b11..cc3df8aebb87 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -474,6 +474,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev) return err; dev->nchannels = msg.u.cardinfo.nchannels; + if (dev->nchannels > MAX_NET_DEVICES) + return -EINVAL; return 0; } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 8ee9d1556e6e..263dd921edc4 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) /* set LED in default state (end of init phase) */ pcan_usb_pro_set_led(dev, 0, 1); + kfree(bi); + kfree(fi); + return 0; err_out: diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0a2a5ee79a17..4e94057ef5cf 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -46,6 +46,7 @@ #include <linux/if_ether.h> #include <linux/can.h> #include <linux/can/dev.h> +#include <linux/can/skb.h> #include <linux/slab.h> #include <net/rtnetlink.h> @@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) stats->rx_packets++; stats->rx_bytes += cfd->len; } - kfree_skb(skb); + consume_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { - struct sock *srcsk = skb->sk; - skb = skb_share_check(skb, GFP_ATOMIC); + skb = can_create_echo_skb(skb); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ - skb->sk = srcsk; vcan_rx(skb, dev); } else { /* no looped packets => no counting */ - kfree_skb(skb); + consume_skb(skb); } return NETDEV_TX_OK; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 8c4babc0efbd..70be100feeb4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -153,6 +153,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, struct sk_buff *skb = tx_buf->skb; u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons; int nbd; + u16 split_bd_len = 0; /* prefetch skb end pointer to speedup dev_kfree_skb() */ prefetch(&skb->end); @@ -160,10 +161,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, DP(NETIF_MSG_TX_DONE, "fp[%d]: pkt_idx %d buff @(%p)->skb %p\n", txdata->txq_index, idx, tx_buf, skb); - /* unmap first bd */ tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd; - dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), - BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE); nbd = le16_to_cpu(tx_start_bd->nbd) - 1; @@ -182,12 +180,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, --nbd; bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); - /* ...and the TSO split header bd since they have no mapping */ + /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */ if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { + tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd; + split_bd_len = BD_UNMAP_LEN(tx_data_bd); --nbd; bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); } + /* unmap first bd */ + dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), + BD_UNMAP_LEN(tx_start_bd) + split_bd_len, + DMA_TO_DEVICE); + /* now free frags */ while (nbd > 0) { diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b51560d56590..68e9dc453e11 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7482,7 +7482,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) { u32 base = (u32) mapping & 0xffffffff; - return (base > 0xffffdcc0) && (base + len + 8 < base); + return base + len + 8 < base; } /* Test for TSO DMA buffers that cross into regions which are within MSS bytes @@ -13777,12 +13777,12 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_netif_stop(tp); + tg3_set_mtu(dev, tp, new_mtu); + tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_set_mtu(dev, tp, new_mtu); - /* Reset PHY, otherwise the read DMA engine will be in a mode that * breaks all requests to 256 bytes. */ @@ -16297,6 +16297,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) /* Clear this out for sanity. */ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */ + tw32(TG3PCI_REG_BASE_ADDR, 0); + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d48099f03b7f..fbd0d7df67d8 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -371,6 +371,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) else bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); + skb_tx_timestamp(skb); + fep->cur_tx = bdp; if (fep->cur_tx == fep->dirty_tx) @@ -379,8 +381,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* Trigger transmission start */ writel(0, fep->hwp + FEC_X_DES_ACTIVE); - skb_tx_timestamp(skb); - return NETDEV_TX_OK; } diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 90ea0b1673ca..716dae7b9d8e 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3023,7 +3023,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | + dev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM; diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 59c76a6815a0..be4d7c1e3c14 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, * it across the board. */ ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) + if (ret_val) { /* If the first read fails, another entity may have * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ - udelay(usec_interval); + if (usec_interval >= 1000) + msleep(usec_interval / 1000); + else + udelay(usec_interval); + } ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); if (ret_val) break; if (phy_status & BMSR_LSTATUS) break; if (usec_interval >= 1000) - mdelay(usec_interval / 1000); + msleep(usec_interval / 1000); else udelay(usec_interval); } diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index 115b0da6e013..5dec66a96793 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -1595,7 +1595,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ - udelay(usec_interval); + if (usec_interval >= 1000) + mdelay(usec_interval/1000); + else + udelay(usec_interval); } ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 571452e786d5..61a1540f1347 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -2019,7 +2019,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM - /*| NETIF_F_FRAGLIST */ ; ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX; diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 75b82b6e8c54..c879969e82fb 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1611,6 +1611,7 @@ static void rhine_reset_task(struct work_struct *work) goto out_unlock; napi_disable(&rp->napi); + netif_tx_disable(dev); spin_lock_bh(&rp->lock); /* clear all descriptors */ diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 5444f2b87d01..52de70bd0bba 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1016,7 +1016,7 @@ static int temac_of_probe(struct platform_device *op) dev_set_drvdata(&op->dev, ndev); SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &temac_netdev_ops; ndev->ethtool_ops = &temac_ethtool_ops; #if 0 diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 24748e8367a1..2e2eeba37a06 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1488,7 +1488,7 @@ static int axienet_of_probe(struct platform_device *op) SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &axienet_netdev_ops; ndev->ethtool_ops = &axienet_ethtool_ops; diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 3169252613fa..5d78c1d08abd 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case HDLCDRVCTL_CALIBRATE: if(!capable(CAP_SYS_RAWIO)) return -EPERM; + if (bi.data.calibrate > INT_MAX / s->par.bitrate) + return -EINVAL; s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; return 0; diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 0721e72f9299..82529a2658d7 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -1058,6 +1058,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; case SIOCYAMGCFG: + memset(&yi, 0, sizeof(yi)); yi.cfg.mask = 0xffffffff; yi.cfg.iobase = yp->iobase; yi.cfg.irq = yp->irq; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 23a0fff0df52..aea78fc2e48f 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -328,7 +328,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) return -EINVAL; nvdev->start_remove = true; - cancel_delayed_work_sync(&ndevctx->dwork); cancel_work_sync(&ndevctx->work); netif_tx_disable(ndev); rndis_filter_device_remove(hdev); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index c70ff7dac00e..9e56eb479a4f 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -797,11 +797,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, const struct sk_buff *skb, const struct iovec *iv, int len) { - struct macvlan_dev *vlan; int ret; int vnet_hdr_len = 0; int vlan_offset = 0; - int copied; + int copied, total; if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; @@ -816,7 +815,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; } - copied = vnet_hdr_len; + total = copied = vnet_hdr_len; + total += skb->len; if (!vlan_tx_tag_present(skb)) len = min_t(int, skb->len, len); @@ -831,6 +831,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); len = min_t(int, skb->len + VLAN_HLEN, len); + total += VLAN_HLEN; copy = min_t(int, vlan_offset, len); ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); @@ -848,16 +849,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, } ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); - copied += len; done: - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); - if (vlan) - macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); - rcu_read_unlock_bh(); - - return ret ? ret : copied; + return ret ? ret : total; } static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, @@ -909,7 +903,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); - ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: return ret; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 0129e824db5b..aeff706f1634 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1412,6 +1412,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = tun_do_read(tun, tfile, iocb, iv, len, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: tun_put(tun); return ret; diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index ad5d1e4384db..97b5de7aebdb 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -915,7 +915,8 @@ static const struct driver_info ax88178_info = { .status = asix_status, .link_reset = ax88178_link_reset, .reset = ax88178_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | + FLAG_MULTI_PACKET, .rx_fixup = asix_rx_fixup_common, .tx_fixup = asix_tx_fixup, }; diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index cea1f3d0311b..d33c3ae2fcea 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1109,6 +1109,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u16 hdr_off; u32 *pkt_hdr; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + skb_trim(skb, skb->len - 4); memcpy(&rx_hdr, skb_tail_pointer(skb), 4); le32_to_cpus(&rx_hdr); diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index c6867f926cff..c0bfc818c701 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; - dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; + + /* dm9620/21a require room for 4 byte padding, even in dm9601 + * mode, so we need +1 to be able to receive full size + * ethernet frames. + */ + dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1; dev->mii.dev = dev->net; dev->mii.mdio_read = dm9601_mdio_read; @@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - int len; + int len, pad; /* format: b1: packet length low @@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, b3..n: packet data */ - len = skb->len; + len = skb->len + DM_TX_OVERHEAD; - if (skb_headroom(skb) < DM_TX_OVERHEAD) { + /* workaround for dm962x errata with tx fifo getting out of + * sync if a USB bulk transfer retry happens right after a + * packet with odd / maxpacket length by adding up to 3 bytes + * padding. + */ + while ((len & 1) || !(len % dev->maxpacket)) + len++; + + len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */ + pad = len - skb->len; + + if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) { struct sk_buff *skb2; - skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); + skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags); dev_kfree_skb_any(skb); skb = skb2; if (!skb) @@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, __skb_push(skb, DM_TX_OVERHEAD); - /* usbnet adds padding if length is a multiple of packet size - if so, adjust length value in header */ - if ((skb->len % dev->maxpacket) == 0) - len++; + if (pad) { + memset(skb->data + skb->len, 0, pad); + __skb_put(skb, pad); + } skb->data[0] = len; skb->data[1] = len >> 8; diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index a7e3f4e55bf3..82ab61d62804 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -86,6 +86,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u32 size; u32 count; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + header = (struct gl_header *) skb->data; // get the packet count of the received skb diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 03832d3780aa..9237c45883cd 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -529,8 +529,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { u8 status; - if (skb->len == 0) { - dev_err(&dev->udev->dev, "unexpected empty rx frame\n"); + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) { + dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); return 0; } diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 93e0716a118c..7f4a3a41c4f8 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -366,6 +366,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) struct nc_trailer *trailer; u16 hdr_len, packet_len; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + if (!(skb->len & 0x01)) { netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", skb->len, dev->net->hard_header_len, dev->hard_mtu, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 34a081f1527f..37d9785974fc 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { __be16 proto; - /* usbnet rx_complete guarantees that skb->len is at least - * hard_header_len, so we can inspect the dest address without - * checking skb->len - */ + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + switch (skb->data[0] & 0xf0) { case 0x40: proto = htons(ETH_P_IP); @@ -709,6 +709,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ + {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index cc49aac70224..691fca4e4c2d 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -494,6 +494,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind); */ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + /* peripheral may have batched packets to us... */ while (likely(skb->len)) { struct rndis_data_hdr *hdr = (void *)skb->data; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 66ebbacf066f..12afae0451e6 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2108,6 +2108,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 rx_cmd_a, rx_cmd_b, align_count, size; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 8836e12b76e7..43e89040379f 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1801,6 +1801,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 header, align_count; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 67d0d07b7514..42f15952025d 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -517,17 +517,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) } // else network stack removes extra byte if we forced a short packet - if (skb->len) { - /* all data was already cloned from skb inside the driver */ - if (dev->driver_info->flags & FLAG_MULTI_PACKET) - dev_kfree_skb_any(skb); - else - usbnet_skb_return(dev, skb); + /* all data was already cloned from skb inside the driver */ + if (dev->driver_info->flags & FLAG_MULTI_PACKET) + goto done; + + if (skb->len < ETH_HLEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); + } else { + usbnet_skb_return(dev, skb); return; } - netif_dbg(dev, rx_err, dev->net, "drop\n"); - dev->net->stats.rx_errors++; done: skb_queue_tail(&dev->done, skb); } @@ -549,13 +551,6 @@ static void rx_complete (struct urb *urb) switch (urb_status) { /* success */ case 0: - if (skb->len < dev->net->hard_header_len) { - state = rx_cleanup; - dev->net->stats.rx_errors++; - dev->net->stats.rx_length_errors++; - netif_dbg(dev, rx_err, dev->net, - "rx length %d\n", skb->len); - } break; /* stalls need manual reset. this is rare ... except that diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 64cf70247048..a0c05e07feeb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -294,26 +294,61 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq, return skb; } -static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb) +static struct sk_buff *receive_small(void *buf, unsigned int len) { - struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); - struct page *page; - int num_buf, i, len; + struct sk_buff * skb = buf; + + len -= sizeof(struct virtio_net_hdr); + skb_trim(skb, len); + + return skb; +} + +static struct sk_buff *receive_big(struct net_device *dev, + struct receive_queue *rq, + void *buf) +{ + struct page *page = buf; + struct sk_buff *skb = page_to_skb(rq, page, 0); + + if (unlikely(!skb)) + goto err; + + return skb; + +err: + dev->stats.rx_dropped++; + give_pages(rq, page); + return NULL; +} + +static struct sk_buff *receive_mergeable(struct net_device *dev, + struct receive_queue *rq, + void *buf, + unsigned int len) +{ + struct skb_vnet_hdr *hdr = page_address(buf); + int num_buf = hdr->mhdr.num_buffers; + struct page *page = buf; + struct sk_buff *skb = page_to_skb(rq, page, len); + int i; + + if (unlikely(!skb)) + goto err_skb; - num_buf = hdr->mhdr.num_buffers; while (--num_buf) { i = skb_shinfo(skb)->nr_frags; if (i >= MAX_SKB_FRAGS) { pr_debug("%s: packet too long\n", skb->dev->name); skb->dev->stats.rx_length_errors++; - return -EINVAL; + goto err_frags; } page = virtqueue_get_buf(rq->vq, &len); if (!page) { - pr_debug("%s: rx error: %d buffers missing\n", - skb->dev->name, hdr->mhdr.num_buffers); - skb->dev->stats.rx_length_errors++; - return -EINVAL; + pr_debug("%s: rx error: %d buffers %d missing\n", + dev->name, hdr->mhdr.num_buffers, num_buf); + dev->stats.rx_length_errors++; + goto err_buf; } if (len > PAGE_SIZE) @@ -323,7 +358,26 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb) --rq->num; } - return 0; + return skb; +err_skb: + give_pages(rq, page); + while (--num_buf) { +err_frags: + buf = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers missing\n", + dev->name, num_buf); + dev->stats.rx_length_errors++; + break; + } + page = buf; + give_pages(rq, page); + --rq->num; + } +err_buf: + dev->stats.rx_dropped++; + dev_kfree_skb(skb); + return NULL; } static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) @@ -332,7 +386,6 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) struct net_device *dev = vi->dev; struct virtnet_stats *stats = this_cpu_ptr(vi->stats); struct sk_buff *skb; - struct page *page; struct skb_vnet_hdr *hdr; if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { @@ -344,25 +397,15 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) dev_kfree_skb(buf); return; } + if (vi->mergeable_rx_bufs) + skb = receive_mergeable(dev, rq, buf, len); + else if (vi->big_packets) + skb = receive_big(dev, rq, buf); + else + skb = receive_small(buf, len); - if (!vi->mergeable_rx_bufs && !vi->big_packets) { - skb = buf; - len -= sizeof(struct virtio_net_hdr); - skb_trim(skb, len); - } else { - page = buf; - skb = page_to_skb(rq, page, len); - if (unlikely(!skb)) { - dev->stats.rx_dropped++; - give_pages(rq, page); - return; - } - if (vi->mergeable_rx_bufs) - if (receive_mergeable(rq, skb)) { - dev_kfree_skb(skb); - return; - } - } + if (unlikely(!skb)) + return; hdr = skb_vnet_hdr(skb); @@ -1285,6 +1328,11 @@ static void virtnet_config_changed(struct virtio_device *vdev) static void virtnet_free_queues(struct virtnet_info *vi) { + int i; + + for (i = 0; i < vi->max_queue_pairs; i++) + netif_napi_del(&vi->rq[i].napi); + kfree(vi->rq); kfree(vi->sq); } @@ -1697,16 +1745,17 @@ static int virtnet_restore(struct virtio_device *vdev) if (err) return err; - if (netif_running(vi->dev)) + if (netif_running(vi->dev)) { + for (i = 0; i < vi->curr_queue_pairs; i++) + if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) + schedule_delayed_work(&vi->refill, 0); + for (i = 0; i < vi->max_queue_pairs; i++) virtnet_napi_enable(&vi->rq[i]); + } netif_device_attach(vi->dev); - for (i = 0; i < vi->curr_queue_pairs; i++) - if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); - mutex_lock(&vi->config_lock); vi->config_enable = true; mutex_unlock(&vi->config_lock); diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 17d7fece35d2..57fc06e0f434 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -1764,7 +1764,7 @@ static struct usb_device_id ar5523_id_table[] = { AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */ AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ - AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 + AR5523_DEVICE_UG(0x129b, 0x160b), /* Gigaset / USB stick 108 (CyberTAN Technology) */ AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */ AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8d78253c26ce..a366d6b4626f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) mask2 |= ATH9K_INT_CST; if (isr2 & AR_ISR_S2_TSFOOR) mask2 |= ATH9K_INT_TSFOOR; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S2, isr2); + isr &= ~AR_ISR_BCNMISC; + } } - isr = REG_READ(ah, AR_ISR_RAC); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) + isr = REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { *masked = 0; return false; @@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked |= ATH9K_INT_TX; - s0_s = REG_READ(ah, AR_ISR_S0_S); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { + s0_s = REG_READ(ah, AR_ISR_S0_S); + s1_s = REG_READ(ah, AR_ISR_S1_S); + } else { + s0_s = REG_READ(ah, AR_ISR_S0); + REG_WRITE(ah, AR_ISR_S0, s0_s); + s1_s = REG_READ(ah, AR_ISR_S1); + REG_WRITE(ah, AR_ISR_S1, s1_s); + + isr &= ~(AR_ISR_TXOK | + AR_ISR_TXDESC | + AR_ISR_TXERR | + AR_ISR_TXEOL); + } + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); } @@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked |= mask2; } - if (AR_SREV_9100(ah)) - return true; - - if (isr & AR_ISR_GENTMR) { + if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) { u32 s5_s; - s5_s = REG_READ(ah, AR_ISR_S5_S); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { + s5_s = REG_READ(ah, AR_ISR_S5_S); + } else { + s5_s = REG_READ(ah, AR_ISR_S5); + } + ah->intr_gen_timer_trigger = MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); @@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) if ((s5_s & AR_ISR_S5_TIM_TIMER) && !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) *masked |= ATH9K_INT_TIM_TIMER; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S5, s5_s); + isr &= ~AR_ISR_GENTMR; + } } + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR, isr); + REG_READ(ah, AR_ISR); + } + + if (AR_SREV_9100(ah)) + return true; + if (sync_cause) { ath9k_debug_sync_cause(common, sync_cause); fatal_int = diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 25b8bbbe74fe..f71a9eded5a4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3937,18 +3937,20 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq) int quick_drop; s32 t[3], f[3] = {5180, 5500, 5785}; - if (!(pBase->miscConfiguration & BIT(1))) + if (!(pBase->miscConfiguration & BIT(4))) return; - if (freq < 4000) - quick_drop = eep->modalHeader2G.quick_drop; - else { - t[0] = eep->base_ext1.quick_drop_low; - t[1] = eep->modalHeader5G.quick_drop; - t[2] = eep->base_ext1.quick_drop_high; - quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3); + if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) { + if (freq < 4000) { + quick_drop = eep->modalHeader2G.quick_drop; + } else { + t[0] = eep->base_ext1.quick_drop_low; + t[1] = eep->modalHeader5G.quick_drop; + t[2] = eep->base_ext1.quick_drop_high; + quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3); + } + REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop); } - REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop); } static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz) @@ -3988,7 +3990,7 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz) struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; u8 bias; - if (!(eep->baseEepHeader.featureEnable & 0x40)) + if (!(eep->baseEepHeader.miscConfiguration & 0x40)) return; if (!AR_SREV_9300(ah)) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 62f1b7636c92..04b3822ef93a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -145,21 +145,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) struct ath9k_vif_iter_data *iter_data = data; int i; - for (i = 0; i < ETH_ALEN; i++) - iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + if (iter_data->hw_macaddr != NULL) { + for (i = 0; i < ETH_ALEN; i++) + iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + } else { + iter_data->hw_macaddr = mac; + } } -static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, +static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_vif_iter_data iter_data; /* - * Use the hardware MAC address as reference, the hardware uses it - * together with the BSSID mask when matching addresses. + * Pick the MAC address of the first interface as the new hardware + * MAC address. The hardware will use it together with the BSSID mask + * when matching addresses. */ - iter_data.hw_macaddr = common->macaddr; + iter_data.hw_macaddr = NULL; memset(&iter_data.mask, 0xff, ETH_ALEN); if (vif) @@ -171,6 +176,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, ath9k_htc_bssid_iter, &iter_data); memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); + + if (iter_data.hw_macaddr) + memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); + ath_hw_setbssidmask(common); } @@ -1076,7 +1085,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, goto out; } - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); priv->vif_slot |= (1 << avp->index); priv->nvifs++; @@ -1139,7 +1148,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); /* * Stop ANI only if there are no associated station interfaces. @@ -1322,21 +1331,22 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_rate trate; + if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) + return; + mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { - memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); - ath9k_htc_setup_rate(priv, sta, &trate); - if (!ath9k_htc_send_rate_cmd(priv, &trate)) - ath_dbg(common, CONFIG, - "Supported rates for sta: %pM updated, rate caps: 0x%X\n", - sta->addr, be32_to_cpu(trate.capflags)); - else - ath_dbg(common, CONFIG, - "Unable to update supported rates for sta: %pM\n", - sta->addr); - } + memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); + ath9k_htc_setup_rate(priv, sta, &trate); + if (!ath9k_htc_send_rate_cmd(priv, &trate)) + ath_dbg(common, CONFIG, + "Supported rates for sta: %pM updated, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); + else + ath_dbg(common, CONFIG, + "Unable to update supported rates for sta: %pM\n", + sta->addr); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a8fee08479ef..82a1b5b16b62 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -889,8 +889,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(ah); /* - * Use the hardware MAC address as reference, the hardware uses it - * together with the BSSID mask when matching addresses. + * Pick the MAC address of the first interface as the new hardware + * MAC address. The hardware will use it together with the BSSID mask + * when matching addresses. */ memset(iter_data, 0, sizeof(*iter_data)); memset(&iter_data->mask, 0xff, ETH_ALEN); diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 7f3d461f7e8d..54376fddfaf9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -731,8 +731,6 @@ enum b43_firmware_file_type { struct b43_request_fw_context { /* The device we are requesting the fw for. */ struct b43_wldev *dev; - /* a completion event structure needed if this call is asynchronous */ - struct completion fw_load_complete; /* a pointer to the firmware object */ const struct firmware *blob; /* The type of firmware to request. */ @@ -809,6 +807,8 @@ enum { struct b43_wldev { struct b43_bus_dev *dev; struct b43_wl *wl; + /* a completion event structure needed if this call is asynchronous */ + struct completion fw_load_complete; /* The device initialization status. * Use b43_status() to query. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a95b77ab360e..0b7edd36cfa2 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2068,6 +2068,7 @@ void b43_do_release_fw(struct b43_firmware_file *fw) static void b43_release_firmware(struct b43_wldev *dev) { + complete(&dev->fw_load_complete); b43_do_release_fw(&dev->fw.ucode); b43_do_release_fw(&dev->fw.pcm); b43_do_release_fw(&dev->fw.initvals); @@ -2093,7 +2094,7 @@ static void b43_fw_cb(const struct firmware *firmware, void *context) struct b43_request_fw_context *ctx = context; ctx->blob = firmware; - complete(&ctx->fw_load_complete); + complete(&ctx->dev->fw_load_complete); } int b43_do_request_fw(struct b43_request_fw_context *ctx, @@ -2140,7 +2141,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, } if (async) { /* do this part asynchronously */ - init_completion(&ctx->fw_load_complete); + init_completion(&ctx->dev->fw_load_complete); err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, ctx->dev->dev->dev, GFP_KERNEL, ctx, b43_fw_cb); @@ -2148,12 +2149,11 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, pr_err("Unable to load firmware\n"); return err; } - /* stall here until fw ready */ - wait_for_completion(&ctx->fw_load_complete); + wait_for_completion(&ctx->dev->fw_load_complete); if (ctx->blob) goto fw_ready; /* On some ARM systems, the async request will fail, but the next sync - * request works. For this reason, we dall through here + * request works. For this reason, we fall through here */ } err = request_firmware(&ctx->blob, ctx->fwname, @@ -2422,6 +2422,7 @@ error: static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl); static void b43_one_core_detach(struct b43_bus_dev *dev); +static int b43_rng_init(struct b43_wl *wl); static void b43_request_firmware(struct work_struct *work) { @@ -2473,6 +2474,10 @@ start_ieee80211: goto err_one_core_detach; wl->hw_registred = true; b43_leds_register(wl->current_dev); + + /* Register HW RNG driver */ + b43_rng_init(wl); + goto out; err_one_core_detach: @@ -4634,9 +4639,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) return; - /* Unregister HW RNG driver */ - b43_rng_exit(dev->wl); - b43_set_status(dev, B43_STAT_UNINIT); /* Stop the microcode PSM. */ @@ -4779,9 +4781,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_set_status(dev, B43_STAT_INITIALIZED); - /* Register HW RNG driver */ - b43_rng_init(dev->wl); - out: return err; @@ -5442,6 +5441,9 @@ static void b43_bcma_remove(struct bcma_device *core) b43_one_core_detach(wldev->dev); + /* Unregister HW RNG driver */ + b43_rng_exit(wl); + b43_leds_unregister(wl); ieee80211_free_hw(wl->hw); @@ -5519,6 +5521,9 @@ static void b43_ssb_remove(struct ssb_device *sdev) b43_one_core_detach(dev); + /* Unregister HW RNG driver */ + b43_rng_exit(wl); + if (list_empty(&wl->devlist)) { b43_leds_unregister(wl); /* Last core on the chip unregistered. diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 8cb206a89083..e85d34b76039 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -821,10 +821,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) { status.band = IEEE80211_BAND_5GHZ; - status.freq = b43_freq_to_channel_5ghz(chanid); + status.freq = b43_channel_to_freq_5ghz(chanid); } else { status.band = IEEE80211_BAND_2GHZ; - status.freq = b43_freq_to_channel_2ghz(chanid); + status.freq = b43_channel_to_freq_2ghz(chanid); } break; default: diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 572668821862..349c77605231 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3919,6 +3919,7 @@ static void b43legacy_remove(struct ssb_device *dev) * as the ieee80211 unreg will destroy the workqueue. */ cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wl->firmware_load); + complete(&wldev->fw_load_complete); B43legacy_WARN_ON(!wl); if (!wldev->fw.ucode) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 822443c5a3b5..9fd01dc5146b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -131,6 +131,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7260_2n_cfg = { @@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7260_n_cfg = { @@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_2ac_cfg = { @@ -158,6 +161,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_2n_cfg = { @@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_n_cfg = { @@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 44e3370ce343..8ca006b12a32 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -241,6 +241,8 @@ struct iwl_eeprom_params { * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device * @temp_offset_v2: support v2 of temperature offset calibration + * @host_interrupt_operation_mode: device needs host interrupt operation + * mode set * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -273,6 +275,7 @@ struct iwl_cfg { const bool rx_with_siso_diversity; const bool internal_wimax_coex; const bool temp_offset_v2; + const bool host_interrupt_operation_mode; }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 20e845d4da04..bba1af4d406c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -463,13 +463,10 @@ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit * * default interrupt coalescing timer is 64 x 32 = 2048 usecs - * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs */ #define IWL_HOST_INT_TIMEOUT_MAX (0xFF) #define IWL_HOST_INT_TIMEOUT_DEF (0x40) #define IWL_HOST_INT_TIMEOUT_MIN (0x0) -#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) -#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) -#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) +#define IWL_HOST_INT_OPER_MODE BIT(31) #endif /* !__iwl_csr_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 6199a0a597a6..a7cf535216c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -180,6 +180,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) { ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); + + if (ch_idx >= NUM_2GHZ_CHANNELS && + !data->sku_cap_band_52GHz_enable) + ch_flags &= ~NVM_CHANNEL_VALID; + if (!(ch_flags & NVM_CHANNEL_VALID)) { IWL_DEBUG_EEPROM(dev, "Ch. %d Flags %x [%sGHz] - No traffic\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 386f2a7c87cb..c26a6dc21eef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -260,4 +260,8 @@ static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) /*********************** END TX SCHEDULER *************************************/ +/* Oscillator clock */ +#define OSC_CLK (0xa04068) +#define OSC_CLK_FORCE_CONTROL (0x8) + #endif /* __iwl_prph_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 2053dccefcd6..109dc8e437f5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file, if (sscanf(buf, "%d %d", &sta_id, &drain) != 2) return -EINVAL; + if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT) + return -EINVAL; + if (drain < 0 || drain > 1) + return -EINVAL; mutex_lock(&mvm->mutex); diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index b29c31a41594..388c8a914960 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -424,6 +424,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, out_unregister: ieee80211_unregister_hw(mvm->hw); + iwl_mvm_leds_exit(mvm); out_free: iwl_phy_db_free(mvm->phy_db); kfree(mvm->scan_cmd); diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 8e1f6c095a9e..b987dfb879df 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -313,7 +313,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, iwl_mvm_scan_fill_ssids(cmd, req); - cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); + cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | + TX_CMD_FLG_BT_DIS); cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); cmd->tx_cmd.rate_n_flags = diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 687b34e387ac..0d9e08160fec 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -401,6 +401,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) mvm->status, table.valid); } + IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); + trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, table.data1, table.data2, table.data3, table.blink1, table.blink2, table.ilink1, diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 567e67ad1f61..296026b08a0c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) /* Set interrupt coalescing timer to default (2048 usecs) */ iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + + /* W/A for interrupt coalescing bug in 7260 and 3160 */ + if (trans->cfg->host_interrupt_operation_mode) + iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } int iwl_pcie_rx_init(struct iwl_trans *trans) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index aeb70e13137a..4088dd5e9244 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -207,6 +207,22 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) } /* + * Enable the oscillator to count wake up time for L1 exit. This + * consumes slightly more power (100uA) - but allows to be sure + * that we wake up from L1 on time. + * + * This looks weird: read twice the same register, discard the + * value, set a bit, and yet again, read that same register + * just to discard the value. But that's the way the hardware + * seems to like it. + */ + iwl_read_prph(trans, OSC_CLK); + iwl_read_prph(trans, OSC_CLK); + iwl_set_bits_prph(trans, OSC_CLK, OSC_CLK_FORCE_CONTROL); + iwl_read_prph(trans, OSC_CLK); + iwl_read_prph(trans, OSC_CLK); + + /* * Enable DMA clock and wait for it to stabilize. * * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits @@ -276,9 +292,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->irq_lock, flags); iwl_pcie_apm_init(trans); - /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); iwl_pcie_set_pwr(trans, false); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1f7578d553ec..5400a1e58d79 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -228,7 +228,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { /* HW_SPEC fw_cap_info */ -#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) +#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(12)|BIT(13))) #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9cf5d8f07df8..50b2fe53219d 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1622,7 +1622,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, const u8 *ie_buf; size_t ie_len; u16 channel = 0; - u64 fw_tsf = 0; + __le64 fw_tsf = 0; u16 beacon_size = 0; u32 curr_bcn_bytes; u32 freq; @@ -1749,7 +1749,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, ie_buf, ie_len, rssi, GFP_KERNEL); bss_priv = (struct mwifiex_bss_priv *)bss->priv; bss_priv->band = band; - bss_priv->fw_tsf = fw_tsf; + bss_priv->fw_tsf = le64_to_cpu(fw_tsf); if (priv->media_connected && !memcmp(bssid, priv->curr_bss_params.bss_descriptor diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 23aa910bc5d0..0a9f59c5ab5a 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -309,8 +309,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, if (bss_desc && bss_desc->ssid.ssid_len && (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor. ssid, &bss_desc->ssid))) { - kfree(bss_desc); - return 0; + ret = 0; + goto done; } /* Exit Adhoc mode first */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h index e19a20a8e955..ecd1ac424047 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h @@ -15,6 +15,8 @@ #ifndef RTL8187_H #define RTL8187_H +#include <linux/cache.h> + #include "rtl818x.h" #include "leds.h" @@ -139,7 +141,10 @@ struct rtl8187_priv { u8 aifsn[4]; u8 rfkill_mask; struct { - __le64 buf; + union { + __le64 buf; + u8 dummy1[L1_CACHE_BYTES]; + } ____cacheline_aligned; struct sk_buff_head queue; } b_tx_status; /* This queue is used by both -b and non-b devices */ struct mutex io_mutex; @@ -147,7 +152,8 @@ struct rtl8187_priv { u8 bits8; __le16 bits16; __le32 bits32; - } *io_dmabuf; + u8 dummy2[L1_CACHE_BYTES]; + } *io_dmabuf ____cacheline_aligned; bool rfkill_off; u16 seqno; }; diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 3698028c910d..6fc0853fd7f9 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1427,7 +1427,8 @@ void rtl_watchdog_wq_callback(void *data) /* if we can't recv beacon for 6s, we should * reconnect this AP */ - if (rtlpriv->link_info.roam_times >= 3) { + if ((rtlpriv->link_info.roam_times >= 3) && + !is_zero_ether_addr(rtlpriv->mac80211.bssid)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AP off, try to reconnect now\n"); rtlpriv->link_info.roam_times = 0; diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index ee84844be008..e2301970c85e 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -46,10 +46,20 @@ void rtl_fw_cb(const struct firmware *firmware, void *context) "Firmware callback routine entered!\n"); complete(&rtlpriv->firmware_loading_complete); if (!firmware) { + if (rtlpriv->cfg->alt_fw_name) { + err = request_firmware(&firmware, + rtlpriv->cfg->alt_fw_name, + rtlpriv->io.dev); + pr_info("Loading alternative firmware %s\n", + rtlpriv->cfg->alt_fw_name); + if (!err) + goto found_alt; + } pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); rtlpriv->max_fw_size = 0; return; } +found_alt: if (firmware->size > rtlpriv->max_fw_size) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Firmware is too big!\n"); @@ -184,6 +194,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS]); } + mac->link_state = MAC80211_LINKED; break; case NL80211_IFTYPE_ADHOC: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 16b6070ae53b..845c8ac1ddf4 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -734,6 +734,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) }; int index = rtlpci->rx_ring[rx_queue_idx].idx; + if (rtlpci->driver_is_goingto_unload) + return; /*RX NORMAL PKT */ while (count--) { /*rx descriptor */ @@ -1630,6 +1632,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) */ set_hal_stop(rtlhal); + rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->disable_interrupt(hw); cancel_work_sync(&rtlpriv->works.lps_change_work); @@ -1647,7 +1650,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) ppsc->rfchange_inprogress = true; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); - rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->hw_disable(hw); /* some things are not needed if firmware not available */ if (!rtlpriv->max_fw_size) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 71e917db8338..ace1a087fe8a 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ if (rtlpriv->cfg->ops->hw_init(hw)) - return 1; + return false; RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*<3> Enable Interrupt */ diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c index 21a5cf060677..a6184b6e1d57 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c @@ -1078,7 +1078,7 @@ static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw rtldm->swing_flag_ofdm = true; } - if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) { + if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) { rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; rtldm->swing_flag_cck = true; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index d2d57a27a7c1..06cb94cf5085 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -158,6 +158,42 @@ static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} }; +static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; + +void dm_restorepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], + rtlpriv->dm.powerindex_backup[index]); +} +EXPORT_SYMBOL_GPL(dm_restorepowerindex); + +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], value); +} +EXPORT_SYMBOL_GPL(dm_writepowerindex); + +void dm_savepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + u8 tmp; + + for (index = 0; index < 6; index++) { + tmp = rtl_read_byte(rtlpriv, power_index_reg[index]); + rtlpriv->dm.powerindex_backup[index] = tmp; + } +} +EXPORT_SYMBOL_GPL(dm_savepowerindex); + static void rtl92c_dm_diginit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index 518e208c0180..4f232a063636 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h @@ -91,6 +91,17 @@ #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define DYNAMIC_FUNC_DISABLE 0x0 +#define DYNAMIC_FUNC_DIG BIT(0) +#define DYNAMIC_FUNC_HP BIT(1) +#define DYNAMIC_FUNC_SS BIT(2) /*Tx Power Tracking*/ +#define DYNAMIC_FUNC_BT BIT(3) +#define DYNAMIC_FUNC_ANT_DIV BIT(4) + +#define RSSI_CCK 0 +#define RSSI_OFDM 1 +#define RSSI_DEFAULT 2 + struct swat_t { u8 failure_cnt; u8 try_flag; @@ -167,5 +178,8 @@ void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index a82b30a1996c..2eb0b38384dd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -937,14 +937,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) bool is92c; int err; u8 tmp_u1b; + unsigned long flags; rtlpci->being_init_adapter = true; + + /* Since this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + rtlpriv->intf_ops->disable_aspm(hw); rtstatus = _rtl92ce_init_mac(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); err = 1; - return err; + goto exit; } err = rtl92c_download_fw(hw); @@ -952,7 +964,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to download FW. Init HW without FW now..\n"); err = 1; - return err; + goto exit; } rtlhal->last_hmeboxnum = 0; @@ -1032,6 +1044,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); } rtl92c_dm_init(hw); +exit: + local_irq_restore(flags); rtlpci->being_init_adapter = false; return err; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c index 16a0b9e59acf..c16209a336ea 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c @@ -101,6 +101,15 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) "PHY_SetTxPowerLevel8192S() Channel = %d\n", rtlphy->current_channel); rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_NORMAL) + dm_restorepowerindex(hw); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + dm_writepowerindex(hw, 0x14); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + dm_writepowerindex(hw, 0x10); } rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h index d947e7d350bb..fafa6bac2a3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h @@ -30,3 +30,6 @@ #include "../rtl8192ce/dm.h" void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 2119313a737b..b878d56d2f4d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -85,17 +85,15 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, if (mac->act_scanning) { tx_agc[RF90_PATH_A] = 0x3f3f3f3f; tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - if (rtlhal->interface == INTF_USB) { - if (tx_agc[idx1] > 0x20 && - rtlefuse->external_pa) - tx_agc[idx1] = 0x20; - } + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + if (rtlhal->interface == INTF_USB) { + if (tx_agc[idx1] > 0x20 && + rtlefuse->external_pa) + tx_agc[idx1] = 0x20; } } } else { @@ -107,7 +105,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, TXHIGHPWRLEVEL_LEVEL2) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; - } else{ + } else { for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { tx_agc[idx1] = ppowerlevel[idx1] | (ppowerlevel[idx1] << 8) | @@ -373,7 +371,12 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, regoffset == RTXAGC_B_MCS07_MCS04) regoffset = 0xc98; for (i = 0; i < 3; i++) { - writeVal = (writeVal > 6) ? (writeVal - 6) : 0; + if (i != 2) + writeVal = (writeVal > 8) ? + (writeVal - 8) : 0; + else + writeVal = (writeVal > 6) ? + (writeVal - 6) : 0; rtl_write_byte(rtlpriv, (u32)(regoffset + i), (u8)writeVal); } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 2bd598526217..8188dcb512f0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -49,6 +49,9 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { @@ -68,14 +71,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) "Can't alloc buffer for fw\n"); return 1; } - + if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) && + !IS_92C_SERIAL(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin"; + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin"; + } else { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; + } + /* provide name of alternative file */ + rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin"; pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); rtlpriv->max_fw_size = 0x4000; err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, rtlpriv->io.dev, GFP_KERNEL, hw, rtl_fw_cb); - - return err; } @@ -306,6 +316,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ /* HP - Lite-On ,8188CUS Slim Combo */ diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c index 8ed31744a054..4f083fc1d360 100644 --- a/drivers/net/wireless/rtlwifi/stats.c +++ b/drivers/net/wireless/rtlwifi/stats.c @@ -176,6 +176,7 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) struct rtl_sta_info *drv_priv = NULL; struct ieee80211_sta *sta = NULL; long undec_sm_pwdb; + long undec_sm_cck; rcu_read_lock(); if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) @@ -185,12 +186,16 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) if (sta) { drv_priv = (struct rtl_sta_info *) sta->drv_priv; undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; + undec_sm_cck = drv_priv->rssi_stat.undec_sm_cck; } else { undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + undec_sm_cck = rtlpriv->dm.undec_sm_cck; } if (undec_sm_pwdb < 0) undec_sm_pwdb = pstatus->rx_pwdb_all; + if (undec_sm_cck < 0) + undec_sm_cck = pstatus->rx_pwdb_all; if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + @@ -200,6 +205,15 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); } + if (pstatus->rx_pwdb_all > (u32) undec_sm_cck) { + undec_sm_cck = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + undec_sm_cck = undec_sm_cck + 1; + } else { + undec_sm_pwdb = (((undec_sm_cck) * (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + } if (sta) { drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 1feebdc92f41..57b12a5883a0 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -477,6 +477,8 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, if (unicast) rtlpriv->link_info.num_rx_inperiod++; } + /* static bcn for roaming */ + rtl_beacon_statistic(hw, skb); } } @@ -548,7 +550,7 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) } } -#define __RX_SKB_MAX_QUEUED 32 +#define __RX_SKB_MAX_QUEUED 64 static void _rtl_rx_work(unsigned long param) { diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index ad9c37a42709..e576a927fde7 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1035,6 +1035,7 @@ struct rtl_ht_agg { struct rssi_sta { long undec_sm_pwdb; + long undec_sm_cck; }; struct rtl_tid_data { @@ -1325,8 +1326,10 @@ struct fast_ant_training { struct rtl_dm { /*PHY status for Dynamic Management */ long entry_min_undec_sm_pwdb; + long undec_sm_cck; long undec_sm_pwdb; /*out dm */ long entry_max_undec_sm_pwdb; + s32 ofdm_pkt_cnt; bool dm_initialgain_enable; bool dynamic_txpower_enable; bool current_turbo_edca; @@ -1341,6 +1344,7 @@ struct rtl_dm { bool inform_fw_driverctrldm; bool current_mrc_switch; u8 txpowercount; + u8 powerindex_backup[6]; u8 thermalvalue_rxgain; u8 thermalvalue_iqk; @@ -1352,7 +1356,9 @@ struct rtl_dm { bool done_txpower; u8 dynamic_txhighpower_lvl; /*Tx high power level */ u8 dm_flag; /*Indicate each dynamic mechanism's status. */ + u8 dm_flag_tmp; u8 dm_type; + u8 dm_rssi_sel; u8 txpower_track_control; bool interrupt_migration; bool disable_tx_int; @@ -1806,6 +1812,7 @@ struct rtl_hal_cfg { bool write_readback; char *name; char *fw_name; + char *alt_fw_name; struct rtl_hal_ops *ops; struct rtl_mod_params *mod_params; struct rtl_hal_usbint_cfg *usb_interface_cfg; @@ -1950,6 +1957,7 @@ struct dig_t { u8 pre_ccastate; u8 cur_ccasate; u8 large_fa_hit; + u8 dig_dynamic_min; u8 forbidden_igi; u8 dig_state; u8 dig_highpwrstate; @@ -2030,22 +2038,15 @@ struct rtl_priv { struct dig_t dm_digtable; struct ps_t dm_pstable; - /* section shared by individual drivers */ - union { - struct { /* data buffer pointer for USB reads */ - __le32 *usb_data; - int usb_data_index; - bool initialized; - }; - struct { /* section for 8723ae */ - bool reg_init; /* true if regs saved */ - u32 reg_874; - u32 reg_c70; - u32 reg_85c; - u32 reg_a74; - bool bt_operation_on; - }; - }; + u32 reg_874; + u32 reg_c70; + u32 reg_85c; + u32 reg_a74; + bool reg_init; /* true if regs saved */ + bool bt_operation_on; + __le32 *usb_data; + int usb_data_index; + bool initialized; bool enter_ps; /* true when entering PS */ u8 rate_mask[5]; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 0c01b8e33fe1..82e0f1fd2254 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -107,6 +107,7 @@ struct netfront_info { } tx_skbs[NET_TX_RING_SIZE]; grant_ref_t gref_tx_head; grant_ref_t grant_tx_ref[NET_TX_RING_SIZE]; + struct page *grant_tx_page[NET_TX_RING_SIZE]; unsigned tx_skb_freelist; spinlock_t rx_lock ____cacheline_aligned_in_smp; @@ -386,6 +387,7 @@ static void xennet_tx_buf_gc(struct net_device *dev) gnttab_release_grant_reference( &np->gref_tx_head, np->grant_tx_ref[id]); np->grant_tx_ref[id] = GRANT_INVALID_REF; + np->grant_tx_page[id] = NULL; add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, id); dev_kfree_skb_irq(skb); } @@ -442,6 +444,7 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly); + np->grant_tx_page[id] = virt_to_page(data); tx->gref = np->grant_tx_ref[id] = ref; tx->offset = offset; tx->size = len; @@ -487,6 +490,7 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, np->xbdev->otherend_id, mfn, GNTMAP_readonly); + np->grant_tx_page[id] = page; tx->gref = np->grant_tx_ref[id] = ref; tx->offset = offset; tx->size = bytes; @@ -586,6 +590,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) mfn = virt_to_mfn(data); gnttab_grant_foreign_access_ref( ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly); + np->grant_tx_page[id] = virt_to_page(data); tx->gref = np->grant_tx_ref[id] = ref; tx->offset = offset; tx->size = len; @@ -1115,10 +1120,11 @@ static void xennet_release_tx_bufs(struct netfront_info *np) continue; skb = np->tx_skbs[i].skb; - gnttab_end_foreign_access_ref(np->grant_tx_ref[i], - GNTMAP_readonly); - gnttab_release_grant_reference(&np->gref_tx_head, - np->grant_tx_ref[i]); + get_page(np->grant_tx_page[i]); + gnttab_end_foreign_access(np->grant_tx_ref[i], + GNTMAP_readonly, + (unsigned long)page_address(np->grant_tx_page[i])); + np->grant_tx_page[i] = NULL; np->grant_tx_ref[i] = GRANT_INVALID_REF; add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, i); dev_kfree_skb_irq(skb); @@ -1127,78 +1133,35 @@ static void xennet_release_tx_bufs(struct netfront_info *np) static void xennet_release_rx_bufs(struct netfront_info *np) { - struct mmu_update *mmu = np->rx_mmu; - struct multicall_entry *mcl = np->rx_mcl; - struct sk_buff_head free_list; - struct sk_buff *skb; - unsigned long mfn; - int xfer = 0, noxfer = 0, unused = 0; int id, ref; - dev_warn(&np->netdev->dev, "%s: fix me for copying receiver.\n", - __func__); - return; - - skb_queue_head_init(&free_list); - spin_lock_bh(&np->rx_lock); for (id = 0; id < NET_RX_RING_SIZE; id++) { - ref = np->grant_rx_ref[id]; - if (ref == GRANT_INVALID_REF) { - unused++; - continue; - } + struct sk_buff *skb; + struct page *page; skb = np->rx_skbs[id]; - mfn = gnttab_end_foreign_transfer_ref(ref); - gnttab_release_grant_reference(&np->gref_rx_head, ref); - np->grant_rx_ref[id] = GRANT_INVALID_REF; - - if (0 == mfn) { - skb_shinfo(skb)->nr_frags = 0; - dev_kfree_skb(skb); - noxfer++; + if (!skb) continue; - } - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - /* Remap the page. */ - const struct page *page = - skb_frag_page(&skb_shinfo(skb)->frags[0]); - unsigned long pfn = page_to_pfn(page); - void *vaddr = page_address(page); + ref = np->grant_rx_ref[id]; + if (ref == GRANT_INVALID_REF) + continue; - MULTI_update_va_mapping(mcl, (unsigned long)vaddr, - mfn_pte(mfn, PAGE_KERNEL), - 0); - mcl++; - mmu->ptr = ((u64)mfn << PAGE_SHIFT) - | MMU_MACHPHYS_UPDATE; - mmu->val = pfn; - mmu++; + page = skb_frag_page(&skb_shinfo(skb)->frags[0]); - set_phys_to_machine(pfn, mfn); - } - __skb_queue_tail(&free_list, skb); - xfer++; - } - - dev_info(&np->netdev->dev, "%s: %d xfer, %d noxfer, %d unused\n", - __func__, xfer, noxfer, unused); + /* gnttab_end_foreign_access() needs a page ref until + * foreign access is ended (which may be deferred). + */ + get_page(page); + gnttab_end_foreign_access(ref, 0, + (unsigned long)page_address(page)); + np->grant_rx_ref[id] = GRANT_INVALID_REF; - if (xfer) { - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - /* Do all the remapping work and M2P updates. */ - MULTI_mmu_update(mcl, np->rx_mmu, mmu - np->rx_mmu, - NULL, DOMID_SELF); - mcl++; - HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl); - } + kfree_skb(skb); } - __skb_queue_purge(&free_list); - spin_unlock_bh(&np->rx_lock); } @@ -1333,6 +1296,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) for (i = 0; i < NET_RX_RING_SIZE; i++) { np->rx_skbs[i] = NULL; np->grant_rx_ref[i] = GRANT_INVALID_REF; + np->grant_tx_page[i] = NULL; } /* A grant for every tx ring slot */ |