diff --git a/[refs] b/[refs] index ce42c6c0a658..0bcd63dc005c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 886d7f444cbf72d5a424ea5fee4e34a0219d4af1 +refs/heads/master: 4c11b8adbc48bd21885fbc671df2f8ac04a75473 diff --git a/trunk/drivers/net/arm/ks8695net.c b/trunk/drivers/net/arm/ks8695net.c index 62d6f88cbab5..54c6d849cf25 100644 --- a/trunk/drivers/net/arm/ks8695net.c +++ b/trunk/drivers/net/arm/ks8695net.c @@ -854,12 +854,12 @@ ks8695_set_msglevel(struct net_device *ndev, u32 value) } /** - * ks8695_wan_get_settings - Get device-specific settings. + * ks8695_get_settings - Get device-specific settings. * @ndev: The network device to read settings from * @cmd: The ethtool structure to read into */ static int -ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; @@ -870,50 +870,69 @@ ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) SUPPORTED_TP | SUPPORTED_MII); cmd->transceiver = XCVR_INTERNAL; - cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - cmd->port = PORT_MII; - cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); - cmd->phy_address = 0; - - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - if ((ctrl & WMC_WAND) == 0) { - /* auto-negotiation is enabled */ - cmd->advertising |= ADVERTISED_Autoneg; - if (ctrl & WMC_WANA100F) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (ctrl & WMC_WANA100H) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (ctrl & WMC_WANA10F) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (ctrl & WMC_WANA10H) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (ctrl & WMC_WANAP) - cmd->advertising |= ADVERTISED_Pause; - cmd->autoneg = AUTONEG_ENABLE; - - cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; - cmd->duplex = (ctrl & WMC_WDS) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - /* auto-negotiation is disabled */ + /* Port specific extras */ + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + cmd->phy_address = 0; + /* not supported for HPNA */ cmd->autoneg = AUTONEG_DISABLE; - cmd->speed = (ctrl & WMC_WANF100) ? - SPEED_100 : SPEED_10; - cmd->duplex = (ctrl & WMC_WANFF) ? - DUPLEX_FULL : DUPLEX_HALF; + /* BUG: Erm, dtype hpna implies no phy regs */ + /* + ctrl = readl(KS8695_MISC_VA + KS8695_HMC); + cmd->speed = (ctrl & HMC_HSS) ? SPEED_100 : SPEED_10; + cmd->duplex = (ctrl & HMC_HDS) ? DUPLEX_FULL : DUPLEX_HALF; + */ + return -EOPNOTSUPP; + case KS8695_DTYPE_WAN: + cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; + cmd->port = PORT_MII; + cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); + cmd->phy_address = 0; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + if ((ctrl & WMC_WAND) == 0) { + /* auto-negotiation is enabled */ + cmd->advertising |= ADVERTISED_Autoneg; + if (ctrl & WMC_WANA100F) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (ctrl & WMC_WANA100H) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (ctrl & WMC_WANA10F) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (ctrl & WMC_WANA10H) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (ctrl & WMC_WANAP) + cmd->advertising |= ADVERTISED_Pause; + cmd->autoneg = AUTONEG_ENABLE; + + cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; + cmd->duplex = (ctrl & WMC_WDS) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + /* auto-negotiation is disabled */ + cmd->autoneg = AUTONEG_DISABLE; + + cmd->speed = (ctrl & WMC_WANF100) ? + SPEED_100 : SPEED_10; + cmd->duplex = (ctrl & WMC_WANFF) ? + DUPLEX_FULL : DUPLEX_HALF; + } + break; + case KS8695_DTYPE_LAN: + return -EOPNOTSUPP; } return 0; } /** - * ks8695_wan_set_settings - Set device-specific settings. + * ks8695_set_settings - Set device-specific settings. * @ndev: The network device to configure * @cmd: The settings to configure */ static int -ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; @@ -937,85 +956,171 @@ ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) ADVERTISED_100baseT_Full)) == 0) return -EINVAL; - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + /* HPNA does not support auto-negotiation. */ + return -EINVAL; + case KS8695_DTYPE_WAN: + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | + WMC_WANA10F | WMC_WANA10H); + if (cmd->advertising & ADVERTISED_100baseT_Full) + ctrl |= WMC_WANA100F; + if (cmd->advertising & ADVERTISED_100baseT_Half) + ctrl |= WMC_WANA100H; + if (cmd->advertising & ADVERTISED_10baseT_Full) + ctrl |= WMC_WANA10F; + if (cmd->advertising & ADVERTISED_10baseT_Half) + ctrl |= WMC_WANA10H; + + /* force a re-negotiation */ + ctrl |= WMC_WANR; + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + break; + case KS8695_DTYPE_LAN: + return -EOPNOTSUPP; + } - ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | - WMC_WANA10F | WMC_WANA10H); - if (cmd->advertising & ADVERTISED_100baseT_Full) - ctrl |= WMC_WANA100F; - if (cmd->advertising & ADVERTISED_100baseT_Half) - ctrl |= WMC_WANA100H; - if (cmd->advertising & ADVERTISED_10baseT_Full) - ctrl |= WMC_WANA10F; - if (cmd->advertising & ADVERTISED_10baseT_Half) - ctrl |= WMC_WANA10H; - - /* force a re-negotiation */ - ctrl |= WMC_WANR; - writel(ctrl, ksp->phyiface_regs + KS8695_WMC); } else { - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - - /* disable auto-negotiation */ - ctrl |= WMC_WAND; - ctrl &= ~(WMC_WANF100 | WMC_WANFF); - - if (cmd->speed == SPEED_100) - ctrl |= WMC_WANF100; - if (cmd->duplex == DUPLEX_FULL) - ctrl |= WMC_WANFF; - - writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + /* BUG: dtype_hpna implies no phy registers */ + /* + ctrl = __raw_readl(KS8695_MISC_VA + KS8695_HMC); + + ctrl &= ~(HMC_HSS | HMC_HDS); + if (cmd->speed == SPEED_100) + ctrl |= HMC_HSS; + if (cmd->duplex == DUPLEX_FULL) + ctrl |= HMC_HDS; + + __raw_writel(ctrl, KS8695_MISC_VA + KS8695_HMC); + */ + return -EOPNOTSUPP; + case KS8695_DTYPE_WAN: + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + /* disable auto-negotiation */ + ctrl |= WMC_WAND; + ctrl &= ~(WMC_WANF100 | WMC_WANFF); + + if (cmd->speed == SPEED_100) + ctrl |= WMC_WANF100; + if (cmd->duplex == DUPLEX_FULL) + ctrl |= WMC_WANFF; + + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); + break; + case KS8695_DTYPE_LAN: + return -EOPNOTSUPP; + } } return 0; } /** - * ks8695_wan_nwayreset - Restart the autonegotiation on the port. + * ks8695_nwayreset - Restart the autonegotiation on the port. * @ndev: The network device to restart autoneotiation on */ static int -ks8695_wan_nwayreset(struct net_device *ndev) +ks8695_nwayreset(struct net_device *ndev) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - - if ((ctrl & WMC_WAND) == 0) - writel(ctrl | WMC_WANR, - ksp->phyiface_regs + KS8695_WMC); - else - /* auto-negotiation not enabled */ + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + /* No phy means no autonegotiation on hpna */ return -EINVAL; + case KS8695_DTYPE_WAN: + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + + if ((ctrl & WMC_WAND) == 0) + writel(ctrl | WMC_WANR, + ksp->phyiface_regs + KS8695_WMC); + else + /* auto-negotiation not enabled */ + return -EINVAL; + break; + case KS8695_DTYPE_LAN: + return -EOPNOTSUPP; + } return 0; } /** - * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising + * ks8695_get_link - Retrieve link status of network interface + * @ndev: The network interface to retrive the link status of. + */ +static u32 +ks8695_get_link(struct net_device *ndev) +{ + struct ks8695_priv *ksp = netdev_priv(ndev); + u32 ctrl; + + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + /* HPNA always has link */ + return 1; + case KS8695_DTYPE_WAN: + /* WAN we can read the PHY for */ + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + return ctrl & WMC_WLS; + case KS8695_DTYPE_LAN: + return -EOPNOTSUPP; + } + return 0; +} + +/** + * ks8695_get_pause - Retrieve network pause/flow-control advertising * @ndev: The device to retrieve settings from * @param: The structure to fill out with the information */ static void -ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) +ks8695_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + switch (ksp->dtype) { + case KS8695_DTYPE_HPNA: + /* No phy link on hpna to configure */ + return; + case KS8695_DTYPE_WAN: + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - /* advertise Pause */ - param->autoneg = (ctrl & WMC_WANAP); + /* advertise Pause */ + param->autoneg = (ctrl & WMC_WANAP); - /* current Rx Flow-control */ - ctrl = ks8695_readreg(ksp, KS8695_DRXC); - param->rx_pause = (ctrl & DRXC_RFCE); + /* current Rx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + param->rx_pause = (ctrl & DRXC_RFCE); - /* current Tx Flow-control */ - ctrl = ks8695_readreg(ksp, KS8695_DTXC); - param->tx_pause = (ctrl & DTXC_TFCE); + /* current Tx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DTXC); + param->tx_pause = (ctrl & DTXC_TFCE); + break; + case KS8695_DTYPE_LAN: + /* The LAN's "phy" is a direct-attached switch */ + return; + } +} + +/** + * ks8695_set_pause - Configure pause/flow-control + * @ndev: The device to configure + * @param: The pause parameters to set + * + * TODO: Implement this + */ +static int +ks8695_set_pause(struct net_device *ndev, struct ethtool_pauseparam *param) +{ + return -EOPNOTSUPP; } /** @@ -1035,17 +1140,12 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) static const struct ethtool_ops ks8695_ethtool_ops = { .get_msglevel = ks8695_get_msglevel, .set_msglevel = ks8695_set_msglevel, - .get_drvinfo = ks8695_get_drvinfo, -}; - -static const struct ethtool_ops ks8695_wan_ethtool_ops = { - .get_msglevel = ks8695_get_msglevel, - .set_msglevel = ks8695_set_msglevel, - .get_settings = ks8695_wan_get_settings, - .set_settings = ks8695_wan_set_settings, - .nway_reset = ks8695_wan_nwayreset, - .get_link = ethtool_op_get_link, - .get_pauseparam = ks8695_wan_get_pause, + .get_settings = ks8695_get_settings, + .set_settings = ks8695_set_settings, + .nway_reset = ks8695_nwayreset, + .get_link = ks8695_get_link, + .get_pauseparam = ks8695_get_pause, + .set_pauseparam = ks8695_set_pause, .get_drvinfo = ks8695_get_drvinfo, }; @@ -1441,6 +1541,7 @@ ks8695_probe(struct platform_device *pdev) /* driver system setup */ ndev->netdev_ops = &ks8695_netdev_ops; + SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); ndev->watchdog_timeo = msecs_to_jiffies(watchdog); netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); @@ -1507,15 +1608,12 @@ ks8695_probe(struct platform_device *pdev) if (ksp->phyiface_regs && ksp->link_irq == -1) { ks8695_init_switch(ksp); ksp->dtype = KS8695_DTYPE_LAN; - SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); } else if (ksp->phyiface_regs && ksp->link_irq != -1) { ks8695_init_wan_phy(ksp); ksp->dtype = KS8695_DTYPE_WAN; - SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); } else { /* No initialisation since HPNA does not have a PHY */ ksp->dtype = KS8695_DTYPE_HPNA; - SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); } /* And bring up the net_device with the net core */ diff --git a/trunk/drivers/net/bfin_mac.c b/trunk/drivers/net/bfin_mac.c index 22abfb39d813..fe75e7a9742e 100644 --- a/trunk/drivers/net/bfin_mac.c +++ b/trunk/drivers/net/bfin_mac.c @@ -1284,12 +1284,19 @@ static void bfin_mac_multicast_hash(struct net_device *dev) { u32 emac_hashhi, emac_hashlo; struct netdev_hw_addr *ha; + char *addrs; u32 crc; emac_hashhi = emac_hashlo = 0; netdev_for_each_mc_addr(ha, dev) { - crc = ether_crc(ETH_ALEN, ha->addr); + addrs = ha->addr; + + /* skip non-multicast addresses */ + if (!is_multicast_ether_addr(addrs)) + continue; + + crc = ether_crc(ETH_ALEN, addrs); crc >>= 26; if (crc & 0x20) diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c index 3437613f0454..7206ab2cbbf8 100644 --- a/trunk/drivers/net/cassini.c +++ b/trunk/drivers/net/cassini.c @@ -3203,7 +3203,7 @@ static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */ int mac_off = 0; -#if defined(CONFIG_SPARC) +#if defined(CONFIG_OF) const unsigned char *addr; #endif @@ -3354,7 +3354,7 @@ static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, if (found & VPD_FOUND_MAC) goto done; -#if defined(CONFIG_SPARC) +#if defined(CONFIG_OF) addr = of_get_property(cp->of_node, "local-mac-address", NULL); if (addr != NULL) { memcpy(dev_addr, addr, 6); @@ -5031,7 +5031,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE : cassini_debug; -#if defined(CONFIG_SPARC) +#if defined(CONFIG_OF) cp->of_node = pci_device_to_OF_node(pdev); #endif diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 4ff88a683f61..e332aee386f6 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -3478,9 +3478,17 @@ static irqreturn_t e1000_intr(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 icr = er32(ICR); - if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags))) + if (unlikely((!icr))) return IRQ_NONE; /* Not our interrupt */ + /* + * we might have caused the interrupt, but the above + * read cleared it, and just in case the driver is + * down there is nothing to do so return handled + */ + if (unlikely(test_bit(__E1000_DOWN, &adapter->flags))) + return IRQ_HANDLED; + if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; /* guard against interrupt when we're going down */ diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index f1d4b450e797..45c4b7bfcf39 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -433,6 +433,7 @@ static void gfar_init_mac(struct net_device *ndev) static struct net_device_stats *gfar_get_stats(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + struct netdev_queue *txq; unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; unsigned long tx_packets = 0, tx_bytes = 0; int i = 0; @@ -448,8 +449,9 @@ static struct net_device_stats *gfar_get_stats(struct net_device *dev) dev->stats.rx_dropped = rx_dropped; for (i = 0; i < priv->num_tx_queues; i++) { - tx_bytes += priv->tx_queue[i]->stats.tx_bytes; - tx_packets += priv->tx_queue[i]->stats.tx_packets; + txq = netdev_get_tx_queue(dev, i); + tx_bytes += txq->tx_bytes; + tx_packets += txq->tx_packets; } dev->stats.tx_bytes = tx_bytes; @@ -2106,8 +2108,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Update transmit stats */ - tx_queue->stats.tx_bytes += skb->len; - tx_queue->stats.tx_packets++; + txq->tx_bytes += skb->len; + txq->tx_packets ++; txbdp = txbdp_start = tx_queue->cur_tx; lstatus = txbdp->lstatus; diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h index 54de4135e932..68984eb88ae0 100644 --- a/trunk/drivers/net/gianfar.h +++ b/trunk/drivers/net/gianfar.h @@ -907,21 +907,12 @@ enum { MQ_MG_MODE }; -/* - * Per TX queue stats - */ -struct tx_q_stats { - unsigned long tx_packets; - unsigned long tx_bytes; -}; - /** * struct gfar_priv_tx_q - per tx queue structure * @txlock: per queue tx spin lock * @tx_skbuff:skb pointers * @skb_curtx: to be used skb pointer * @skb_dirtytx:the last used skb pointer - * @stats: bytes/packets stats * @qindex: index of this queue * @dev: back pointer to the dev structure * @grp: back pointer to the group to which this queue belongs @@ -943,7 +934,6 @@ struct gfar_priv_tx_q { struct txbd8 *tx_bd_base; struct txbd8 *cur_tx; struct txbd8 *dirty_tx; - struct tx_q_stats stats; struct net_device *dev; struct gfar_priv_grp *grp; u16 skb_curtx; diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 602078b84892..a060610a42db 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -6667,6 +6667,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) { + struct net_device *netdev = tx_ring->netdev; + struct netdev_queue *txq; unsigned int first; unsigned int tx_flags = 0; u8 hdr_len = 0; @@ -6763,6 +6765,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, /* add the ATR filter if ATR is on */ if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state)) ixgbe_atr(tx_ring, skb, tx_flags, protocol); + txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); + txq->tx_bytes += skb->len; + txq->tx_packets++; ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len); ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED); @@ -6920,6 +6925,8 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); int i; + /* accurate rx/tx bytes/packets stats */ + dev_txq_stats_fold(netdev, stats); rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = ACCESS_ONCE(adapter->rx_ring[i]); @@ -6936,22 +6943,6 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, stats->rx_bytes += bytes; } } - - for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbe_ring *ring = ACCESS_ONCE(adapter->tx_ring[i]); - u64 bytes, packets; - unsigned int start; - - if (ring) { - do { - start = u64_stats_fetch_begin_bh(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; - } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); - stats->tx_packets += packets; - stats->tx_bytes += bytes; - } - } rcu_read_unlock(); /* following stats updated by ixgbe_watchdog_task() */ stats->multicast = netdev->stats.multicast; diff --git a/trunk/drivers/net/macvtap.c b/trunk/drivers/net/macvtap.c index 5933621ac3ff..21845affea13 100644 --- a/trunk/drivers/net/macvtap.c +++ b/trunk/drivers/net/macvtap.c @@ -585,7 +585,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); if (vlan) - vlan->dev->stats.tx_dropped++; + netdev_get_tx_queue(vlan->dev, 0)->tx_dropped++; rcu_read_unlock_bh(); return err; diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index bde7d61f1930..bb8645ab247c 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -554,8 +554,6 @@ struct rtl8169_private { struct mii_if_info mii; struct rtl8169_counters counters; u32 saved_wolopts; - - const struct firmware *fw; }; MODULE_AUTHOR("Realtek and the Linux r8169 crew "); @@ -1768,29 +1766,6 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) } } -static void rtl_release_firmware(struct rtl8169_private *tp) -{ - release_firmware(tp->fw); - tp->fw = NULL; -} - -static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) -{ - const struct firmware **fw = &tp->fw; - int rc = !*fw; - - if (rc) { - rc = request_firmware(fw, fw_name, &tp->pci_dev->dev); - if (rc < 0) - goto out; - } - - /* TODO: release firmware once rtl_phy_write_fw signals failures. */ - rtl_phy_write_fw(tp, *fw); -out: - return rc; -} - static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -2164,6 +2139,7 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) { 0x0d, 0xf880 } }; void __iomem *ioaddr = tp->mmio_addr; + const struct firmware *fw; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); @@ -2227,8 +2203,11 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x001b); - if ((rtl_readphy(tp, 0x06) != 0xbf00) || - (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { + if (rtl_readphy(tp, 0x06) == 0xbf00 && + request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) { + rtl_phy_write_fw(tp, fw); + release_firmware(fw); + } else { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } @@ -2278,6 +2257,7 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) { 0x0d, 0xf880 } }; void __iomem *ioaddr = tp->mmio_addr; + const struct firmware *fw; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); @@ -2332,8 +2312,11 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x001b); - if ((rtl_readphy(tp, 0x06) != 0xb300) || - (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { + if (rtl_readphy(tp, 0x06) == 0xb300 && + request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) { + rtl_phy_write_fw(tp, fw); + release_firmware(fw); + } else { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } @@ -3217,8 +3200,6 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) cancel_delayed_work_sync(&tp->task); - rtl_release_firmware(tp); - unregister_netdev(dev); if (pci_dev_run_wake(pdev)) diff --git a/trunk/drivers/net/sfc/efx.c b/trunk/drivers/net/sfc/efx.c index 002bac743843..711449c6e675 100644 --- a/trunk/drivers/net/sfc/efx.c +++ b/trunk/drivers/net/sfc/efx.c @@ -1153,9 +1153,6 @@ static int efx_wanted_channels(void) int count; int cpu; - if (rss_cpus) - return rss_cpus; - if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) { printk(KERN_WARNING "sfc: RSS disabled due to allocation failure\n"); @@ -1269,18 +1266,27 @@ static void efx_remove_interrupts(struct efx_nic *efx) efx->legacy_irq = 0; } +struct efx_tx_queue * +efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) +{ + unsigned tx_channel_offset = + separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; + EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels || + type >= EFX_TXQ_TYPES); + return &efx->channel[tx_channel_offset + index]->tx_queue[type]; +} + static void efx_set_channels(struct efx_nic *efx) { struct efx_channel *channel; struct efx_tx_queue *tx_queue; - - efx->tx_channel_offset = + unsigned tx_channel_offset = separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; /* Channel pointers were set in efx_init_struct() but we now * need to clear them for TX queues in any RX-only channels. */ efx_for_each_channel(channel, efx) { - if (channel->channel - efx->tx_channel_offset >= + if (channel->channel - tx_channel_offset >= efx->n_tx_channels) { efx_for_each_channel_tx_queue(tx_queue, channel) tx_queue->channel = NULL; diff --git a/trunk/drivers/net/sfc/net_driver.h b/trunk/drivers/net/sfc/net_driver.h index 28df8665256a..bdce66ddf93a 100644 --- a/trunk/drivers/net/sfc/net_driver.h +++ b/trunk/drivers/net/sfc/net_driver.h @@ -735,7 +735,6 @@ struct efx_nic { unsigned next_buffer_table; unsigned n_channels; unsigned n_rx_channels; - unsigned tx_channel_offset; unsigned n_tx_channels; unsigned int rx_buffer_len; unsigned int rx_buffer_order; @@ -930,13 +929,8 @@ efx_get_channel(struct efx_nic *efx, unsigned index) _channel = (_channel->channel + 1 < (_efx)->n_channels) ? \ (_efx)->channel[_channel->channel + 1] : NULL) -static inline struct efx_tx_queue * -efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) -{ - EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels || - type >= EFX_TXQ_TYPES); - return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type]; -} +extern struct efx_tx_queue * +efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type); static inline struct efx_tx_queue * efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type) diff --git a/trunk/drivers/net/tile/tilepro.c b/trunk/drivers/net/tile/tilepro.c index 7cb301da7474..0e6bac5ec65b 100644 --- a/trunk/drivers/net/tile/tilepro.c +++ b/trunk/drivers/net/tile/tilepro.c @@ -142,6 +142,14 @@ MODULE_AUTHOR("Tilera"); MODULE_LICENSE("GPL"); + +#define IS_MULTICAST(mac_addr) \ + (((u8 *)(mac_addr))[0] & 0x01) + +#define IS_BROADCAST(mac_addr) \ + (((u16 *)(mac_addr))[0] == 0xffff) + + /* * Queue of incoming packets for a specific cpu and device. * @@ -787,7 +795,7 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index) /* * FIXME: Implement HW multicast filter. */ - if (is_unicast_ether_addr(buf)) { + if (!IS_MULTICAST(buf) && !IS_BROADCAST(buf)) { /* Filter packets not for our address. */ const u8 *mine = dev->dev_addr; filter = compare_ether_addr(mine, buf); diff --git a/trunk/drivers/net/usb/cdc_ncm.c b/trunk/drivers/net/usb/cdc_ncm.c index d776c4a8d3c1..593c104ab199 100644 --- a/trunk/drivers/net/usb/cdc_ncm.c +++ b/trunk/drivers/net/usb/cdc_ncm.c @@ -1021,15 +1021,13 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) (temp > CDC_NCM_MAX_DATAGRAM_SIZE) || (temp < ETH_HLEN)) { pr_debug("invalid frame detected (ignored)" "offset[%u]=%u, length=%u, skb=%p\n", - x, offset, temp, skb_in); + x, offset, temp, skb); if (!x) goto error; break; } else { skb = skb_clone(skb_in, GFP_ATOMIC); - if (!skb) - goto error; skb->len = temp; skb->data = ((u8 *)skb_in->data) + offset; skb_set_tail_pointer(skb, temp); diff --git a/trunk/drivers/net/vxge/vxge-main.c b/trunk/drivers/net/vxge/vxge-main.c index c81a6512c683..1ac9b568f1b0 100644 --- a/trunk/drivers/net/vxge/vxge-main.c +++ b/trunk/drivers/net/vxge/vxge-main.c @@ -4120,7 +4120,6 @@ int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override) "hotplug event.\n"); out: - release_firmware(fw); return ret; } diff --git a/trunk/drivers/vhost/vhost.c b/trunk/drivers/vhost/vhost.c index ade0568c07a4..38244f59cdd9 100644 --- a/trunk/drivers/vhost/vhost.c +++ b/trunk/drivers/vhost/vhost.c @@ -97,26 +97,22 @@ void vhost_poll_stop(struct vhost_poll *poll) remove_wait_queue(poll->wqh, &poll->wait); } -static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, - unsigned seq) -{ - int left; - spin_lock_irq(&dev->work_lock); - left = seq - work->done_seq; - spin_unlock_irq(&dev->work_lock); - return left <= 0; -} - static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) { unsigned seq; + int left; int flushing; spin_lock_irq(&dev->work_lock); seq = work->queue_seq; work->flushing++; spin_unlock_irq(&dev->work_lock); - wait_event(work->done, vhost_work_seq_done(dev, work, seq)); + wait_event(work->done, ({ + spin_lock_irq(&dev->work_lock); + left = seq - work->done_seq <= 0; + spin_unlock_irq(&dev->work_lock); + left; + })); spin_lock_irq(&dev->work_lock); flushing = --work->flushing; spin_unlock_irq(&dev->work_lock); diff --git a/trunk/include/linux/etherdevice.h b/trunk/include/linux/etherdevice.h index ab68f785fd19..bec8b82889bf 100644 --- a/trunk/include/linux/etherdevice.h +++ b/trunk/include/linux/etherdevice.h @@ -98,17 +98,6 @@ static inline int is_broadcast_ether_addr(const u8 *addr) return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; } -/** - * is_unicast_ether_addr - Determine if the Ethernet address is unicast - * @addr: Pointer to a six-byte array containing the Ethernet address - * - * Return true if the address is a unicast address. - */ -static inline int is_unicast_ether_addr(const u8 *addr) -{ - return !is_multicast_ether_addr(addr); -} - /** * is_valid_ether_addr - Determine if the given Ethernet address is valid * @addr: Pointer to a six-byte array containing the Ethernet address diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index d971346b0340..be4957cf6511 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -520,6 +520,9 @@ struct netdev_queue { * please use this field instead of dev->trans_start */ unsigned long trans_start; + u64 tx_bytes; + u64 tx_packets; + u64 tx_dropped; } ____cacheline_aligned_in_smp; static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) @@ -2262,6 +2265,8 @@ extern void dev_load(struct net *net, const char *name); extern void dev_mcast_init(void); extern struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, struct rtnl_link_stats64 *storage); +extern void dev_txq_stats_fold(const struct net_device *dev, + struct rtnl_link_stats64 *stats); extern int netdev_max_backlog; extern int netdev_tstamp_prequeue; diff --git a/trunk/include/net/ah.h b/trunk/include/net/ah.h index ca95b98969dd..be7798dea6f4 100644 --- a/trunk/include/net/ah.h +++ b/trunk/include/net/ah.h @@ -4,7 +4,7 @@ #include /* This is the maximum truncated ICV length that we know of. */ -#define MAX_AH_AUTH_LEN 64 +#define MAX_AH_AUTH_LEN 16 struct crypto_ahash; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 83507c265e48..a3ef808b5e36 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -5523,6 +5523,34 @@ void netdev_run_todo(void) } } +/** + * dev_txq_stats_fold - fold tx_queues stats + * @dev: device to get statistics from + * @stats: struct rtnl_link_stats64 to hold results + */ +void dev_txq_stats_fold(const struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + u64 tx_bytes = 0, tx_packets = 0, tx_dropped = 0; + unsigned int i; + struct netdev_queue *txq; + + for (i = 0; i < dev->num_tx_queues; i++) { + txq = netdev_get_tx_queue(dev, i); + spin_lock_bh(&txq->_xmit_lock); + tx_bytes += txq->tx_bytes; + tx_packets += txq->tx_packets; + tx_dropped += txq->tx_dropped; + spin_unlock_bh(&txq->_xmit_lock); + } + if (tx_bytes || tx_packets || tx_dropped) { + stats->tx_bytes = tx_bytes; + stats->tx_packets = tx_packets; + stats->tx_dropped = tx_dropped; + } +} +EXPORT_SYMBOL(dev_txq_stats_fold); + /* Convert net_device_stats to rtnl_link_stats64. They have the same * fields in the same order, with only the type differing. */ @@ -5566,6 +5594,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev)); } else { netdev_stats_to_stats64(storage, &dev->stats); + dev_txq_stats_fold(dev, storage); } storage->rx_dropped += atomic_long_read(&dev->rx_dropped); return storage; diff --git a/trunk/net/sched/sch_teql.c b/trunk/net/sched/sch_teql.c index 84ce48eadff4..af9360d1f6eb 100644 --- a/trunk/net/sched/sch_teql.c +++ b/trunk/net/sched/sch_teql.c @@ -59,10 +59,6 @@ struct teql_master struct net_device *dev; struct Qdisc *slaves; struct list_head master_list; - unsigned long tx_bytes; - unsigned long tx_packets; - unsigned long tx_errors; - unsigned long tx_dropped; }; struct teql_sched_data @@ -278,6 +274,7 @@ static inline int teql_resolve(struct sk_buff *skb, static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) { struct teql_master *master = netdev_priv(dev); + struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); struct Qdisc *start, *q; int busy; int nores; @@ -317,8 +314,8 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) __netif_tx_unlock(slave_txq); master->slaves = NEXT_SLAVE(q); netif_wake_queue(dev); - master->tx_packets++; - master->tx_bytes += length; + txq->tx_packets++; + txq->tx_bytes += length; return NETDEV_TX_OK; } __netif_tx_unlock(slave_txq); @@ -345,10 +342,10 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); return NETDEV_TX_BUSY; } - master->tx_errors++; + dev->stats.tx_errors++; drop: - master->tx_dropped++; + txq->tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -401,18 +398,6 @@ static int teql_master_close(struct net_device *dev) return 0; } -static struct rtnl_link_stats64 *teql_master_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats) -{ - struct teql_master *m = netdev_priv(dev); - - stats->tx_packets = m->tx_packets; - stats->tx_bytes = m->tx_bytes; - stats->tx_errors = m->tx_errors; - stats->tx_dropped = m->tx_dropped; - return stats; -} - static int teql_master_mtu(struct net_device *dev, int new_mtu) { struct teql_master *m = netdev_priv(dev); @@ -437,7 +422,6 @@ static const struct net_device_ops teql_netdev_ops = { .ndo_open = teql_master_open, .ndo_stop = teql_master_close, .ndo_start_xmit = teql_master_xmit, - .ndo_get_stats64 = teql_master_stats64, .ndo_change_mtu = teql_master_mtu, };