ice: Handle LAN overflow event for VF queues
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / ice / ice_virtchnl_pf.c
index 3666647..53a9e09 100644 (file)
@@ -1513,6 +1513,72 @@ static void ice_vc_reset_vf(struct ice_vf *vf)
        ice_reset_vf(vf, false);
 }
 
+/**
+ * ice_get_vf_from_pfq - get the VF who owns the PF space queue passed in
+ * @pf: PF used to index all VFs
+ * @pfq: queue index relative to the PF's function space
+ *
+ * If no VF is found who owns the pfq then return NULL, otherwise return a
+ * pointer to the VF who owns the pfq
+ */
+static struct ice_vf *ice_get_vf_from_pfq(struct ice_pf *pf, u16 pfq)
+{
+       int vf_id;
+
+       ice_for_each_vf(pf, vf_id) {
+               struct ice_vf *vf = &pf->vf[vf_id];
+               struct ice_vsi *vsi;
+               u16 rxq_idx;
+
+               vsi = pf->vsi[vf->lan_vsi_idx];
+
+               ice_for_each_rxq(vsi, rxq_idx)
+                       if (vsi->rxq_map[rxq_idx] == pfq)
+                               return vf;
+       }
+
+       return NULL;
+}
+
+/**
+ * ice_globalq_to_pfq - convert from global queue index to PF space queue index
+ * @pf: PF used for conversion
+ * @globalq: global queue index used to convert to PF space queue index
+ */
+static u32 ice_globalq_to_pfq(struct ice_pf *pf, u32 globalq)
+{
+       return globalq - pf->hw.func_caps.common_cap.rxq_first_id;
+}
+
+/**
+ * ice_vf_lan_overflow_event - handle LAN overflow event for a VF
+ * @pf: PF that the LAN overflow event happened on
+ * @event: structure holding the event information for the LAN overflow event
+ *
+ * Determine if the LAN overflow event was caused by a VF queue. If it was not
+ * caused by a VF, do nothing. If a VF caused this LAN overflow event trigger a
+ * reset on the offending VF.
+ */
+void
+ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event)
+{
+       u32 gldcb_rtctq, queue;
+       struct ice_vf *vf;
+
+       gldcb_rtctq = le32_to_cpu(event->desc.params.lan_overflow.prtdcb_ruptq);
+       dev_dbg(ice_pf_to_dev(pf), "GLDCB_RTCTQ: 0x%08x\n", gldcb_rtctq);
+
+       /* event returns device global Rx queue number */
+       queue = (gldcb_rtctq & GLDCB_RTCTQ_RXQNUM_M) >>
+               GLDCB_RTCTQ_RXQNUM_S;
+
+       vf = ice_get_vf_from_pfq(pf, ice_globalq_to_pfq(pf, queue));
+       if (!vf)
+               return;
+
+       ice_vc_reset_vf(vf);
+}
+
 /**
  * ice_vc_send_msg_to_vf - Send message to VF
  * @vf: pointer to the VF info