diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 7dc7810b7482..c422220db0ae 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -151,18 +151,22 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | struct lpfc_scsi_buf* | 153 | struct lpfc_scsi_buf* |
154 | lpfc_sli_get_scsi_buf(struct lpfc_hba * phba) | 154 | lpfc_get_scsi_buf(struct lpfc_hba * phba) |
155 | { | 155 | { |
156 | struct lpfc_scsi_buf * lpfc_cmd = NULL; | 156 | struct lpfc_scsi_buf * lpfc_cmd = NULL; |
157 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | 157 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; |
158 | unsigned long iflag = 0; | ||
158 | 159 | ||
160 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | ||
159 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 161 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); |
162 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | ||
160 | return lpfc_cmd; | 163 | return lpfc_cmd; |
161 | } | 164 | } |
162 | 165 | ||
163 | static void | 166 | static void |
164 | lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | 167 | lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) |
165 | { | 168 | { |
169 | unsigned long iflag = 0; | ||
166 | /* | 170 | /* |
167 | * There are only two special cases to consider. (1) the scsi command | 171 | * There are only two special cases to consider. (1) the scsi command |
168 | * requested scatter-gather usage or (2) the scsi command allocated | 172 | * requested scatter-gather usage or (2) the scsi command allocated |
@@ -180,8 +184,10 @@ lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | |||
180 | } | 184 | } |
181 | } | 185 | } |
182 | 186 | ||
187 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | ||
183 | psb->pCmd = NULL; | 188 | psb->pCmd = NULL; |
184 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); | 189 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); |
190 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | ||
185 | } | 191 | } |
186 | 192 | ||
187 | static int | 193 | static int |
@@ -403,7 +409,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
403 | struct lpfc_rport_data *rdata = lpfc_cmd->rdata; | 409 | struct lpfc_rport_data *rdata = lpfc_cmd->rdata; |
404 | struct lpfc_nodelist *pnode = rdata->pnode; | 410 | struct lpfc_nodelist *pnode = rdata->pnode; |
405 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; | 411 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; |
406 | unsigned long iflag; | ||
407 | 412 | ||
408 | lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; | 413 | lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; |
409 | lpfc_cmd->status = pIocbOut->iocb.ulpStatus; | 414 | lpfc_cmd->status = pIocbOut->iocb.ulpStatus; |
@@ -457,9 +462,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
457 | 462 | ||
458 | cmd->scsi_done(cmd); | 463 | cmd->scsi_done(cmd); |
459 | 464 | ||
460 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
461 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 465 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
462 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
463 | } | 466 | } |
464 | 467 | ||
465 | static void | 468 | static void |
@@ -707,6 +710,37 @@ lpfc_info(struct Scsi_Host *host) | |||
707 | return lpfcinfobuf; | 710 | return lpfcinfobuf; |
708 | } | 711 | } |
709 | 712 | ||
713 | static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba) | ||
714 | { | ||
715 | unsigned long poll_tmo_expires = | ||
716 | (jiffies + msecs_to_jiffies(phba->cfg_poll_tmo)); | ||
717 | |||
718 | if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt) | ||
719 | mod_timer(&phba->fcp_poll_timer, | ||
720 | poll_tmo_expires); | ||
721 | } | ||
722 | |||
723 | void lpfc_poll_start_timer(struct lpfc_hba * phba) | ||
724 | { | ||
725 | lpfc_poll_rearm_timer(phba); | ||
726 | } | ||
727 | |||
728 | void lpfc_poll_timeout(unsigned long ptr) | ||
729 | { | ||
730 | struct lpfc_hba *phba = (struct lpfc_hba *)ptr; | ||
731 | unsigned long iflag; | ||
732 | |||
733 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
734 | |||
735 | if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { | ||
736 | lpfc_sli_poll_fcp_ring (phba); | ||
737 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) | ||
738 | lpfc_poll_rearm_timer(phba); | ||
739 | } | ||
740 | |||
741 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
742 | } | ||
743 | |||
710 | static int | 744 | static int |
711 | lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | 745 | lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) |
712 | { | 746 | { |
@@ -733,7 +767,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
733 | cmnd->result = ScsiResult(DID_BUS_BUSY, 0); | 767 | cmnd->result = ScsiResult(DID_BUS_BUSY, 0); |
734 | goto out_fail_command; | 768 | goto out_fail_command; |
735 | } | 769 | } |
736 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); | 770 | lpfc_cmd = lpfc_get_scsi_buf (phba); |
737 | if (lpfc_cmd == NULL) { | 771 | if (lpfc_cmd == NULL) { |
738 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | 772 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, |
739 | "%d:0707 driver's buffer pool is empty, " | 773 | "%d:0707 driver's buffer pool is empty, " |
@@ -761,11 +795,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
761 | &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); | 795 | &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); |
762 | if (err) | 796 | if (err) |
763 | goto out_host_busy_free_buf; | 797 | goto out_host_busy_free_buf; |
798 | |||
799 | if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { | ||
800 | lpfc_sli_poll_fcp_ring(phba); | ||
801 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) | ||
802 | lpfc_poll_rearm_timer(phba); | ||
803 | } | ||
804 | |||
764 | return 0; | 805 | return 0; |
765 | 806 | ||
766 | out_host_busy_free_buf: | 807 | out_host_busy_free_buf: |
767 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 808 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
768 | cmnd->host_scribble = NULL; | ||
769 | out_host_busy: | 809 | out_host_busy: |
770 | return SCSI_MLQUEUE_HOST_BUSY; | 810 | return SCSI_MLQUEUE_HOST_BUSY; |
771 | 811 | ||
@@ -839,9 +879,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
839 | goto out; | 879 | goto out; |
840 | } | 880 | } |
841 | 881 | ||
882 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) | ||
883 | lpfc_sli_poll_fcp_ring (phba); | ||
884 | |||
842 | /* Wait for abort to complete */ | 885 | /* Wait for abort to complete */ |
843 | while (lpfc_cmd->pCmd == cmnd) | 886 | while (lpfc_cmd->pCmd == cmnd) |
844 | { | 887 | { |
888 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) | ||
889 | lpfc_sli_poll_fcp_ring (phba); | ||
890 | |||
845 | spin_unlock_irq(phba->host->host_lock); | 891 | spin_unlock_irq(phba->host->host_lock); |
846 | schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ); | 892 | schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ); |
847 | spin_lock_irq(phba->host->host_lock); | 893 | spin_lock_irq(phba->host->host_lock); |
@@ -905,7 +951,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
905 | break; | 951 | break; |
906 | } | 952 | } |
907 | 953 | ||
908 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); | 954 | lpfc_cmd = lpfc_get_scsi_buf (phba); |
909 | if (lpfc_cmd == NULL) | 955 | if (lpfc_cmd == NULL) |
910 | goto out; | 956 | goto out; |
911 | 957 | ||
@@ -1001,7 +1047,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1001 | lpfc_block_requests(phba); | 1047 | lpfc_block_requests(phba); |
1002 | spin_lock_irq(shost->host_lock); | 1048 | spin_lock_irq(shost->host_lock); |
1003 | 1049 | ||
1004 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); | 1050 | lpfc_cmd = lpfc_get_scsi_buf(phba); |
1005 | if (lpfc_cmd == NULL) | 1051 | if (lpfc_cmd == NULL) |
1006 | goto out; | 1052 | goto out; |
1007 | 1053 | ||
@@ -1136,10 +1182,10 @@ lpfc_slave_alloc(struct scsi_device *sdev) | |||
1136 | break; | 1182 | break; |
1137 | } | 1183 | } |
1138 | 1184 | ||
1139 | spin_lock_irqsave(phba->host->host_lock, flags); | 1185 | spin_lock_irqsave(&phba->scsi_buf_list_lock, flags); |
1140 | phba->total_scsi_bufs++; | 1186 | phba->total_scsi_bufs++; |
1141 | list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list); | 1187 | list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list); |
1142 | spin_unlock_irqrestore(phba->host->host_lock, flags); | 1188 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, flags); |
1143 | } | 1189 | } |
1144 | return 0; | 1190 | return 0; |
1145 | } | 1191 | } |
@@ -1163,6 +1209,12 @@ lpfc_slave_configure(struct scsi_device *sdev) | |||
1163 | */ | 1209 | */ |
1164 | rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5; | 1210 | rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5; |
1165 | 1211 | ||
1212 | if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { | ||
1213 | lpfc_sli_poll_fcp_ring(phba); | ||
1214 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) | ||
1215 | lpfc_poll_rearm_timer(phba); | ||
1216 | } | ||
1217 | |||
1166 | return 0; | 1218 | return 0; |
1167 | } | 1219 | } |
1168 | 1220 | ||