Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: Handle LAN overflow event for VF queues

Currently we are not handling LAN overflow events. There can be cases
where LAN overflow events occur on VF queues, especially with Link Flow
Control (LFC) enabled on the controlling PF. In order to recover from
the LAN overflow event caused by a VF we need to determine if the queue
belongs to a VF and reset that VF accordingly.

The struct ice_aqc_event_lan_overflow returns a copy of the GLDCB_RTCTQ
register, which tells us what the queue index is in the global/device
space. The global queue index needs to first be converted to a PF space
queue index and then it can be used to find if a VF owns it.

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Brett Creeley and committed by
Jeff Kirsher
2309ae38 39066dc5

+86
+11
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 1661 1661 struct ice_aqc_get_pkg_info pkg_info[1]; 1662 1662 }; 1663 1663 1664 + /* Lan Queue Overflow Event (direct, 0x1001) */ 1665 + struct ice_aqc_event_lan_overflow { 1666 + __le32 prtdcb_ruptq; 1667 + __le32 qtx_ctl; 1668 + u8 reserved[8]; 1669 + }; 1670 + 1664 1671 /** 1665 1672 * struct ice_aq_desc - Admin Queue (AQ) descriptor 1666 1673 * @flags: ICE_AQ_FLAG_* flags ··· 1737 1730 struct ice_aqc_alloc_free_res_cmd sw_res_ctrl; 1738 1731 struct ice_aqc_set_event_mask set_event_mask; 1739 1732 struct ice_aqc_get_link_status get_link_status; 1733 + struct ice_aqc_event_lan_overflow lan_overflow; 1740 1734 } params; 1741 1735 }; 1742 1736 ··· 1867 1859 ice_aqc_opc_download_pkg = 0x0C40, 1868 1860 ice_aqc_opc_update_pkg = 0x0C42, 1869 1861 ice_aqc_opc_get_pkg_info_list = 0x0C43, 1862 + 1863 + /* Standalone Commands/Events */ 1864 + ice_aqc_opc_event_lan_overflow = 0x1001, 1870 1865 1871 1866 /* debug commands */ 1872 1867 ice_aqc_opc_fw_logging = 0xFF09,
+2
drivers/net/ethernet/intel/ice/ice_hw_autogen.h
··· 286 286 #define GL_PWR_MODE_CTL 0x000B820C 287 287 #define GL_PWR_MODE_CTL_CAR_MAX_BW_S 30 288 288 #define GL_PWR_MODE_CTL_CAR_MAX_BW_M ICE_M(0x3, 30) 289 + #define GLDCB_RTCTQ_RXQNUM_S 0 290 + #define GLDCB_RTCTQ_RXQNUM_M ICE_M(0x7FF, 0) 289 291 #define GLPRT_BPRCL(_i) (0x00381380 + ((_i) * 8)) 290 292 #define GLPRT_BPTCL(_i) (0x00381240 + ((_i) * 8)) 291 293 #define GLPRT_CRCERRS(_i) (0x00380100 + ((_i) * 8))
+3
drivers/net/ethernet/intel/ice/ice_main.c
··· 1029 1029 if (ice_handle_link_event(pf, &event)) 1030 1030 dev_err(dev, "Could not handle link event\n"); 1031 1031 break; 1032 + case ice_aqc_opc_event_lan_overflow: 1033 + ice_vf_lan_overflow_event(pf, &event); 1034 + break; 1032 1035 case ice_mbx_opc_send_msg_to_pf: 1033 1036 ice_vc_process_vf_msg(pf, &event); 1034 1037 break;
+66
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
··· 1514 1514 } 1515 1515 1516 1516 /** 1517 + * ice_get_vf_from_pfq - get the VF who owns the PF space queue passed in 1518 + * @pf: PF used to index all VFs 1519 + * @pfq: queue index relative to the PF's function space 1520 + * 1521 + * If no VF is found who owns the pfq then return NULL, otherwise return a 1522 + * pointer to the VF who owns the pfq 1523 + */ 1524 + static struct ice_vf *ice_get_vf_from_pfq(struct ice_pf *pf, u16 pfq) 1525 + { 1526 + int vf_id; 1527 + 1528 + ice_for_each_vf(pf, vf_id) { 1529 + struct ice_vf *vf = &pf->vf[vf_id]; 1530 + struct ice_vsi *vsi; 1531 + u16 rxq_idx; 1532 + 1533 + vsi = pf->vsi[vf->lan_vsi_idx]; 1534 + 1535 + ice_for_each_rxq(vsi, rxq_idx) 1536 + if (vsi->rxq_map[rxq_idx] == pfq) 1537 + return vf; 1538 + } 1539 + 1540 + return NULL; 1541 + } 1542 + 1543 + /** 1544 + * ice_globalq_to_pfq - convert from global queue index to PF space queue index 1545 + * @pf: PF used for conversion 1546 + * @globalq: global queue index used to convert to PF space queue index 1547 + */ 1548 + static u32 ice_globalq_to_pfq(struct ice_pf *pf, u32 globalq) 1549 + { 1550 + return globalq - pf->hw.func_caps.common_cap.rxq_first_id; 1551 + } 1552 + 1553 + /** 1554 + * ice_vf_lan_overflow_event - handle LAN overflow event for a VF 1555 + * @pf: PF that the LAN overflow event happened on 1556 + * @event: structure holding the event information for the LAN overflow event 1557 + * 1558 + * Determine if the LAN overflow event was caused by a VF queue. If it was not 1559 + * caused by a VF, do nothing. If a VF caused this LAN overflow event trigger a 1560 + * reset on the offending VF. 1561 + */ 1562 + void 1563 + ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) 1564 + { 1565 + u32 gldcb_rtctq, queue; 1566 + struct ice_vf *vf; 1567 + 1568 + gldcb_rtctq = le32_to_cpu(event->desc.params.lan_overflow.prtdcb_ruptq); 1569 + dev_dbg(ice_pf_to_dev(pf), "GLDCB_RTCTQ: 0x%08x\n", gldcb_rtctq); 1570 + 1571 + /* event returns device global Rx queue number */ 1572 + queue = (gldcb_rtctq & GLDCB_RTCTQ_RXQNUM_M) >> 1573 + GLDCB_RTCTQ_RXQNUM_S; 1574 + 1575 + vf = ice_get_vf_from_pfq(pf, ice_globalq_to_pfq(pf, queue)); 1576 + if (!vf) 1577 + return; 1578 + 1579 + ice_vc_reset_vf(vf); 1580 + } 1581 + 1582 + /** 1517 1583 * ice_vc_send_msg_to_vf - Send message to VF 1518 1584 * @vf: pointer to the VF info 1519 1585 * @v_opcode: virtual channel opcode
+4
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
··· 122 122 int 123 123 ice_get_vf_stats(struct net_device *netdev, int vf_id, 124 124 struct ifla_vf_stats *vf_stats); 125 + void 126 + ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event); 127 + 125 128 #else /* CONFIG_PCI_IOV */ 126 129 #define ice_process_vflr_event(pf) do {} while (0) 127 130 #define ice_free_vfs(pf) do {} while (0) ··· 132 129 #define ice_vc_notify_link_state(pf) do {} while (0) 133 130 #define ice_vc_notify_reset(pf) do {} while (0) 134 131 #define ice_set_vf_state_qs_dis(vf) do {} while (0) 132 + #define ice_vf_lan_overflow_event(pf, event) do {} while (0) 135 133 136 134 static inline bool 137 135 ice_reset_all_vfs(struct ice_pf __always_unused *pf,