diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 14:27:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 14:27:40 -0700 |
commit | f9da455b93f6ba076935b4ef4589f61e529ae046 (patch) | |
tree | 3c4e69ce1ba1d6bf65915b97a76ca2172105b278 /drivers/net/ethernet/intel/i40evf/i40evf_main.c | |
parent | 0e04c641b199435f3779454055f6a7de258ecdfc (diff) | |
parent | e5eca6d41f53db48edd8cf88a3f59d2c30227f8e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
1) Seccomp BPF filters can now be JIT'd, from Alexei Starovoitov.
2) Multiqueue support in xen-netback and xen-netfront, from Andrew J
Benniston.
3) Allow tweaking of aggregation settings in cdc_ncm driver, from Bjørn
Mork.
4) BPF now has a "random" opcode, from Chema Gonzalez.
5) Add more BPF documentation and improve test framework, from Daniel
Borkmann.
6) Support TCP fastopen over ipv6, from Daniel Lee.
7) Add software TSO helper functions and use them to support software
TSO in mvneta and mv643xx_eth drivers. From Ezequiel Garcia.
8) Support software TSO in fec driver too, from Nimrod Andy.
9) Add Broadcom SYSTEMPORT driver, from Florian Fainelli.
10) Handle broadcasts more gracefully over macvlan when there are large
numbers of interfaces configured, from Herbert Xu.
11) Allow more control over fwmark used for non-socket based responses,
from Lorenzo Colitti.
12) Do TCP congestion window limiting based upon measurements, from Neal
Cardwell.
13) Support busy polling in SCTP, from Neal Horman.
14) Allow RSS key to be configured via ethtool, from Venkata Duvvuru.
15) Bridge promisc mode handling improvements from Vlad Yasevich.
16) Don't use inetpeer entries to implement ID generation any more, it
performs poorly, from Eric Dumazet.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1522 commits)
rtnetlink: fix userspace API breakage for iproute2 < v3.9.0
tcp: fixing TLP's FIN recovery
net: fec: Add software TSO support
net: fec: Add Scatter/gather support
net: fec: Increase buffer descriptor entry number
net: fec: Factorize feature setting
net: fec: Enable IP header hardware checksum
net: fec: Factorize the .xmit transmit function
bridge: fix compile error when compiling without IPv6 support
bridge: fix smatch warning / potential null pointer dereference
via-rhine: fix full-duplex with autoneg disable
bnx2x: Enlarge the dorq threshold for VFs
bnx2x: Check for UNDI in uncommon branch
bnx2x: Fix 1G-baseT link
bnx2x: Fix link for KR with swapped polarity lane
sctp: Fix sk_ack_backlog wrap-around problem
net/core: Add VF link state control policy
net/fsl: xgmac_mdio is dependent on OF_MDIO
net/fsl: Make xgmac_mdio read error message useful
net_sched: drr: warn when qdisc is not work conserving
...
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_main.c | 185 |
1 files changed, 102 insertions, 83 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 2797548fde0d..7fc5f3b5d6bf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -12,6 +12,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * * The full GNU General Public License is included in this distribution in * the file called "COPYING". * @@ -25,13 +28,15 @@ #include "i40e_prototype.h" static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter); static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter); +static void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter); +static void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter); 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"; -#define DRV_VERSION "0.9.16" +#define DRV_VERSION "0.9.34" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2014 Intel Corporation."; @@ -167,7 +172,6 @@ static void i40evf_tx_timeout(struct net_device *netdev) struct i40evf_adapter *adapter = netdev_priv(netdev); adapter->tx_timeout_count++; - dev_info(&adapter->pdev->dev, "TX timeout detected.\n"); if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) { adapter->flags |= I40EVF_FLAG_RESET_NEEDED; schedule_work(&adapter->reset_task); @@ -657,12 +661,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) f = i40evf_find_vlan(adapter, vlan); if (NULL == f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (NULL == f) { - dev_info(&adapter->pdev->dev, - "%s: no memory for new VLAN filter\n", - __func__); + if (NULL == f) return NULL; - } + f->vlan = vlan; INIT_LIST_HEAD(&f->list); @@ -688,7 +689,6 @@ static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) f->remove = true; adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; } - return; } /** @@ -767,14 +767,12 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter, if (NULL == f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); if (NULL == f) { - dev_info(&adapter->pdev->dev, - "%s: no memory for new filter\n", __func__); clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); return NULL; } - memcpy(f->macaddr, macaddr, ETH_ALEN); + ether_addr_copy(f->macaddr, macaddr); list_add(&f->list, &adapter->mac_filter_list); f->add = true; @@ -807,9 +805,8 @@ static int i40evf_set_mac(struct net_device *netdev, void *p) f = i40evf_add_filter(adapter, addr->sa_data); if (f) { - memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); - memcpy(netdev->dev_addr, adapter->hw.mac.addr, - netdev->addr_len); + ether_addr_copy(hw->mac.addr, addr->sa_data); + ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); } return (f == NULL) ? -ENOMEM : 0; @@ -841,7 +838,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev) list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { bool found = false; - if (f->macaddr[0] & 0x01) { + if (is_multicast_ether_addr(f->macaddr)) { netdev_for_each_mc_addr(mca, netdev) { if (ether_addr_equal(mca->addr, f->macaddr)) { found = true; @@ -970,6 +967,9 @@ void i40evf_down(struct i40evf_adapter *adapter) struct net_device *netdev = adapter->netdev; struct i40evf_mac_filter *f; + if (adapter->state == __I40EVF_DOWN) + return; + /* remove all MAC filters */ list_for_each_entry(f, &adapter->mac_filter_list, list) { f->remove = true; @@ -1027,30 +1027,21 @@ i40evf_acquire_msix_vectors(struct i40evf_adapter *adapter, int vectors) * Right now, we simply care about how many we'll get; we'll * set them up later while requesting irq's. */ - while (vectors >= vector_threshold) { - err = pci_enable_msix(adapter->pdev, adapter->msix_entries, - vectors); - if (!err) /* Success in acquiring all requested vectors. */ - break; - else if (err < 0) - vectors = 0; /* Nasty failure, quit now */ - else /* err == number of vectors we should try again with */ - vectors = err; - } - - if (vectors < vector_threshold) { - dev_err(&adapter->pdev->dev, "Unable to allocate MSI-X interrupts.\n"); + err = pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + vector_threshold, vectors); + if (err < 0) { + dev_err(&adapter->pdev->dev, "Unable to allocate MSI-X interrupts\n"); kfree(adapter->msix_entries); adapter->msix_entries = NULL; - err = -EIO; - } else { - /* Adjust for only the vectors we'll use, which is minimum - * of max_msix_q_vectors + NONQ_VECS, or the number of - * vectors we were allocated. - */ - adapter->num_msix_vectors = vectors; + return err; } - return err; + + /* Adjust for only the vectors we'll use, which is minimum + * of max_msix_q_vectors + NONQ_VECS, or the number of + * vectors we were allocated. + */ + adapter->num_msix_vectors = err; + return 0; } /** @@ -1096,14 +1087,14 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) tx_ring->queue_index = i; tx_ring->netdev = adapter->netdev; tx_ring->dev = &adapter->pdev->dev; - tx_ring->count = I40EVF_DEFAULT_TXD; + tx_ring->count = adapter->tx_desc_count; adapter->tx_rings[i] = tx_ring; rx_ring = &tx_ring[1]; rx_ring->queue_index = i; rx_ring->netdev = adapter->netdev; rx_ring->dev = &adapter->pdev->dev; - rx_ring->count = I40EVF_DEFAULT_RXD; + rx_ring->count = adapter->rx_desc_count; adapter->rx_rings[i] = rx_ring; } @@ -1141,9 +1132,6 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter) v_budget = min_t(int, pairs, (int)(num_online_cpus() * 2)) + NONQ_VECS; v_budget = min_t(int, v_budget, (int)adapter->vf_res->max_vectors); - /* A failure in MSI-X entry allocation isn't fatal, but it does - * mean we disable MSI-X capabilities of the adapter. - */ adapter->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry), GFP_KERNEL); if (!adapter->msix_entries) { @@ -1183,7 +1171,7 @@ static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter) q_vector->vsi = &adapter->vsi; q_vector->v_idx = q_idx; netif_napi_add(adapter->netdev, &q_vector->napi, - i40evf_napi_poll, 64); + i40evf_napi_poll, NAPI_POLL_WEIGHT); adapter->q_vector[q_idx] = q_vector; } @@ -1236,8 +1224,6 @@ void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter) pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); adapter->msix_entries = NULL; - - return; } /** @@ -1309,7 +1295,6 @@ static void i40evf_watchdog_task(struct work_struct *work) goto restart_watchdog; if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) { - dev_info(&adapter->pdev->dev, "Checking for redemption\n"); if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) { /* A chance for redemption! */ dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n"); @@ -1340,8 +1325,7 @@ static void i40evf_watchdog_task(struct work_struct *work) (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) { adapter->state = __I40EVF_RESETTING; adapter->flags |= I40EVF_FLAG_RESET_PENDING; - dev_err(&adapter->pdev->dev, "Hardware reset detected.\n"); - dev_info(&adapter->pdev->dev, "Scheduling reset task\n"); + dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); schedule_work(&adapter->reset_task); adapter->aq_pending = 0; adapter->aq_required = 0; @@ -1413,7 +1397,7 @@ restart_watchdog: } /** - * i40evf_configure_rss - increment to next available tx queue + * next_queue - increment to next available tx queue * @adapter: board private structure * @j: queue counter * @@ -1504,15 +1488,12 @@ 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) { - dev_info(&adapter->pdev->dev, "Reset now occurring\n"); + if (rstat_val != I40E_VFR_VFACTIVE) break; - } else { + else msleep(I40EVF_RESET_WAIT_MS); - } } if (i == I40EVF_RESET_WAIT_COUNT) { - dev_err(&adapter->pdev->dev, "Reset was not detected\n"); adapter->flags &= ~I40EVF_FLAG_RESET_PENDING; goto continue_reset; /* act like the reset happened */ } @@ -1521,22 +1502,24 @@ 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) { - dev_info(&adapter->pdev->dev, "Reset is complete. Reinitializing.\n"); + if (rstat_val == I40E_VFR_VFACTIVE) break; - } else { + else msleep(I40EVF_RESET_WAIT_MS); - } } if (i == I40EVF_RESET_WAIT_COUNT) { /* reset never finished */ - dev_err(&adapter->pdev->dev, "Reset never finished (%x). PF driver is dead, and so am I.\n", + dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", rstat_val); adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; - if (netif_running(adapter->netdev)) - i40evf_close(adapter->netdev); - + if (netif_running(adapter->netdev)) { + set_bit(__I40E_DOWN, &adapter->vsi.state); + i40evf_down(adapter); + i40evf_free_traffic_irqs(adapter); + i40evf_free_all_tx_resources(adapter); + i40evf_free_all_rx_resources(adapter); + } i40evf_free_misc_irq(adapter); i40evf_reset_interrupt_capability(adapter); i40evf_free_queues(adapter); @@ -1591,7 +1574,7 @@ continue_reset: } return; reset_err: - dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit.\n"); + dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); i40evf_close(adapter->netdev); } @@ -1607,6 +1590,7 @@ static void i40evf_adminq_task(struct work_struct *work) struct i40e_arq_event_info event; struct i40e_virtchnl_msg *v_msg; i40e_status ret; + u32 val, oldval; u16 pending; if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) @@ -1614,11 +1598,9 @@ static void i40evf_adminq_task(struct work_struct *work) event.msg_size = I40EVF_MAX_AQ_BUF_SIZE; event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); - if (!event.msg_buf) { - dev_info(&adapter->pdev->dev, "%s: no memory for ARQ clean\n", - __func__); + if (!event.msg_buf) return; - } + v_msg = (struct i40e_virtchnl_msg *)&event.desc; do { ret = i40evf_clean_arq_element(hw, &event, &pending); @@ -1636,6 +1618,41 @@ static void i40evf_adminq_task(struct work_struct *work) } } while (pending); + /* check for error indications */ + val = rd32(hw, hw->aq.arq.len); + oldval = val; + if (val & I40E_VF_ARQLEN_ARQVFE_MASK) { + dev_info(&adapter->pdev->dev, "ARQ VF Error detected\n"); + val &= ~I40E_VF_ARQLEN_ARQVFE_MASK; + } + if (val & I40E_VF_ARQLEN_ARQOVFL_MASK) { + dev_info(&adapter->pdev->dev, "ARQ Overflow Error detected\n"); + val &= ~I40E_VF_ARQLEN_ARQOVFL_MASK; + } + if (val & I40E_VF_ARQLEN_ARQCRIT_MASK) { + dev_info(&adapter->pdev->dev, "ARQ Critical Error detected\n"); + val &= ~I40E_VF_ARQLEN_ARQCRIT_MASK; + } + if (oldval != val) + wr32(hw, hw->aq.arq.len, val); + + val = rd32(hw, hw->aq.asq.len); + oldval = val; + if (val & I40E_VF_ATQLEN_ATQVFE_MASK) { + dev_info(&adapter->pdev->dev, "ASQ VF Error detected\n"); + val &= ~I40E_VF_ATQLEN_ATQVFE_MASK; + } + if (val & I40E_VF_ATQLEN_ATQOVFL_MASK) { + dev_info(&adapter->pdev->dev, "ASQ Overflow Error detected\n"); + val &= ~I40E_VF_ATQLEN_ATQOVFL_MASK; + } + if (val & I40E_VF_ATQLEN_ATQCRIT_MASK) { + dev_info(&adapter->pdev->dev, "ASQ Critical Error detected\n"); + val &= ~I40E_VF_ATQLEN_ATQCRIT_MASK; + } + if (oldval != val) + wr32(hw, hw->aq.asq.len, val); + /* re-enable Admin queue interrupt cause */ i40evf_misc_irq_enable(adapter); @@ -1673,6 +1690,7 @@ static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + adapter->tx_rings[i]->count = adapter->tx_desc_count; err = i40evf_setup_tx_descriptors(adapter->tx_rings[i]); if (!err) continue; @@ -1700,6 +1718,7 @@ static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + adapter->rx_rings[i]->count = adapter->rx_desc_count; err = i40evf_setup_rx_descriptors(adapter->rx_rings[i]); if (!err) continue; @@ -1804,12 +1823,11 @@ static int i40evf_close(struct net_device *netdev) if (adapter->state <= __I40EVF_DOWN) return 0; - /* signal that we are down to the interrupt handler */ - adapter->state = __I40EVF_DOWN; set_bit(__I40E_DOWN, &adapter->vsi.state); i40evf_down(adapter); + adapter->state = __I40EVF_DOWN; i40evf_free_traffic_irqs(adapter); i40evf_free_all_tx_resources(adapter); @@ -1848,8 +1866,6 @@ void i40evf_reinit_locked(struct i40evf_adapter *adapter) WARN_ON(in_interrupt()); - adapter->state = __I40EVF_RESETTING; - i40evf_down(adapter); /* allocate transmit descriptors */ @@ -1872,7 +1888,7 @@ void i40evf_reinit_locked(struct i40evf_adapter *adapter) return; err_reinit: - dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit.\n"); + dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); i40evf_close(netdev); } @@ -1967,7 +1983,7 @@ static void i40evf_init_task(struct work_struct *work) } err = i40evf_check_reset_complete(hw); if (err) { - dev_err(&pdev->dev, "Device is still in reset (%d)\n", + dev_info(&pdev->dev, "Device is still in reset (%d), retrying\n", err); goto err; } @@ -1993,14 +2009,14 @@ static void i40evf_init_task(struct work_struct *work) break; case __I40EVF_INIT_VERSION_CHECK: if (!i40evf_asq_done(hw)) { - dev_err(&pdev->dev, "Admin queue command never completed.\n"); + dev_err(&pdev->dev, "Admin queue command never completed\n"); goto err; } /* aq msg sent, awaiting reply */ err = i40evf_verify_api_ver(adapter); if (err) { - dev_err(&pdev->dev, "Unable to verify API version (%d)\n", + dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", err); goto err; } @@ -2074,12 +2090,12 @@ static void i40evf_init_task(struct work_struct *work) netdev->hw_features &= ~NETIF_F_RXCSUM; if (!is_valid_ether_addr(adapter->hw.mac.addr)) { - dev_info(&pdev->dev, "Invalid MAC address %pMAC, using random\n", + dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n", adapter->hw.mac.addr); random_ether_addr(adapter->hw.mac.addr); } - memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); - memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); + 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); @@ -2087,7 +2103,7 @@ static void i40evf_init_task(struct work_struct *work) if (NULL == f) goto err_sw_init; - memcpy(f->macaddr, adapter->hw.mac.addr, ETH_ALEN); + ether_addr_copy(f->macaddr, adapter->hw.mac.addr); f->add = true; adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER; @@ -2098,6 +2114,8 @@ static void i40evf_init_task(struct work_struct *work) adapter->watchdog_timer.data = (unsigned long)adapter; mod_timer(&adapter->watchdog_timer, jiffies + 1); + adapter->tx_desc_count = I40EVF_DEFAULT_TXD; + adapter->rx_desc_count = I40EVF_DEFAULT_RXD; err = i40evf_init_interrupt_scheme(adapter); if (err) goto err_sw_init; @@ -2114,8 +2132,10 @@ static void i40evf_init_task(struct work_struct *work) adapter->vsi.back = adapter; adapter->vsi.base_vector = 1; adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK; - adapter->vsi.rx_itr_setting = I40E_ITR_DYNAMIC; - adapter->vsi.tx_itr_setting = I40E_ITR_DYNAMIC; + adapter->vsi.rx_itr_setting = (I40E_ITR_DYNAMIC | + ITR_REG_TO_USEC(I40E_ITR_RX_DEF)); + adapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC | + ITR_REG_TO_USEC(I40E_ITR_TX_DEF)); adapter->vsi.netdev = adapter->netdev; if (!adapter->netdev_registered) { @@ -2128,7 +2148,7 @@ static void i40evf_init_task(struct work_struct *work) netif_tx_stop_all_queues(netdev); - dev_info(&pdev->dev, "MAC address: %pMAC\n", adapter->hw.mac.addr); + dev_info(&pdev->dev, "MAC address: %pM\n", adapter->hw.mac.addr); if (netdev->features & NETIF_F_GRO) dev_info(&pdev->dev, "GRO is enabled\n"); @@ -2152,12 +2172,11 @@ err_alloc: err: /* Things went into the weeds, so try again later */ if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) { - dev_err(&pdev->dev, "Failed to communicate with PF; giving up.\n"); + dev_err(&pdev->dev, "Failed to communicate with PF; giving up\n"); adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; return; /* do not reschedule */ } schedule_delayed_work(&adapter->init_task, HZ * 3); - return; } /** |