Commit 7da33a8f 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-05-29

This series contains updates to ice driver only.

Bruce cleans up white space issues and fixes complaints about using
bitop assignments using operands of different sizes.

Anirudh cleans up code that is no longer needed now that the firmware
supports the functionality.  Adds support for ethtool selftestto the ice
driver, which includes testing link, interrupts, eeprom, registers and
packet loopback.  Also, cleaned up duplicate code.

Tony implements support for toggling receive VLAN filter via ethtool.

Brett bumps up the minimum receive descriptor count per queue to resolve
dropped packets.  Refactored the interrupt tracking for the ice driver
to resolve issues seen with the co-existence of features and SR-IOV, so
instead of having a hardware IRQ tracker and a software IRQ tracker,
simply use one tracker.  Also adds a helper function to trigger software
interrupts.

Mitch changes how Malicious Driver Detection (MDD) events are handled,
to ensure all VFs checked for MDD events and just log the event instead
of disabling the VF, which was preventing proper release of resources if
the VF is rebooted or the VF driver reloaded.

Dave cleans up a redundant call to register LLDP MIB change events.

Dan adds support to retrieve the current setting of firmware logging
from the hardware to properly initialize the hardware structure.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a3e2f6ad e89e899f
......@@ -46,13 +46,20 @@ extern const char ice_drv_ver[];
#define ICE_REQ_DESC_MULTIPLE 32
#define ICE_MIN_NUM_DESC ICE_REQ_DESC_MULTIPLE
#define ICE_MAX_NUM_DESC 8160
/* set default number of Rx/Tx descriptors to the minimum between
* ICE_MAX_NUM_DESC and the number of descriptors to fill up an entire page
#define ICE_DFLT_MIN_RX_DESC 512
/* if the default number of Rx descriptors between ICE_MAX_NUM_DESC and the
* number of descriptors to fill up an entire page is greater than or equal to
* ICE_DFLT_MIN_RX_DESC set it based on page size, otherwise set it to
* ICE_DFLT_MIN_RX_DESC
*/
#define ICE_DFLT_NUM_RX_DESC \
min_t(u16, ICE_MAX_NUM_DESC, \
max_t(u16, ALIGN(PAGE_SIZE / sizeof(union ice_32byte_rx_desc), \
ICE_REQ_DESC_MULTIPLE), \
ICE_DFLT_MIN_RX_DESC))
/* set default number of Tx descriptors to the minimum between ICE_MAX_NUM_DESC
* and the number of descriptors to fill up an entire page
*/
#define ICE_DFLT_NUM_RX_DESC min_t(u16, ICE_MAX_NUM_DESC, \
ALIGN(PAGE_SIZE / \
sizeof(union ice_32byte_rx_desc), \
ICE_REQ_DESC_MULTIPLE))
#define ICE_DFLT_NUM_TX_DESC min_t(u16, ICE_MAX_NUM_DESC, \
ALIGN(PAGE_SIZE / \
sizeof(struct ice_tx_desc), \
......@@ -160,7 +167,7 @@ struct ice_tc_cfg {
struct ice_res_tracker {
u16 num_entries;
u16 search_hint;
u16 end;
u16 list[1];
};
......@@ -182,6 +189,7 @@ struct ice_sw {
};
enum ice_state {
__ICE_TESTING,
__ICE_DOWN,
__ICE_NEEDS_RESTART,
__ICE_PREPARED_FOR_RESET, /* set by driver when prepared */
......@@ -244,8 +252,7 @@ struct ice_vsi {
u32 rx_buf_failed;
u32 rx_page_failed;
int num_q_vectors;
int sw_base_vector; /* Irq base for OS reserved vectors */
int hw_base_vector; /* HW (absolute) index of a vector */
int base_vector; /* IRQ base for OS reserved vectors */
enum ice_vsi_type type;
u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */
......@@ -340,10 +347,12 @@ struct ice_pf {
/* OS reserved IRQ details */
struct msix_entry *msix_entries;
struct ice_res_tracker *sw_irq_tracker;
/* HW reserved Interrupts for this PF */
struct ice_res_tracker *hw_irq_tracker;
struct ice_res_tracker *irq_tracker;
/* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the
* number of MSIX vectors needed for all SR-IOV VFs from the number of
* MSIX vectors allowed on this PF.
*/
u16 sriov_base_vector;
struct ice_vsi **vsi; /* VSIs created by the driver */
struct ice_sw *first_sw; /* first switch created by firmware */
......@@ -365,10 +374,8 @@ struct ice_pf {
struct mutex sw_mutex; /* lock for protecting VSI alloc flow */
u32 msg_enable;
u32 hw_csum_rx_error;
u32 sw_oicr_idx; /* Other interrupt cause SW vector index */
u32 oicr_idx; /* Other interrupt cause MSIX vector index */
u32 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
u32 hw_oicr_idx; /* Other interrupt cause vector HW index */
u32 num_avail_hw_msix; /* remaining HW MSIX vectors left unclaimed */
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 */
......@@ -392,6 +399,7 @@ struct ice_pf {
unsigned long tx_timeout_last_recovery;
u32 tx_timeout_recovery_level;
char int_name[ICE_INT_NAME_STR_LEN];
u32 sw_int_count;
};
struct ice_netdev_priv {
......@@ -409,7 +417,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
struct ice_q_vector *q_vector)
{
u32 vector = (vsi && q_vector) ? q_vector->reg_idx :
((struct ice_pf *)hw->back)->hw_oicr_idx;
((struct ice_pf *)hw->back)->oicr_idx;
int itr = ICE_ITR_NONE;
u32 val;
......@@ -444,9 +452,13 @@ ice_find_vsi_by_type(struct ice_pf *pf, enum ice_vsi_type type)
return NULL;
}
int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);
int ice_vsi_setup_rx_rings(struct ice_vsi *vsi);
void ice_set_ethtool_ops(struct net_device *netdev);
int ice_up(struct ice_vsi *vsi);
int ice_down(struct ice_vsi *vsi);
int ice_vsi_cfg(struct ice_vsi *vsi);
struct ice_vsi *ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi);
int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);
......@@ -455,5 +467,7 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup);
int ice_pf_ena_all_vsi(struct ice_pf *pf, bool locked);
void ice_pf_dis_all_vsi(struct ice_pf *pf, bool locked);
#endif /* CONFIG_DCB */
int ice_open(struct net_device *netdev);
int ice_stop(struct net_device *netdev);
#endif /* _ICE_H_ */
......@@ -1112,6 +1112,14 @@ struct ice_aqc_set_event_mask {
u8 reserved1[6];
};
/* Set MAC Loopback command (direct 0x0620) */
struct ice_aqc_set_mac_lb {
u8 lb_mode;
#define ICE_AQ_MAC_LB_EN BIT(0)
#define ICE_AQ_MAC_LB_OSC_CLK BIT(1)
u8 reserved[15];
};
/* Set Port Identification LED (direct, 0x06E9) */
struct ice_aqc_set_port_id_led {
u8 lport_num;
......@@ -1145,6 +1153,17 @@ struct ice_aqc_nvm {
__le32 addr_low;
};
/* NVM Checksum Command (direct, 0x0706) */
struct ice_aqc_nvm_checksum {
u8 flags;
#define ICE_AQC_NVM_CHECKSUM_VERIFY BIT(0)
#define ICE_AQC_NVM_CHECKSUM_RECALC BIT(1)
u8 rsvd;
__le16 checksum; /* Used only by response */
#define ICE_AQC_NVM_CHECKSUM_CORRECT 0xBABA
u8 rsvd2[12];
};
/**
* Send to PF command (indirect 0x0801) ID is only used by PF
*
......@@ -1539,6 +1558,7 @@ struct ice_aq_desc {
struct ice_aqc_query_txsched_res query_sched_res;
struct ice_aqc_query_port_ets port_ets;
struct ice_aqc_nvm nvm;
struct ice_aqc_nvm_checksum nvm_checksum;
struct ice_aqc_pf_vf_msg virt;
struct ice_aqc_lldp_get_mib lldp_get_mib;
struct ice_aqc_lldp_set_mib_change lldp_set_event;
......@@ -1554,6 +1574,7 @@ struct ice_aq_desc {
struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res;
struct ice_aqc_fw_logging fw_logging;
struct ice_aqc_get_clear_fw_log get_clear_fw_log;
struct ice_aqc_set_mac_lb set_mac_lb;
struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
struct ice_aqc_set_event_mask set_event_mask;
struct ice_aqc_get_link_status get_link_status;
......@@ -1642,10 +1663,12 @@ enum ice_adminq_opc {
ice_aqc_opc_restart_an = 0x0605,
ice_aqc_opc_get_link_status = 0x0607,
ice_aqc_opc_set_event_mask = 0x0613,
ice_aqc_opc_set_mac_lb = 0x0620,
ice_aqc_opc_set_port_id_led = 0x06E9,
/* NVM commands */
ice_aqc_opc_nvm_read = 0x0701,
ice_aqc_opc_nvm_checksum = 0x0706,
/* PF/VF mailbox commands */
ice_mbx_opc_send_msg_to_pf = 0x0801,
......@@ -1671,6 +1694,7 @@ enum ice_adminq_opc {
/* debug commands */
ice_aqc_opc_fw_logging = 0xFF09,
ice_aqc_opc_fw_logging_info = 0xFF10,
};
#endif /* _ICE_ADMINQ_CMD_H_ */
......@@ -51,9 +51,6 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw)
*/
void ice_dev_onetime_setup(struct ice_hw *hw)
{
/* configure Rx - set non pxe mode */
wr32(hw, GLLAN_RCTL_0, 0x1);
#define MBX_PF_VT_PFALLOC 0x00231E80
/* set VFs per PF */
wr32(hw, MBX_PF_VT_PFALLOC, rd32(hw, PF_VT_PFALLOC_HIF));
......@@ -475,6 +472,49 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
#define ICE_FW_LOG_DESC_SIZE_MAX \
ICE_FW_LOG_DESC_SIZE(ICE_AQC_FW_LOG_ID_MAX)
/**
* ice_get_fw_log_cfg - get FW logging configuration
* @hw: pointer to the HW struct
*/
static enum ice_status ice_get_fw_log_cfg(struct ice_hw *hw)
{
struct ice_aqc_fw_logging_data *config;
struct ice_aq_desc desc;
enum ice_status status;
u16 size;
size = ICE_FW_LOG_DESC_SIZE_MAX;
config = devm_kzalloc(ice_hw_to_dev(hw), size, GFP_KERNEL);
if (!config)
return ICE_ERR_NO_MEMORY;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_BUF);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
status = ice_aq_send_cmd(hw, &desc, config, size, NULL);
if (!status) {
u16 i;
/* Save fw logging information into the hw structure */
for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
u16 v, m, flgs;
v = le16_to_cpu(config->entry[i]);
m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S;
if (m < ICE_AQC_FW_LOG_ID_MAX)
hw->fw_log.evnts[m].cur = flgs;
}
}
devm_kfree(ice_hw_to_dev(hw), config);
return status;
}
/**
* ice_cfg_fw_log - configure FW logging
* @hw: pointer to the HW struct
......@@ -529,6 +569,11 @@ static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable)
(!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq)))
return 0;
/* Get current FW log settings */
status = ice_get_fw_log_cfg(hw);
if (status)
return status;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging);
cmd = &desc.params.fw_logging;
......@@ -2172,6 +2217,29 @@ ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
/**
* ice_aq_set_mac_loopback
* @hw: pointer to the HW struct
* @ena_lpbk: Enable or Disable loopback
* @cd: pointer to command details structure or NULL
*
* Enable/disable loopback on a given port
*/
enum ice_status
ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
{
struct ice_aqc_set_mac_lb *cmd;
struct ice_aq_desc desc;
cmd = &desc.params.set_mac_lb;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
if (ena_lpbk)
cmd->lb_mode = ICE_AQ_MAC_LB_EN;
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
/**
* ice_aq_set_port_id_led
* @pi: pointer to the port information
......@@ -2928,7 +2996,6 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
return ICE_ERR_CFG;
if (!num_queues) {
/* if queue is disabled already yet the disable queue command
* has to be sent to complete the VF reset, then call
......
......@@ -9,6 +9,8 @@
#include "ice_switch.h"
#include <linux/avf/virtchnl.h>
enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);
void
ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf, u16 buf_len);
enum ice_status ice_init_hw(struct ice_hw *hw);
......@@ -94,6 +96,9 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
enum ice_status
ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd);
enum ice_status
ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
struct ice_sq_cd *cd);
......
......@@ -6,6 +6,9 @@
#ifndef _ICE_HW_AUTOGEN_H_
#define _ICE_HW_AUTOGEN_H_
#define PF0INT_ITR_0(_i) (0x03000004 + ((_i) * 4096))
#define PF0INT_ITR_1(_i) (0x03000008 + ((_i) * 4096))
#define PF0INT_ITR_2(_i) (0x0300000C + ((_i) * 4096))
#define QTX_COMM_DBELL(_DBQM) (0x002C0000 + ((_DBQM) * 4))
#define QTX_COMM_HEAD(_DBQM) (0x000E0000 + ((_DBQM) * 4))
#define QTX_COMM_HEAD_HEAD_S 0
......@@ -155,6 +158,7 @@
#define PFINT_OICR_HMC_ERR_M BIT(26)
#define PFINT_OICR_PE_CRITERR_M BIT(28)
#define PFINT_OICR_VFLR_M BIT(29)
#define PFINT_OICR_SWINT_M BIT(31)
#define PFINT_OICR_CTL 0x0016CA80
#define PFINT_OICR_CTL_MSIX_INDX_M ICE_M(0x7FF, 0)
#define PFINT_OICR_CTL_ITR_INDX_S 11
......
This diff is collapsed.
......@@ -64,6 +64,8 @@ bool ice_is_reset_in_progress(unsigned long *state);
void ice_vsi_free_q_vectors(struct ice_vsi *vsi);
void ice_trigger_sw_intr(struct ice_hw *hw, struct ice_q_vector *q_vector);
void ice_vsi_put_qs(struct ice_vsi *vsi);
#ifdef CONFIG_DCB
......
This diff is collapsed.
......@@ -316,3 +316,34 @@ ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
return status;
}
/**
* ice_nvm_validate_checksum
* @hw: pointer to the HW struct
*
* Verify NVM PFA checksum validity (0x0706)
*/
enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw)
{
struct ice_aqc_nvm_checksum *cmd;
struct ice_aq_desc desc;
enum ice_status status;
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status)
return status;
cmd = &desc.params.nvm_checksum;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum);
cmd->flags = ICE_AQC_NVM_CHECKSUM_VERIFY;
status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
ice_release_nvm(hw);
if (!status)
if (le16_to_cpu(cmd->checksum) != ICE_AQC_NVM_CHECKSUM_CORRECT)
status = ICE_ERR_NVM_CHECKSUM;
return status;
}
......@@ -26,6 +26,7 @@ enum ice_status {
ICE_ERR_IN_USE = -16,
ICE_ERR_MAX_LIMIT = -17,
ICE_ERR_RESET_ONGOING = -18,
ICE_ERR_NVM_CHECKSUM = -51,
ICE_ERR_BUF_TOO_SHORT = -52,
ICE_ERR_NVM_BLANK_MODE = -53,
ICE_ERR_AQ_ERROR = -100,
......
......@@ -8,9 +8,11 @@
#define ICE_SW_CFG_MAX_BUF_LEN 2048
#define ICE_DFLT_VSI_INVAL 0xff
#define ICE_FLTR_RX BIT(0)
#define ICE_FLTR_TX BIT(1)
#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
#define ICE_VSI_INVAL_ID 0xffff
#define ICE_INVAL_Q_HANDLE 0xFFFF
#define ICE_INVAL_Q_HANDLE 0xFFFF
/* VSI queue context structure */
struct ice_q_ctx {
......@@ -69,9 +71,6 @@ struct ice_fltr_info {
/* rule ID returned by firmware once filter rule is created */
u16 fltr_rule_id;
u16 flag;
#define ICE_FLTR_RX BIT(0)
#define ICE_FLTR_TX BIT(1)
#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
/* Source VSI for LOOKUP_TX or source port for LOOKUP_RX */
u16 src;
......
......@@ -1874,10 +1874,10 @@ int ice_tso(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
cd_mss = skb_shinfo(skb)->gso_size;
/* record cdesc_qw1 with TSO parameters */
off->cd_qw1 |= ICE_TX_DESC_DTYPE_CTX |
(ICE_TX_CTX_DESC_TSO << ICE_TXD_CTX_QW1_CMD_S) |
(cd_tso_len << ICE_TXD_CTX_QW1_TSO_LEN_S) |
(cd_mss << ICE_TXD_CTX_QW1_MSS_S);
off->cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
(ICE_TX_CTX_DESC_TSO << ICE_TXD_CTX_QW1_CMD_S) |
(cd_tso_len << ICE_TXD_CTX_QW1_TSO_LEN_S) |
(cd_mss << ICE_TXD_CTX_QW1_MSS_S));
first->tx_flags |= ICE_TX_FLAGS_TSO;
return 1;
}
......
......@@ -86,6 +86,7 @@ enum ice_media_type {
enum ice_vsi_type {
ICE_VSI_PF = 0,
ICE_VSI_VF,
ICE_VSI_LB = 6,
};
struct ice_link_status {
......
......@@ -205,8 +205,7 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
wr32(hw, VPINT_ALLOC(vf->vf_id), 0);
wr32(hw, VPINT_ALLOC_PCI(vf->vf_id), 0);
first = vf->first_vector_idx +
hw->func_caps.common_cap.msix_vector_first_id;
first = vf->first_vector_idx;
last = first + pf->num_vf_msix - 1;
for (v = first; v <= last; v++) {
u32 reg;
......@@ -231,6 +230,42 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
"Scattered mode for VF Rx queues is not yet implemented\n");
}
/**
* ice_sriov_free_msix_res - Reset/free any used MSIX resources
* @pf: pointer to the PF structure
*
* If MSIX entries from the pf->irq_tracker were needed then we need to
* reset the irq_tracker->end and give back the entries we needed to
* num_avail_sw_msix.
*
* If no MSIX entries were taken from the pf->irq_tracker then just clear
* the pf->sriov_base_vector.
*
* Returns 0 on success, and -EINVAL on error.
*/
static int ice_sriov_free_msix_res(struct ice_pf *pf)
{
struct ice_res_tracker *res;
if (!pf)
return -EINVAL;
res = pf->irq_tracker;
if (!res)
return -EINVAL;
/* give back irq_tracker resources used */
if (pf->sriov_base_vector < res->num_entries) {
res->end = res->num_entries;
pf->num_avail_sw_msix +=
res->num_entries - pf->sriov_base_vector;
}
pf->sriov_base_vector = 0;
return 0;
}
/**
* ice_free_vfs - Free all VFs
* @pf: pointer to the PF structure
......@@ -288,6 +323,10 @@ void ice_free_vfs(struct ice_pf *pf)
}
}
if (ice_sriov_free_msix_res(pf))
dev_err(&pf->pdev->dev,
"Failed to free MSIX resources used by SR-IOV\n");
devm_kfree(&pf->pdev->dev, pf->vf);
pf->vf = NULL;
......@@ -456,6 +495,22 @@ ice_vf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, u16 vf_id)
return ice_vsi_setup(pf, pi, ICE_VSI_VF, vf_id);
}
/**
* ice_calc_vf_first_vector_idx - Calculate absolute MSIX vector index in HW
* @pf: pointer to PF structure
* @vf: pointer to VF that the first MSIX vector index is being calculated for
*
* This returns the first MSIX vector index in HW that is used by this VF and
* this will always be the OICR index in the AVF driver so any functionality
* using vf->first_vector_idx for queue configuration will have to increment by
* 1 to avoid meddling with the OICR index.
*/
static int ice_calc_vf_first_vector_idx(struct ice_pf *pf, struct ice_vf *vf)
{
return pf->hw.func_caps.common_cap.msix_vector_first_id +
pf->sriov_base_vector + vf->vf_id * pf->num_vf_msix;
}
/**
* ice_alloc_vsi_res - Setup VF VSI and its resources
* @vf: pointer to the VF structure
......@@ -470,6 +525,9 @@ static int ice_alloc_vsi_res(struct ice_vf *vf)
struct ice_vsi *vsi;
int status = 0;
/* first vector index is the VFs OICR index */
vf->first_vector_idx = ice_calc_vf_first_vector_idx(pf, vf);
vsi = ice_vf_vsi_setup(pf, pf->hw.port_info, vf->vf_id);
if (!vsi) {
......@@ -480,14 +538,6 @@ static int ice_alloc_vsi_res(struct ice_vf *vf)
vf->lan_vsi_idx = vsi->idx;
vf->lan_vsi_num = vsi->vsi_num;
/* first vector index is the VFs OICR index */
vf->first_vector_idx = vsi->hw_base_vector;
/* Since hw_base_vector holds the vector where data queue interrupts
* starts, increment by 1 since VFs allocated vectors include OICR intr
* as well.
*/
vsi->hw_base_vector += 1;
/* Check if port VLAN exist before, and restore it accordingly */
if (vf->port_vlan_id) {
ice_vsi_manage_pvid(vsi, vf->port_vlan_id, true);
......@@ -580,8 +630,7 @@ static void ice_ena_vf_mappings(struct ice_vf *vf)
hw = &pf->hw;
vsi = pf->vsi[vf->lan_vsi_idx];
first = vf->first_vector_idx +
hw->func_caps.common_cap.msix_vector_first_id;
first = vf->first_vector_idx;
last = (first + pf->num_vf_msix) - 1;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
......@@ -686,6 +735,97 @@ ice_determine_res(struct ice_pf *pf, u16 avail_res, u16 max_res, u16 min_res)
return 0;
}
/**
* ice_calc_vf_reg_idx - Calculate the VF's register index in the PF space
* @vf: VF to calculate the register index for
* @q_vector: a q_vector associated to the VF
*/
int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)
{
struct ice_pf *pf;
if (!vf || !q_vector)
return -EINVAL;
pf = vf->pf;
/* always add one to account for the OICR being the first MSIX */
return pf->sriov_base_vector + pf->num_vf_msix * vf->vf_id +
q_vector->v_idx + 1;
}
/**
* ice_get_max_valid_res_idx - Get the max valid resource index
* @res: pointer to the resource to find the max valid index for
*
* Start from the end of the ice_res_tracker and return right when we find the
* first res->list entry with the ICE_RES_VALID_BIT set. This function is only
* valid for SR-IOV because it is the only consumer that manipulates the
* res->end and this is always called when res->end is set to res->num_entries.
*/
static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)
{
int i;
if (!res)
return -EINVAL;
for (i = res->num_entries - 1; i >= 0; i--)
if (res->list[i] & ICE_RES_VALID_BIT)
return i;
return 0;
}
/**
* ice_sriov_set_msix_res - Set any used MSIX resources
* @pf: pointer to PF structure
* @num_msix_needed: number of MSIX vectors needed for all SR-IOV VFs
*
* This function allows SR-IOV resources to be taken from the end of the PF's
* allowed HW MSIX vectors so in many cases the irq_tracker will not
* be needed. In these cases we just set the pf->sriov_base_vector and return
* success.
*
* If SR-IOV needs to use any pf->irq_tracker entries it updates the
* irq_tracker->end based on the first entry needed for SR-IOV. This makes it
* so any calls to ice_get_res() using the irq_tracker will not try to use
* resources at or beyond the newly set value.
*
* Return 0 on success, and -EINVAL when there are not enough MSIX vectors in
* in the PF's space available for SR-IOV.
*/
static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)
{
int max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);
u16 pf_total_msix_vectors =
pf->hw.func_caps.common_cap.num_msix_vectors;
struct ice_res_tracker *res = pf->irq_tracker;
int sriov_base_vector;
if (max_valid_res_idx < 0)
return max_valid_res_idx;
sriov_base_vector = pf_total_msix_vectors - num_msix_needed;
/* make sure we only grab irq_tracker entries from the list end and
* that we have enough available MSIX vectors
*/
if (sriov_base_vector <= max_valid_res_idx)
return -EINVAL;
pf->sriov_base_vector = sriov_base_vector;
/* dip into irq_tracker entries and update used resources */
if (num_msix_needed > (pf_total_msix_vectors - res->num_entries)) {
pf->num_avail_sw_msix -=
res->num_entries - pf->sriov_base_vector;
res->end = pf->sriov_base_vector;
}
return 0;
}
/**
* ice_check_avail_res - check if vectors and queues are available
* @pf: pointer to the PF structure
......@@ -696,11 +836,16 @@ ice_determine_res(struct ice_pf *pf, u16 avail_res, u16 max_res, u16 min_res)
*/
static int ice_check_avail_res(struct ice_pf *pf)
{
u16 num_msix, num_txq, num_rxq;
int max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);
u16 num_msix, num_txq, num_rxq, num_avail_msix;
if (!pf->num_alloc_vfs)
if (!pf->num_alloc_vfs || max_valid_res_idx < 0)
return -EINVAL;
/* add 1 to max_valid_res_idx to account for it being 0-based */
num_avail_msix = pf->hw.func_caps.common_cap.num_msix_vectors -
(max_valid_res_idx + 1);
/* Grab from HW interrupts common pool
* Note: By the time the user decides it needs more vectors in a VF
* its already too late since one must decide this prior to creating the
......@@ -717,11 +862,11 @@ static int ice_check_avail_res(struct ice_pf *pf)
* grab default interrupt vectors (5 as supported by AVF driver).
*/
if (pf->num_alloc_vfs <= 16) {
num_msix = ice_determine_res(pf, pf->num_avail_hw_msix,
num_msix = ice_determine_res(pf, num_avail_msix,
ICE_MAX_INTR_PER_VF,
ICE_MIN_INTR_PER_VF);
} else if (pf->num_alloc_vfs <= ICE_MAX_VF_COUNT) {
num_msix = ice_determine_res(pf, pf->num_avail_hw_msix,
num_msix = ice_determine_res(pf, num_avail_msix,
ICE_DFLT_INTR_PER_VF,
ICE_MIN_INTR_PER_VF);
} else {
......@@ -750,6 +895,9 @@ static int ice_check_avail_res(struct ice_pf *pf)
if (!num_txq || !num_rxq)
return -EIO;
if (ice_sriov_set_msix_res(pf, num_msix * pf->num_alloc_vfs))
return -EINVAL;
/* since AVF driver works with only queue pairs which means, it expects
* to have equal number of Rx and Tx queues, so take the minimum of
* available Tx or Rx queues
......@@ -938,6 +1086,10 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
vf->num_vf_qs = 0;
}
if (ice_sriov_free_msix_res(pf))
dev_err(&pf->pdev->dev,
"Failed to free MSIX resources used by SR-IOV\n");
if (ice_check_avail_res(pf)) {
dev_err(&pf->pdev->dev,
"Cannot allocate VF resources, try with fewer number of VFs\n");
......@@ -1119,7 +1271,7 @@ static int ice_alloc_vfs(struct ice_pf *pf, u16 num_alloc_vfs)
int i, ret;
/* Disable global interrupt 0 so we don't try to handle the VFLR. */
wr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx),
wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);
ice_flush(hw);
......
......@@ -101,6 +101,8 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted);
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);
#else /* CONFIG_PCI_IOV */
#define ice_process_vflr_event(pf) do {} while (0)
#define ice_free_vfs(pf) do {} while (0)
......@@ -166,5 +168,11 @@ ice_set_vf_link_state(struct net_device __always_unused *netdev,
return -EOPNOTSUPP;
}
static inline int
ice_calc_vf_reg_idx(struct ice_vf __always_unused *vf,
struct ice_q_vector __always_unused *q_vector)
{
return 0;
}
#endif /* CONFIG_PCI_IOV */
#endif /* _ICE_VIRTCHNL_PF_H_ */
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