aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMintz, Yuval <Yuval.Mintz@cavium.com>2017-02-27 04:06:32 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-27 09:22:09 -0500
commitfd3c615ae13a853ab26211e14f70b416cc8f8134 (patch)
treecf7f5adebaf75054e3aec992947b64bec1a8ddcc
parent4ca257eed6adf58d325c39c320a06dbcd34c43db (diff)
qed: Fix race with multiple VFs
A PF syncronizes all IOV activity relating to its VFs by using a single workqueue handling the work. The workqueue would reach a bitmask of pending VF events and act upon each in turn. Problem is that the indication of a VF message [which sets the 'vf event' bit for that VF] arrives and is set in the slowpath attention context, which isn't syncronized with the processing of the events. When multiple VFs are present, it's possible that PF would lose the indication of one of the VF's pending evens, leading that VF to later timeout. Instead of adding locks/barriers, simply move from a bitmask into a per-VF indication inside that VF entry in the PF database. Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.c39
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.h4
2 files changed, 26 insertions, 17 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index 29ed785f1dc2..253c2bbe1e4e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -3014,8 +3014,7 @@ cleanup:
3014 ack_vfs[vfid / 32] |= BIT((vfid % 32)); 3014 ack_vfs[vfid / 32] |= BIT((vfid % 32));
3015 p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &= 3015 p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &=
3016 ~(1ULL << (rel_vf_id % 64)); 3016 ~(1ULL << (rel_vf_id % 64));
3017 p_hwfn->pf_iov_info->pending_events[rel_vf_id / 64] &= 3017 p_vf->vf_mbx.b_pending_msg = false;
3018 ~(1ULL << (rel_vf_id % 64));
3019 } 3018 }
3020 3019
3021 return rc; 3020 return rc;
@@ -3128,11 +3127,20 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
3128 mbx = &p_vf->vf_mbx; 3127 mbx = &p_vf->vf_mbx;
3129 3128
3130 /* qed_iov_process_mbx_request */ 3129 /* qed_iov_process_mbx_request */
3131 DP_VERBOSE(p_hwfn, QED_MSG_IOV, 3130 if (!mbx->b_pending_msg) {
3132 "VF[%02x]: Processing mailbox message\n", p_vf->abs_vf_id); 3131 DP_NOTICE(p_hwfn,
3132 "VF[%02x]: Trying to process mailbox message when none is pending\n",
3133 p_vf->abs_vf_id);
3134 return;
3135 }
3136 mbx->b_pending_msg = false;
3133 3137
3134 mbx->first_tlv = mbx->req_virt->first_tlv; 3138 mbx->first_tlv = mbx->req_virt->first_tlv;
3135 3139
3140 DP_VERBOSE(p_hwfn, QED_MSG_IOV,
3141 "VF[%02x]: Processing mailbox message [type %04x]\n",
3142 p_vf->abs_vf_id, mbx->first_tlv.tl.type);
3143
3136 /* check if tlv type is known */ 3144 /* check if tlv type is known */
3137 if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) && 3145 if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) &&
3138 !p_vf->b_malicious) { 3146 !p_vf->b_malicious) {
@@ -3219,20 +3227,19 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
3219 } 3227 }
3220} 3228}
3221 3229
3222static void qed_iov_pf_add_pending_events(struct qed_hwfn *p_hwfn, u8 vfid) 3230void qed_iov_pf_get_pending_events(struct qed_hwfn *p_hwfn, u64 *events)
3223{ 3231{
3224 u64 add_bit = 1ULL << (vfid % 64); 3232 int i;
3225 3233
3226 p_hwfn->pf_iov_info->pending_events[vfid / 64] |= add_bit; 3234 memset(events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH);
3227}
3228 3235
3229static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn, 3236 qed_for_each_vf(p_hwfn, i) {
3230 u64 *events) 3237 struct qed_vf_info *p_vf;
3231{
3232 u64 *p_pending_events = p_hwfn->pf_iov_info->pending_events;
3233 3238
3234 memcpy(events, p_pending_events, sizeof(u64) * QED_VF_ARRAY_LENGTH); 3239 p_vf = &p_hwfn->pf_iov_info->vfs_array[i];
3235 memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH); 3240 if (p_vf->vf_mbx.b_pending_msg)
3241 events[i / 64] |= 1ULL << (i % 64);
3242 }
3236} 3243}
3237 3244
3238static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn, 3245static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn,
@@ -3266,7 +3273,7 @@ static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
3266 p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo; 3273 p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo;
3267 3274
3268 /* Mark the event and schedule the workqueue */ 3275 /* Mark the event and schedule the workqueue */
3269 qed_iov_pf_add_pending_events(p_hwfn, p_vf->relative_vf_id); 3276 p_vf->vf_mbx.b_pending_msg = true;
3270 qed_schedule_iov(p_hwfn, QED_IOV_WQ_MSG_FLAG); 3277 qed_schedule_iov(p_hwfn, QED_IOV_WQ_MSG_FLAG);
3271 3278
3272 return 0; 3279 return 0;
@@ -4030,7 +4037,7 @@ static void qed_handle_vf_msg(struct qed_hwfn *hwfn)
4030 return; 4037 return;
4031 } 4038 }
4032 4039
4033 qed_iov_pf_get_and_clear_pending_events(hwfn, events); 4040 qed_iov_pf_get_pending_events(hwfn, events);
4034 4041
4035 DP_VERBOSE(hwfn, QED_MSG_IOV, 4042 DP_VERBOSE(hwfn, QED_MSG_IOV,
4036 "Event mask of VF events: 0x%llx 0x%llx 0x%llx\n", 4043 "Event mask of VF events: 0x%llx 0x%llx 0x%llx\n",
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
index fc08cc2da6a7..a89605821522 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
@@ -140,6 +140,9 @@ struct qed_iov_vf_mbx {
140 /* Address in VF where a pending message is located */ 140 /* Address in VF where a pending message is located */
141 dma_addr_t pending_req; 141 dma_addr_t pending_req;
142 142
143 /* Message from VF awaits handling */
144 bool b_pending_msg;
145
143 u8 *offset; 146 u8 *offset;
144 147
145 /* saved VF request header */ 148 /* saved VF request header */
@@ -232,7 +235,6 @@ struct qed_vf_info {
232 */ 235 */
233struct qed_pf_iov { 236struct qed_pf_iov {
234 struct qed_vf_info vfs_array[MAX_NUM_VFS]; 237 struct qed_vf_info vfs_array[MAX_NUM_VFS];
235 u64 pending_events[QED_VF_ARRAY_LENGTH];
236 u64 pending_flr[QED_VF_ARRAY_LENGTH]; 238 u64 pending_flr[QED_VF_ARRAY_LENGTH];
237 239
238 /* Allocate message address continuosuly and split to each VF */ 240 /* Allocate message address continuosuly and split to each VF */