Skip to content

Commit 007676b

Browse files
refactormanJeff Kirsher
authored andcommitted
ice: Add support for VF reset events
Post VF initialization, there are a couple of different ways in which a VF reset can be triggered. One is when the underlying PF itself goes through a reset and other is via a VFLR interrupt. ice_reset_vf introduced in this patch handles both these cases. Also introduced in this patch is a helper function ice_aq_send_msg_to_vf to send messages to VF over the mailbox queue. The PF uses this to send reset notifications to VFs. Signed-off-by: Anirudh Venkataramanan <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 8ede017 commit 007676b

File tree

10 files changed

+272
-1
lines changed

10 files changed

+272
-1
lines changed

drivers/net/ethernet/intel/ice/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ ice-y := ice_main.o \
1616
ice_lib.o \
1717
ice_txrx.o \
1818
ice_ethtool.o
19-
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o
19+
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "ice_common.h"
3838
#include "ice_sched.h"
3939
#include "ice_virtchnl_pf.h"
40+
#include "ice_sriov.h"
4041

4142
extern const char ice_drv_ver[];
4243
#define ICE_BAR0 0
@@ -155,6 +156,7 @@ enum ice_state {
155156
__ICE_ADMINQ_EVENT_PENDING,
156157
__ICE_MAILBOXQ_EVENT_PENDING,
157158
__ICE_MDD_EVENT_PENDING,
159+
__ICE_VFLR_EVENT_PENDING,
158160
__ICE_FLTR_OVERFLOW_PROMISC,
159161
__ICE_VF_DIS,
160162
__ICE_CFG_BUSY,

drivers/net/ethernet/intel/ice/ice_adminq_cmd.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,19 @@ struct ice_aqc_nvm {
10771077
__le32 addr_low;
10781078
};
10791079

1080+
/**
1081+
* Send to PF command (indirect 0x0801) id is only used by PF
1082+
*
1083+
* Send to VF command (indirect 0x0802) id is only used by PF
1084+
*
1085+
*/
1086+
struct ice_aqc_pf_vf_msg {
1087+
__le32 id;
1088+
u32 reserved;
1089+
__le32 addr_high;
1090+
__le32 addr_low;
1091+
};
1092+
10801093
/* Get/Set RSS key (indirect 0x0B04/0x0B02) */
10811094
struct ice_aqc_get_set_rss_key {
10821095
#define ICE_AQC_GSET_RSS_KEY_VSI_VALID BIT(15)
@@ -1334,6 +1347,7 @@ struct ice_aq_desc {
13341347
struct ice_aqc_query_txsched_res query_sched_res;
13351348
struct ice_aqc_add_move_delete_elem add_move_delete_elem;
13361349
struct ice_aqc_nvm nvm;
1350+
struct ice_aqc_pf_vf_msg virt;
13371351
struct ice_aqc_get_set_rss_lut get_set_rss_lut;
13381352
struct ice_aqc_get_set_rss_key get_set_rss_key;
13391353
struct ice_aqc_add_txqs add_txqs;
@@ -1431,6 +1445,9 @@ enum ice_adminq_opc {
14311445
/* NVM commands */
14321446
ice_aqc_opc_nvm_read = 0x0701,
14331447

1448+
/* PF/VF mailbox commands */
1449+
ice_mbx_opc_send_msg_to_vf = 0x0802,
1450+
14341451
/* RSS commands */
14351452
ice_aqc_opc_set_rss_key = 0x0B02,
14361453
ice_aqc_opc_set_rss_lut = 0x0B03,

drivers/net/ethernet/intel/ice/ice_hw_autogen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
#define PFINT_OICR_PCI_EXCEPTION_M BIT(21)
137137
#define PFINT_OICR_HMC_ERR_M BIT(26)
138138
#define PFINT_OICR_PE_CRITERR_M BIT(28)
139+
#define PFINT_OICR_VFLR_M BIT(29)
139140
#define PFINT_OICR_CTL 0x0016CA80
140141
#define PFINT_OICR_CTL_MSIX_INDX_M ICE_M(0x7FF, 0)
141142
#define PFINT_OICR_CTL_ITR_INDX_S 11

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ ice_prepare_for_reset(struct ice_pf *pf)
342342
{
343343
struct ice_hw *hw = &pf->hw;
344344

345+
/* Notify VFs of impending reset */
346+
if (ice_check_sq_alive(hw, &hw->mailboxq))
347+
ice_vc_notify_reset(pf);
348+
345349
/* disable the VSIs and their queues that are not already DOWN */
346350
ice_pf_dis_all_vsi(pf);
347351

@@ -1064,6 +1068,7 @@ static void ice_service_task(struct work_struct *work)
10641068
ice_check_for_hang_subtask(pf);
10651069
ice_sync_fltr_subtask(pf);
10661070
ice_handle_mdd_event(pf);
1071+
ice_process_vflr_event(pf);
10671072
ice_watchdog_subtask(pf);
10681073
ice_clean_adminq_subtask(pf);
10691074
ice_clean_mailboxq_subtask(pf);
@@ -1077,6 +1082,7 @@ static void ice_service_task(struct work_struct *work)
10771082
*/
10781083
if (time_after(jiffies, (start_time + pf->serv_tmr_period)) ||
10791084
test_bit(__ICE_MDD_EVENT_PENDING, pf->state) ||
1085+
test_bit(__ICE_VFLR_EVENT_PENDING, pf->state) ||
10801086
test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state) ||
10811087
test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
10821088
mod_timer(&pf->serv_tmr, jiffies);
@@ -1229,6 +1235,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
12291235
PFINT_OICR_MAL_DETECT_M |
12301236
PFINT_OICR_GRST_M |
12311237
PFINT_OICR_PCI_EXCEPTION_M |
1238+
PFINT_OICR_VFLR_M |
12321239
PFINT_OICR_HMC_ERR_M |
12331240
PFINT_OICR_PE_CRITERR_M);
12341241

@@ -1261,6 +1268,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
12611268
ena_mask &= ~PFINT_OICR_MAL_DETECT_M;
12621269
set_bit(__ICE_MDD_EVENT_PENDING, pf->state);
12631270
}
1271+
if (oicr & PFINT_OICR_VFLR_M) {
1272+
ena_mask &= ~PFINT_OICR_VFLR_M;
1273+
set_bit(__ICE_VFLR_EVENT_PENDING, pf->state);
1274+
}
12641275

12651276
if (oicr & PFINT_OICR_GRST_M) {
12661277
u32 reset;
@@ -3224,6 +3235,10 @@ static int ice_vsi_rebuild_all(struct ice_pf *pf)
32243235
if (!pf->vsi[i])
32253236
continue;
32263237

3238+
/* VF VSI rebuild isn't supported yet */
3239+
if (pf->vsi[i]->type == ICE_VSI_VF)
3240+
continue;
3241+
32273242
err = ice_vsi_rebuild(pf->vsi[i]);
32283243
if (err) {
32293244
dev_err(&pf->pdev->dev,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2018, Intel Corporation. */
3+
4+
#include "ice_common.h"
5+
#include "ice_adminq_cmd.h"
6+
#include "ice_sriov.h"
7+
8+
/**
9+
* ice_aq_send_msg_to_vf
10+
* @hw: pointer to the hardware structure
11+
* @vfid: VF ID to send msg
12+
* @v_opcode: opcodes for VF-PF communication
13+
* @v_retval: return error code
14+
* @msg: pointer to the msg buffer
15+
* @msglen: msg length
16+
* @cd: pointer to command details
17+
*
18+
* Send message to VF driver (0x0802) using mailbox
19+
* queue and asynchronously sending message via
20+
* ice_sq_send_cmd() function
21+
*/
22+
enum ice_status
23+
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
24+
u8 *msg, u16 msglen, struct ice_sq_cd *cd)
25+
{
26+
struct ice_aqc_pf_vf_msg *cmd;
27+
struct ice_aq_desc desc;
28+
29+
ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_vf);
30+
31+
cmd = &desc.params.virt;
32+
cmd->id = cpu_to_le32(vfid);
33+
34+
desc.cookie_high = cpu_to_le32(v_opcode);
35+
desc.cookie_low = cpu_to_le32(v_retval);
36+
37+
if (msglen)
38+
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
39+
40+
return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
41+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2018, Intel Corporation. */
3+
4+
#ifndef _ICE_SRIOV_H_
5+
#define _ICE_SRIOV_H_
6+
7+
#include "ice_common.h"
8+
9+
#ifdef CONFIG_PCI_IOV
10+
enum ice_status
11+
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
12+
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
13+
14+
#else /* CONFIG_PCI_IOV */
15+
static inline enum ice_status
16+
ice_aq_send_msg_to_vf(struct ice_hw __always_unused *hw,
17+
u16 __always_unused vfid, u32 __always_unused v_opcode,
18+
u32 __always_unused v_retval, u8 __always_unused *msg,
19+
u16 __always_unused msglen,
20+
struct ice_sq_cd __always_unused *cd)
21+
{
22+
return 0;
23+
}
24+
#endif /* CONFIG_PCI_IOV */
25+
#endif /* _ICE_SRIOV_H_ */

drivers/net/ethernet/intel/ice/ice_status.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
/* Error Codes */
88
enum ice_status {
9+
ICE_SUCCESS = 0,
10+
11+
/* Generic codes : Range -1..-49 */
912
ICE_ERR_PARAM = -1,
1013
ICE_ERR_NOT_IMPL = -2,
1114
ICE_ERR_NOT_READY = -3,

drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,36 @@
44
#include "ice.h"
55
#include "ice_lib.h"
66

7+
/**
8+
* ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
9+
* @pf: pointer to the PF structure
10+
* @v_opcode: operation code
11+
* @v_retval: return value
12+
* @msg: pointer to the msg buffer
13+
* @msglen: msg length
14+
*/
15+
static void
16+
ice_vc_vf_broadcast(struct ice_pf *pf, enum virtchnl_ops v_opcode,
17+
enum ice_status v_retval, u8 *msg, u16 msglen)
18+
{
19+
struct ice_hw *hw = &pf->hw;
20+
struct ice_vf *vf = pf->vf;
21+
int i;
22+
23+
for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
24+
/* Not all vfs are enabled so skip the ones that are not */
25+
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
26+
!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
27+
continue;
28+
29+
/* Ignore return value on purpose - a given VF may fail, but
30+
* we need to keep going and send to all of them
31+
*/
32+
ice_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval, msg,
33+
msglen, NULL);
34+
}
35+
}
36+
737
/**
838
* ice_get_vf_vector - get VF interrupt vector register offset
939
* @vf_msix: number of MSIx vector per VF on a PF
@@ -693,6 +723,97 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
693723
return true;
694724
}
695725

726+
/**
727+
* ice_reset_vf - Reset a particular VF
728+
* @vf: pointer to the VF structure
729+
* @is_vflr: true if VFLR was issued, false if not
730+
*
731+
* Returns true if the VF is reset, false otherwise.
732+
*/
733+
static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
734+
{
735+
struct ice_pf *pf = vf->pf;
736+
struct ice_hw *hw = &pf->hw;
737+
bool rsd = false;
738+
u32 reg;
739+
int i;
740+
741+
/* If the VFs have been disabled, this means something else is
742+
* resetting the VF, so we shouldn't continue.
743+
*/
744+
if (test_and_set_bit(__ICE_VF_DIS, pf->state))
745+
return false;
746+
747+
ice_trigger_vf_reset(vf, is_vflr);
748+
749+
if (test_bit(ICE_VF_STATE_ENA, vf->vf_states)) {
750+
ice_vsi_stop_tx_rings(pf->vsi[vf->lan_vsi_idx], ICE_VF_RESET,
751+
vf->vf_id);
752+
ice_vsi_stop_rx_rings(pf->vsi[vf->lan_vsi_idx]);
753+
clear_bit(ICE_VF_STATE_ENA, vf->vf_states);
754+
} else {
755+
/* Call Disable LAN Tx queue AQ call even when queues are not
756+
* enabled. This is needed for successful completiom of VFR
757+
*/
758+
ice_dis_vsi_txq(pf->vsi[vf->lan_vsi_idx]->port_info, 0,
759+
NULL, NULL, ICE_VF_RESET, vf->vf_id, NULL);
760+
}
761+
762+
/* poll VPGEN_VFRSTAT reg to make sure
763+
* that reset is complete
764+
*/
765+
for (i = 0; i < 10; i++) {
766+
/* VF reset requires driver to first reset the VF and then
767+
* poll the status register to make sure that the reset
768+
* completed successfully.
769+
*/
770+
usleep_range(10000, 20000);
771+
reg = rd32(hw, VPGEN_VFRSTAT(vf->vf_id));
772+
if (reg & VPGEN_VFRSTAT_VFRD_M) {
773+
rsd = true;
774+
break;
775+
}
776+
}
777+
778+
/* Display a warning if VF didn't manage to reset in time, but need to
779+
* continue on with the operation.
780+
*/
781+
if (!rsd)
782+
dev_warn(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
783+
vf->vf_id);
784+
785+
usleep_range(10000, 20000);
786+
787+
/* free VF resources to begin resetting the VSI state */
788+
ice_free_vf_res(vf);
789+
790+
ice_cleanup_and_realloc_vf(vf);
791+
792+
ice_flush(hw);
793+
clear_bit(__ICE_VF_DIS, pf->state);
794+
795+
return true;
796+
}
797+
798+
/**
799+
* ice_vc_notify_reset - Send pending reset message to all VFs
800+
* @pf: pointer to the PF structure
801+
*
802+
* indicate a pending reset to all VFs on a given PF
803+
*/
804+
void ice_vc_notify_reset(struct ice_pf *pf)
805+
{
806+
struct virtchnl_pf_event pfe;
807+
808+
if (!pf->num_alloc_vfs)
809+
return;
810+
811+
pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
812+
pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
813+
ice_vc_vf_broadcast(pf, VIRTCHNL_OP_EVENT, ICE_SUCCESS,
814+
(u8 *)&pfe, sizeof(struct virtchnl_pf_event));
815+
}
816+
696817
/**
697818
* ice_alloc_vfs - Allocate and set up VFs resources
698819
* @pf: pointer to the PF structure
@@ -845,3 +966,45 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
845966

846967
return 0;
847968
}
969+
970+
/**
971+
* ice_process_vflr_event - Free VF resources via IRQ calls
972+
* @pf: pointer to the PF structure
973+
*
974+
* called from the VLFR IRQ handler to
975+
* free up VF resources and state variables
976+
*/
977+
void ice_process_vflr_event(struct ice_pf *pf)
978+
{
979+
struct ice_hw *hw = &pf->hw;
980+
int vf_id;
981+
u32 reg;
982+
983+
if (!test_bit(__ICE_VFLR_EVENT_PENDING, pf->state) ||
984+
!pf->num_alloc_vfs)
985+
return;
986+
987+
/* Re-enable the VFLR interrupt cause here, before looking for which
988+
* VF got reset. Otherwise, if another VF gets a reset while the
989+
* first one is being processed, that interrupt will be lost, and
990+
* that VF will be stuck in reset forever.
991+
*/
992+
reg = rd32(hw, PFINT_OICR_ENA);
993+
reg |= PFINT_OICR_VFLR_M;
994+
wr32(hw, PFINT_OICR_ENA, reg);
995+
ice_flush(hw);
996+
997+
clear_bit(__ICE_VFLR_EVENT_PENDING, pf->state);
998+
for (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) {
999+
struct ice_vf *vf = &pf->vf[vf_id];
1000+
u32 reg_idx, bit_idx;
1001+
1002+
reg_idx = (hw->func_caps.vf_base_id + vf_id) / 32;
1003+
bit_idx = (hw->func_caps.vf_base_id + vf_id) % 32;
1004+
/* read GLGEN_VFLRSTAT register to find out the flr VFs */
1005+
reg = rd32(hw, GLGEN_VFLRSTAT(reg_idx));
1006+
if (reg & BIT(bit_idx))
1007+
/* GLGEN_VFLRSTAT bit will be cleared in ice_reset_vf */
1008+
ice_reset_vf(vf, true);
1009+
}
1010+
}

drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ struct ice_vf {
5151
};
5252

5353
#ifdef CONFIG_PCI_IOV
54+
void ice_process_vflr_event(struct ice_pf *pf);
5455
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
5556
void ice_free_vfs(struct ice_pf *pf);
57+
void ice_vc_notify_reset(struct ice_pf *pf);
5658
bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr);
5759
#else /* CONFIG_PCI_IOV */
60+
#define ice_process_vflr_event(pf) do {} while (0)
5861
#define ice_free_vfs(pf) do {} while (0)
62+
#define ice_vc_notify_reset(pf) do {} while (0)
5963

6064
static inline bool
6165
ice_reset_all_vfs(struct ice_pf __always_unused *pf,

0 commit comments

Comments
 (0)