diff options
Diffstat (limited to 'kernel/drivers/net/ethernet/intel/fm10k')
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k.h | 19 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 11 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 223 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 46 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_main.c | 116 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 53 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 54 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 225 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 123 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.h | 8 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 13 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_type.h | 9 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 14 |
13 files changed, 622 insertions, 292 deletions
diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k.h b/kernel/drivers/net/ethernet/intel/fm10k/fm10k.h index c8c8c5bae..144402004 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -101,12 +101,19 @@ struct fm10k_tx_queue_stats { u64 csum_err; u64 tx_busy; u64 tx_done_old; + u64 csum_good; }; struct fm10k_rx_queue_stats { u64 alloc_failed; u64 csum_err; u64 errors; + u64 csum_good; + u64 switch_errors; + u64 drops; + u64 pp_errors; + u64 link_errors; + u64 length_errors; }; struct fm10k_ring { @@ -251,6 +258,7 @@ struct fm10k_intfc { #define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(1 << 2) #define FM10K_FLAG_RX_TS_ENABLED (u32)(1 << 3) #define FM10K_FLAG_SWPRI_CONFIG (u32)(1 << 4) +#define FM10K_FLAG_DEBUG_STATS (u32)(1 << 5) int xcast_mode; /* Tx fast path data */ @@ -277,6 +285,17 @@ struct fm10k_intfc { u64 rx_drops_nic; u64 rx_overrun_pf; u64 rx_overrun_vf; + + /* Debug Statistics */ + u64 hw_sm_mbx_full; + u64 hw_csum_tx_good; + u64 hw_csum_rx_good; + u64 rx_switch_errors; + u64 rx_drops; + u64 rx_pp_errors; + u64 rx_link_errors; + u64 rx_length_errors; + u32 tx_timeout_count; /* RX */ diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c index f45b4d71a..5304bc1fb 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c @@ -37,7 +37,8 @@ static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos) } static void *fm10k_dbg_desc_seq_next(struct seq_file *s, - void __always_unused *v, loff_t *pos) + void __always_unused *v, + loff_t *pos) { struct fm10k_ring *ring = s->private; @@ -45,7 +46,7 @@ static void *fm10k_dbg_desc_seq_next(struct seq_file *s, } static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s, - __always_unused void *v) + void __always_unused *v) { /* Do nothing. */ } @@ -175,7 +176,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) return; /* Generate a folder for each q_vector */ - sprintf(name, "q_vector.%03d", q_vector->v_idx); + snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx); q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc); if (!q_vector->dbg_q_vector) @@ -185,7 +186,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) for (i = 0; i < q_vector->tx.count; i++) { struct fm10k_ring *ring = &q_vector->tx.ring[i]; - sprintf(name, "tx_ring.%03d", ring->queue_index); + snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index); debugfs_create_file(name, 0600, q_vector->dbg_q_vector, ring, @@ -196,7 +197,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) for (i = 0; i < q_vector->rx.count; i++) { struct fm10k_ring *ring = &q_vector->rx.ring[i]; - sprintf(name, "rx_ring.%03d", ring->queue_index); + snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index); debugfs_create_file(name, 0600, q_vector->dbg_q_vector, ring, diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 4b9d9f88a..2ce0eba5e 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -76,19 +76,22 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = { FM10K_STAT("mac_rules_used", hw.swapi.mac.used), FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail), - FM10K_STAT("mbx_tx_busy", hw.mbx.tx_busy), - FM10K_STAT("mbx_tx_oversized", hw.mbx.tx_dropped), - FM10K_STAT("mbx_tx_messages", hw.mbx.tx_messages), - FM10K_STAT("mbx_tx_dwords", hw.mbx.tx_dwords), - FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages), - FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords), - FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err), - FM10K_STAT("tx_hang_count", tx_timeout_count), FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), }; +static const struct fm10k_stats fm10k_gstrings_debug_stats[] = { + FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full), + FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good), + FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good), + FM10K_STAT("rx_switch_errors", rx_switch_errors), + FM10K_STAT("rx_drops", rx_drops), + FM10K_STAT("rx_pp_errors", rx_pp_errors), + FM10K_STAT("rx_link_errors", rx_link_errors), + FM10K_STAT("rx_length_errors", rx_length_errors), +}; + static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { FM10K_STAT("timeout", stats.timeout.count), FM10K_STAT("ur", stats.ur.count), @@ -100,14 +103,33 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { FM10K_STAT("nodesc_drop", stats.nodesc_drop.count), }; +#define FM10K_MBX_STAT(_name, _stat) { \ + .stat_string = _name, \ + .sizeof_stat = FIELD_SIZEOF(struct fm10k_mbx_info, _stat), \ + .stat_offset = offsetof(struct fm10k_mbx_info, _stat) \ +} + +static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = { + FM10K_MBX_STAT("mbx_tx_busy", tx_busy), + FM10K_MBX_STAT("mbx_tx_oversized", tx_dropped), + FM10K_MBX_STAT("mbx_tx_messages", tx_messages), + FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords), + FM10K_MBX_STAT("mbx_rx_messages", rx_messages), + FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords), + FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err), +}; + #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) +#define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats) #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats) +#define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats) #define FM10K_QUEUE_STATS_LEN(_n) \ ( (_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64))) #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \ - FM10K_NETDEV_STATS_LEN) + FM10K_NETDEV_STATS_LEN + \ + FM10K_MBX_STATS_LEN) static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = { "Mailbox test (on/offline)" @@ -120,46 +142,97 @@ enum fm10k_self_test_types { FM10K_TEST_MAX = FM10K_TEST_LEN }; -static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data) +enum { + FM10K_PRV_FLAG_DEBUG_STATS, + FM10K_PRV_FLAG_LEN, +}; + +static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = { + "debug-statistics", +}; + +static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) { struct fm10k_intfc *interface = netdev_priv(dev); + struct fm10k_iov_data *iov_data = interface->iov_data; char *p = (char *)data; - int i; + unsigned int i; + unsigned int j; - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *fm10k_gstrings_test, - FM10K_TEST_LEN * ETH_GSTRING_LEN); - break; - case ETH_SS_STATS: - for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_net_stats[i].stat_string, + for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_net_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_global_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_debug_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } - for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_global_stats[i].stat_string, + } + + for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_mbx_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + if (interface->hw.mac.type != fm10k_mac_vf) { + for (i = 0; i < FM10K_PF_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_pf_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } + } - if (interface->hw.mac.type != fm10k_mac_vf) - for (i = 0; i < FM10K_PF_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_pf_stats[i].stat_string, - ETH_GSTRING_LEN); + if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { + for (i = 0; i < iov_data->num_vfs; i++) { + for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { + snprintf(p, + ETH_GSTRING_LEN, + "vf_%u_%s", i, + fm10k_gstrings_mbx_stats[j].stat_string); p += ETH_GSTRING_LEN; } - - for (i = 0; i < interface->hw.mac.max_queues; i++) { - sprintf(p, "tx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "tx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; } + } + + for (i = 0; i < interface->hw.mac.max_queues; i++) { + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + } +} + +static void fm10k_get_strings(struct net_device *dev, + u32 stringset, u8 *data) +{ + char *p = (char *)data; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *fm10k_gstrings_test, + FM10K_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + fm10k_get_stat_strings(dev, data); + break; + case ETH_SS_PRIV_FLAGS: + memcpy(p, fm10k_prv_flags, + FM10K_PRV_FLAG_LEN * ETH_GSTRING_LEN); break; } } @@ -167,6 +240,7 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data) static int fm10k_get_sset_count(struct net_device *dev, int sset) { struct fm10k_intfc *interface = netdev_priv(dev); + struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_hw *hw = &interface->hw; int stats_len = FM10K_STATIC_STATS_LEN; @@ -179,7 +253,16 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) if (hw->mac.type != fm10k_mac_vf) stats_len += FM10K_PF_STATS_LEN; + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + stats_len += FM10K_DEBUG_STATS_LEN; + + if (iov_data) + stats_len += FM10K_MBX_STATS_LEN * iov_data->num_vfs; + } + return stats_len; + case ETH_SS_PRIV_FLAGS: + return FM10K_PRV_FLAG_LEN; default: return -EOPNOTSUPP; } @@ -191,6 +274,7 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, { const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64); struct fm10k_intfc *interface = netdev_priv(netdev); + struct fm10k_iov_data *iov_data = interface->iov_data; struct net_device_stats *net_stats = &netdev->stats; char *p; int i, j; @@ -210,13 +294,47 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } - if (interface->hw.mac.type != fm10k_mac_vf) + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { + p = (char *)interface + fm10k_gstrings_debug_stats[i].stat_offset; + *(data++) = (fm10k_gstrings_debug_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + } + + for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { + p = (char *)&interface->hw.mbx + fm10k_gstrings_mbx_stats[i].stat_offset; + *(data++) = (fm10k_gstrings_mbx_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + + if (interface->hw.mac.type != fm10k_mac_vf) { for (i = 0; i < FM10K_PF_STATS_LEN; i++) { p = (char *)interface + fm10k_gstrings_pf_stats[i].stat_offset; *(data++) = (fm10k_gstrings_pf_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } + } + + if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { + for (i = 0; i < iov_data->num_vfs; i++) { + struct fm10k_vf_info *vf_info; + vf_info = &iov_data->vf_info[i]; + + /* skip stats if we don't have a vf info */ + if (!vf_info) { + data += FM10K_MBX_STATS_LEN; + continue; + } + + for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { + p = (char *)&vf_info->mbx + fm10k_gstrings_mbx_stats[j].stat_offset; + *(data++) = (fm10k_gstrings_mbx_stats[j].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + } + } for (i = 0; i < interface->hw.mac.max_queues; i++) { struct fm10k_ring *ring; @@ -397,10 +515,6 @@ static void fm10k_get_drvinfo(struct net_device *dev, sizeof(info->version) - 1); strncpy(info->bus_info, pci_name(interface->pdev), sizeof(info->bus_info) - 1); - - info->n_stats = fm10k_get_sset_count(dev, ETH_SS_STATS); - - info->regdump_len = fm10k_get_regs_len(dev); } static void fm10k_get_pauseparam(struct net_device *dev, @@ -880,6 +994,33 @@ static void fm10k_self_test(struct net_device *dev, eth_test->flags |= ETH_TEST_FL_FAILED; } +static u32 fm10k_get_priv_flags(struct net_device *netdev) +{ + struct fm10k_intfc *interface = netdev_priv(netdev); + u32 priv_flags = 0; + + if (interface->flags & FM10K_FLAG_DEBUG_STATS) + priv_flags |= 1 << FM10K_PRV_FLAG_DEBUG_STATS; + + return priv_flags; +} + +static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) +{ + struct fm10k_intfc *interface = netdev_priv(netdev); + + if (priv_flags >= (1 << FM10K_PRV_FLAG_LEN)) + return -EINVAL; + + if (priv_flags & (1 << FM10K_PRV_FLAG_DEBUG_STATS)) + interface->flags |= FM10K_FLAG_DEBUG_STATS; + else + interface->flags &= ~FM10K_FLAG_DEBUG_STATS; + + return 0; +} + + static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) { return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG; @@ -1093,6 +1234,8 @@ static const struct ethtool_ops fm10k_ethtool_ops = { .get_regs = fm10k_get_regs, .get_regs_len = fm10k_get_regs_len, .self_test = fm10k_self_test, + .get_priv_flags = fm10k_get_priv_flags, + .set_priv_flags = fm10k_set_priv_flags, .get_rxfh_indir_size = fm10k_get_reta_size, .get_rxfh_key_size = fm10k_get_rssrk_size, .get_rxfh = fm10k_get_rssh, diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 5b08e6284..acfb8b1f8 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -137,8 +137,11 @@ process_mbx: } /* guarantee we have free space in the SM mailbox */ - if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) + if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) { + /* keep track of how many times this occurs */ + interface->hw_sm_mbx_full++; break; + } /* cleanup mailbox and process received messages */ mbx->ops.process(hw, mbx); @@ -228,9 +231,6 @@ int fm10k_iov_resume(struct pci_dev *pdev) hw->iov.ops.set_lport(hw, vf_info, i, FM10K_VF_FLAG_MULTI_CAPABLE); - /* assign our default vid to the VF following reset */ - vf_info->sw_vid = hw->mac.default_vid; - /* mailbox is disconnected so we don't send a message */ hw->iov.ops.assign_default_mac_vlan(hw, vf_info); @@ -400,11 +400,31 @@ int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs) return num_vfs; } +static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface, + struct fm10k_vf_info *vf_info) +{ + struct fm10k_hw *hw = &interface->hw; + + /* assigning the MAC address will send a mailbox message */ + fm10k_mbx_lock(interface); + + /* disable LPORT for this VF which clears switch rules */ + hw->iov.ops.reset_lport(hw, vf_info); + + /* assign new MAC+VLAN for this VF */ + hw->iov.ops.assign_default_mac_vlan(hw, vf_info); + + /* re-enable the LPORT for this VF */ + hw->iov.ops.set_lport(hw, vf_info, vf_info->vf_idx, + FM10K_VF_FLAG_MULTI_CAPABLE); + + fm10k_mbx_unlock(interface); +} + int fm10k_ndo_set_vf_mac(struct net_device *netdev, int vf_idx, u8 *mac) { struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_iov_data *iov_data = interface->iov_data; - struct fm10k_hw *hw = &interface->hw; struct fm10k_vf_info *vf_info; /* verify SR-IOV is active and that vf idx is valid */ @@ -419,13 +439,7 @@ int fm10k_ndo_set_vf_mac(struct net_device *netdev, int vf_idx, u8 *mac) vf_info = &iov_data->vf_info[vf_idx]; ether_addr_copy(vf_info->mac, mac); - /* assigning the MAC will send a mailbox message so lock is needed */ - fm10k_mbx_lock(interface); - - /* assign MAC address to VF */ - hw->iov.ops.assign_default_mac_vlan(hw, vf_info); - - fm10k_mbx_unlock(interface); + fm10k_reset_vf_info(interface, vf_info); return 0; } @@ -455,16 +469,10 @@ int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int vf_idx, u16 vid, /* record default VLAN ID for VF */ vf_info->pf_vid = vid; - /* assigning the VLAN will send a mailbox message so lock is needed */ - fm10k_mbx_lock(interface); - /* Clear the VLAN table for the VF */ hw->mac.ops.update_vlan(hw, FM10K_VLAN_ALL, vf_info->vsi, false); - /* Update VF assignment and trigger reset */ - hw->iov.ops.assign_default_mac_vlan(hw, vf_info); - - fm10k_mbx_unlock(interface); + fm10k_reset_vf_info(interface, vf_info); return 0; } diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_main.c index c9da1b5d4..e76a44cf3 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -269,16 +269,19 @@ static bool fm10k_add_rx_frag(struct fm10k_rx_buffer *rx_buffer, struct sk_buff *skb) { struct page *page = rx_buffer->page; + unsigned char *va = page_address(page) + rx_buffer->page_offset; unsigned int size = le16_to_cpu(rx_desc->w.length); #if (PAGE_SIZE < 8192) unsigned int truesize = FM10K_RX_BUFSZ; #else - unsigned int truesize = ALIGN(size, L1_CACHE_BYTES); + unsigned int truesize = SKB_DATA_ALIGN(size); #endif + unsigned int pull_len; - if ((size <= FM10K_RX_HDR_LEN) && !skb_is_nonlinear(skb)) { - unsigned char *va = page_address(page) + rx_buffer->page_offset; + if (unlikely(skb_is_nonlinear(skb))) + goto add_tail_frag; + if (likely(size <= FM10K_RX_HDR_LEN)) { memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); /* page is not reserved, we can reuse buffer as-is */ @@ -290,8 +293,21 @@ static bool fm10k_add_rx_frag(struct fm10k_rx_buffer *rx_buffer, return false; } + /* we need the header to contain the greater of either ETH_HLEN or + * 60 bytes if the skb->len is less than 60 for skb_pad. + */ + pull_len = eth_get_headlen(va, FM10K_RX_HDR_LEN); + + /* align pull length to size of long to optimize memcpy performance */ + memcpy(__skb_put(skb, pull_len), va, ALIGN(pull_len, sizeof(long))); + + /* update all of the pointers */ + va += pull_len; + size -= pull_len; + +add_tail_frag: skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, - rx_buffer->page_offset, size, truesize); + (unsigned long)va & ~PAGE_MASK, size, truesize); return fm10k_can_reuse_rx_page(rx_buffer, page, truesize); } @@ -382,6 +398,8 @@ static inline void fm10k_rx_checksum(struct fm10k_ring *ring, return; skb->ip_summed = CHECKSUM_UNNECESSARY; + + ring->rx_stats.csum_good++; } #define FM10K_RSS_L4_TYPES_MASK \ @@ -481,8 +499,11 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring, if (rx_desc->w.vlan) { u16 vid = le16_to_cpu(rx_desc->w.vlan); - if (vid != rx_ring->vid) + if ((vid & VLAN_VID_MASK) != rx_ring->vid) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); + else if (vid & VLAN_PRIO_MASK) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + vid & VLAN_PRIO_MASK); } fm10k_type_trans(rx_ring, rx_desc, skb); @@ -518,44 +539,6 @@ static bool fm10k_is_non_eop(struct fm10k_ring *rx_ring, } /** - * fm10k_pull_tail - fm10k specific version of skb_pull_tail - * @skb: pointer to current skb being adjusted - * - * This function is an fm10k specific version of __pskb_pull_tail. The - * main difference between this version and the original function is that - * this function can make several assumptions about the state of things - * that allow for significant optimizations versus the standard function. - * As a result we can do things like drop a frag and maintain an accurate - * truesize for the skb. - */ -static void fm10k_pull_tail(struct sk_buff *skb) -{ - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; - unsigned char *va; - unsigned int pull_len; - - /* it is valid to use page_address instead of kmap since we are - * working with pages allocated out of the lomem pool per - * alloc_page(GFP_ATOMIC) - */ - va = skb_frag_address(frag); - - /* we need the header to contain the greater of either ETH_HLEN or - * 60 bytes if the skb->len is less than 60 for skb_pad. - */ - pull_len = eth_get_headlen(va, FM10K_RX_HDR_LEN); - - /* align pull length to size of long to optimize memcpy performance */ - skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); - - /* update all of the pointers */ - skb_frag_size_sub(frag, pull_len); - frag->page_offset += pull_len; - skb->data_len -= pull_len; - skb->tail += pull_len; -} - -/** * fm10k_cleanup_headers - Correct corrupted or empty headers * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor @@ -575,15 +558,23 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring, { if (unlikely((fm10k_test_staterr(rx_desc, FM10K_RXD_STATUS_RXE)))) { +#define FM10K_TEST_RXD_BIT(rxd, bit) \ + ((rxd)->w.csum_err & cpu_to_le16(bit)) + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_ERROR)) + rx_ring->rx_stats.switch_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_NO_DESCRIPTOR)) + rx_ring->rx_stats.drops++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_PP_ERROR)) + rx_ring->rx_stats.pp_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_READY)) + rx_ring->rx_stats.link_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_TOO_BIG)) + rx_ring->rx_stats.length_errors++; dev_kfree_skb_any(skb); rx_ring->rx_stats.errors++; return true; } - /* place header in linear portion of buffer */ - if (skb_is_nonlinear(skb)) - fm10k_pull_tail(skb); - /* if eth_skb_pad returns an error the skb was freed */ if (eth_skb_pad(skb)) return true; @@ -602,9 +593,9 @@ static void fm10k_receive_skb(struct fm10k_q_vector *q_vector, napi_gro_receive(&q_vector->napi, skb); } -static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, - struct fm10k_ring *rx_ring, - int budget) +static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, + struct fm10k_ring *rx_ring, + int budget) { struct sk_buff *skb = rx_ring->skb; unsigned int total_bytes = 0, total_packets = 0; @@ -671,7 +662,7 @@ static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, q_vector->rx.total_packets += total_packets; q_vector->rx.total_bytes += total_bytes; - return total_packets < budget; + return total_packets; } #define VXLAN_HLEN (sizeof(struct udphdr) + 8) @@ -904,6 +895,7 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, /* update TX checksum flag */ first->tx_flags |= FM10K_TX_FLAGS_CSUM; + tx_ring->tx_stats.csum_good++; no_csum: /* populate Tx descriptor header size and mss */ @@ -1105,9 +1097,7 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, struct fm10k_tx_buffer *first; int tso; u32 tx_flags = 0; -#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD unsigned short f; -#endif u16 count = TXD_USE_COUNT(skb_headlen(skb)); /* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD, @@ -1115,12 +1105,9 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, * + 2 desc gap to keep tail from touching head * otherwise try next time */ -#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); -#else - count += skb_shinfo(skb)->nr_frags; -#endif + if (fm10k_maybe_stop_tx(tx_ring, count + 3)) { tx_ring->tx_stats.tx_busy++; return NETDEV_TX_BUSY; @@ -1435,7 +1422,7 @@ static int fm10k_poll(struct napi_struct *napi, int budget) struct fm10k_q_vector *q_vector = container_of(napi, struct fm10k_q_vector, napi); struct fm10k_ring *ring; - int per_ring_budget; + int per_ring_budget, work_done = 0; bool clean_complete = true; fm10k_for_each_ring(ring, q_vector->tx) @@ -1449,16 +1436,19 @@ static int fm10k_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; - fm10k_for_each_ring(ring, q_vector->rx) - clean_complete &= fm10k_clean_rx_irq(q_vector, ring, - per_ring_budget); + fm10k_for_each_ring(ring, q_vector->rx) { + int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget); + + work_done += work; + clean_complete &= !!(work < per_ring_budget); + } /* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget; /* all work done, exit the polling mode */ - napi_complete(napi); + napi_complete_done(napi, work_done); /* re-enable the q_vector */ fm10k_qv_enable(q_vector); @@ -1918,7 +1908,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) u32 reta, base; /* If the netdev is initialized we have to maintain table if possible */ - if (interface->netdev->reg_state) { + if (interface->netdev->reg_state != NETREG_UNINITIALIZED) { for (i = FM10K_RETA_SIZE; i--;) { reta = interface->reta[i]; if ((((reta << 24) >> 24) < rss_i) && diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 1b2738380..af09a1b27 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -129,8 +129,8 @@ static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo) * fm10k_fifo_drop_all - Drop all messages in FIFO * @fifo: pointer to FIFO * - * This function resets the head pointer to drop all messages in the FIFO, - * and ensure the FIFO is empty. + * This function resets the head pointer to drop all messages in the FIFO and + * ensure the FIFO is empty. **/ static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo) { @@ -899,6 +899,27 @@ static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx) } /** + * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mailbox header + * @mbx: pointer to mailbox + * + * This function creates a fake disconnect header for loading into remote + * mailbox header. The primary purpose is to prevent errors on immediate + * start up after mbx->connect. + **/ +static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx) +{ + u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) | + FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) | + FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD); + u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1); + + mbx->mbx_lock |= FM10K_MBX_ACK; + + /* load header to memory to be written */ + mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC); +} + +/** * fm10k_mbx_create_error_msg - Generate a error message * @mbx: pointer to mailbox * @err: local error encountered @@ -1046,9 +1067,26 @@ static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw, **/ static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx) { + u16 len, head, ack; + /* reset our outgoing max size back to Rx limits */ mbx->max_size = mbx->rx.size - 1; + /* update mbx->pulled to account for tail_len and ack */ + head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD); + ack = fm10k_mbx_index_len(mbx, head, mbx->tail); + mbx->pulled += mbx->tail_len - ack; + + /* now drop any messages which have started or finished transmitting */ + while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) { + len = fm10k_fifo_head_drop(&mbx->tx); + mbx->tx_dropped++; + if (mbx->pulled >= len) + mbx->pulled -= len; + else + mbx->pulled = 0; + } + /* just do a quick resysnc to start of message */ mbx->pushed = 0; mbx->pulled = 0; @@ -1259,16 +1297,11 @@ static s32 fm10k_mbx_process_error(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const u32 *hdr = &mbx->mbx_hdr; - s32 err_no; u16 head; /* we will need to pull all of the fields for verification */ head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); - /* we only have lower 10 bits of error number so add upper bits */ - err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO); - err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO); - switch (mbx->state) { case FM10K_STATE_OPEN: case FM10K_STATE_DISCONNECT: @@ -1423,8 +1456,10 @@ static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) /* Place mbx in ready to connect state */ mbx->state = FM10K_STATE_CONNECT; + fm10k_mbx_reset_work(mbx); + /* initialize header of remote mailbox */ - fm10k_mbx_create_disconnect_hdr(mbx); + fm10k_mbx_create_fake_disconnect_hdr(mbx); fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr); /* enable interrupt and notify other party of new message */ @@ -1730,7 +1765,7 @@ static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw, mbx->state = FM10K_STATE_CLOSED; mbx->remote = 0; fm10k_mbx_reset_work(mbx); - fm10k_mbx_update_max_size(mbx, 0); + fm10k_fifo_drop_all(&mbx->tx); fm10k_write_reg(hw, mbx->mbmem_reg, 0); } diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 2f4f41b7e..7781e8089 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -627,8 +627,10 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* verify the skb head is not shared */ err = skb_cow_head(skb, 0); - if (err) + if (err) { + dev_kfree_skb(skb); return NETDEV_TX_OK; + } /* locate vlan header */ vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); @@ -758,6 +760,7 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_hw *hw = &interface->hw; s32 err; + int i; /* updates do not apply to VLAN 0 */ if (!vid) @@ -775,8 +778,25 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) if (!set) clear_bit(vid, interface->active_vlans); - /* if default VLAN is already present do nothing */ - if (vid == hw->mac.default_vid) + /* disable the default VID on ring if we have an active VLAN */ + for (i = 0; i < interface->num_rx_queues; i++) { + struct fm10k_ring *rx_ring = interface->rx_ring[i]; + u16 rx_vid = rx_ring->vid & (VLAN_N_VID - 1); + + if (test_bit(rx_vid, interface->active_vlans)) + rx_ring->vid |= FM10K_VLAN_CLEAR; + else + rx_ring->vid &= ~FM10K_VLAN_CLEAR; + } + + /* Do not remove default VID related entries from VLAN and MAC tables */ + if (!set && vid == hw->mac.default_vid) + return 0; + + /* Do not throw an error if the interface is down. We will sync once + * we come up + */ + if (test_bit(__FM10K_DOWN, &interface->state)) return 0; fm10k_mbx_lock(interface); @@ -923,18 +943,12 @@ static int __fm10k_mc_sync(struct net_device *dev, struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_hw *hw = &interface->hw; u16 vid, glort = interface->glort; - s32 err; - - if (!is_multicast_ether_addr(addr)) - return -EADDRNOTAVAIL; /* update table with current entries */ for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { - err = hw->mac.ops.update_mc_addr(hw, glort, addr, vid, sync); - if (err) - return err; + hw->mac.ops.update_mc_addr(hw, glort, addr, vid, sync); } return 0; @@ -1002,21 +1016,6 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) int xcast_mode; u16 vid, glort; - /* restore our address if perm_addr is set */ - if (hw->mac.type == fm10k_mac_vf) { - if (is_valid_ether_addr(hw->mac.perm_addr)) { - ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); - ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr); - ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr); - netdev->addr_assign_type &= ~NET_ADDR_RANDOM; - } - - if (hw->mac.vlan_override) - netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; - else - netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; - } - /* record glort for this interface */ glort = interface->glort; @@ -1051,7 +1050,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) vid, true, 0); } - /* update xcast mode before syncronizing addresses */ + /* update xcast mode before synchronizing addresses */ hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); /* synchronize all of the addresses */ @@ -1339,8 +1338,7 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv) dglort.rss_l = fls(interface->ring_feature[RING_F_RSS].mask); dglort.pc_l = fls(interface->ring_feature[RING_F_QOS].mask); dglort.glort = interface->glort; - if (l2_accel) - dglort.shared_l = fls(l2_accel->size); + dglort.shared_l = fls(l2_accel->size); hw->mac.ops.configure_dglort_map(hw, &dglort); /* If table is empty remove it */ diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index df9fda38b..74be792f3 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -170,6 +170,21 @@ static void fm10k_reinit(struct fm10k_intfc *interface) /* reassociate interrupts */ fm10k_mbx_request_irq(interface); + /* update hardware address for VFs if perm_addr has changed */ + if (hw->mac.type == fm10k_mac_vf) { + if (is_valid_ether_addr(hw->mac.perm_addr)) { + ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); + ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr); + ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr); + netdev->addr_assign_type &= ~NET_ADDR_RANDOM; + } + + if (hw->mac.vlan_override) + netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; + else + netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; + } + /* reset clock */ fm10k_ts_reset(interface); @@ -259,8 +274,6 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface) * @interface: board private structure * * This function will process both the upstream and downstream mailboxes. - * It is necessary for us to hold the rtnl_lock while doing this as the - * mailbox accesses are protected by this lock. **/ static void fm10k_mbx_subtask(struct fm10k_intfc *interface) { @@ -315,6 +328,9 @@ void fm10k_update_stats(struct fm10k_intfc *interface) { struct net_device_stats *net_stats = &interface->netdev->stats; struct fm10k_hw *hw = &interface->hw; + u64 hw_csum_tx_good = 0, hw_csum_rx_good = 0, rx_length_errors = 0; + u64 rx_switch_errors = 0, rx_drops = 0, rx_pp_errors = 0; + u64 rx_link_errors = 0; u64 rx_errors = 0, rx_csum_errors = 0, tx_csum_errors = 0; u64 restart_queue = 0, tx_busy = 0, alloc_failed = 0; u64 rx_bytes_nic = 0, rx_pkts_nic = 0, rx_drops_nic = 0; @@ -334,6 +350,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface) tx_csum_errors += tx_ring->tx_stats.csum_err; bytes += tx_ring->stats.bytes; pkts += tx_ring->stats.packets; + hw_csum_tx_good += tx_ring->tx_stats.csum_good; } interface->restart_queue = restart_queue; @@ -341,6 +358,8 @@ void fm10k_update_stats(struct fm10k_intfc *interface) net_stats->tx_bytes = bytes; net_stats->tx_packets = pkts; interface->tx_csum_errors = tx_csum_errors; + interface->hw_csum_tx_good = hw_csum_tx_good; + /* gather some stats to the interface struct that are per queue */ for (bytes = 0, pkts = 0, i = 0; i < interface->num_rx_queues; i++) { struct fm10k_ring *rx_ring = interface->rx_ring[i]; @@ -350,12 +369,24 @@ void fm10k_update_stats(struct fm10k_intfc *interface) alloc_failed += rx_ring->rx_stats.alloc_failed; rx_csum_errors += rx_ring->rx_stats.csum_err; rx_errors += rx_ring->rx_stats.errors; + hw_csum_rx_good += rx_ring->rx_stats.csum_good; + rx_switch_errors += rx_ring->rx_stats.switch_errors; + rx_drops += rx_ring->rx_stats.drops; + rx_pp_errors += rx_ring->rx_stats.pp_errors; + rx_link_errors += rx_ring->rx_stats.link_errors; + rx_length_errors += rx_ring->rx_stats.length_errors; } net_stats->rx_bytes = bytes; net_stats->rx_packets = pkts; interface->alloc_failed = alloc_failed; interface->rx_csum_errors = rx_csum_errors; + interface->hw_csum_rx_good = hw_csum_rx_good; + interface->rx_switch_errors = rx_switch_errors; + interface->rx_drops = rx_drops; + interface->rx_pp_errors = rx_pp_errors; + interface->rx_link_errors = rx_link_errors; + interface->rx_length_errors = rx_length_errors; hw->mac.ops.update_hw_stats(hw, &interface->stats); @@ -483,7 +514,7 @@ static void fm10k_service_task(struct work_struct *work) interface = container_of(work, struct fm10k_intfc, service_task); - /* tasks always capable of running, but must be rtnl protected */ + /* tasks run even when interface is down */ fm10k_mbx_subtask(interface); fm10k_detach_subtask(interface); fm10k_reset_subtask(interface); @@ -663,6 +694,10 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, /* assign default VLAN to queue */ ring->vid = hw->mac.default_vid; + /* if we have an active VLAN, disable default VID */ + if (test_bit(hw->mac.default_vid, interface->active_vlans)) + ring->vid |= FM10K_VLAN_CLEAR; + /* Map interrupt */ if (ring->q_vector) { rxint = ring->q_vector->v_idx + NON_Q_VECTORS(hw); @@ -861,10 +896,12 @@ void fm10k_netpoll(struct net_device *netdev) #endif #define FM10K_ERR_MSG(type) case (type): error = #type; break -static void fm10k_print_fault(struct fm10k_intfc *interface, int type, +static void fm10k_handle_fault(struct fm10k_intfc *interface, int type, struct fm10k_fault *fault) { struct pci_dev *pdev = interface->pdev; + struct fm10k_hw *hw = &interface->hw; + struct fm10k_iov_data *iov_data = interface->iov_data; char *error; switch (type) { @@ -918,6 +955,30 @@ static void fm10k_print_fault(struct fm10k_intfc *interface, int type, "%s Address: 0x%llx SpecInfo: 0x%x Func: %02x.%0x\n", error, fault->address, fault->specinfo, PCI_SLOT(fault->func), PCI_FUNC(fault->func)); + + /* For VF faults, clear out the respective LPORT, reset the queue + * resources, and then reconnect to the mailbox. This allows the + * VF in question to resume behavior. For transient faults that are + * the result of non-malicious behavior this will log the fault and + * allow the VF to resume functionality. Obviously for malicious VFs + * they will be able to attempt malicious behavior again. In this + * case, the system administrator will need to step in and manually + * remove or disable the VF in question. + */ + if (fault->func && iov_data) { + int vf = fault->func - 1; + struct fm10k_vf_info *vf_info = &iov_data->vf_info[vf]; + + hw->iov.ops.reset_lport(hw, vf_info); + hw->iov.ops.reset_resources(hw, vf_info); + + /* reset_lport disables the VF, so re-enable it */ + hw->iov.ops.set_lport(hw, vf_info, vf, + FM10K_VF_FLAG_MULTI_CAPABLE); + + /* reset_resources will disconnect from the mbx */ + vf_info->mbx.ops.connect(hw, &vf_info->mbx); + } } static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr) @@ -941,7 +1002,7 @@ static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr) continue; } - fm10k_print_fault(interface, type, &fault); + fm10k_handle_fault(interface, type, &fault); } } @@ -1559,6 +1620,7 @@ void fm10k_down(struct fm10k_intfc *interface) /* free any buffers still on the rings */ fm10k_clean_all_tx_rings(interface); + fm10k_clean_all_rx_rings(interface); } /** @@ -1704,22 +1766,86 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, static void fm10k_slot_warn(struct fm10k_intfc *interface) { - struct device *dev = &interface->pdev->dev; + enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN; + enum pci_bus_speed speed = PCI_SPEED_UNKNOWN; struct fm10k_hw *hw = &interface->hw; + int max_gts = 0, expected_gts = 0; + + if (pcie_get_minimum_link(interface->pdev, &speed, &width) || + speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) { + dev_warn(&interface->pdev->dev, + "Unable to determine PCI Express bandwidth.\n"); + return; + } - if (hw->mac.ops.is_slot_appropriate(hw)) + switch (speed) { + case PCIE_SPEED_2_5GT: + /* 8b/10b encoding reduces max throughput by 20% */ + max_gts = 2 * width; + break; + case PCIE_SPEED_5_0GT: + /* 8b/10b encoding reduces max throughput by 20% */ + max_gts = 4 * width; + break; + case PCIE_SPEED_8_0GT: + /* 128b/130b encoding has less than 2% impact on throughput */ + max_gts = 8 * width; + break; + default: + dev_warn(&interface->pdev->dev, + "Unable to determine PCI Express bandwidth.\n"); + return; + } + + dev_info(&interface->pdev->dev, + "PCI Express bandwidth of %dGT/s available\n", + max_gts); + dev_info(&interface->pdev->dev, + "(Speed:%s, Width: x%d, Encoding Loss:%s, Payload:%s)\n", + (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : + speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : + speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : + "Unknown"), + hw->bus.width, + (speed == PCIE_SPEED_2_5GT ? "20%" : + speed == PCIE_SPEED_5_0GT ? "20%" : + speed == PCIE_SPEED_8_0GT ? "<2%" : + "Unknown"), + (hw->bus.payload == fm10k_bus_payload_128 ? "128B" : + hw->bus.payload == fm10k_bus_payload_256 ? "256B" : + hw->bus.payload == fm10k_bus_payload_512 ? "512B" : + "Unknown")); + + switch (hw->bus_caps.speed) { + case fm10k_bus_speed_2500: + /* 8b/10b encoding reduces max throughput by 20% */ + expected_gts = 2 * hw->bus_caps.width; + break; + case fm10k_bus_speed_5000: + /* 8b/10b encoding reduces max throughput by 20% */ + expected_gts = 4 * hw->bus_caps.width; + break; + case fm10k_bus_speed_8000: + /* 128b/130b encoding has less than 2% impact on throughput */ + expected_gts = 8 * hw->bus_caps.width; + break; + default: + dev_warn(&interface->pdev->dev, + "Unable to determine expected PCI Express bandwidth.\n"); return; + } - dev_warn(dev, - "For optimal performance, a %s %s slot is recommended.\n", - (hw->bus_caps.width == fm10k_bus_width_pcie_x1 ? "x1" : - hw->bus_caps.width == fm10k_bus_width_pcie_x4 ? "x4" : - "x8"), - (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s" : - hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s" : - "8.0GT/s")); - dev_warn(dev, - "A slot with more lanes and/or higher speed is suggested.\n"); + if (max_gts < expected_gts) { + dev_warn(&interface->pdev->dev, + "This device requires %dGT/s of bandwidth for optimal performance.\n", + expected_gts); + dev_warn(&interface->pdev->dev, + "A %sslot with x%d lanes is suggested.\n", + (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s " : + hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s " : + hw->bus_caps.speed == fm10k_bus_speed_8000 ? "8.0GT/s " : ""), + hw->bus_caps.width); + } } /** @@ -1738,32 +1864,19 @@ static int fm10k_probe(struct pci_dev *pdev, { struct net_device *netdev; struct fm10k_intfc *interface; - struct fm10k_hw *hw; int err; - u64 dma_mask; err = pci_enable_device_mem(pdev); if (err) return err; - /* By default fm10k only supports a 48 bit DMA mask */ - dma_mask = DMA_BIT_MASK(48) | dma_get_required_mask(&pdev->dev); - - if ((dma_mask <= DMA_BIT_MASK(32)) || - dma_set_mask_and_coherent(&pdev->dev, dma_mask)) { - dma_mask &= DMA_BIT_MASK(32); - + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)); + if (err) err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (err) { - err = dma_set_coherent_mask(&pdev->dev, - DMA_BIT_MASK(32)); - if (err) { - dev_err(&pdev->dev, - "No usable DMA configuration, aborting\n"); - goto err_dma; - } - } + if (err) { + dev_err(&pdev->dev, + "DMA configuration failed: %d\n", err); + goto err_dma; } err = pci_request_selected_regions(pdev, @@ -1772,7 +1885,7 @@ static int fm10k_probe(struct pci_dev *pdev, fm10k_driver_name); if (err) { dev_err(&pdev->dev, - "pci_request_selected_regions failed 0x%x\n", err); + "pci_request_selected_regions failed: %d\n", err); goto err_pci_reg; } @@ -1794,7 +1907,6 @@ static int fm10k_probe(struct pci_dev *pdev, interface->netdev = netdev; interface->pdev = pdev; - hw = &interface->hw; interface->uc_addr = ioremap(pci_resource_start(pdev, 0), FM10K_UC_ADDR_SIZE); @@ -1836,24 +1948,12 @@ static int fm10k_probe(struct pci_dev *pdev, /* Register PTP interface */ fm10k_ptp_register(interface); - /* print bus type/speed/width info */ - dev_info(&pdev->dev, "(PCI Express:%s Width: %s Payload: %s)\n", - (hw->bus.speed == fm10k_bus_speed_8000 ? "8.0GT/s" : - hw->bus.speed == fm10k_bus_speed_5000 ? "5.0GT/s" : - hw->bus.speed == fm10k_bus_speed_2500 ? "2.5GT/s" : - "Unknown"), - (hw->bus.width == fm10k_bus_width_pcie_x8 ? "x8" : - hw->bus.width == fm10k_bus_width_pcie_x4 ? "x4" : - hw->bus.width == fm10k_bus_width_pcie_x1 ? "x1" : - "Unknown"), - (hw->bus.payload == fm10k_bus_payload_128 ? "128B" : - hw->bus.payload == fm10k_bus_payload_256 ? "256B" : - hw->bus.payload == fm10k_bus_payload_512 ? "512B" : - "Unknown")); - /* print warning for non-optimal configurations */ fm10k_slot_warn(interface); + /* report MAC address for logging */ + dev_info(&pdev->dev, "%pM\n", netdev->dev_addr); + /* enable SR-IOV after registering netdev to enforce PF/VF ordering */ fm10k_iov_configure(pdev, 0); @@ -1994,6 +2094,16 @@ static int fm10k_resume(struct pci_dev *pdev) if (err) return err; + /* assume host is not ready, to prevent race with watchdog in case we + * actually don't have connection to the switch + */ + interface->host_ready = false; + fm10k_watchdog_host_not_ready(interface); + + /* clear the service task disable bit to allow service task to start */ + clear_bit(__FM10K_SERVICE_DISABLE, &interface->state); + fm10k_service_event_schedule(interface); + /* restore SR-IOV interface */ fm10k_iov_resume(pdev); @@ -2021,6 +2131,15 @@ static int fm10k_suspend(struct pci_dev *pdev, fm10k_iov_suspend(pdev); + /* the watchdog tasks may read registers, which will appear like a + * surprise-remove event once the PCI device is disabled. This will + * cause us to close the netdevice, so we don't retain the open/closed + * state post-resume. Prevent this by disabling the service task while + * suspended, until we actually resume. + */ + set_bit(__FM10K_SERVICE_DISABLE, &interface->state); + cancel_work_sync(&interface->service_task); + rtnl_lock(); if (netif_running(netdev)) diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 891e21874..8c0bdc4e4 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -59,6 +59,11 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE)) return FM10K_ERR_DMA_PENDING; + /* verify the switch is ready for reset */ + reg = fm10k_read_reg(hw, FM10K_DMA_CTRL2); + if (!(reg & FM10K_DMA_CTRL2_SWITCH_READY)) + goto out; + /* Inititate data path reset */ reg |= FM10K_DMA_CTRL_DATAPATH_RESET; fm10k_write_reg(hw, FM10K_DMA_CTRL, reg); @@ -72,6 +77,7 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) if (!(reg & FM10K_IP_NOTINRESET)) err = FM10K_ERR_RESET_FAILED; +out: return err; } @@ -185,19 +191,6 @@ static s32 fm10k_init_hw_pf(struct fm10k_hw *hw) } /** - * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU - * @hw: pointer to hardware structure - * - * Looks at the PCIe bus info to confirm whether or not this slot can support - * the necessary bandwidth for this device. - **/ -static bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw) -{ - return (hw->bus.speed == hw->bus_caps.speed) && - (hw->bus.width == hw->bus_caps.width); -} - -/** * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table * @hw: pointer to hardware structure * @vid: VLAN ID to add to table @@ -1046,6 +1039,12 @@ static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i); } + /* repeat the first ring for all the remaining VF rings */ + for (i = queues_per_pool; i < qmap_stride; i++) { + fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx); + fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx); + } + return 0; } @@ -1156,6 +1155,24 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, } /** + * fm10k_iov_select_vid - Select correct default VID + * @hw: Pointer to hardware structure + * @vid: VID to correct + * + * Will report an error if VID is out of range. For VID = 0, it will return + * either the pf_vid or sw_vid depending on which one is set. + */ +static inline s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid) +{ + if (!vid) + return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid; + else if (vf_info->pf_vid && vid != vf_info->pf_vid) + return FM10K_ERR_PARAM; + else + return vid; +} + +/** * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF * @hw: Pointer to hardware structure * @results: Pointer array to message, results[0] is pointer to message @@ -1169,9 +1186,10 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; - int err = 0; u8 mac[ETH_ALEN]; u32 *result; + int err = 0; + bool set; u16 vlan; u32 vid; @@ -1187,19 +1205,21 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (err) return err; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vid || (vid == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vid |= vf_info->pf_vid; - else - vid |= vf_info->sw_vid; - } else if (vid != vf_info->pf_vid) { + /* verify upper 16 bits are zero */ + if (vid >> 16) return FM10K_ERR_PARAM; - } + + set = !(vid & FM10K_VLAN_CLEAR); + vid &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vid); + if (err < 0) + return err; + else + vid = err; /* update VSI info for VF in regards to VLAN table */ - err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, - !(vid & FM10K_VLAN_CLEAR)); + err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) { @@ -1215,19 +1235,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, memcmp(mac, vf_info->mac, ETH_ALEN)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + else + vlan = err; /* notify switch of request for new unicast address */ - err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, mac, vlan, - !(vlan & FM10K_VLAN_CLEAR), 0); + err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, + mac, vlan, set, 0); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) { @@ -1242,19 +1261,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + else + vlan = err; /* notify switch of request for new multicast address */ - err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, vlan, - !(vlan & FM10K_VLAN_CLEAR)); + err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, + mac, vlan, set); } return err; @@ -1345,6 +1363,14 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false); + /* we need to clear VF_FLAG_ENABLED flags in order to ensure + * that we actually re-enable the LPORT state below. Note that + * this has no impact if the VF is already disabled, as the + * flags are already cleared. + */ + if (!err) + vf_info->vf_flags = FM10K_VF_FLAG_CAPABLE(vf_info); + /* when enabling the port we should reset the rate limiters */ hw->iov.ops.configure_tc(hw, vf_info->vf_idx, vf_info->rate); @@ -1786,8 +1812,8 @@ static s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb) if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK) return FM10K_ERR_PARAM; - if (ppb < 0) - systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE; + if (ppb > 0) + systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE; fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust); @@ -1835,7 +1861,6 @@ static struct fm10k_mac_ops mac_ops_pf = { .init_hw = &fm10k_init_hw_pf, .start_hw = &fm10k_start_hw_generic, .stop_hw = &fm10k_stop_hw_generic, - .is_slot_appropriate = &fm10k_is_slot_appropriate_pf, .update_vlan = &fm10k_update_vlan_pf, .read_mac_addr = &fm10k_read_mac_addr_pf, .update_uc_addr = &fm10k_update_uc_addr_pf, diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.h b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.h index 7ab1db4ff..40a0dbc62 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.h +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_pf.h @@ -81,26 +81,26 @@ struct fm10k_mac_update { __le16 glort; u8 flags; u8 action; -}; +} __packed; struct fm10k_global_table_data { __le32 used; __le32 avail; -}; +} __packed; struct fm10k_swapi_error { __le32 status; struct fm10k_global_table_data mac; struct fm10k_global_table_data nexthop; struct fm10k_global_table_data ffu; -}; +} __packed; struct fm10k_swapi_1588_timestamp { __le64 egress; __le64 ingress; __le16 dglort; __le16 sglort; -}; +} __packed; s32 fm10k_msg_lport_map_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[]; diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c index 9043633c3..b4945e8ab 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c @@ -70,16 +70,16 @@ void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb) * if none are present then insert skb in tail of list */ skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort); - if (!skb) + if (!skb) { + skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; __skb_queue_tail(list, clone); + } spin_unlock_irqrestore(&list->lock, flags); /* if list is already has one then we just free the clone */ if (skb) - kfree_skb(skb); - else - skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; + dev_kfree_skb(clone); } void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort, @@ -103,9 +103,10 @@ void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort, if (!skb) return; - /* timestamp the sk_buff and return it to the socket */ + /* timestamp the sk_buff and free out copy */ fm10k_systime_to_hwtstamp(interface, &shhwtstamps, systime); - skb_complete_tx_timestamp(skb, &shhwtstamps); + skb_tstamp_tx(skb, &shhwtstamps); + dev_kfree_skb_any(skb); } void fm10k_ts_tx_subtask(struct fm10k_intfc *interface) diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 4af96686c..318a212f0 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -369,7 +369,7 @@ struct fm10k_hw; /* Registers contained in BAR 4 for Switch management */ #define FM10K_SW_SYSTIME_ADJUST 0x0224D #define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF -#define FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE 0x80000000 +#define FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE 0x80000000 #define FM10K_SW_SYSTIME_PULSE(_n) ((_n) + 0x02252) enum fm10k_int_source { @@ -521,7 +521,6 @@ struct fm10k_mac_ops { s32 (*stop_hw)(struct fm10k_hw *); s32 (*get_bus_info)(struct fm10k_hw *); s32 (*get_host_state)(struct fm10k_hw *, bool *); - bool (*is_slot_appropriate)(struct fm10k_hw *); s32 (*update_vlan)(struct fm10k_hw *, u32, u8, bool); s32 (*read_mac_addr)(struct fm10k_hw *); s32 (*update_uc_addr)(struct fm10k_hw *, u16, const u8 *, @@ -763,6 +762,12 @@ enum fm10k_rxdesc_xc { #define FM10K_RXD_STATUS_L4E 0x4000 /* L4 csum error */ #define FM10K_RXD_STATUS_IPE 0x8000 /* IPv4 csum error */ +#define FM10K_RXD_ERR_SWITCH_ERROR 0x0001 /* Switch found bad packet */ +#define FM10K_RXD_ERR_NO_DESCRIPTOR 0x0002 /* No descriptor available */ +#define FM10K_RXD_ERR_PP_ERROR 0x0004 /* RAM error during processing */ +#define FM10K_RXD_ERR_SWITCH_READY 0x0008 /* Link transition mid-packet */ +#define FM10K_RXD_ERR_TOO_BIG 0x0010 /* Pkt too big for single buf */ + struct fm10k_ftag { __be16 swpri_type_user; __be16 vlan; diff --git a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 94f0f6a14..36c8b0aa0 100644 --- a/kernel/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/kernel/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -131,19 +131,6 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) return 0; } -/** - * fm10k_is_slot_appropriate_vf - Indicate appropriate slot for this SKU - * @hw: pointer to hardware structure - * - * Looks at the PCIe bus info to confirm whether or not this slot can support - * the necessary bandwidth for this device. Since the VF has no control over - * the "slot" it is in, always indicate that the slot is appropriate. - **/ -static bool fm10k_is_slot_appropriate_vf(struct fm10k_hw *hw) -{ - return true; -} - /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = { FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN), @@ -552,7 +539,6 @@ static struct fm10k_mac_ops mac_ops_vf = { .init_hw = &fm10k_init_hw_vf, .start_hw = &fm10k_start_hw_generic, .stop_hw = &fm10k_stop_hw_vf, - .is_slot_appropriate = &fm10k_is_slot_appropriate_vf, .update_vlan = &fm10k_update_vlan_vf, .read_mac_addr = &fm10k_read_mac_addr_vf, .update_uc_addr = &fm10k_update_uc_addr_vf, |