diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 206 |
1 files changed, 83 insertions, 123 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 79c752eef991..a8de6a3de499 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -304,7 +304,6 @@ static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t, | |||
304 | struct req_que **, struct rsp_que **); | 304 | struct req_que **, struct rsp_que **); |
305 | static void qla2x00_free_fw_dump(struct qla_hw_data *); | 305 | static void qla2x00_free_fw_dump(struct qla_hw_data *); |
306 | static void qla2x00_mem_free(struct qla_hw_data *); | 306 | static void qla2x00_mem_free(struct qla_hw_data *); |
307 | static void qla2x00_sp_free_dma(srb_t *); | ||
308 | 307 | ||
309 | /* -------------------------------------------------------------------------- */ | 308 | /* -------------------------------------------------------------------------- */ |
310 | static int qla2x00_alloc_queues(struct qla_hw_data *ha) | 309 | static int qla2x00_alloc_queues(struct qla_hw_data *ha) |
@@ -559,28 +558,75 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str) | |||
559 | return str; | 558 | return str; |
560 | } | 559 | } |
561 | 560 | ||
562 | static inline srb_t * | 561 | void |
563 | qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport, | 562 | qla2x00_sp_free_dma(void *vha, void *ptr) |
564 | struct scsi_cmnd *cmd) | ||
565 | { | 563 | { |
566 | srb_t *sp; | 564 | srb_t *sp = (srb_t *)ptr; |
567 | struct qla_hw_data *ha = vha->hw; | 565 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); |
566 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
567 | void *ctx = GET_CMD_CTX_SP(sp); | ||
568 | 568 | ||
569 | sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC); | 569 | if (sp->flags & SRB_DMA_VALID) { |
570 | if (!sp) { | 570 | scsi_dma_unmap(cmd); |
571 | ql_log(ql_log_warn, vha, 0x3006, | 571 | sp->flags &= ~SRB_DMA_VALID; |
572 | "Memory allocation failed for sp.\n"); | ||
573 | return sp; | ||
574 | } | 572 | } |
575 | 573 | ||
576 | atomic_set(&sp->ref_count, 1); | 574 | if (sp->flags & SRB_CRC_PROT_DMA_VALID) { |
577 | sp->fcport = fcport; | 575 | dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), |
578 | sp->cmd = cmd; | 576 | scsi_prot_sg_count(cmd), cmd->sc_data_direction); |
579 | sp->flags = 0; | 577 | sp->flags &= ~SRB_CRC_PROT_DMA_VALID; |
580 | CMD_SP(cmd) = (void *)sp; | 578 | } |
581 | sp->ctx = NULL; | 579 | |
580 | if (sp->flags & SRB_CRC_CTX_DSD_VALID) { | ||
581 | /* List assured to be having elements */ | ||
582 | qla2x00_clean_dsd_pool(ha, sp); | ||
583 | sp->flags &= ~SRB_CRC_CTX_DSD_VALID; | ||
584 | } | ||
585 | |||
586 | if (sp->flags & SRB_CRC_CTX_DMA_VALID) { | ||
587 | dma_pool_free(ha->dl_dma_pool, ctx, | ||
588 | ((struct crc_context *)ctx)->crc_ctx_dma); | ||
589 | sp->flags &= ~SRB_CRC_CTX_DMA_VALID; | ||
590 | } | ||
591 | |||
592 | if (sp->flags & SRB_FCP_CMND_DMA_VALID) { | ||
593 | struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx; | ||
594 | |||
595 | dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, | ||
596 | ctx1->fcp_cmnd_dma); | ||
597 | list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); | ||
598 | ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; | ||
599 | ha->gbl_dsd_avail += ctx1->dsd_use_cnt; | ||
600 | mempool_free(ctx1, ha->ctx_mempool); | ||
601 | ctx1 = NULL; | ||
602 | } | ||
603 | |||
604 | CMD_SP(cmd) = NULL; | ||
605 | mempool_free(sp, ha->srb_mempool); | ||
606 | } | ||
607 | |||
608 | static void | ||
609 | qla2x00_sp_compl(void *data, void *ptr, int res) | ||
610 | { | ||
611 | struct qla_hw_data *ha = (struct qla_hw_data *)data; | ||
612 | srb_t *sp = (srb_t *)ptr; | ||
613 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); | ||
614 | |||
615 | cmd->result = res; | ||
616 | |||
617 | if (atomic_read(&sp->ref_count) == 0) { | ||
618 | ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015, | ||
619 | "SP reference-count to ZERO -- sp=%p cmd=%p.\n", | ||
620 | sp, GET_CMD_SP(sp)); | ||
621 | if (ql2xextended_error_logging & ql_dbg_io) | ||
622 | BUG(); | ||
623 | return; | ||
624 | } | ||
625 | if (!atomic_dec_and_test(&sp->ref_count)) | ||
626 | return; | ||
582 | 627 | ||
583 | return sp; | 628 | qla2x00_sp_free_dma(ha, sp); |
629 | cmd->scsi_done(cmd); | ||
584 | } | 630 | } |
585 | 631 | ||
586 | static int | 632 | static int |
@@ -644,10 +690,17 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
644 | goto qc24_target_busy; | 690 | goto qc24_target_busy; |
645 | } | 691 | } |
646 | 692 | ||
647 | sp = qla2x00_get_new_sp(base_vha, fcport, cmd); | 693 | sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC); |
648 | if (!sp) | 694 | if (!sp) |
649 | goto qc24_host_busy; | 695 | goto qc24_host_busy; |
650 | 696 | ||
697 | sp->u.scmd.cmd = cmd; | ||
698 | sp->type = SRB_SCSI_CMD; | ||
699 | atomic_set(&sp->ref_count, 1); | ||
700 | CMD_SP(cmd) = (void *)sp; | ||
701 | sp->free = qla2x00_sp_free_dma; | ||
702 | sp->done = qla2x00_sp_compl; | ||
703 | |||
651 | rval = ha->isp_ops->start_scsi(sp); | 704 | rval = ha->isp_ops->start_scsi(sp); |
652 | if (rval != QLA_SUCCESS) { | 705 | if (rval != QLA_SUCCESS) { |
653 | ql_dbg(ql_dbg_io, vha, 0x3013, | 706 | ql_dbg(ql_dbg_io, vha, 0x3013, |
@@ -658,8 +711,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
658 | return 0; | 711 | return 0; |
659 | 712 | ||
660 | qc24_host_busy_free_sp: | 713 | qc24_host_busy_free_sp: |
661 | qla2x00_sp_free_dma(sp); | 714 | qla2x00_sp_free_dma(ha, sp); |
662 | mempool_free(sp, ha->srb_mempool); | ||
663 | 715 | ||
664 | qc24_host_busy: | 716 | qc24_host_busy: |
665 | return SCSI_MLQUEUE_HOST_BUSY; | 717 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -893,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
893 | } | 945 | } |
894 | 946 | ||
895 | spin_lock_irqsave(&ha->hardware_lock, flags); | 947 | spin_lock_irqsave(&ha->hardware_lock, flags); |
896 | qla2x00_sp_compl(ha, sp); | 948 | sp->done(ha, sp, 0); |
897 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 949 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
898 | 950 | ||
899 | /* Did the command return during mailbox execution? */ | 951 | /* Did the command return during mailbox execution? */ |
@@ -925,6 +977,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | |||
925 | struct qla_hw_data *ha = vha->hw; | 977 | struct qla_hw_data *ha = vha->hw; |
926 | struct req_que *req; | 978 | struct req_que *req; |
927 | srb_t *sp; | 979 | srb_t *sp; |
980 | struct scsi_cmnd *cmd; | ||
928 | 981 | ||
929 | status = QLA_SUCCESS; | 982 | status = QLA_SUCCESS; |
930 | 983 | ||
@@ -935,28 +988,29 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | |||
935 | sp = req->outstanding_cmds[cnt]; | 988 | sp = req->outstanding_cmds[cnt]; |
936 | if (!sp) | 989 | if (!sp) |
937 | continue; | 990 | continue; |
938 | if ((sp->ctx) && !IS_PROT_IO(sp)) | 991 | if (sp->type != SRB_SCSI_CMD) |
939 | continue; | 992 | continue; |
940 | if (vha->vp_idx != sp->fcport->vha->vp_idx) | 993 | if (vha->vp_idx != sp->fcport->vha->vp_idx) |
941 | continue; | 994 | continue; |
942 | match = 0; | 995 | match = 0; |
996 | cmd = GET_CMD_SP(sp); | ||
943 | switch (type) { | 997 | switch (type) { |
944 | case WAIT_HOST: | 998 | case WAIT_HOST: |
945 | match = 1; | 999 | match = 1; |
946 | break; | 1000 | break; |
947 | case WAIT_TARGET: | 1001 | case WAIT_TARGET: |
948 | match = sp->cmd->device->id == t; | 1002 | match = cmd->device->id == t; |
949 | break; | 1003 | break; |
950 | case WAIT_LUN: | 1004 | case WAIT_LUN: |
951 | match = (sp->cmd->device->id == t && | 1005 | match = (cmd->device->id == t && |
952 | sp->cmd->device->lun == l); | 1006 | cmd->device->lun == l); |
953 | break; | 1007 | break; |
954 | } | 1008 | } |
955 | if (!match) | 1009 | if (!match) |
956 | continue; | 1010 | continue; |
957 | 1011 | ||
958 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1012 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
959 | status = qla2x00_eh_wait_on_command(sp->cmd); | 1013 | status = qla2x00_eh_wait_on_command(cmd); |
960 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1014 | spin_lock_irqsave(&ha->hardware_lock, flags); |
961 | } | 1015 | } |
962 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1016 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -1249,7 +1303,6 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1249 | int que, cnt; | 1303 | int que, cnt; |
1250 | unsigned long flags; | 1304 | unsigned long flags; |
1251 | srb_t *sp; | 1305 | srb_t *sp; |
1252 | struct srb_ctx *ctx; | ||
1253 | struct qla_hw_data *ha = vha->hw; | 1306 | struct qla_hw_data *ha = vha->hw; |
1254 | struct req_que *req; | 1307 | struct req_que *req; |
1255 | 1308 | ||
@@ -1262,31 +1315,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1262 | sp = req->outstanding_cmds[cnt]; | 1315 | sp = req->outstanding_cmds[cnt]; |
1263 | if (sp) { | 1316 | if (sp) { |
1264 | req->outstanding_cmds[cnt] = NULL; | 1317 | req->outstanding_cmds[cnt] = NULL; |
1265 | if (!sp->ctx || | 1318 | sp->done(vha, sp, res); |
1266 | (sp->flags & SRB_FCP_CMND_DMA_VALID) || | ||
1267 | IS_PROT_IO(sp)) { | ||
1268 | sp->cmd->result = res; | ||
1269 | qla2x00_sp_compl(ha, sp); | ||
1270 | } else { | ||
1271 | ctx = sp->ctx; | ||
1272 | if (ctx->type == SRB_ELS_CMD_RPT || | ||
1273 | ctx->type == SRB_ELS_CMD_HST || | ||
1274 | ctx->type == SRB_CT_CMD) { | ||
1275 | struct fc_bsg_job *bsg_job = | ||
1276 | ctx->u.bsg_job; | ||
1277 | if (bsg_job->request->msgcode | ||
1278 | == FC_BSG_HST_CT) | ||
1279 | kfree(sp->fcport); | ||
1280 | bsg_job->req->errors = 0; | ||
1281 | bsg_job->reply->result = res; | ||
1282 | bsg_job->job_done(bsg_job); | ||
1283 | kfree(sp->ctx); | ||
1284 | mempool_free(sp, | ||
1285 | ha->srb_mempool); | ||
1286 | } else { | ||
1287 | ctx->u.iocb_cmd->free(sp); | ||
1288 | } | ||
1289 | } | ||
1290 | } | 1319 | } |
1291 | } | 1320 | } |
1292 | } | 1321 | } |
@@ -3820,75 +3849,6 @@ qla2x00_rst_aen(scsi_qla_host_t *vha) | |||
3820 | } | 3849 | } |
3821 | } | 3850 | } |
3822 | 3851 | ||
3823 | static void | ||
3824 | qla2x00_sp_free_dma(srb_t *sp) | ||
3825 | { | ||
3826 | struct scsi_cmnd *cmd = sp->cmd; | ||
3827 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
3828 | |||
3829 | if (sp->flags & SRB_DMA_VALID) { | ||
3830 | scsi_dma_unmap(cmd); | ||
3831 | sp->flags &= ~SRB_DMA_VALID; | ||
3832 | } | ||
3833 | |||
3834 | if (sp->flags & SRB_CRC_PROT_DMA_VALID) { | ||
3835 | dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), | ||
3836 | scsi_prot_sg_count(cmd), cmd->sc_data_direction); | ||
3837 | sp->flags &= ~SRB_CRC_PROT_DMA_VALID; | ||
3838 | } | ||
3839 | |||
3840 | if (sp->flags & SRB_CRC_CTX_DSD_VALID) { | ||
3841 | /* List assured to be having elements */ | ||
3842 | qla2x00_clean_dsd_pool(ha, sp); | ||
3843 | sp->flags &= ~SRB_CRC_CTX_DSD_VALID; | ||
3844 | } | ||
3845 | |||
3846 | if (sp->flags & SRB_CRC_CTX_DMA_VALID) { | ||
3847 | dma_pool_free(ha->dl_dma_pool, sp->ctx, | ||
3848 | ((struct crc_context *)sp->ctx)->crc_ctx_dma); | ||
3849 | sp->flags &= ~SRB_CRC_CTX_DMA_VALID; | ||
3850 | } | ||
3851 | |||
3852 | if (sp->flags & SRB_FCP_CMND_DMA_VALID) { | ||
3853 | struct ct6_dsd *ctx = sp->ctx; | ||
3854 | dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, | ||
3855 | ctx->fcp_cmnd_dma); | ||
3856 | list_splice(&ctx->dsd_list, &ha->gbl_dsd_list); | ||
3857 | ha->gbl_dsd_inuse -= ctx->dsd_use_cnt; | ||
3858 | ha->gbl_dsd_avail += ctx->dsd_use_cnt; | ||
3859 | mempool_free(sp->ctx, ha->ctx_mempool); | ||
3860 | sp->ctx = NULL; | ||
3861 | } | ||
3862 | |||
3863 | CMD_SP(cmd) = NULL; | ||
3864 | } | ||
3865 | |||
3866 | static void | ||
3867 | qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) | ||
3868 | { | ||
3869 | struct scsi_cmnd *cmd = sp->cmd; | ||
3870 | |||
3871 | qla2x00_sp_free_dma(sp); | ||
3872 | mempool_free(sp, ha->srb_mempool); | ||
3873 | cmd->scsi_done(cmd); | ||
3874 | } | ||
3875 | |||
3876 | void | ||
3877 | qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp) | ||
3878 | { | ||
3879 | if (atomic_read(&sp->ref_count) == 0) { | ||
3880 | ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015, | ||
3881 | "SP reference-count to ZERO -- sp=%p cmd=%p.\n", | ||
3882 | sp, sp->cmd); | ||
3883 | if (ql2xextended_error_logging & ql_dbg_io) | ||
3884 | BUG(); | ||
3885 | return; | ||
3886 | } | ||
3887 | if (!atomic_dec_and_test(&sp->ref_count)) | ||
3888 | return; | ||
3889 | qla2x00_sp_final_compl(ha, sp); | ||
3890 | } | ||
3891 | |||
3892 | /************************************************************************** | 3852 | /************************************************************************** |
3893 | * qla2x00_timer | 3853 | * qla2x00_timer |
3894 | * | 3854 | * |
@@ -3959,7 +3919,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3959 | sp = req->outstanding_cmds[index]; | 3919 | sp = req->outstanding_cmds[index]; |
3960 | if (!sp) | 3920 | if (!sp) |
3961 | continue; | 3921 | continue; |
3962 | if (sp->ctx && !IS_PROT_IO(sp)) | 3922 | if (sp->type != SRB_SCSI_CMD) |
3963 | continue; | 3923 | continue; |
3964 | sfcp = sp->fcport; | 3924 | sfcp = sp->fcport; |
3965 | if (!(sfcp->flags & FCF_FCP2_DEVICE)) | 3925 | if (!(sfcp->flags & FCF_FCP2_DEVICE)) |