diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 1140 |
1 files changed, 729 insertions, 411 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 861b722c267..275ca9a1719 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -38,8 +38,8 @@ static const char i40e_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 0 -#define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 36 +#define DRV_VERSION_MINOR 4 +#define DRV_VERSION_BUILD 10 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN @@ -67,12 +67,10 @@ static int i40e_veb_get_bw_info(struct i40e_veb *veb); */ static DEFINE_PCI_DEVICE_TABLE(i40e_pci_tbl) = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_XL710), 0}, - {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X710), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QEMU), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_A), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_B), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_C), 0}, - {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_D), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_A), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0}, @@ -356,6 +354,7 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( struct rtnl_link_stats64 *stats) { struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_ring *tx_ring, *rx_ring; struct i40e_vsi *vsi = np->vsi; struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi); int i; @@ -368,7 +367,6 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( rcu_read_lock(); for (i = 0; i < vsi->num_queue_pairs; i++) { - struct i40e_ring *tx_ring, *rx_ring; u64 bytes, packets; unsigned int start; @@ -397,7 +395,7 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( } rcu_read_unlock(); - /* following stats updated by ixgbe_watchdog_task() */ + /* following stats updated by i40e_watchdog_subtask() */ stats->multicast = vsi_stats->multicast; stats->tx_errors = vsi_stats->tx_errors; stats->tx_dropped = vsi_stats->tx_dropped; @@ -530,6 +528,12 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi) i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx), vsi->stat_offsets_loaded, &oes->rx_discards, &es->rx_discards); + i40e_stat_update32(hw, I40E_GLV_RUPP(stat_idx), + vsi->stat_offsets_loaded, + &oes->rx_unknown_protocol, &es->rx_unknown_protocol); + i40e_stat_update32(hw, I40E_GLV_TEPC(stat_idx), + vsi->stat_offsets_loaded, + &oes->tx_errors, &es->tx_errors); i40e_stat_update48(hw, I40E_GLV_GORCH(stat_idx), I40E_GLV_GORCL(stat_idx), @@ -648,10 +652,10 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf) return; /* Clear the __I40E_HANG_CHECK_ARMED bit for all Tx rings */ - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; - if (!vsi) + if (!vsi || !vsi->tx_rings[0]) continue; for (i = 0; i < vsi->num_queue_pairs; i++) { @@ -702,10 +706,10 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) } /* Clear the __I40E_HANG_CHECK_ARMED bit for Tx rings */ - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; - if (!vsi) + if (!vsi || !vsi->tx_rings[0]) continue; for (i = 0; i < vsi->num_queue_pairs; i++) { @@ -720,19 +724,18 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) } /** - * i40e_update_stats - Update the board statistics counters. + * i40e_update_vsi_stats - Update the vsi statistics counters. * @vsi: the VSI to be updated * * There are a few instances where we store the same stat in a * couple of different structs. This is partly because we have * the netdev stats that need to be filled out, which is slightly * different from the "eth_stats" defined by the chip and used in - * VF communications. We sort it all out here in a central place. + * VF communications. We sort it out here. **/ -void i40e_update_stats(struct i40e_vsi *vsi) +static void i40e_update_vsi_stats(struct i40e_vsi *vsi) { struct i40e_pf *pf = vsi->back; - struct i40e_hw *hw = &pf->hw; struct rtnl_link_stats64 *ons; struct rtnl_link_stats64 *ns; /* netdev stats */ struct i40e_eth_stats *oes; @@ -741,8 +744,6 @@ void i40e_update_stats(struct i40e_vsi *vsi) u32 rx_page, rx_buf; u64 rx_p, rx_b; u64 tx_p, tx_b; - u32 val; - int i; u16 q; if (test_bit(__I40E_DOWN, &vsi->state) || @@ -804,196 +805,256 @@ void i40e_update_stats(struct i40e_vsi *vsi) ns->tx_packets = tx_p; ns->tx_bytes = tx_b; - i40e_update_eth_stats(vsi); /* update netdev stats from eth stats */ - ons->rx_errors = oes->rx_errors; - ns->rx_errors = es->rx_errors; + i40e_update_eth_stats(vsi); ons->tx_errors = oes->tx_errors; ns->tx_errors = es->tx_errors; ons->multicast = oes->rx_multicast; ns->multicast = es->rx_multicast; + ons->rx_dropped = oes->rx_discards; + ns->rx_dropped = es->rx_discards; ons->tx_dropped = oes->tx_discards; ns->tx_dropped = es->tx_discards; - /* Get the port data only if this is the main PF VSI */ + /* pull in a couple PF stats if this is the main vsi */ if (vsi == pf->vsi[pf->lan_vsi]) { - struct i40e_hw_port_stats *nsd = &pf->stats; - struct i40e_hw_port_stats *osd = &pf->stats_offsets; + ns->rx_crc_errors = pf->stats.crc_errors; + ns->rx_errors = pf->stats.crc_errors + pf->stats.illegal_bytes; + ns->rx_length_errors = pf->stats.rx_length_errors; + } +} - i40e_stat_update48(hw, I40E_GLPRT_GORCH(hw->port), - I40E_GLPRT_GORCL(hw->port), - pf->stat_offsets_loaded, - &osd->eth.rx_bytes, &nsd->eth.rx_bytes); - i40e_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port), - I40E_GLPRT_GOTCL(hw->port), - pf->stat_offsets_loaded, - &osd->eth.tx_bytes, &nsd->eth.tx_bytes); - i40e_stat_update32(hw, I40E_GLPRT_RDPC(hw->port), - pf->stat_offsets_loaded, - &osd->eth.rx_discards, - &nsd->eth.rx_discards); - i40e_stat_update32(hw, I40E_GLPRT_TDPC(hw->port), - pf->stat_offsets_loaded, - &osd->eth.tx_discards, - &nsd->eth.tx_discards); - i40e_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port), - I40E_GLPRT_MPRCL(hw->port), - pf->stat_offsets_loaded, - &osd->eth.rx_multicast, - &nsd->eth.rx_multicast); +/** + * i40e_update_pf_stats - Update the pf statistics counters. + * @pf: the PF to be updated + **/ +static void i40e_update_pf_stats(struct i40e_pf *pf) +{ + struct i40e_hw_port_stats *osd = &pf->stats_offsets; + struct i40e_hw_port_stats *nsd = &pf->stats; + struct i40e_hw *hw = &pf->hw; + u32 val; + int i; - i40e_stat_update32(hw, I40E_GLPRT_TDOLD(hw->port), - pf->stat_offsets_loaded, - &osd->tx_dropped_link_down, - &nsd->tx_dropped_link_down); + i40e_stat_update48(hw, I40E_GLPRT_GORCH(hw->port), + I40E_GLPRT_GORCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.rx_bytes, &nsd->eth.rx_bytes); + i40e_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port), + I40E_GLPRT_GOTCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.tx_bytes, &nsd->eth.tx_bytes); + i40e_stat_update32(hw, I40E_GLPRT_RDPC(hw->port), + pf->stat_offsets_loaded, + &osd->eth.rx_discards, + &nsd->eth.rx_discards); + i40e_stat_update32(hw, I40E_GLPRT_TDPC(hw->port), + pf->stat_offsets_loaded, + &osd->eth.tx_discards, + &nsd->eth.tx_discards); - i40e_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port), - pf->stat_offsets_loaded, - &osd->crc_errors, &nsd->crc_errors); - ns->rx_crc_errors = nsd->crc_errors; + i40e_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port), + I40E_GLPRT_UPRCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.rx_unicast, + &nsd->eth.rx_unicast); + i40e_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port), + I40E_GLPRT_MPRCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.rx_multicast, + &nsd->eth.rx_multicast); + i40e_stat_update48(hw, I40E_GLPRT_BPRCH(hw->port), + I40E_GLPRT_BPRCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.rx_broadcast, + &nsd->eth.rx_broadcast); + i40e_stat_update48(hw, I40E_GLPRT_UPTCH(hw->port), + I40E_GLPRT_UPTCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.tx_unicast, + &nsd->eth.tx_unicast); + i40e_stat_update48(hw, I40E_GLPRT_MPTCH(hw->port), + I40E_GLPRT_MPTCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.tx_multicast, + &nsd->eth.tx_multicast); + i40e_stat_update48(hw, I40E_GLPRT_BPTCH(hw->port), + I40E_GLPRT_BPTCL(hw->port), + pf->stat_offsets_loaded, + &osd->eth.tx_broadcast, + &nsd->eth.tx_broadcast); - i40e_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port), - pf->stat_offsets_loaded, - &osd->illegal_bytes, &nsd->illegal_bytes); - ns->rx_errors = nsd->crc_errors - + nsd->illegal_bytes; + i40e_stat_update32(hw, I40E_GLPRT_TDOLD(hw->port), + pf->stat_offsets_loaded, + &osd->tx_dropped_link_down, + &nsd->tx_dropped_link_down); - i40e_stat_update32(hw, I40E_GLPRT_MLFC(hw->port), - pf->stat_offsets_loaded, - &osd->mac_local_faults, - &nsd->mac_local_faults); - i40e_stat_update32(hw, I40E_GLPRT_MRFC(hw->port), - pf->stat_offsets_loaded, - &osd->mac_remote_faults, - &nsd->mac_remote_faults); + i40e_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port), + pf->stat_offsets_loaded, + &osd->crc_errors, &nsd->crc_errors); - i40e_stat_update32(hw, I40E_GLPRT_RLEC(hw->port), - pf->stat_offsets_loaded, - &osd->rx_length_errors, - &nsd->rx_length_errors); - ns->rx_length_errors = nsd->rx_length_errors; + i40e_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port), + pf->stat_offsets_loaded, + &osd->illegal_bytes, &nsd->illegal_bytes); - i40e_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port), - pf->stat_offsets_loaded, - &osd->link_xon_rx, &nsd->link_xon_rx); - i40e_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port), - pf->stat_offsets_loaded, - &osd->link_xon_tx, &nsd->link_xon_tx); - i40e_update_prio_xoff_rx(pf); /* handles I40E_GLPRT_LXOFFRXC */ - i40e_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port), - pf->stat_offsets_loaded, - &osd->link_xoff_tx, &nsd->link_xoff_tx); - - for (i = 0; i < 8; i++) { - i40e_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_rx[i], - &nsd->priority_xon_rx[i]); - i40e_stat_update32(hw, I40E_GLPRT_PXONTXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_tx[i], - &nsd->priority_xon_tx[i]); - i40e_stat_update32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xoff_tx[i], - &nsd->priority_xoff_tx[i]); - i40e_stat_update32(hw, - I40E_GLPRT_RXON2OFFCNT(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_2_xoff[i], - &nsd->priority_xon_2_xoff[i]); - } + i40e_stat_update32(hw, I40E_GLPRT_MLFC(hw->port), + pf->stat_offsets_loaded, + &osd->mac_local_faults, + &nsd->mac_local_faults); + i40e_stat_update32(hw, I40E_GLPRT_MRFC(hw->port), + pf->stat_offsets_loaded, + &osd->mac_remote_faults, + &nsd->mac_remote_faults); - i40e_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port), - I40E_GLPRT_PRC64L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_64, &nsd->rx_size_64); - i40e_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port), - I40E_GLPRT_PRC127L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_127, &nsd->rx_size_127); - i40e_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port), - I40E_GLPRT_PRC255L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_255, &nsd->rx_size_255); - i40e_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port), - I40E_GLPRT_PRC511L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_511, &nsd->rx_size_511); - i40e_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port), - I40E_GLPRT_PRC1023L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_1023, &nsd->rx_size_1023); - i40e_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port), - I40E_GLPRT_PRC1522L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_1522, &nsd->rx_size_1522); - i40e_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port), - I40E_GLPRT_PRC9522L(hw->port), - pf->stat_offsets_loaded, - &osd->rx_size_big, &nsd->rx_size_big); + i40e_stat_update32(hw, I40E_GLPRT_RLEC(hw->port), + pf->stat_offsets_loaded, + &osd->rx_length_errors, + &nsd->rx_length_errors); - i40e_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port), - I40E_GLPRT_PTC64L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_64, &nsd->tx_size_64); - i40e_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port), - I40E_GLPRT_PTC127L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_127, &nsd->tx_size_127); - i40e_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port), - I40E_GLPRT_PTC255L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_255, &nsd->tx_size_255); - i40e_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port), - I40E_GLPRT_PTC511L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_511, &nsd->tx_size_511); - i40e_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port), - I40E_GLPRT_PTC1023L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_1023, &nsd->tx_size_1023); - i40e_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port), - I40E_GLPRT_PTC1522L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_1522, &nsd->tx_size_1522); - i40e_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port), - I40E_GLPRT_PTC9522L(hw->port), - pf->stat_offsets_loaded, - &osd->tx_size_big, &nsd->tx_size_big); + i40e_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port), + pf->stat_offsets_loaded, + &osd->link_xon_rx, &nsd->link_xon_rx); + i40e_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port), + pf->stat_offsets_loaded, + &osd->link_xon_tx, &nsd->link_xon_tx); + i40e_update_prio_xoff_rx(pf); /* handles I40E_GLPRT_LXOFFRXC */ + i40e_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port), + pf->stat_offsets_loaded, + &osd->link_xoff_tx, &nsd->link_xoff_tx); - i40e_stat_update32(hw, I40E_GLPRT_RUC(hw->port), - pf->stat_offsets_loaded, - &osd->rx_undersize, &nsd->rx_undersize); - i40e_stat_update32(hw, I40E_GLPRT_RFC(hw->port), - pf->stat_offsets_loaded, - &osd->rx_fragments, &nsd->rx_fragments); - i40e_stat_update32(hw, I40E_GLPRT_ROC(hw->port), + for (i = 0; i < 8; i++) { + i40e_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i), pf->stat_offsets_loaded, - &osd->rx_oversize, &nsd->rx_oversize); - i40e_stat_update32(hw, I40E_GLPRT_RJC(hw->port), + &osd->priority_xon_rx[i], + &nsd->priority_xon_rx[i]); + i40e_stat_update32(hw, I40E_GLPRT_PXONTXC(hw->port, i), pf->stat_offsets_loaded, - &osd->rx_jabber, &nsd->rx_jabber); - - val = rd32(hw, I40E_PRTPM_EEE_STAT); - nsd->tx_lpi_status = - (val & I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK) >> - I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT; - nsd->rx_lpi_status = - (val & I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK) >> - I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT; - i40e_stat_update32(hw, I40E_PRTPM_TLPIC, + &osd->priority_xon_tx[i], + &nsd->priority_xon_tx[i]); + i40e_stat_update32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i), pf->stat_offsets_loaded, - &osd->tx_lpi_count, &nsd->tx_lpi_count); - i40e_stat_update32(hw, I40E_PRTPM_RLPIC, + &osd->priority_xoff_tx[i], + &nsd->priority_xoff_tx[i]); + i40e_stat_update32(hw, + I40E_GLPRT_RXON2OFFCNT(hw->port, i), pf->stat_offsets_loaded, - &osd->rx_lpi_count, &nsd->rx_lpi_count); + &osd->priority_xon_2_xoff[i], + &nsd->priority_xon_2_xoff[i]); } + i40e_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port), + I40E_GLPRT_PRC64L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_64, &nsd->rx_size_64); + i40e_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port), + I40E_GLPRT_PRC127L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_127, &nsd->rx_size_127); + i40e_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port), + I40E_GLPRT_PRC255L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_255, &nsd->rx_size_255); + i40e_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port), + I40E_GLPRT_PRC511L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_511, &nsd->rx_size_511); + i40e_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port), + I40E_GLPRT_PRC1023L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_1023, &nsd->rx_size_1023); + i40e_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port), + I40E_GLPRT_PRC1522L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_1522, &nsd->rx_size_1522); + i40e_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port), + I40E_GLPRT_PRC9522L(hw->port), + pf->stat_offsets_loaded, + &osd->rx_size_big, &nsd->rx_size_big); + + i40e_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port), + I40E_GLPRT_PTC64L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_64, &nsd->tx_size_64); + i40e_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port), + I40E_GLPRT_PTC127L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_127, &nsd->tx_size_127); + i40e_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port), + I40E_GLPRT_PTC255L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_255, &nsd->tx_size_255); + i40e_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port), + I40E_GLPRT_PTC511L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_511, &nsd->tx_size_511); + i40e_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port), + I40E_GLPRT_PTC1023L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_1023, &nsd->tx_size_1023); + i40e_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port), + I40E_GLPRT_PTC1522L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_1522, &nsd->tx_size_1522); + i40e_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port), + I40E_GLPRT_PTC9522L(hw->port), + pf->stat_offsets_loaded, + &osd->tx_size_big, &nsd->tx_size_big); + + i40e_stat_update32(hw, I40E_GLPRT_RUC(hw->port), + pf->stat_offsets_loaded, + &osd->rx_undersize, &nsd->rx_undersize); + i40e_stat_update32(hw, I40E_GLPRT_RFC(hw->port), + pf->stat_offsets_loaded, + &osd->rx_fragments, &nsd->rx_fragments); + i40e_stat_update32(hw, I40E_GLPRT_ROC(hw->port), + pf->stat_offsets_loaded, + &osd->rx_oversize, &nsd->rx_oversize); + i40e_stat_update32(hw, I40E_GLPRT_RJC(hw->port), + pf->stat_offsets_loaded, + &osd->rx_jabber, &nsd->rx_jabber); + + /* FDIR stats */ + i40e_stat_update32(hw, I40E_GLQF_PCNT(pf->fd_atr_cnt_idx), + pf->stat_offsets_loaded, + &osd->fd_atr_match, &nsd->fd_atr_match); + i40e_stat_update32(hw, I40E_GLQF_PCNT(pf->fd_sb_cnt_idx), + pf->stat_offsets_loaded, + &osd->fd_sb_match, &nsd->fd_sb_match); + + val = rd32(hw, I40E_PRTPM_EEE_STAT); + nsd->tx_lpi_status = + (val & I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK) >> + I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT; + nsd->rx_lpi_status = + (val & I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK) >> + I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT; + i40e_stat_update32(hw, I40E_PRTPM_TLPIC, + pf->stat_offsets_loaded, + &osd->tx_lpi_count, &nsd->tx_lpi_count); + i40e_stat_update32(hw, I40E_PRTPM_RLPIC, + pf->stat_offsets_loaded, + &osd->rx_lpi_count, &nsd->rx_lpi_count); + pf->stat_offsets_loaded = true; } /** + * i40e_update_stats - Update the various statistics counters. + * @vsi: the VSI to be updated + * + * Update the various stats for this VSI and its related entities. + **/ +void i40e_update_stats(struct i40e_vsi *vsi) +{ + struct i40e_pf *pf = vsi->back; + + if (vsi == pf->vsi[pf->lan_vsi]) + i40e_update_pf_stats(pf); + + i40e_update_vsi_stats(vsi); +} + +/** * i40e_find_filter - Search VSI filter list for specific mac/vlan filter * @vsi: the VSI to be searched * @macaddr: the MAC address @@ -1101,6 +1162,30 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, } /** + * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM + * @vsi: the PF Main VSI - inappropriate for any other VSI + * @macaddr: the MAC address + **/ +static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr) +{ + struct i40e_aqc_remove_macvlan_element_data element; + struct i40e_pf *pf = vsi->back; + i40e_status aq_ret; + + /* Only appropriate for the PF main VSI */ + if (vsi->type != I40E_VSI_MAIN) + return; + + ether_addr_copy(element.mac_addr, macaddr); + element.vlan_tag = 0; + element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | + I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; + aq_ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL); + if (aq_ret) + dev_err(&pf->pdev->dev, "Could not remove default MAC-VLAN\n"); +} + +/** * i40e_add_filter - Add a mac/vlan filter to the VSI * @vsi: the VSI to be searched * @macaddr: the MAC address @@ -1125,7 +1210,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, if (!f) goto add_filter_out; - memcpy(f->macaddr, macaddr, ETH_ALEN); + ether_addr_copy(f->macaddr, macaddr); f->vlan = vlan; f->changed = true; @@ -1249,7 +1334,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) return -EADDRNOTAVAIL; } - memcpy(vsi->back->hw.mac.addr, addr->sa_data, netdev->addr_len); + ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data); } /* In order to be sure to not drop any packets, add the new address @@ -1263,7 +1348,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false); i40e_sync_vsi_filters(vsi); - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + ether_addr_copy(netdev->dev_addr, addr->sa_data); return 0; } @@ -1313,7 +1398,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, vsi->tc_config.numtc = numtc; vsi->tc_config.enabled_tc = enabled_tc ? enabled_tc : 1; /* Number of queues per enabled TC */ - num_tc_qps = rounddown_pow_of_two(vsi->alloc_queue_pairs/numtc); + num_tc_qps = vsi->alloc_queue_pairs/numtc; num_tc_qps = min_t(int, num_tc_qps, I40E_MAX_QUEUES_PER_TC); /* Setup queue offset/count for all TCs for given VSI */ @@ -1520,8 +1605,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) cmd_flags = 0; /* add to delete list */ - memcpy(del_list[num_del].mac_addr, - f->macaddr, ETH_ALEN); + ether_addr_copy(del_list[num_del].mac_addr, f->macaddr); del_list[num_del].vlan_tag = cpu_to_le16((u16)(f->vlan == I40E_VLAN_ANY ? 0 : f->vlan)); @@ -1542,7 +1626,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) num_del = 0; memset(del_list, 0, sizeof(*del_list)); - if (aq_ret) + if (aq_ret && + pf->hw.aq.asq_last_status != + I40E_AQ_RC_ENOENT) dev_info(&pf->pdev->dev, "ignoring delete macvlan error, err %d, aq_err %d while flushing a full buffer\n", aq_ret, @@ -1554,7 +1640,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) del_list, num_del, NULL); num_del = 0; - if (aq_ret) + if (aq_ret && + pf->hw.aq.asq_last_status != I40E_AQ_RC_ENOENT) dev_info(&pf->pdev->dev, "ignoring delete macvlan error, err %d, aq_err %d\n", aq_ret, pf->hw.aq.asq_last_status); @@ -1583,8 +1670,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) cmd_flags = 0; /* add to add array */ - memcpy(add_list[num_add].mac_addr, - f->macaddr, ETH_ALEN); + ether_addr_copy(add_list[num_add].mac_addr, f->macaddr); add_list[num_add].vlan_tag = cpu_to_le16( (u16)(f->vlan == I40E_VLAN_ANY ? 0 : f->vlan)); @@ -1681,7 +1767,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) return; pf->flags &= ~I40E_FLAG_FILTER_SYNC; - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v] && (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) i40e_sync_vsi_filters(pf->vsi[v]); @@ -1698,7 +1784,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) static int i40e_change_mtu(struct net_device *netdev, int new_mtu) { struct i40e_netdev_priv *np = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; struct i40e_vsi *vsi = np->vsi; /* MTU < 68 is an error and causes problems on some kernels */ @@ -2312,6 +2398,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) rx_ctx.crcstrip = 1; rx_ctx.l2tsel = 1; rx_ctx.showiv = 1; + /* set the prefena field to 1 because the manual says to */ + rx_ctx.prefena = 1; /* clear the context in the HMC */ err = i40e_clear_lan_rx_queue_context(hw, pf_q); @@ -2413,6 +2501,7 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi) **/ static void i40e_vsi_config_dcb_rings(struct i40e_vsi *vsi) { + struct i40e_ring *tx_ring, *rx_ring; u16 qoffset, qcount; int i, n; @@ -2426,8 +2515,8 @@ static void i40e_vsi_config_dcb_rings(struct i40e_vsi *vsi) qoffset = vsi->tc_config.tc_info[n].qoffset; qcount = vsi->tc_config.tc_info[n].qcount; for (i = qoffset; i < (qoffset + qcount); i++) { - struct i40e_ring *rx_ring = vsi->rx_rings[i]; - struct i40e_ring *tx_ring = vsi->tx_rings[i]; + rx_ring = vsi->rx_rings[i]; + tx_ring = vsi->tx_rings[i]; rx_ring->dcb_tc = n; tx_ring->dcb_tc = n; } @@ -2565,7 +2654,6 @@ static void i40e_enable_misc_int_causes(struct i40e_hw *hw) I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK | I40E_PFINT_ICR0_ENA_GPIO_MASK | I40E_PFINT_ICR0_ENA_TIMESYNC_MASK | - I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK | I40E_PFINT_ICR0_ENA_HMC_ERR_MASK | I40E_PFINT_ICR0_ENA_VFLR_MASK | I40E_PFINT_ICR0_ENA_ADMINQ_MASK; @@ -2733,6 +2821,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) &q_vector->affinity_mask); } + vsi->irqs_ready = true; return 0; free_queue_irqs: @@ -2897,12 +2986,9 @@ static irqreturn_t i40e_intr(int irq, void *data) u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0); if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) { - ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; + icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; i40e_ptp_tx_hwtstamp(pf); - prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK; } - - wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat); } /* If a critical error is pending we have no choice but to reset the @@ -3155,6 +3241,12 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) pf_q = vsi->base_queue; for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) { + + /* warn the TX unit of coming changes */ + i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable); + if (!enable) + udelay(10); + for (j = 0; j < 50; j++) { tx_reg = rd32(hw, I40E_QTX_ENA(pf_q)); if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) == @@ -3163,9 +3255,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) usleep_range(1000, 2000); } /* Skip if the queue is already in the requested state */ - if (enable && (tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) - continue; - if (!enable && !(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) + if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) continue; /* turn on/off the queue */ @@ -3181,13 +3271,8 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) /* wait for the change to finish */ for (j = 0; j < 10; j++) { tx_reg = rd32(hw, I40E_QTX_ENA(pf_q)); - if (enable) { - if ((tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) - break; - } else { - if (!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) - break; - } + if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) + break; udelay(10); } @@ -3226,15 +3311,9 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) usleep_range(1000, 2000); } - if (enable) { - /* is STAT set ? */ - if ((rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) - continue; - } else { - /* is !STAT set ? */ - if (!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) - continue; - } + /* Skip if the queue is already in the requested state */ + if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) + continue; /* turn on/off the queue */ if (enable) @@ -3247,13 +3326,8 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) for (j = 0; j < 10; j++) { rx_reg = rd32(hw, I40E_QRX_ENA(pf_q)); - if (enable) { - if ((rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) - break; - } else { - if (!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) - break; - } + if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) + break; udelay(10); } @@ -3307,6 +3381,10 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi) if (!vsi->q_vectors) return; + if (!vsi->irqs_ready) + return; + + vsi->irqs_ready = false; for (i = 0; i < vsi->num_q_vectors; i++) { u16 vector = i + base; @@ -3479,7 +3557,7 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf) int i; i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1); - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) + for (i = 0; i < pf->num_alloc_vsi; i++) if (pf->vsi[i]) i40e_vsi_free_q_vectors(pf->vsi[i]); i40e_reset_interrupt_capability(pf); @@ -3516,6 +3594,19 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi) } /** + * i40e_vsi_close - Shut down a VSI + * @vsi: the vsi to be quelled + **/ +static void i40e_vsi_close(struct i40e_vsi *vsi) +{ + if (!test_and_set_bit(__I40E_DOWN, &vsi->state)) + i40e_down(vsi); + i40e_vsi_free_irq(vsi); + i40e_vsi_free_tx_resources(vsi); + i40e_vsi_free_rx_resources(vsi); +} + +/** * i40e_quiesce_vsi - Pause a given VSI * @vsi: the VSI being paused **/ @@ -3528,8 +3619,7 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi) if (vsi->netdev && netif_running(vsi->netdev)) { vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); } else { - set_bit(__I40E_DOWN, &vsi->state); - i40e_down(vsi); + i40e_vsi_close(vsi); } } @@ -3546,7 +3636,7 @@ static void i40e_unquiesce_vsi(struct i40e_vsi *vsi) if (vsi->netdev && netif_running(vsi->netdev)) vsi->netdev->netdev_ops->ndo_open(vsi->netdev); else - i40e_up(vsi); /* this clears the DOWN bit */ + i40e_vsi_open(vsi); /* this clears the DOWN bit */ } /** @@ -3557,7 +3647,7 @@ static void i40e_pf_quiesce_all_vsi(struct i40e_pf *pf) { int v; - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v]) i40e_quiesce_vsi(pf->vsi[v]); } @@ -3571,7 +3661,7 @@ static void i40e_pf_unquiesce_all_vsi(struct i40e_pf *pf) { int v; - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v]) i40e_unquiesce_vsi(pf->vsi[v]); } @@ -4012,7 +4102,7 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) } /* Update each VSI */ - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (!pf->vsi[v]) continue; @@ -4031,6 +4121,8 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) pf->vsi[v]->seid); /* Will try to configure as many components */ } else { + /* Re-configure VSI vectors based on updated TC map */ + i40e_vsi_map_rings_to_vectors(pf->vsi[v]); if (pf->vsi[v]->netdev) i40e_dcbnl_set_all(pf->vsi[v]); } @@ -4068,14 +4160,69 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) /* When status is not DISABLED then DCBX in FW */ pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE; - pf->flags |= I40E_FLAG_DCB_ENABLED; + + pf->flags |= I40E_FLAG_DCB_CAPABLE; + /* Enable DCB tagging only when more than one TC */ + if (i40e_dcb_get_num_tc(&hw->local_dcbx_config) > 1) + pf->flags |= I40E_FLAG_DCB_ENABLED; } + } else { + dev_info(&pf->pdev->dev, "AQ Querying DCB configuration failed: %d\n", + pf->hw.aq.asq_last_status); } out: return err; } #endif /* CONFIG_I40E_DCB */ +#define SPEED_SIZE 14 +#define FC_SIZE 8 +/** + * i40e_print_link_message - print link up or down + * @vsi: the VSI for which link needs a message + */ +static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) +{ + char speed[SPEED_SIZE] = "Unknown"; + char fc[FC_SIZE] = "RX/TX"; + + if (!isup) { + netdev_info(vsi->netdev, "NIC Link is Down\n"); + return; + } + + switch (vsi->back->hw.phy.link_info.link_speed) { + case I40E_LINK_SPEED_40GB: + strncpy(speed, "40 Gbps", SPEED_SIZE); + break; + case I40E_LINK_SPEED_10GB: + strncpy(speed, "10 Gbps", SPEED_SIZE); + break; + case I40E_LINK_SPEED_1GB: + strncpy(speed, "1000 Mbps", SPEED_SIZE); + break; + default: + break; + } + + switch (vsi->back->hw.fc.current_mode) { + case I40E_FC_FULL: + strncpy(fc, "RX/TX", FC_SIZE); + break; + case I40E_FC_TX_PAUSE: + strncpy(fc, "TX", FC_SIZE); + break; + case I40E_FC_RX_PAUSE: + strncpy(fc, "RX", FC_SIZE); + break; + default: + strncpy(fc, "None", FC_SIZE); + break; + } + + netdev_info(vsi->netdev, "NIC Link is Up %s Full Duplex, Flow Control: %s\n", + speed, fc); +} /** * i40e_up_complete - Finish the last steps of bringing up a connection @@ -4102,11 +4249,11 @@ static int i40e_up_complete(struct i40e_vsi *vsi) if ((pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP) && (vsi->netdev)) { - netdev_info(vsi->netdev, "NIC Link is Up\n"); + i40e_print_link_message(vsi, true); netif_tx_start_all_queues(vsi->netdev); netif_carrier_on(vsi->netdev); } else if (vsi->netdev) { - netdev_info(vsi->netdev, "NIC Link is Down\n"); + i40e_print_link_message(vsi, false); } /* replay FDIR SB filters */ @@ -4271,6 +4418,14 @@ static int i40e_open(struct net_device *netdev) if (err) return err; + /* configure global TSO hardware offload settings */ + wr32(&pf->hw, I40E_GLLAN_TSOMSK_F, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_M, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN | + TCP_FLAG_CWR) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16); + #ifdef CONFIG_I40E_VXLAN vxlan_get_rx_port(netdev); #endif @@ -4304,24 +4459,32 @@ int i40e_vsi_open(struct i40e_vsi *vsi) if (err) goto err_setup_rx; - if (!vsi->netdev) { - err = EINVAL; - goto err_setup_rx; - } - snprintf(int_name, sizeof(int_name) - 1, "%s-%s", - dev_driver_string(&pf->pdev->dev), vsi->netdev->name); - err = i40e_vsi_request_irq(vsi, int_name); - if (err) - goto err_setup_rx; + if (vsi->netdev) { + snprintf(int_name, sizeof(int_name) - 1, "%s-%s", + dev_driver_string(&pf->pdev->dev), vsi->netdev->name); + err = i40e_vsi_request_irq(vsi, int_name); + if (err) + goto err_setup_rx; - /* Notify the stack of the actual queue counts. */ - err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_queue_pairs); - if (err) - goto err_set_queues; + /* Notify the stack of the actual queue counts. */ + err = netif_set_real_num_tx_queues(vsi->netdev, + vsi->num_queue_pairs); + if (err) + goto err_set_queues; - err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_queue_pairs); - if (err) - goto err_set_queues; + err = netif_set_real_num_rx_queues(vsi->netdev, + vsi->num_queue_pairs); + if (err) + goto err_set_queues; + + } else if (vsi->type == I40E_VSI_FDIR) { + snprintf(int_name, sizeof(int_name) - 1, "%s-fdir", + dev_driver_string(&pf->pdev->dev)); + err = i40e_vsi_request_irq(vsi, int_name); + } else { + err = -EINVAL; + goto err_setup_rx; + } err = i40e_up_complete(vsi); if (err) @@ -4378,14 +4541,7 @@ static int i40e_close(struct net_device *netdev) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; - if (test_and_set_bit(__I40E_DOWN, &vsi->state)) - return 0; - - i40e_down(vsi); - i40e_vsi_free_irq(vsi); - - i40e_vsi_free_tx_resources(vsi); - i40e_vsi_free_rx_resources(vsi); + i40e_vsi_close(vsi); return 0; } @@ -4405,6 +4561,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) WARN_ON(in_interrupt()); + if (i40e_check_asq_alive(&pf->hw)) + i40e_vc_notify_reset(pf); + /* do the biggest reset indicated */ if (reset_flags & (1 << __I40E_GLOBAL_RESET_REQUESTED)) { @@ -4470,7 +4629,7 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) /* Find the VSI(s) that requested a re-init */ dev_info(&pf->pdev->dev, "VSI reinit requested\n"); - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; if (vsi != NULL && test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) { @@ -4560,6 +4719,10 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, int ret = 0; u8 type; + /* Not DCB capable or capability disabled */ + if (!(pf->flags & I40E_FLAG_DCB_CAPABLE)) + return ret; + /* Ignore if event is not for Nearest Bridge */ type = ((mib->type >> I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); @@ -4601,6 +4764,12 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, if (!need_reconfig) goto exit; + /* Enable DCB tagging only when more than one TC */ + if (i40e_dcb_get_num_tc(dcbx_cfg) > 1) + pf->flags |= I40E_FLAG_DCB_ENABLED; + else + pf->flags &= ~I40E_FLAG_DCB_ENABLED; + /* Reconfiguration needed quiesce all VSIs */ i40e_pf_quiesce_all_vsi(pf); @@ -4671,7 +4840,7 @@ static void i40e_service_event_complete(struct i40e_pf *pf) BUG_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state)); /* flush memory to make sure state is correct before next watchog */ - smp_mb__before_clear_bit(); + smp_mb__before_atomic(); clear_bit(__I40E_SERVICE_SCHED, &pf->state); } @@ -4704,8 +4873,7 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf) (pf->flags & I40E_FLAG_FD_SB_ENABLED)) return; fcnt_prog = i40e_get_current_fd_count(pf); - fcnt_avail = pf->hw.fdir_shared_filter_count + - pf->fdir_pf_filter_count; + fcnt_avail = i40e_get_fd_cnt_all(pf); if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) { if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) && (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) { @@ -4798,7 +4966,7 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up) i40e_veb_link_event(pf->veb[i], link_up); /* ... now the local VSIs */ - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) + for (i = 0; i < pf->num_alloc_vsi; i++) if (pf->vsi[i] && (pf->vsi[i]->uplink_seid == veb->seid)) i40e_vsi_link_event(pf->vsi[i], link_up); } @@ -4816,10 +4984,8 @@ static void i40e_link_event(struct i40e_pf *pf) if (new_link == old_link) return; - if (!test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state)) - netdev_info(pf->vsi[pf->lan_vsi]->netdev, - "NIC Link is %s\n", (new_link ? "Up" : "Down")); + i40e_print_link_message(pf->vsi[pf->lan_vsi], new_link); /* Notify the base of the switch tree connected to * the link. Floating VEBs are not notified. @@ -4857,7 +5023,7 @@ static void i40e_check_hang_subtask(struct i40e_pf *pf) * for each q_vector * force an interrupt */ - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; int armed = 0; @@ -4907,7 +5073,7 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) /* Update the stats for active netdevs so the network stack * can look at updated numbers whenever it cares to */ - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) + for (i = 0; i < pf->num_alloc_vsi; i++) if (pf->vsi[i] && pf->vsi[i]->netdev) i40e_update_stats(pf->vsi[i]); @@ -5013,11 +5179,47 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) u16 pending, i = 0; i40e_status ret; u16 opcode; + u32 oldval; u32 val; if (!test_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state)) return; + /* check for error indications */ + val = rd32(&pf->hw, pf->hw.aq.arq.len); + oldval = val; + if (val & I40E_PF_ARQLEN_ARQVFE_MASK) { + dev_info(&pf->pdev->dev, "ARQ VF Error detected\n"); + val &= ~I40E_PF_ARQLEN_ARQVFE_MASK; + } + if (val & I40E_PF_ARQLEN_ARQOVFL_MASK) { + dev_info(&pf->pdev->dev, "ARQ Overflow Error detected\n"); + val &= ~I40E_PF_ARQLEN_ARQOVFL_MASK; + } + if (val & I40E_PF_ARQLEN_ARQCRIT_MASK) { + dev_info(&pf->pdev->dev, "ARQ Critical Error detected\n"); + val &= ~I40E_PF_ARQLEN_ARQCRIT_MASK; + } + if (oldval != val) + wr32(&pf->hw, pf->hw.aq.arq.len, val); + + val = rd32(&pf->hw, pf->hw.aq.asq.len); + oldval = val; + if (val & I40E_PF_ATQLEN_ATQVFE_MASK) { + dev_info(&pf->pdev->dev, "ASQ VF Error detected\n"); + val &= ~I40E_PF_ATQLEN_ATQVFE_MASK; + } + if (val & I40E_PF_ATQLEN_ATQOVFL_MASK) { + dev_info(&pf->pdev->dev, "ASQ Overflow Error detected\n"); + val &= ~I40E_PF_ATQLEN_ATQOVFL_MASK; + } + if (val & I40E_PF_ATQLEN_ATQCRIT_MASK) { + dev_info(&pf->pdev->dev, "ASQ Critical Error detected\n"); + val &= ~I40E_PF_ATQLEN_ATQCRIT_MASK; + } + if (oldval != val) + wr32(&pf->hw, pf->hw.aq.asq.len, val); + event.msg_size = I40E_MAX_AQ_BUF_SIZE; event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); if (!event.msg_buf) @@ -5123,7 +5325,7 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb) int ret; /* build VSI that owns this VEB, temporarily attached to base VEB */ - for (v = 0; v < pf->hw.func_caps.num_vsis && !ctl_vsi; v++) { + for (v = 0; v < pf->num_alloc_vsi && !ctl_vsi; v++) { if (pf->vsi[v] && pf->vsi[v]->veb_idx == veb->idx && pf->vsi[v]->flags & I40E_VSI_FLAG_VEB_OWNER) { @@ -5153,7 +5355,7 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb) goto end_reconstitute; /* create the remaining VSIs attached to this VEB */ - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (!pf->vsi[v] || pf->vsi[v] == ctl_vsi) continue; @@ -5221,9 +5423,6 @@ static int i40e_get_capabilities(struct i40e_pf *pf) } } while (err); - /* increment MSI-X count because current FW skips one */ - pf->hw.func_caps.num_msix_vectors++; - if (((pf->hw.aq.fw_maj_ver == 2) && (pf->hw.aq.fw_min_ver < 22)) || (pf->hw.aq.fw_maj_ver < 2)) { pf->hw.func_caps.num_msix_vectors++; @@ -5262,15 +5461,14 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi); static void i40e_fdir_sb_setup(struct i40e_pf *pf) { struct i40e_vsi *vsi; - bool new_vsi = false; - int err, i; + int i; if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED)) return; /* find existing VSI and see if it needs configuring */ vsi = NULL; - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { vsi = pf->vsi[i]; break; @@ -5283,47 +5481,12 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf) pf->vsi[pf->lan_vsi]->seid, 0); if (!vsi) { dev_info(&pf->pdev->dev, "Couldn't create FDir VSI\n"); - goto err_vsi; + pf->flags &= ~I40E_FLAG_FD_SB_ENABLED; + return; } - new_vsi = true; } - i40e_vsi_setup_irqhandler(vsi, i40e_fdir_clean_ring); - - err = i40e_vsi_setup_tx_resources(vsi); - if (err) - goto err_setup_tx; - err = i40e_vsi_setup_rx_resources(vsi); - if (err) - goto err_setup_rx; - if (new_vsi) { - char int_name[IFNAMSIZ + 9]; - err = i40e_vsi_configure(vsi); - if (err) - goto err_setup_rx; - snprintf(int_name, sizeof(int_name) - 1, "%s-fdir", - dev_driver_string(&pf->pdev->dev)); - err = i40e_vsi_request_irq(vsi, int_name); - if (err) - goto err_setup_rx; - err = i40e_up_complete(vsi); - if (err) - goto err_up_complete; - clear_bit(__I40E_NEEDS_RESTART, &vsi->state); - } - - return; - -err_up_complete: - i40e_down(vsi); - i40e_vsi_free_irq(vsi); -err_setup_rx: - i40e_vsi_free_rx_resources(vsi); -err_setup_tx: - i40e_vsi_free_tx_resources(vsi); -err_vsi: - pf->flags &= ~I40E_FLAG_FD_SB_ENABLED; - i40e_vsi_clear(vsi); + i40e_vsi_setup_irqhandler(vsi, i40e_fdir_clean_ring); } /** @@ -5335,7 +5498,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) int i; i40e_fdir_filter_exit(pf); - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { i40e_vsi_release(pf->vsi[i]); break; @@ -5352,7 +5515,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) static int i40e_prep_for_reset(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; - i40e_status ret; + i40e_status ret = 0; u32 v; clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); @@ -5361,13 +5524,10 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n"); - if (i40e_check_asq_alive(hw)) - i40e_vc_notify_reset(pf); - /* quiesce the VSIs and their queues that are not already DOWN */ i40e_pf_quiesce_all_vsi(pf); - for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v]) pf->vsi[v]->seid = 0; } @@ -5375,22 +5535,40 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) i40e_shutdown_adminq(&pf->hw); /* call shutdown HMC */ - ret = i40e_shutdown_lan_hmc(hw); - if (ret) { - dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); - clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); + if (hw->hmc.hmc_obj) { + ret = i40e_shutdown_lan_hmc(hw); + if (ret) { + dev_warn(&pf->pdev->dev, + "shutdown_lan_hmc failed: %d\n", ret); + clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); + } } return ret; } /** + * i40e_send_version - update firmware with driver version + * @pf: PF struct + */ +static void i40e_send_version(struct i40e_pf *pf) +{ + struct i40e_driver_version dv; + + dv.major_version = DRV_VERSION_MAJOR; + dv.minor_version = DRV_VERSION_MINOR; + dv.build_version = DRV_VERSION_BUILD; + dv.subbuild_version = 0; + strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string)); + i40e_aq_send_driver_version(&pf->hw, &dv, NULL); +} + +/** * i40e_reset_and_rebuild - reset and rebuild using a saved config * @pf: board private structure * @reinit: if the Main VSI needs to re-initialized. **/ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) { - struct i40e_driver_version dv; struct i40e_hw *hw = &pf->hw; i40e_status ret; u32 v; @@ -5400,8 +5578,10 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) * because the reset will make them disappear. */ ret = i40e_pf_reset(hw); - if (ret) + if (ret) { dev_info(&pf->pdev->dev, "PF reset failed, %d\n", ret); + goto end_core_reset; + } pf->pfr_count++; if (test_bit(__I40E_DOWN, &pf->state)) @@ -5421,6 +5601,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) i40e_verify_eeprom(pf); } + i40e_clear_pxe_mode(hw); ret = i40e_get_capabilities(pf); if (ret) { dev_info(&pf->pdev->dev, "i40e_get_capabilities failed, %d\n", @@ -5521,13 +5702,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } /* tell the firmware that we're starting */ - dv.major_version = DRV_VERSION_MAJOR; - dv.minor_version = DRV_VERSION_MINOR; - dv.build_version = DRV_VERSION_BUILD; - dv.subbuild_version = 0; - i40e_aq_send_driver_version(&pf->hw, &dv, NULL); - - dev_info(&pf->pdev->dev, "reset complete\n"); + i40e_send_version(pf); end_core_reset: clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); @@ -5637,7 +5812,6 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) **/ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) { - const int vxlan_hdr_qwords = 4; struct i40e_hw *hw = &pf->hw; i40e_status ret; u8 filter_index; @@ -5655,7 +5829,6 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) port = pf->vxlan_ports[i]; ret = port ? i40e_aq_add_udp_tunnel(hw, ntohs(port), - vxlan_hdr_qwords, I40E_AQC_TUNNEL_TYPE_VXLAN, &filter_index, NULL) : i40e_aq_del_udp_tunnel(hw, i, NULL); @@ -5834,15 +6007,15 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) * find next empty vsi slot, looping back around if necessary */ i = pf->next_vsi; - while (i < pf->hw.func_caps.num_vsis && pf->vsi[i]) + while (i < pf->num_alloc_vsi && pf->vsi[i]) i++; - if (i >= pf->hw.func_caps.num_vsis) { + if (i >= pf->num_alloc_vsi) { i = 0; while (i < pf->next_vsi && pf->vsi[i]) i++; } - if (i < pf->hw.func_caps.num_vsis && !pf->vsi[i]) { + if (i < pf->num_alloc_vsi && !pf->vsi[i]) { vsi_idx = i; /* Found one! */ } else { ret = -ENODEV; @@ -5865,6 +6038,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) vsi->netdev_registered = false; vsi->work_limit = I40E_DEFAULT_IRQ_WORK; INIT_LIST_HEAD(&vsi->mac_filter_list); + vsi->irqs_ready = false; ret = i40e_set_num_rings_in_vsi(vsi); if (ret) @@ -5982,14 +6156,12 @@ static void i40e_vsi_clear_rings(struct i40e_vsi *vsi) **/ static int i40e_alloc_rings(struct i40e_vsi *vsi) { + struct i40e_ring *tx_ring, *rx_ring; struct i40e_pf *pf = vsi->back; int i; /* Set basic values in the rings to be used later during open() */ for (i = 0; i < vsi->alloc_queue_pairs; i++) { - struct i40e_ring *tx_ring; - struct i40e_ring *rx_ring; - /* allocate space for both Tx and Rx in one shot */ tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL); if (!tx_ring) @@ -6047,8 +6219,6 @@ static int i40e_reserve_msix_vectors(struct i40e_pf *pf, int vectors) vectors = 0; } - pf->num_msix_entries = vectors; - return vectors; } @@ -6102,6 +6272,16 @@ static int i40e_init_msix(struct i40e_pf *pf) for (i = 0; i < v_budget; i++) pf->msix_entries[i].entry = i; vec = i40e_reserve_msix_vectors(pf, v_budget); + + if (vec != v_budget) { + /* If we have limited resources, we will start with no vectors + * for the special features and then allocate vectors to some + * of these features based on the policy and at the end disable + * the features that did not get any vectors. + */ + pf->num_vmdq_msix = 0; + } + if (vec < I40E_MIN_MSIX) { pf->flags &= ~I40E_FLAG_MSIX_ENABLED; kfree(pf->msix_entries); @@ -6110,27 +6290,25 @@ static int i40e_init_msix(struct i40e_pf *pf) } else if (vec == I40E_MIN_MSIX) { /* Adjust for minimal MSIX use */ - dev_info(&pf->pdev->dev, "Features disabled, not enough MSI-X vectors\n"); - pf->flags &= ~I40E_FLAG_VMDQ_ENABLED; pf->num_vmdq_vsis = 0; pf->num_vmdq_qps = 0; - pf->num_vmdq_msix = 0; pf->num_lan_qps = 1; pf->num_lan_msix = 1; } else if (vec != v_budget) { + /* reserve the misc vector */ + vec--; + /* Scale vector usage down */ pf->num_vmdq_msix = 1; /* force VMDqs to only one vector */ - vec--; /* reserve the misc vector */ + pf->num_vmdq_vsis = 1; /* partition out the remaining vectors */ switch (vec) { case 2: - pf->num_vmdq_vsis = 1; pf->num_lan_msix = 1; break; case 3: - pf->num_vmdq_vsis = 1; pf->num_lan_msix = 2; break; default: @@ -6142,6 +6320,11 @@ static int i40e_init_msix(struct i40e_pf *pf) } } + if ((pf->flags & I40E_FLAG_VMDQ_ENABLED) && + (pf->num_vmdq_msix == 0)) { + dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n"); + pf->flags &= ~I40E_FLAG_VMDQ_ENABLED; + } return err; } @@ -6166,7 +6349,7 @@ static int i40e_vsi_alloc_q_vector(struct i40e_vsi *vsi, int v_idx) cpumask_set_cpu(v_idx, &q_vector->affinity_mask); if (vsi->netdev) netif_napi_add(vsi->netdev, &q_vector->napi, - i40e_napi_poll, vsi->work_limit); + i40e_napi_poll, NAPI_POLL_WEIGHT); q_vector->rx.latency_range = I40E_LOW_LATENCY; q_vector->tx.latency_range = I40E_LOW_LATENCY; @@ -6226,7 +6409,7 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf) if (err) { pf->flags &= ~(I40E_FLAG_MSIX_ENABLED | I40E_FLAG_RSS_ENABLED | - I40E_FLAG_DCB_ENABLED | + I40E_FLAG_DCB_CAPABLE | I40E_FLAG_SRIOV_ENABLED | I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED | @@ -6359,7 +6542,6 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) return 0; queue_count = min_t(int, queue_count, pf->rss_size_max); - queue_count = rounddown_pow_of_two(queue_count); if (queue_count != pf->rss_size) { i40e_prep_for_reset(pf); @@ -6402,6 +6584,10 @@ static int i40e_sw_init(struct i40e_pf *pf) I40E_FLAG_MSIX_ENABLED | I40E_FLAG_RX_1BUF_ENABLED; + /* Set default ITR */ + pf->rx_itr_default = I40E_ITR_DYNAMIC | I40E_ITR_RX_DEF; + pf->tx_itr_default = I40E_ITR_DYNAMIC | I40E_ITR_TX_DEF; + /* Depending on PF configurations, it is possible that the RSS * maximum might end up larger than the available queues */ @@ -6411,7 +6597,6 @@ static int i40e_sw_init(struct i40e_pf *pf) if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus()); - pf->rss_size = rounddown_pow_of_two(pf->rss_size); } else { pf->rss_size = 1; } @@ -6427,8 +6612,12 @@ static int i40e_sw_init(struct i40e_pf *pf) (pf->hw.func_caps.fd_filters_best_effort > 0)) { pf->flags |= I40E_FLAG_FD_ATR_ENABLED; pf->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE; + /* Setup a counter for fd_atr per pf */ + pf->fd_atr_cnt_idx = I40E_FD_ATR_STAT_IDX(pf->hw.pf_id); if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) { pf->flags |= I40E_FLAG_FD_SB_ENABLED; + /* Setup a counter for fd_sb per pf */ + pf->fd_sb_cnt_idx = I40E_FD_SB_STAT_IDX(pf->hw.pf_id); } else { dev_info(&pf->pdev->dev, "Flow Director Sideband mode Disabled in MFP mode\n"); @@ -6644,6 +6833,96 @@ static void i40e_del_vxlan_port(struct net_device *netdev, } #endif +#ifdef HAVE_FDB_OPS +#ifdef USE_CONST_DEV_UC_CHAR +static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, + u16 flags) +#else +static int i40e_ndo_fdb_add(struct ndmsg *ndm, + struct net_device *dev, + unsigned char *addr, + u16 flags) +#endif +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + struct i40e_pf *pf = np->vsi->back; + int err = 0; + + if (!(pf->flags & I40E_FLAG_SRIOV_ENABLED)) + return -EOPNOTSUPP; + + /* Hardware does not support aging addresses so if a + * ndm_state is given only allow permanent addresses + */ + if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { + netdev_info(dev, "FDB only supports static addresses\n"); + return -EINVAL; + } + + if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) + err = dev_uc_add_excl(dev, addr); + else if (is_multicast_ether_addr(addr)) + err = dev_mc_add_excl(dev, addr); + else + err = -EINVAL; + + /* Only return duplicate errors if NLM_F_EXCL is set */ + if (err == -EEXIST && !(flags & NLM_F_EXCL)) + err = 0; + + return err; +} + +#ifndef USE_DEFAULT_FDB_DEL_DUMP +#ifdef USE_CONST_DEV_UC_CHAR +static int i40e_ndo_fdb_del(struct ndmsg *ndm, + struct net_device *dev, + const unsigned char *addr) +#else +static int i40e_ndo_fdb_del(struct ndmsg *ndm, + struct net_device *dev, + unsigned char *addr) +#endif +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + struct i40e_pf *pf = np->vsi->back; + int err = -EOPNOTSUPP; + + if (ndm->ndm_state & NUD_PERMANENT) { + netdev_info(dev, "FDB only supports static addresses\n"); + return -EINVAL; + } + + if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { + if (is_unicast_ether_addr(addr)) + err = dev_uc_del(dev, addr); + else if (is_multicast_ether_addr(addr)) + err = dev_mc_del(dev, addr); + else + err = -EINVAL; + } + + return err; +} + +static int i40e_ndo_fdb_dump(struct sk_buff *skb, + struct netlink_callback *cb, + struct net_device *dev, + int idx) +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + struct i40e_pf *pf = np->vsi->back; + + if (pf->flags & I40E_FLAG_SRIOV_ENABLED) + idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); + + return idx; +} + +#endif /* USE_DEFAULT_FDB_DEL_DUMP */ +#endif /* HAVE_FDB_OPS */ static const struct net_device_ops i40e_netdev_ops = { .ndo_open = i40e_open, .ndo_stop = i40e_close, @@ -6664,13 +6943,21 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_set_features = i40e_set_features, .ndo_set_vf_mac = i40e_ndo_set_vf_mac, .ndo_set_vf_vlan = i40e_ndo_set_vf_port_vlan, - .ndo_set_vf_tx_rate = i40e_ndo_set_vf_bw, + .ndo_set_vf_rate = i40e_ndo_set_vf_bw, .ndo_get_vf_config = i40e_ndo_get_vf_config, .ndo_set_vf_link_state = i40e_ndo_set_vf_link_state, + .ndo_set_vf_spoofchk = i40e_ndo_set_vf_spoofck, #ifdef CONFIG_I40E_VXLAN .ndo_add_vxlan_port = i40e_add_vxlan_port, .ndo_del_vxlan_port = i40e_del_vxlan_port, #endif +#ifdef HAVE_FDB_OPS + .ndo_fdb_add = i40e_ndo_fdb_add, +#ifndef USE_DEFAULT_FDB_DEL_DUMP + .ndo_fdb_del = i40e_ndo_fdb_del, + .ndo_fdb_dump = i40e_ndo_fdb_dump, +#endif +#endif }; /** @@ -6712,18 +6999,29 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_IPV6_CSUM | NETIF_F_TSO | + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_RXCSUM | - NETIF_F_NTUPLE | NETIF_F_RXHASH | 0; + if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) + netdev->features |= NETIF_F_NTUPLE; + /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; if (vsi->type == I40E_VSI_MAIN) { SET_NETDEV_DEV(netdev, &pf->pdev->dev); - memcpy(mac_addr, hw->mac.perm_addr, ETH_ALEN); + ether_addr_copy(mac_addr, hw->mac.perm_addr); + /* The following two steps are necessary to prevent reception + * of tagged packets - by default the NVM loads a MAC-VLAN + * filter that will accept any tagged packet. This is to + * prevent that during normal operations until a specific + * VLAN tag filter has been set. + */ + i40e_rm_default_mac_filter(vsi, mac_addr); + i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true); } else { /* relate the VSI_VMDQ name to the VSI_MAIN name */ snprintf(netdev->name, IFNAMSIZ, "%sv%%d", @@ -6733,8 +7031,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) } i40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false); - memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); - memcpy(netdev->perm_addr, mac_addr, ETH_ALEN); + ether_addr_copy(netdev->dev_addr, mac_addr); + ether_addr_copy(netdev->perm_addr, mac_addr); /* vlan gets same features (except vlan offload) * after any tweaks for specific VSI types */ @@ -6766,7 +7064,6 @@ static void i40e_vsi_delete(struct i40e_vsi *vsi) return; i40e_aq_delete_element(&vsi->back->hw, vsi->seid, NULL); - return; } /** @@ -6892,6 +7189,13 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ctxt.info.valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID); ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL; + if (pf->vf[vsi->vf_id].spoofchk) { + ctxt.info.valid_sections |= + cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID); + ctxt.info.sec_flags |= + (I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK | + I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK); + } /* Setup the VSI tx/rx queue map for TC0 only for now */ i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, true); break; @@ -6976,11 +7280,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) unregister_netdev(vsi->netdev); } } else { - if (!test_and_set_bit(__I40E_DOWN, &vsi->state)) - i40e_down(vsi); - i40e_vsi_free_irq(vsi); - i40e_vsi_free_tx_resources(vsi); - i40e_vsi_free_rx_resources(vsi); + i40e_vsi_close(vsi); } i40e_vsi_disable_irq(vsi); } @@ -7007,7 +7307,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) * the orphan VEBs yet. We'll wait for an explicit remove request * from up the network stack. */ - for (n = 0, i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (n = 0, i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->uplink_seid == uplink_seid && (pf->vsi[i]->flags & I40E_VSI_FLAG_VEB_OWNER) == 0) { @@ -7186,7 +7486,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, if (!veb && uplink_seid != pf->mac_seid) { - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->seid == uplink_seid) { vsi = pf->vsi[i]; break; @@ -7429,7 +7729,7 @@ static void i40e_switch_branch_release(struct i40e_veb *branch) * NOTE: Removing the last VSI on a VEB has the SIDE EFFECT of removing * the VEB itself, so don't use (*branch) after this loop. */ - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (!pf->vsi[i]) continue; if (pf->vsi[i]->uplink_seid == branch_seid && @@ -7481,7 +7781,7 @@ void i40e_veb_release(struct i40e_veb *veb) pf = veb->pf; /* find the remaining VSI and check for extras */ - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->uplink_seid == veb->seid) { n++; vsi = pf->vsi[i]; @@ -7510,8 +7810,6 @@ void i40e_veb_release(struct i40e_veb *veb) i40e_aq_delete_element(&pf->hw, veb->seid, NULL); i40e_veb_clear(veb); - - return; } /** @@ -7595,10 +7893,10 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, } /* make sure there is such a vsi and uplink */ - for (vsi_idx = 0; vsi_idx < pf->hw.func_caps.num_vsis; vsi_idx++) + for (vsi_idx = 0; vsi_idx < pf->num_alloc_vsi; vsi_idx++) if (pf->vsi[vsi_idx] && pf->vsi[vsi_idx]->seid == vsi_seid) break; - if (vsi_idx >= pf->hw.func_caps.num_vsis && vsi_seid != 0) { + if (vsi_idx >= pf->num_alloc_vsi && vsi_seid != 0) { dev_info(&pf->pdev->dev, "vsi seid %d not found\n", vsi_seid); return NULL; @@ -7633,6 +7931,8 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, ret = i40e_add_veb(veb, pf->vsi[vsi_idx]); if (ret) goto err_veb; + if (vsi_idx == pf->lan_vsi) + pf->lan_veb = veb->idx; return veb; @@ -7768,15 +8068,6 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) "header: %d reported %d total\n", num_reported, num_total); - if (num_reported) { - int sz = sizeof(*sw_config) * num_reported; - - kfree(pf->sw_config); - pf->sw_config = kzalloc(sz, GFP_KERNEL); - if (pf->sw_config) - memcpy(pf->sw_config, sw_config, sz); - } - for (i = 0; i < num_reported; i++) { struct i40e_aqc_switch_config_element_resp *ele = &sw_config->element[i]; @@ -7943,9 +8234,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) queues_left = pf->hw.func_caps.num_tx_qp; if ((queues_left == 1) || - !(pf->flags & I40E_FLAG_MSIX_ENABLED) || - !(pf->flags & (I40E_FLAG_RSS_ENABLED | I40E_FLAG_FD_SB_ENABLED | - I40E_FLAG_DCB_ENABLED))) { + !(pf->flags & I40E_FLAG_MSIX_ENABLED)) { /* one qp for PF, no queues for anything else */ queues_left = 0; pf->rss_size = pf->num_lan_qps = 1; @@ -7954,14 +8243,27 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) pf->flags &= ~(I40E_FLAG_RSS_ENABLED | I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED | - I40E_FLAG_DCB_ENABLED | + I40E_FLAG_DCB_CAPABLE | I40E_FLAG_SRIOV_ENABLED | I40E_FLAG_VMDQ_ENABLED); + } else if (!(pf->flags & (I40E_FLAG_RSS_ENABLED | + I40E_FLAG_FD_SB_ENABLED | + I40E_FLAG_FD_ATR_ENABLED | + I40E_FLAG_DCB_CAPABLE))) { + /* one qp for PF */ + pf->rss_size = pf->num_lan_qps = 1; + queues_left -= pf->num_lan_qps; + + pf->flags &= ~(I40E_FLAG_RSS_ENABLED | + I40E_FLAG_FD_SB_ENABLED | + I40E_FLAG_FD_ATR_ENABLED | + I40E_FLAG_DCB_ENABLED | + I40E_FLAG_VMDQ_ENABLED); } else { /* Not enough queues for all TCs */ - if ((pf->flags & I40E_FLAG_DCB_ENABLED) && + if ((pf->flags & I40E_FLAG_DCB_CAPABLE) && (queues_left < I40E_MAX_TRAFFIC_CLASS)) { - pf->flags &= ~I40E_FLAG_DCB_ENABLED; + pf->flags &= ~I40E_FLAG_DCB_CAPABLE; dev_info(&pf->pdev->dev, "not enough queues for DCB. DCB is disabled.\n"); } pf->num_lan_qps = pf->rss_size_max; @@ -7992,7 +8294,6 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) } pf->queues_left = queues_left; - return; } /** @@ -8049,12 +8350,13 @@ static void i40e_print_features(struct i40e_pf *pf) if (pf->flags & I40E_FLAG_RSS_ENABLED) buf += sprintf(buf, "RSS "); - buf += sprintf(buf, "FDir "); if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) - buf += sprintf(buf, "ATR "); - if (pf->flags & I40E_FLAG_FD_SB_ENABLED) + buf += sprintf(buf, "FD_ATR "); + if (pf->flags & I40E_FLAG_FD_SB_ENABLED) { + buf += sprintf(buf, "FD_SB "); buf += sprintf(buf, "NTUPLE "); - if (pf->flags & I40E_FLAG_DCB_ENABLED) + } + if (pf->flags & I40E_FLAG_DCB_CAPABLE) buf += sprintf(buf, "DCB "); if (pf->flags & I40E_FLAG_PTP) buf += sprintf(buf, "PTP "); @@ -8077,13 +8379,13 @@ static void i40e_print_features(struct i40e_pf *pf) **/ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct i40e_driver_version dv; struct i40e_pf *pf; struct i40e_hw *hw; static u16 pfs_found; u16 link_status; int err = 0; u32 len; + u32 i; err = pci_enable_device_mem(pdev); if (err) @@ -8195,6 +8497,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_verify_eeprom(pf); + /* Rev 0 hardware was never productized */ + if (hw->revision_id < 1) + dev_warn(&pdev->dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues with your hardware. If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n"); + i40e_clear_pxe_mode(hw); err = i40e_get_capabilities(pf); if (err) @@ -8228,7 +8534,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_mac_addr; } dev_info(&pdev->dev, "MAC address: %pM\n", hw->mac.addr); - memcpy(hw->mac.perm_addr, hw->mac.addr, ETH_ALEN); + ether_addr_copy(hw->mac.perm_addr, hw->mac.addr); pci_set_drvdata(pdev, pf); pci_save_state(pdev); @@ -8236,8 +8542,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = i40e_init_pf_dcb(pf); if (err) { dev_info(&pdev->dev, "init_pf_dcb failed: %d\n", err); - pf->flags &= ~I40E_FLAG_DCB_ENABLED; - goto err_init_dcb; + pf->flags &= ~I40E_FLAG_DCB_CAPABLE; + /* Continue without DCB enabled */ } #endif /* CONFIG_I40E_DCB */ @@ -8258,10 +8564,18 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_determine_queue_usage(pf); i40e_init_interrupt_scheme(pf); - /* Set up the *vsi struct based on the number of VSIs in the HW, - * and set up our local tracking of the MAIN PF vsi. + /* The number of VSIs reported by the FW is the minimum guaranteed + * to us; HW supports far more and we share the remaining pool with + * the other PFs. We allocate space for more than the guarantee with + * the understanding that we might not get them all later. */ - len = sizeof(struct i40e_vsi *) * pf->hw.func_caps.num_vsis; + if (pf->hw.func_caps.num_vsis < I40E_MIN_VSI_ALLOC) + pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC; + else + pf->num_alloc_vsi = pf->hw.func_caps.num_vsis; + + /* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */ + len = sizeof(struct i40e_vsi *) * pf->num_alloc_vsi; pf->vsi = kzalloc(len, GFP_KERNEL); if (!pf->vsi) { err = -ENOMEM; @@ -8273,6 +8587,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err); goto err_vsis; } + /* if FDIR VSI was set up, start it now */ + for (i = 0; i < pf->num_alloc_vsi; i++) { + if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { + i40e_vsi_open(pf->vsi[i]); + break; + } + } /* The main driver is (mostly) up and happy. We need to set this state * before setting up the misc vector or we get a race and the vector @@ -8294,6 +8615,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } +#ifdef CONFIG_PCI_IOV /* prep for VF support */ if ((pf->flags & I40E_FLAG_SRIOV_ENABLED) && (pf->flags & I40E_FLAG_MSIX_ENABLED) && @@ -8316,17 +8638,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err); } } +#endif /* CONFIG_PCI_IOV */ pfs_found++; i40e_dbg_pf_init(pf); /* tell the firmware that we're starting */ - dv.major_version = DRV_VERSION_MAJOR; - dv.minor_version = DRV_VERSION_MINOR; - dv.build_version = DRV_VERSION_BUILD; - dv.subbuild_version = 0; - i40e_aq_send_driver_version(&pf->hw, &dv, NULL); + i40e_send_version(pf); /* since everything's happy, start the service_task timer */ mod_timer(&pf->service_timer, @@ -8367,9 +8686,6 @@ err_vsis: err_switch_setup: i40e_reset_interrupt_capability(pf); del_timer_sync(&pf->service_timer); -#ifdef CONFIG_I40E_DCB -err_init_dcb: -#endif /* CONFIG_I40E_DCB */ err_mac_addr: err_configure_lan_hmc: (void)i40e_shutdown_lan_hmc(hw); @@ -8450,10 +8766,13 @@ static void i40e_remove(struct pci_dev *pdev) } /* shutdown and destroy the HMC */ - ret_code = i40e_shutdown_lan_hmc(&pf->hw); - if (ret_code) - dev_warn(&pdev->dev, - "Failed to destroy the HMC resources: %d\n", ret_code); + if (pf->hw.hmc.hmc_obj) { + ret_code = i40e_shutdown_lan_hmc(&pf->hw); + if (ret_code) + dev_warn(&pdev->dev, + "Failed to destroy the HMC resources: %d\n", + ret_code); + } /* shutdown the adminq */ ret_code = i40e_shutdown_adminq(&pf->hw); @@ -8464,7 +8783,7 @@ static void i40e_remove(struct pci_dev *pdev) /* Clear all dynamic memory lists of rings, q_vectors, and VSIs */ i40e_clear_interrupt_scheme(pf); - for (i = 0; i < pf->hw.func_caps.num_vsis; i++) { + for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i]) { i40e_vsi_clear_rings(pf->vsi[i]); i40e_vsi_clear(pf->vsi[i]); @@ -8479,7 +8798,6 @@ static void i40e_remove(struct pci_dev *pdev) kfree(pf->qp_pile); kfree(pf->irq_pile); - kfree(pf->sw_config); kfree(pf->vsi); /* force a PF reset to clean anything leftover */ |