diff options
author | Bart Van Assche <bvanassche@acm.org> | 2013-08-14 11:38:24 -0400 |
---|---|---|
committer | Robert Love <robert.w.love@intel.com> | 2013-09-04 16:37:53 -0400 |
commit | f95b35cfcacadac16dbc5477fd22b0786256a3d1 (patch) | |
tree | 18441baa204e00aa8327c71408a2a3bd9df96d46 /drivers/scsi | |
parent | cae7b6dd6c569f18f5c8e3f33cac60fbaeb58140 (diff) |
libfc: Reduce exchange lock contention in fc_exch_recv_abts()
Reduce the time during which the exchange lock is held by allocating
a frame before obtaining the exchange lock.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 2a7fd5afecca..47ebc7b1e143 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -1307,9 +1307,16 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) | |||
1307 | 1307 | ||
1308 | if (!ep) | 1308 | if (!ep) |
1309 | goto reject; | 1309 | goto reject; |
1310 | |||
1311 | fp = fc_frame_alloc(ep->lp, sizeof(*ap)); | ||
1312 | if (!fp) | ||
1313 | goto free; | ||
1314 | |||
1310 | spin_lock_bh(&ep->ex_lock); | 1315 | spin_lock_bh(&ep->ex_lock); |
1311 | if (ep->esb_stat & ESB_ST_COMPLETE) { | 1316 | if (ep->esb_stat & ESB_ST_COMPLETE) { |
1312 | spin_unlock_bh(&ep->ex_lock); | 1317 | spin_unlock_bh(&ep->ex_lock); |
1318 | |||
1319 | fc_frame_free(fp); | ||
1313 | goto reject; | 1320 | goto reject; |
1314 | } | 1321 | } |
1315 | if (!(ep->esb_stat & ESB_ST_REC_QUAL)) { | 1322 | if (!(ep->esb_stat & ESB_ST_REC_QUAL)) { |
@@ -1317,12 +1324,6 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) | |||
1317 | fc_exch_hold(ep); /* hold for REC_QUAL */ | 1324 | fc_exch_hold(ep); /* hold for REC_QUAL */ |
1318 | } | 1325 | } |
1319 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | 1326 | fc_exch_timer_set_locked(ep, ep->r_a_tov); |
1320 | |||
1321 | fp = fc_frame_alloc(ep->lp, sizeof(*ap)); | ||
1322 | if (!fp) { | ||
1323 | spin_unlock_bh(&ep->ex_lock); | ||
1324 | goto free; | ||
1325 | } | ||
1326 | fh = fc_frame_header_get(fp); | 1327 | fh = fc_frame_header_get(fp); |
1327 | ap = fc_frame_payload_get(fp, sizeof(*ap)); | 1328 | ap = fc_frame_payload_get(fp, sizeof(*ap)); |
1328 | memset(ap, 0, sizeof(*ap)); | 1329 | memset(ap, 0, sizeof(*ap)); |
@@ -1338,13 +1339,14 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) | |||
1338 | fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); | 1339 | fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); |
1339 | ep->esb_stat |= ESB_ST_ABNORMAL; | 1340 | ep->esb_stat |= ESB_ST_ABNORMAL; |
1340 | spin_unlock_bh(&ep->ex_lock); | 1341 | spin_unlock_bh(&ep->ex_lock); |
1342 | |||
1343 | free: | ||
1341 | fc_frame_free(rx_fp); | 1344 | fc_frame_free(rx_fp); |
1342 | return; | 1345 | return; |
1343 | 1346 | ||
1344 | reject: | 1347 | reject: |
1345 | fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID); | 1348 | fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID); |
1346 | free: | 1349 | goto free; |
1347 | fc_frame_free(rx_fp); | ||
1348 | } | 1350 | } |
1349 | 1351 | ||
1350 | /** | 1352 | /** |