aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vmxnet3/vmxnet3_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/vmxnet3/vmxnet3_drv.c')
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c194
1 files changed, 80 insertions, 114 deletions
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 0ef676d..28ceef2 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -24,6 +24,7 @@
*
*/
+#include <linux/module.h>
#include <net/ip6_checksum.h>
#include "vmxnet3_int.h"
@@ -405,10 +406,8 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
struct vmxnet3_tx_buf_info *tbi;
- union Vmxnet3_GenericDesc *gdesc;
tbi = tq->buf_info + tq->tx_ring.next2comp;
- gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
if (tbi->skb) {
@@ -656,10 +655,11 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
- frag->page = rbi->page;
+ __skb_frag_set_page(frag, rbi->page);
frag->page_offset = 0;
- frag->size = rcd->len;
- skb->data_len += frag->size;
+ skb_frag_size_set(frag, rcd->len);
+ skb->data_len += rcd->len;
+ skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
}
@@ -746,21 +746,21 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
tbi = tq->buf_info + tq->tx_ring.next2fill;
tbi->map_type = VMXNET3_MAP_PAGE;
- tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- tbi->len = frag->size;
+ tbi->len = skb_frag_size(frag);
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
- gdesc->dword[2] = cpu_to_le32(dw2 | frag->size);
+ gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
gdesc->dword[3] = 0;
dev_dbg(&adapter->netdev->dev,
@@ -921,7 +921,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
skb_shinfo(skb)->nr_frags + 1;
- ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
+ ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
ctx.mss = skb_shinfo(skb)->gso_size;
if (ctx.mss) {
@@ -1274,18 +1274,18 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
skb = ctx->skb;
if (rcd->eop) {
skb->len += skb->data_len;
- skb->truesize += skb->data_len;
vmxnet3_rx_csum(adapter, skb,
(union Vmxnet3_GenericDesc *)rcd);
skb->protocol = eth_type_trans(skb, adapter->netdev);
- if (unlikely(adapter->vlan_grp && rcd->ts)) {
- vlan_hwaccel_receive_skb(skb,
- adapter->vlan_grp, rcd->tci);
- } else {
+ if (unlikely(rcd->ts))
+ __vlan_hwaccel_put_tag(skb, rcd->tci);
+
+ if (adapter->netdev->features & NETIF_F_LRO)
netif_receive_skb(skb);
- }
+ else
+ napi_gro_receive(&rq->napi, skb);
ctx->skb = NULL;
}
@@ -1734,11 +1734,20 @@ vmxnet3_netpoll(struct net_device *netdev)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
- vmxnet3_disable_all_intrs(adapter);
-
- vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size);
- vmxnet3_enable_all_intrs(adapter);
+ switch (adapter->intr.type) {
+#ifdef CONFIG_PCI_MSI
+ case VMXNET3_IT_MSIX: {
+ int i;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ vmxnet3_msix_rx(0, &adapter->rx_queue[i]);
+ break;
+ }
+#endif
+ case VMXNET3_IT_MSI:
+ default:
+ vmxnet3_intr(0, adapter->netdev);
+ break;
+ }
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -1906,94 +1915,38 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
}
}
+
static void
-vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- struct Vmxnet3_DriverShared *shared = adapter->shared;
u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- if (grp) {
- /* add vlan rx stripping. */
- if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
- int i;
- adapter->vlan_grp = grp;
-
- /*
- * Clear entire vfTable; then enable untagged pkts.
- * Note: setting one entry in vfTable to non-zero turns
- * on VLAN rx filtering.
- */
- for (i = 0; i < VMXNET3_VFT_SIZE; i++)
- vfTable[i] = 0;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- } else {
- printk(KERN_ERR "%s: vlan_rx_register when device has "
- "no NETIF_F_HW_VLAN_RX\n", netdev->name);
- }
- } else {
- /* remove vlan rx stripping. */
- struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
- adapter->vlan_grp = NULL;
+ u16 vid;
- if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
- int i;
+ /* allow untagged pkts */
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
- /* clear entire vfTable; this also disables
- * VLAN rx filtering
- */
- vfTable[i] = 0;
- }
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- }
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
}
static void
-vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
+vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
- if (adapter->vlan_grp) {
- u16 vid;
+ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+ if (!(netdev->flags & IFF_PROMISC)) {
u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- bool activeVlan = false;
+ unsigned long flags;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (vlan_group_get_device(adapter->vlan_grp, vid)) {
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- activeVlan = true;
- }
- }
- if (activeVlan) {
- /* continue to allow untagged pkts */
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
- }
+ VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
}
-}
-
-static void
-vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
- struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
-
- VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ set_bit(vid, adapter->active_vlans);
}
@@ -2001,14 +1954,19 @@ static void
vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
- unsigned long flags;
- VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
- spin_lock_irqsave(&adapter->cmd_lock, flags);
- VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
- VMXNET3_CMD_UPDATE_VLAN_FILTERS);
- spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ if (!(netdev->flags & IFF_PROMISC)) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ unsigned long flags;
+
+ VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ }
+
+ clear_bit(vid, adapter->active_vlans);
}
@@ -2045,8 +2003,14 @@ vmxnet3_set_mc(struct net_device *netdev)
u8 *new_table = NULL;
u32 new_mode = VMXNET3_RXM_UCAST;
- if (netdev->flags & IFF_PROMISC)
+ if (netdev->flags & IFF_PROMISC) {
+ u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+ memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
+
new_mode |= VMXNET3_RXM_PROMISC;
+ } else {
+ vmxnet3_restore_vlan(adapter);
+ }
if (netdev->flags & IFF_BROADCAST)
new_mode |= VMXNET3_RXM_BCAST;
@@ -2080,6 +2044,8 @@ vmxnet3_set_mc(struct net_device *netdev)
rxConf->rxMode = cpu_to_le32(new_mode);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_RX_MODE);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_UPDATE_VLAN_FILTERS);
}
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -2689,12 +2655,13 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX |
- NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO;
+ NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_LRO;
if (dma64)
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ netdev->hw_features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features = netdev->hw_features &
+ ~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_FILTER;
netdev_info(adapter->netdev,
"features: sg csum vlan jf tso tsoIPv6 lro%s\n",
@@ -2912,10 +2879,9 @@ vmxnet3_probe_device(struct pci_dev *pdev,
.ndo_set_mac_address = vmxnet3_set_mac_addr,
.ndo_change_mtu = vmxnet3_change_mtu,
.ndo_set_features = vmxnet3_set_features,
- .ndo_get_stats = vmxnet3_get_stats,
+ .ndo_get_stats64 = vmxnet3_get_stats64,
.ndo_tx_timeout = vmxnet3_tx_timeout,
- .ndo_set_multicast_list = vmxnet3_set_mc,
- .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
+ .ndo_set_rx_mode = vmxnet3_set_mc,
.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3038,6 +3004,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
goto err_ver;
}
+ SET_NETDEV_DEV(netdev, &pdev->dev);
vmxnet3_declare_features(adapter, dma64);
adapter->dev_number = atomic_read(&devices_found);
@@ -3083,7 +3050,6 @@ vmxnet3_probe_device(struct pci_dev *pdev,
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
- SET_NETDEV_DEV(netdev, &pdev->dev);
err = register_netdev(netdev);
if (err) {