diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 09:38:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 09:38:14 -0700 |
commit | ae045e2455429c418a418a3376301a9e5753a0a8 (patch) | |
tree | b445bdeecd3f38aa0d0a29c9585cee49e4ccb0f1 /drivers/net/ethernet/intel/i40evf/i40evf_main.c | |
parent | f4f142ed4ef835709c7e6d12eaca10d190bcebed (diff) | |
parent | d247b6ab3ce6dd43665780865ec5fa145d9ab6bd (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
"Highlights:
1) Steady transitioning of the BPF instructure to a generic spot so
all kernel subsystems can make use of it, from Alexei Starovoitov.
2) SFC driver supports busy polling, from Alexandre Rames.
3) Take advantage of hash table in UDP multicast delivery, from David
Held.
4) Lighten locking, in particular by getting rid of the LRU lists, in
inet frag handling. From Florian Westphal.
5) Add support for various RFC6458 control messages in SCTP, from
Geir Ola Vaagland.
6) Allow to filter bridge forwarding database dumps by device, from
Jamal Hadi Salim.
7) virtio-net also now supports busy polling, from Jason Wang.
8) Some low level optimization tweaks in pktgen from Jesper Dangaard
Brouer.
9) Add support for ipv6 address generation modes, so that userland
can have some input into the process. From Jiri Pirko.
10) Consolidate common TCP connection request code in ipv4 and ipv6,
from Octavian Purdila.
11) New ARP packet logger in netfilter, from Pablo Neira Ayuso.
12) Generic resizable RCU hash table, with intial users in netlink and
nftables. From Thomas Graf.
13) Maintain a name assignment type so that userspace can see where a
network device name came from (enumerated by kernel, assigned
explicitly by userspace, etc.) From Tom Gundersen.
14) Automatic flow label generation on transmit in ipv6, from Tom
Herbert.
15) New packet timestamping facilities from Willem de Bruijn, meant to
assist in measuring latencies going into/out-of the packet
scheduler, latency from TCP data transmission to ACK, etc"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1536 commits)
cxgb4 : Disable recursive mailbox commands when enabling vi
net: reduce USB network driver config options.
tg3: Modify tg3_tso_bug() to handle multiple TX rings
amd-xgbe: Perform phy connect/disconnect at dev open/stop
amd-xgbe: Use dma_set_mask_and_coherent to set DMA mask
net: sun4i-emac: fix memory leak on bad packet
sctp: fix possible seqlock seadlock in sctp_packet_transmit()
Revert "net: phy: Set the driver when registering an MDIO bus device"
cxgb4vf: Turn off SGE RX/TX Callback Timers and interrupts in PCI shutdown routine
team: Simplify return path of team_newlink
bridge: Update outdated comment on promiscuous mode
net-timestamp: ACK timestamp for bytestreams
net-timestamp: TCP timestamping
net-timestamp: SCHED timestamp on entering packet scheduler
net-timestamp: add key to disambiguate concurrent datagrams
net-timestamp: move timestamp flags out of sk_flags
net-timestamp: extend SCM_TIMESTAMPING ancillary data struct
cxgb4i : Move stray CPL definitions to cxgb4 driver
tcp: reduce spurious retransmits due to transient SACK reneging
qlcnic: Initialize dcbnl_ops before register_netdev
...
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_main.c | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 7fc5f3b5d6bf..ab15f4d07e41 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,9 +34,9 @@ static int i40evf_close(struct net_device *netdev); char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = - "Intel(R) XL710 X710 Virtual Function Network Driver"; + "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "0.9.34" +#define DRV_VERSION "0.9.40" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2014 Intel Corporation."; @@ -260,6 +260,12 @@ static void i40evf_fire_sw_int(struct i40evf_adapter *adapter, int i; uint32_t dyn_ctl; + if (mask & 1) { + dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTL01); + dyn_ctl |= I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK | + I40E_VFINT_DYN_CTLN_CLEARPBA_MASK; + wr32(hw, I40E_VFINT_DYN_CTL01, dyn_ctl); + } for (i = 1; i < adapter->num_msix_vectors; i++) { if (mask & (1 << i)) { dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTLN1(i - 1)); @@ -278,6 +284,7 @@ void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush) { struct i40e_hw *hw = &adapter->hw; + i40evf_misc_irq_enable(adapter); i40evf_irq_enable_queues(adapter, ~0); if (flush) @@ -520,7 +527,8 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter) struct net_device *netdev = adapter->netdev; int err; - sprintf(adapter->misc_vector_name, "i40evf:mbx"); + snprintf(adapter->misc_vector_name, + sizeof(adapter->misc_vector_name) - 1, "i40evf:mbx"); err = request_irq(adapter->msix_entries[0].vector, &i40evf_msix_aq, 0, adapter->misc_vector_name, netdev); @@ -761,7 +769,7 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter, while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) - mdelay(1); + udelay(1); f = i40evf_find_filter(adapter, macaddr); if (NULL == f) { @@ -833,7 +841,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev) while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) - mdelay(1); + udelay(1); /* remove filter if not in netdev list */ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { bool found = false; @@ -1290,12 +1298,16 @@ static void i40evf_watchdog_task(struct work_struct *work) struct i40evf_adapter, watchdog_task); struct i40e_hw *hw = &adapter->hw; + uint32_t rstat_val; if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) goto restart_watchdog; if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) { - if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) { + rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & + I40E_VFGEN_RSTAT_VFR_STATE_MASK; + if ((rstat_val == I40E_VFR_VFACTIVE) || + (rstat_val == I40E_VFR_COMPLETED)) { /* A chance for redemption! */ dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n"); adapter->state = __I40EVF_STARTUP; @@ -1321,8 +1333,11 @@ static void i40evf_watchdog_task(struct work_struct *work) goto watchdog_done; /* check for reset */ + rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & + I40E_VFGEN_RSTAT_VFR_STATE_MASK; if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && - (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) { + (rstat_val != I40E_VFR_VFACTIVE) && + (rstat_val != I40E_VFR_COMPLETED)) { adapter->state = __I40EVF_RESETTING; adapter->flags |= I40EVF_FLAG_RESET_PENDING; dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); @@ -1388,6 +1403,8 @@ static void i40evf_watchdog_task(struct work_struct *work) watchdog_done: clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); restart_watchdog: + if (adapter->state == __I40EVF_REMOVE) + return; if (adapter->aq_required) mod_timer(&adapter->watchdog_timer, jiffies + msecs_to_jiffies(20)); @@ -1488,7 +1505,8 @@ static void i40evf_reset_task(struct work_struct *work) for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if (rstat_val != I40E_VFR_VFACTIVE) + if ((rstat_val != I40E_VFR_VFACTIVE) && + (rstat_val != I40E_VFR_COMPLETED)) break; else msleep(I40EVF_RESET_WAIT_MS); @@ -1502,12 +1520,16 @@ static void i40evf_reset_task(struct work_struct *work) for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if (rstat_val == I40E_VFR_VFACTIVE) + if ((rstat_val == I40E_VFR_VFACTIVE) || + (rstat_val == I40E_VFR_COMPLETED)) break; else msleep(I40EVF_RESET_WAIT_MS); } if (i == I40EVF_RESET_WAIT_COUNT) { + struct i40evf_mac_filter *f, *ftmp; + struct i40evf_vlan_filter *fv, *fvtmp; + /* reset never finished */ dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", rstat_val); @@ -1520,9 +1542,23 @@ static void i40evf_reset_task(struct work_struct *work) i40evf_free_all_tx_resources(adapter); i40evf_free_all_rx_resources(adapter); } + + /* Delete all of the filters, both MAC and VLAN. */ + list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, + list) { + list_del(&f->list); + kfree(f); + } + list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, + list) { + list_del(&fv->list); + kfree(fv); + } + i40evf_free_misc_irq(adapter); i40evf_reset_interrupt_capability(adapter); i40evf_free_queues(adapter); + i40evf_free_q_vectors(adapter); kfree(adapter->vf_res); i40evf_shutdown_adminq(hw); adapter->netdev->flags &= ~IFF_UP; @@ -1939,8 +1975,10 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw) int i; for (i = 0; i < 100; i++) { - rstat = rd32(hw, I40E_VFGEN_RSTAT); - if (rstat == I40E_VFR_VFACTIVE) + rstat = rd32(hw, I40E_VFGEN_RSTAT) & + I40E_VFGEN_RSTAT_VFR_STATE_MASK; + if ((rstat == I40E_VFR_VFACTIVE) || + (rstat == I40E_VFR_COMPLETED)) return 0; udelay(10); } @@ -2006,7 +2044,6 @@ static void i40evf_init_task(struct work_struct *work) } adapter->state = __I40EVF_INIT_VERSION_CHECK; goto restart; - break; case __I40EVF_INIT_VERSION_CHECK: if (!i40evf_asq_done(hw)) { dev_err(&pdev->dev, "Admin queue command never completed\n"); @@ -2018,17 +2055,20 @@ static void i40evf_init_task(struct work_struct *work) if (err) { dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", err); + if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { + dev_info(&pdev->dev, "Resending request\n"); + err = i40evf_send_api_ver(adapter); + } goto err; } err = i40evf_send_vf_config_msg(adapter); if (err) { - dev_err(&pdev->dev, "Unable send config request (%d)\n", + dev_err(&pdev->dev, "Unable to send config request (%d)\n", err); goto err; } adapter->state = __I40EVF_INIT_GET_RESOURCES; goto restart; - break; case __I40EVF_INIT_GET_RESOURCES: /* aq msg sent, awaiting reply */ if (!adapter->vf_res) { @@ -2097,8 +2137,6 @@ static void i40evf_init_task(struct work_struct *work) ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); - INIT_LIST_HEAD(&adapter->mac_filter_list); - INIT_LIST_HEAD(&adapter->vlan_filter_list); f = kzalloc(sizeof(*f), GFP_ATOMIC); if (NULL == f) goto err_sw_init; @@ -2280,6 +2318,9 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->bus.device = PCI_SLOT(pdev->devfn); hw->bus.func = PCI_FUNC(pdev->devfn); + INIT_LIST_HEAD(&adapter->mac_filter_list); + INIT_LIST_HEAD(&adapter->vlan_filter_list); + INIT_WORK(&adapter->reset_task, i40evf_reset_task); INIT_WORK(&adapter->adminq_task, i40evf_adminq_task); INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task); @@ -2391,6 +2432,7 @@ static void i40evf_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct i40evf_adapter *adapter = netdev_priv(netdev); + struct i40evf_mac_filter *f, *ftmp; struct i40e_hw *hw = &adapter->hw; cancel_delayed_work_sync(&adapter->init_task); @@ -2406,9 +2448,12 @@ static void i40evf_remove(struct pci_dev *pdev) i40evf_misc_irq_disable(adapter); i40evf_free_misc_irq(adapter); i40evf_reset_interrupt_capability(adapter); + i40evf_free_q_vectors(adapter); } - del_timer_sync(&adapter->watchdog_timer); + if (adapter->watchdog_timer.function) + del_timer_sync(&adapter->watchdog_timer); + flush_scheduled_work(); if (hw->aq.asq.count) @@ -2419,6 +2464,13 @@ static void i40evf_remove(struct pci_dev *pdev) i40evf_free_queues(adapter); kfree(adapter->vf_res); + /* If we got removed before an up/down sequence, we've got a filter + * hanging out there that we need to get rid of. + */ + list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { + list_del(&f->list); + kfree(f); + } free_netdev(netdev); |