Commit 8e4a2adc authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2019-08-26

This series contains updates to ice driver only.

Usha fixes the statistics reported on 4 port NICs which were reporting
the incorrect statistics due to using the incorrect port identifier.

Victor fixes an issue when trying to traverse to the first node of a
requested layer by adding a sibling head pointer for each layer per
traffic class.

Anirudh cleans up the locking and logic for enabling and disabling
VSI's to make it more consistent.  Updates the driver to do dynamic
allocation of queue management bitmaps and arrays, rather than
statically allocating them which consumes more memory than required.
Refactor the logic in ice_ena_msix_range() for clarity and add
additional checks for when requested resources exceed what is available.

Jesse updates the debugging print statements to make it more useful when
dealing with link and PHY related issues.

Krzysztof adds a local variable to the VSI rebuild path to improve
readability.

Akeem limits the reporting of MDD events from VFs so that the kernel
log is not clogged up with MDD events which are duplicate or potentially
false positives.  Fixed a reset issue that would result in the system
getting into a state that could only be resolved by a reboot by
testing if the VF is in a disabled state during a reset.

Michal adds a check to avoid trying to access memory that has not be
allocated by checking the number of queue pairs.

Jake fixes a static analysis warning due to a cast of a u8 to unsigned
long, so just update ice_is_tc_ena() to take a unsigned long so that a
cast is not necessary.

Colin Ian King fixes a potential infinite loop where a u8 is being
compared to an int.

Maciej refactors the queue handling functions that work on queue arrays
so that the logic can be done for a single queue.

Paul adds support for VFs to enable and disable single queues.

