diff options
author | Vasu Dev <vasu.dev@intel.com> | 2009-11-03 14:48:00 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:09 -0500 |
commit | c46be11a683acc1ccf86883ea906f171b90ff29a (patch) | |
tree | 5c9766a2e6f1403acd3b8ceec281ef6803df418c /drivers/scsi/libfc | |
parent | a7bbc7f40aa01eefef3d367349e1e6e87881a305 (diff) |
[SCSI] libfc: reduce can_queue for all FCP frame allocation failures
Currently can_queue is reduced only if frame alloc fails
during fc_fcp_send_data but frame alloc can fail at several
other places in FCP data path and can_queue needs to be
reduced for any FCP frame alloc failure.
This patch adds fc_fcp_frame_alloc for all FCP frame allocations
and if fc_frame_alloc fails in fc_fcp_frame_alloc then reduce
can_queue in fc_fcp_frame_alloc, this will reduce can_queue for
all FCP frame alloc failures.
This required moving fc_fcp_reduce_can_queue up, to build without
adding its prototype. Also renamed fc_fcp_reduce_can_queue to
fc_fcp_can_queue_ramp_down.
Removes fc_fcp_reduce_can_queue calling from fc_fcp_recv since
not needed with added fc_fcp_frame_alloc reducing can_queue.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 102 |
1 files changed, 59 insertions, 43 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 567eee7b8609..ac5c148d0182 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -327,6 +327,57 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) | |||
327 | } | 327 | } |
328 | 328 | ||
329 | /** | 329 | /** |
330 | * fc_fcp_can_queue_ramp_down() - reduces can_queue | ||
331 | * @lport: lport to reduce can_queue | ||
332 | * | ||
333 | * If we are getting memory allocation failures, then we may | ||
334 | * be trying to execute too many commands. We let the running | ||
335 | * commands complete or timeout, then try again with a reduced | ||
336 | * can_queue. Eventually we will hit the point where we run | ||
337 | * on all reserved structs. | ||
338 | */ | ||
339 | static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport) | ||
340 | { | ||
341 | struct fc_fcp_internal *si = fc_get_scsi_internal(lport); | ||
342 | unsigned long flags; | ||
343 | int can_queue; | ||
344 | |||
345 | spin_lock_irqsave(lport->host->host_lock, flags); | ||
346 | if (si->throttled) | ||
347 | goto done; | ||
348 | si->throttled = 1; | ||
349 | |||
350 | can_queue = lport->host->can_queue; | ||
351 | can_queue >>= 1; | ||
352 | if (!can_queue) | ||
353 | can_queue = 1; | ||
354 | lport->host->can_queue = can_queue; | ||
355 | shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n" | ||
356 | "Reducing can_queue to %d.\n", can_queue); | ||
357 | done: | ||
358 | spin_unlock_irqrestore(lport->host->host_lock, flags); | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * fc_fcp_frame_alloc() - Allocates fc_frame structure and buffer. | ||
363 | * @lport: fc lport struct | ||
364 | * @len: payload length | ||
365 | * | ||
366 | * Allocates fc_frame structure and buffer but if fails to allocate | ||
367 | * then reduce can_queue. | ||
368 | */ | ||
369 | static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport, | ||
370 | size_t len) | ||
371 | { | ||
372 | struct fc_frame *fp; | ||
373 | |||
374 | fp = fc_frame_alloc(lport, len); | ||
375 | if (!fp) | ||
376 | fc_fcp_can_queue_ramp_down(lport); | ||
377 | return fp; | ||
378 | } | ||
379 | |||
380 | /** | ||
330 | * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target | 381 | * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target |
331 | * @fsp: The FCP packet the data is on | 382 | * @fsp: The FCP packet the data is on |
332 | * @fp: The data frame | 383 | * @fp: The data frame |
@@ -616,38 +667,6 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
616 | } | 667 | } |
617 | 668 | ||
618 | /** | 669 | /** |
619 | * fc_fcp_reduce_can_queue() - Reduce the can_queue value for a local port | ||
620 | * @lport: The local port to reduce can_queue on | ||
621 | * | ||
622 | * If we are getting memory allocation failures, then we may | ||
623 | * be trying to execute too many commands. We let the running | ||
624 | * commands complete or timeout, then try again with a reduced | ||
625 | * can_queue. Eventually we will hit the point where we run | ||
626 | * on all reserved structs. | ||
627 | */ | ||
628 | static void fc_fcp_reduce_can_queue(struct fc_lport *lport) | ||
629 | { | ||
630 | struct fc_fcp_internal *si = fc_get_scsi_internal(lport); | ||
631 | unsigned long flags; | ||
632 | int can_queue; | ||
633 | |||
634 | spin_lock_irqsave(lport->host->host_lock, flags); | ||
635 | if (si->throttled) | ||
636 | goto done; | ||
637 | si->throttled = 1; | ||
638 | |||
639 | can_queue = lport->host->can_queue; | ||
640 | can_queue >>= 1; | ||
641 | if (!can_queue) | ||
642 | can_queue = 1; | ||
643 | lport->host->can_queue = can_queue; | ||
644 | shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n" | ||
645 | "Reducing can_queue to %d.\n", can_queue); | ||
646 | done: | ||
647 | spin_unlock_irqrestore(lport->host->host_lock, flags); | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * fc_fcp_recv() - Reveive an FCP frame | 670 | * fc_fcp_recv() - Reveive an FCP frame |
652 | * @seq: The sequence the frame is on | 671 | * @seq: The sequence the frame is on |
653 | * @fp: The received frame | 672 | * @fp: The received frame |
@@ -665,8 +684,10 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
665 | u8 r_ctl; | 684 | u8 r_ctl; |
666 | int rc = 0; | 685 | int rc = 0; |
667 | 686 | ||
668 | if (IS_ERR(fp)) | 687 | if (IS_ERR(fp)) { |
669 | goto errout; | 688 | fc_fcp_error(fsp, fp); |
689 | return; | ||
690 | } | ||
670 | 691 | ||
671 | fh = fc_frame_header_get(fp); | 692 | fh = fc_frame_header_get(fp); |
672 | r_ctl = fh->fh_r_ctl; | 693 | r_ctl = fh->fh_r_ctl; |
@@ -720,11 +741,6 @@ unlock: | |||
720 | fc_fcp_unlock_pkt(fsp); | 741 | fc_fcp_unlock_pkt(fsp); |
721 | out: | 742 | out: |
722 | fc_frame_free(fp); | 743 | fc_frame_free(fp); |
723 | errout: | ||
724 | if (IS_ERR(fp)) | ||
725 | fc_fcp_error(fsp, fp); | ||
726 | else if (rc == -ENOMEM) | ||
727 | fc_fcp_reduce_can_queue(lport); | ||
728 | } | 744 | } |
729 | 745 | ||
730 | /** | 746 | /** |
@@ -886,7 +902,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) | |||
886 | struct fc_seq *csp; | 902 | struct fc_seq *csp; |
887 | 903 | ||
888 | csp = lport->tt.seq_start_next(seq); | 904 | csp = lport->tt.seq_start_next(seq); |
889 | conf_frame = fc_frame_alloc(fsp->lp, 0); | 905 | conf_frame = fc_fcp_frame_alloc(fsp->lp, 0); |
890 | if (conf_frame) { | 906 | if (conf_frame) { |
891 | f_ctl = FC_FC_SEQ_INIT; | 907 | f_ctl = FC_FC_SEQ_INIT; |
892 | f_ctl |= FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 908 | f_ctl |= FC_FC_LAST_SEQ | FC_FC_END_SEQ; |
@@ -1026,7 +1042,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, | |||
1026 | if (fc_fcp_lock_pkt(fsp)) | 1042 | if (fc_fcp_lock_pkt(fsp)) |
1027 | return 0; | 1043 | return 0; |
1028 | 1044 | ||
1029 | fp = fc_frame_alloc(lport, sizeof(fsp->cdb_cmd)); | 1045 | fp = fc_fcp_frame_alloc(lport, sizeof(fsp->cdb_cmd)); |
1030 | if (!fp) { | 1046 | if (!fp) { |
1031 | rc = -1; | 1047 | rc = -1; |
1032 | goto unlock; | 1048 | goto unlock; |
@@ -1306,7 +1322,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1306 | fc_fcp_complete_locked(fsp); | 1322 | fc_fcp_complete_locked(fsp); |
1307 | return; | 1323 | return; |
1308 | } | 1324 | } |
1309 | fp = fc_frame_alloc(lport, sizeof(struct fc_els_rec)); | 1325 | fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec)); |
1310 | if (!fp) | 1326 | if (!fp) |
1311 | goto retry; | 1327 | goto retry; |
1312 | 1328 | ||
@@ -1557,7 +1573,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
1557 | if (!(rpriv->flags & FC_RP_FLAGS_RETRY) || | 1573 | if (!(rpriv->flags & FC_RP_FLAGS_RETRY) || |
1558 | rpriv->rp_state != RPORT_ST_READY) | 1574 | rpriv->rp_state != RPORT_ST_READY) |
1559 | goto retry; /* shouldn't happen */ | 1575 | goto retry; /* shouldn't happen */ |
1560 | fp = fc_frame_alloc(lport, sizeof(*srr)); | 1576 | fp = fc_fcp_frame_alloc(lport, sizeof(*srr)); |
1561 | if (!fp) | 1577 | if (!fp) |
1562 | goto retry; | 1578 | goto retry; |
1563 | 1579 | ||