Henry fixed the order of operations in ice_remove() which was trying to
use adminq operations that were already disabled.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3894793e ae2bdbb4
......@@ -73,8 +73,6 @@ extern const char ice_drv_ver[];
#define ICE_MBXRQ_LEN 512
#define ICE_MIN_MSIX 2
#define ICE_NO_VSI 0xffff
#define ICE_MAX_TXQS 2048
#define ICE_MAX_RXQS 2048
#define ICE_VSI_MAP_CONTIG 0
#define ICE_VSI_MAP_SCATTER 1
#define ICE_MAX_SCATTER_TXQS 16
......@@ -284,8 +282,8 @@ struct ice_vsi {
/* queue information */
u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
u8 rx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
u16 txq_map[ICE_MAX_TXQS]; /* index in pf->avail_txqs */
u16 rxq_map[ICE_MAX_RXQS]; /* index in pf->avail_rxqs */
u16 *txq_map; /* index in pf->avail_txqs */
u16 *rxq_map; /* index in pf->avail_rxqs */
u16 alloc_txq; /* Allocated Tx queues */
u16 num_txq; /* Used Tx queues */
u16 alloc_rxq; /* Allocated Rx queues */
......@@ -355,9 +353,9 @@ struct ice_pf {
u16 num_vf_qps; /* num queue pairs per VF */
u16 num_vf_msix; /* num vectors per VF */
DECLARE_BITMAP(state, __ICE_STATE_NBITS);
DECLARE_BITMAP(avail_txqs, ICE_MAX_TXQS);
DECLARE_BITMAP(avail_rxqs, ICE_MAX_RXQS);
DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS);
unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */
unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */
unsigned long serv_tmr_period;
unsigned long serv_tmr_prev;
struct timer_list serv_tmr;
......@@ -368,6 +366,8 @@ struct ice_pf {
u32 hw_csum_rx_error;
u32 oicr_idx; /* Other interrupt cause MSIX vector index */
u32 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
u16 max_pf_txqs; /* Total Tx queues PF wide */
u16 max_pf_rxqs; /* Total Rx queues PF wide */
u32 num_lan_msix; /* Total MSIX vectors for base driver */
u16 num_lan_tx; /* num LAN Tx queues setup */
u16 num_lan_rx; /* num LAN Rx queues setup */
......
......@@ -263,21 +263,23 @@ enum ice_status
ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
struct ice_link_status *link, struct ice_sq_cd *cd)
{
struct ice_link_status *hw_link_info_old, *hw_link_info;
struct ice_aqc_get_link_status_data link_data = { 0 };
struct ice_aqc_get_link_status *resp;
struct ice_link_status *li_old, *li;
enum ice_media_type *hw_media_type;
struct ice_fc_info *hw_fc_info;
bool tx_pause, rx_pause;
struct ice_aq_desc desc;
enum ice_status status;
struct ice_hw *hw;
u16 cmd_flags;
if (!pi)
return ICE_ERR_PARAM;
hw_link_info_old = &pi->phy.link_info_old;
hw = pi->hw;
li_old = &pi->phy.link_info_old;
hw_media_type = &pi->phy.media_type;
hw_link_info = &pi->phy.link_info;
li = &pi->phy.link_info;
hw_fc_info = &pi->fc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
......@@ -286,27 +288,27 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
resp->cmd_flags = cpu_to_le16(cmd_flags);
resp->lport_num = pi->lport;
status = ice_aq_send_cmd(pi->hw, &desc, &link_data, sizeof(link_data),
cd);
status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
if (status)
return status;
/* save off old link status information */
*hw_link_info_old = *hw_link_info;
*li_old = *li;
/* update current link status information */
hw_link_info->link_speed = le16_to_cpu(link_data.link_speed);
hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low);
hw_link_info->phy_type_high = le64_to_cpu(link_data.phy_type_high);
li->link_speed = le16_to_cpu(link_data.link_speed);
li->phy_type_low = le64_to_cpu(link_data.phy_type_low);
li->phy_type_high = le64_to_cpu(link_data.phy_type_high);
*hw_media_type = ice_get_media_type(pi);
hw_link_info->link_info = link_data.link_info;
hw_link_info->an_info = link_data.an_info;
hw_link_info->ext_info = link_data.ext_info;
hw_link_info->max_frame_size = le16_to_cpu(link_data.max_frame_size);
hw_link_info->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
hw_link_info->topo_media_conflict = link_data.topo_media_conflict;
hw_link_info->pacing = link_data.cfg & ICE_AQ_CFG_PACING_M;
li->link_info = link_data.link_info;
li->an_info = link_data.an_info;
li->ext_info = link_data.ext_info;
li->max_frame_size = le16_to_cpu(link_data.max_frame_size);
li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
li->topo_media_conflict = link_data.topo_media_conflict;
li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
ICE_AQ_CFG_PACING_TYPE_M);
/* update fc info */
tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
......@@ -320,12 +322,24 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
else
hw_fc_info->current_mode = ICE_FC_NONE;
hw_link_info->lse_ena =
!!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
li->lse_ena = !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
ice_debug(hw, ICE_DBG_LINK, "link_speed = 0x%x\n", li->link_speed);
ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
(unsigned long long)li->phy_type_low);
ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
(unsigned long long)li->phy_type_high);
ice_debug(hw, ICE_DBG_LINK, "media_type = 0x%x\n", *hw_media_type);
ice_debug(hw, ICE_DBG_LINK, "link_info = 0x%x\n", li->link_info);
ice_debug(hw, ICE_DBG_LINK, "an_info = 0x%x\n", li->an_info);
ice_debug(hw, ICE_DBG_LINK, "ext_info = 0x%x\n", li->ext_info);
ice_debug(hw, ICE_DBG_LINK, "lse_ena = 0x%x\n", li->lse_ena);
ice_debug(hw, ICE_DBG_LINK, "max_frame = 0x%x\n", li->max_frame_size);
ice_debug(hw, ICE_DBG_LINK, "pacing = 0x%x\n", li->pacing);
/* save link status information */
if (link)
*link = *hw_link_info;
*link = *li;
/* flag cleared so calling functions don't call AQ again */
pi->phy.get_link_info = false;
......@@ -2000,6 +2014,17 @@ ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
desc.params.set_phy.lport_num = lport;
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
(unsigned long long)le64_to_cpu(cfg->phy_type_low));
ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
(unsigned long long)le64_to_cpu(cfg->phy_type_high));
ice_debug(hw, ICE_DBG_LINK, "caps = 0x%x\n", cfg->caps);
ice_debug(hw, ICE_DBG_LINK, "low_power_ctrl = 0x%x\n",
cfg->low_power_ctrl);
ice_debug(hw, ICE_DBG_LINK, "eee_cap = 0x%x\n", cfg->eee_cap);
ice_debug(hw, ICE_DBG_LINK, "eeer_value = 0x%x\n", cfg->eeer_value);
ice_debug(hw, ICE_DBG_LINK, "link_fec_opt = 0x%x\n", cfg->link_fec_opt);
return ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
}
......
......@@ -500,30 +500,31 @@ void ice_update_dcb_stats(struct ice_pf *pf)
{
struct ice_hw_port_stats *prev_ps, *cur_ps;
struct ice_hw *hw = &pf->hw;
u8 pf_id = hw->pf_id;
u8 port;
int i;
port = hw->port_info->lport;
prev_ps = &pf->stats_prev;
cur_ps = &pf->stats;
for (i = 0; i < 8; i++) {
ice_stat_update32(hw, GLPRT_PXOFFRXC(pf_id, i),
ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
pf->stat_prev_loaded,
&prev_ps->priority_xoff_rx[i],
&cur_ps->priority_xoff_rx[i]);
ice_stat_update32(hw, GLPRT_PXONRXC(pf_id, i),
ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
pf->stat_prev_loaded,
&prev_ps->priority_xon_rx[i],
&cur_ps->priority_xon_rx[i]);
ice_stat_update32(hw, GLPRT_PXONTXC(pf_id, i),
ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
pf->stat_prev_loaded,
&prev_ps->priority_xon_tx[i],
&cur_ps->priority_xon_tx[i]);
ice_stat_update32(hw, GLPRT_PXOFFTXC(pf_id, i),
ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
pf->stat_prev_loaded,
&prev_ps->priority_xoff_tx[i],
&cur_ps->priority_xoff_tx[i]);
ice_stat_update32(hw, GLPRT_RXON2OFFCNT(pf_id, i),
ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
pf->stat_prev_loaded,
&prev_ps->priority_xon_2_xoff[i],
&cur_ps->priority_xon_2_xoff[i]);
......
This diff is collapsed.
......@@ -6,7 +6,21 @@
#include "ice.h"
int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
struct ice_txq_meta {
/* Tx-scheduler element identifier */
u32 q_teid;
/* Entry in VSI's txq_map bitmap */
u16 q_id;
/* Relative index of Tx queue within TC */
u16 q_handle;
/* VSI index that Tx queue belongs to */
u16 vsi_idx;
/* TC number that Tx queue belongs to */
u8 tc;
};
int
ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
const u8 *macaddr);
void ice_free_fltr_list(struct device *dev, struct list_head *h);
......@@ -25,6 +39,16 @@ ice_cfg_txq_interrupt(struct ice_vsi *vsi, u16 txq, u16 msix_idx, u16 itr_idx);
void
ice_cfg_rxq_interrupt(struct ice_vsi *vsi, u16 rxq, u16 msix_idx, u16 itr_idx);
int
ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
u16 rel_vmvf_num, struct ice_ring *ring,
struct ice_txq_meta *txq_meta);
void ice_fill_txq_meta(struct ice_vsi *vsi, struct ice_ring *ring,
struct ice_txq_meta *txq_meta);
int ice_vsi_ctrl_rx_ring(struct ice_vsi *vsi, bool ena, u16 rxq_idx);
#endif /* CONFIG_PCI_IOV */
int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid);
......
This diff is collapsed.
......@@ -260,33 +260,17 @@ ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
/**
* ice_sched_get_first_node - get the first node of the given layer
* @hw: pointer to the HW struct
* @pi: port information structure
* @parent: pointer the base node of the subtree
* @layer: layer number
*
* This function retrieves the first node of the given layer from the subtree
*/
static struct ice_sched_node *
ice_sched_get_first_node(struct ice_hw *hw, struct ice_sched_node *parent,
u8 layer)
ice_sched_get_first_node(struct ice_port_info *pi,
struct ice_sched_node *parent, u8 layer)
{
u8 i;
if (layer < hw->sw_entry_point_layer)
return NULL;
for (i = 0; i < parent->num_children; i++) {
struct ice_sched_node *node = parent->children[i];
if (node) {
if (node->tx_sched_layer == layer)
return node;
/* this recursion is intentional, and wouldn't
* go more than 9 calls
*/
return ice_sched_get_first_node(hw, node, layer);
}
}
return NULL;
return pi->sib_head[parent->tc_num][layer];
}
/**
......@@ -342,7 +326,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
parent = node->parent;
/* root has no parent */
if (parent) {
struct ice_sched_node *p, *tc_node;
struct ice_sched_node *p;
/* update the parent */
for (i = 0; i < parent->num_children; i++)
......@@ -354,16 +338,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
break;
}
/* search for previous sibling that points to this node and
* remove the reference
*/
tc_node = ice_sched_get_tc_node(pi, node->tc_num);
if (!tc_node) {
ice_debug(hw, ICE_DBG_SCHED,
"Invalid TC number %d\n", node->tc_num);
goto err_exit;
}
p = ice_sched_get_first_node(hw, tc_node, node->tx_sched_layer);
p = ice_sched_get_first_node(pi, node, node->tx_sched_layer);
while (p) {
if (p->sibling == node) {
p->sibling = node->sibling;
......@@ -371,8 +346,13 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
}
p = p->sibling;
}
/* update the sibling head if head is getting removed */
if (pi->sib_head[node->tc_num][node->tx_sched_layer] == node)
pi->sib_head[node->tc_num][node->tx_sched_layer] =
node->sibling;
}
err_exit:
/* leaf nodes have no children */
if (node->children)
devm_kfree(ice_hw_to_dev(hw), node->children);
......@@ -743,13 +723,17 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
/* add it to previous node sibling pointer */
/* Note: siblings are not linked across branches */
prev = ice_sched_get_first_node(hw, tc_node, layer);
prev = ice_sched_get_first_node(pi, tc_node, layer);
if (prev && prev != new_node) {
while (prev->sibling)
prev = prev->sibling;
prev->sibling = new_node;
}
/* initialize the sibling head */
if (!pi->sib_head[tc_node->tc_num][layer])
pi->sib_head[tc_node->tc_num][layer] = new_node;
if (i == 0)
*first_node_teid = teid;
}
......@@ -1160,7 +1144,7 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
goto lan_q_exit;
/* get the first queue group node from VSI sub-tree */
qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer);
qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer);
while (qgrp_node) {
/* make sure the qgroup node is part of the VSI subtree */
if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
......@@ -1191,7 +1175,7 @@ ice_sched_get_vsi_node(struct ice_hw *hw, struct ice_sched_node *tc_node,
u8 vsi_layer;
vsi_layer = ice_sched_get_vsi_layer(hw);
node = ice_sched_get_first_node(hw, tc_node, vsi_layer);
node = ice_sched_get_first_node(hw->port_info, tc_node, vsi_layer);
/* Check whether it already exists */
while (node) {
......@@ -1316,7 +1300,8 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
/* If intermediate nodes are reached max children
* then add a new one.
*/
node = ice_sched_get_first_node(hw, tc_node, (u8)i);
node = ice_sched_get_first_node(hw->port_info, tc_node,
(u8)i);
/* scan all the siblings */
while (node) {
if (node->num_children < hw->max_children[i])
......
......@@ -13,9 +13,9 @@
#define ICE_BYTES_PER_WORD 2
#define ICE_BYTES_PER_DWORD 4
static inline bool ice_is_tc_ena(u8 bitmap, u8 tc)
static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc)
{
return test_bit(tc, (unsigned long *)&bitmap);
return test_bit(tc, &bitmap);
}
/* Driver always calls main vsi_handle first */
......@@ -347,6 +347,8 @@ struct ice_port_info {
struct ice_mac_info mac;
struct ice_phy_info phy;
struct mutex sched_lock; /* protect access to TXSched tree */
struct ice_sched_node *
sib_head[ICE_MAX_TRAFFIC_CLASS][ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct ice_dcbx_cfg local_dcbx_cfg; /* Oper/Local Cfg */
/* DCBX info */
struct ice_dcbx_cfg remote_dcbx_cfg; /* Peer Cfg */
......
......@@ -15,8 +15,8 @@
#define ICE_MAX_MACADDR_PER_VF 12
/* Malicious Driver Detection */
#define ICE_DFLT_NUM_MDD_EVENTS_ALLOWED 3
#define ICE_DFLT_NUM_INVAL_MSGS_ALLOWED 10
#define ICE_MDD_EVENTS_THRESHOLD 30
/* Static VF transaction/status register def */
#define VF_DEVICE_STATUS 0xAA
......@@ -41,9 +41,9 @@
/* Specific VF states */
enum ice_vf_states {
ICE_VF_STATE_INIT = 0,
ICE_VF_STATE_ACTIVE,
ICE_VF_STATE_ENA,
ICE_VF_STATE_INIT = 0, /* PF is initializing VF */
ICE_VF_STATE_ACTIVE, /* VF resources are allocated for use */
ICE_VF_STATE_QS_ENA, /* VF queue(s) enabled */
ICE_VF_STATE_DIS,
ICE_VF_STATE_MC_PROMISC,
ICE_VF_STATE_UC_PROMISC,
......@@ -68,6 +68,8 @@ struct ice_vf {
struct virtchnl_version_info vf_ver;
u32 driver_caps; /* reported by VF driver */
struct virtchnl_ether_addr dflt_lan_addr;
DECLARE_BITMAP(txq_ena, ICE_MAX_BASE_QS_PER_VF);
DECLARE_BITMAP(rxq_ena, ICE_MAX_BASE_QS_PER_VF);
u16 port_vlan_id;
u8 pf_set_mac:1; /* VF MAC address set by VMM admin */
u8 trusted:1;
......@@ -90,6 +92,7 @@ struct ice_vf {
u16 num_mac;
u16 num_vlan;
u16 num_vf_qs; /* num of queue configured per VF */
u16 num_qs_ena; /* total num of Tx/Rx queue enabled */
};
#ifdef CONFIG_PCI_IOV
......@@ -116,12 +119,15 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);
int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);
void ice_set_vf_state_qs_dis(struct ice_vf *vf);
#else /* CONFIG_PCI_IOV */
#define ice_process_vflr_event(pf) do {} while (0)
#define ice_free_vfs(pf) do {} while (0)
#define ice_vc_process_vf_msg(pf, event) do {} while (0)
#define ice_vc_notify_link_state(pf) do {} while (0)
#define ice_vc_notify_reset(pf) do {} while (0)
#define ice_set_vf_state_qs_dis(vf) do {} while (0)
static inline bool
ice_reset_all_vfs(struct ice_pf __always_unused *pf,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment