From 04673e38f56b30cd39b1fa0f386137d818b17781 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:45 -0800 Subject: [PATCH 001/168] scsi: lpfc: Fix frequency of Release WQE CQEs The driver controls when the hardware sends completions that communicate consumption of elements from the WQ. This is done by setting a WQEC bit on a WQE. The current driver sets it on every Nth WQE posting. However, the driver isn't clearing the bit if the WQE is reused. Thus, if the queue depth isn't evenly divisible by N, with enough time, it can be set on every element, creating a lot of overhead and risking CQ full conditions. Correct by clearing the bit when not setting it on an Nth element. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5f5528a12308..149f21f53b13 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -129,6 +129,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) /* set consumption flag every once in a while */ if (!((q->host_index + 1) % q->entry_repost)) bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); + else + bf_set(wqe_wqec, &wqe->generic.wqe_com, 0); if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); From c176ffa0841c632593c5007f1d1c9ed126481daa Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:46 -0800 Subject: [PATCH 002/168] scsi: lpfc: Increase CQ and WQ sizes for SCSI Increased CQ and WQ sizes for SCSI FCP, matching those used for NVMe development. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_hw4.h | 3 +++ drivers/scsi/lpfc/lpfc_init.c | 36 ++++++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_sli.c | 3 ++- drivers/scsi/lpfc/lpfc_sli4.h | 5 +++++ 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 61fb46da05d4..d042f9118e3b 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -760,6 +760,7 @@ struct lpfc_hba { uint8_t mds_diags_support; uint32_t initial_imax; uint8_t bbcredit_support; + uint8_t enab_exp_wqcq_pages; /* HBA Config Parameters */ uint32_t cfg_ack0; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 73c2f6971d2b..ef469129fb71 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3212,6 +3212,9 @@ struct lpfc_sli4_parameters { #define cfg_cqv_SHIFT 14 #define cfg_cqv_MASK 0x00000003 #define cfg_cqv_WORD word4 +#define cfg_cqpsize_SHIFT 16 +#define cfg_cqpsize_MASK 0x000000ff +#define cfg_cqpsize_WORD word4 uint32_t word5; uint32_t word6; #define cfg_mqv_SHIFT 14 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f539c554588c..40ffa0111142 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8011,9 +8011,10 @@ static int lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) { struct lpfc_queue *qdesc; + uint32_t wqesize; /* Create Fast Path FCP CQs */ - if (phba->fcp_embed_io) + if (phba->enab_exp_wqcq_pages) /* Increase the CQ size when WQEs contain an embedded cdb */ qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, phba->sli4_hba.cq_esize, @@ -8031,15 +8032,18 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) phba->sli4_hba.fcp_cq[wqidx] = qdesc; /* Create Fast Path FCP WQs */ - if (phba->fcp_embed_io) + if (phba->enab_exp_wqcq_pages) { /* Increase the WQ size when WQEs contain an embedded cdb */ + wqesize = (phba->fcp_embed_io) ? + LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize; qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, - LPFC_WQE128_SIZE, + wqesize, LPFC_WQE_EXP_COUNT); - else + } else qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, phba->sli4_hba.wq_esize, phba->sli4_hba.wq_ecount); + if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0503 Failed allocate fast-path FCP WQ (%d)\n", @@ -10476,15 +10480,21 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; /* - * Issue IOs with CDB embedded in WQE to minimized the number - * of DMAs the firmware has to do. Setting this to 1 also forces - * the driver to use 128 bytes WQEs for FCP IOs. + * Check whether the adapter supports an embedded copy of the + * FCP CMD IU within the WQE for FCP_Ixxx commands. In order + * to use this option, 128-byte WQEs must be used. */ if (bf_get(cfg_ext_embed_cb, mbx_sli4_parameters)) phba->fcp_embed_io = 1; else phba->fcp_embed_io = 0; + if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) && + (bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) && + (sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT)) + phba->enab_exp_wqcq_pages = 1; + else + phba->enab_exp_wqcq_pages = 0; /* * Check if the SLI port supports MDS Diagnostics */ @@ -12227,6 +12237,7 @@ int lpfc_fof_queue_create(struct lpfc_hba *phba) { struct lpfc_queue *qdesc; + uint32_t wqesize; /* Create FOF EQ */ qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, @@ -12240,7 +12251,7 @@ lpfc_fof_queue_create(struct lpfc_hba *phba) if (phba->cfg_fof) { /* Create OAS CQ */ - if (phba->fcp_embed_io) + if (phba->enab_exp_wqcq_pages) qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, phba->sli4_hba.cq_esize, @@ -12256,16 +12267,19 @@ lpfc_fof_queue_create(struct lpfc_hba *phba) phba->sli4_hba.oas_cq = qdesc; /* Create OAS WQ */ - if (phba->fcp_embed_io) + if (phba->enab_exp_wqcq_pages) { + wqesize = (phba->fcp_embed_io) ? + LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize; qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, - LPFC_WQE128_SIZE, + wqesize, LPFC_WQE_EXP_COUNT); - else + } else qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, phba->sli4_hba.wq_esize, phba->sli4_hba.wq_ecount); + if (!qdesc) goto out_error; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 149f21f53b13..d08d9b48f6b1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -14910,7 +14910,8 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, bf_set(lpfc_mbox_hdr_version, &shdr->request, phba->sli4_hba.pc_sli4_params.wqv); - if (phba->sli4_hba.pc_sli4_params.wqsize & LPFC_WQ_SZ128_SUPPORT) + if ((phba->sli4_hba.pc_sli4_params.wqsize & LPFC_WQ_SZ128_SUPPORT) || + (wq->page_size > SLI4_PAGE_SIZE)) wq_create_version = LPFC_Q_CREATE_VERSION_1; else wq_create_version = LPFC_Q_CREATE_VERSION_0; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 81fb58e59e60..a9af9980fc43 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -485,6 +485,11 @@ struct lpfc_pc_sli4_params { uint8_t wqpcnt; }; +#define LPFC_CQ_4K_PAGE_SZ 0x1 +#define LPFC_CQ_16K_PAGE_SZ 0x4 +#define LPFC_WQ_4K_PAGE_SZ 0x1 +#define LPFC_WQ_16K_PAGE_SZ 0x4 + struct lpfc_iov { uint32_t pf_number; uint32_t vf_number; From 281d61902ffbab47901f8616a38a45144627dd9e Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:47 -0800 Subject: [PATCH 003/168] scsi: lpfc: move placement of target destroy on driver detach Ensure nvme localports/targetports are torn down before dismantling the adapter sli interface on driver detachment. This aids leaving interfaces live while nvme may be making callbacks to abort it. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 40ffa0111142..bff5c95cf5df 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11503,13 +11503,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) /* Remove FC host and then SCSI host with the physical port */ fc_remove_host(shost); scsi_remove_host(shost); - /* - * Bring down the SLI Layer. This step disables all interrupts, - * clears the rings, discards all mailbox commands, and resets - * the HBA FCoE function. - */ - lpfc_debugfs_terminate(vport); - lpfc_sli4_hba_unset(phba); /* Perform ndlp cleanup on the physical port. The nvme and nvmet * localports are destroyed after to cleanup all transport memory. @@ -11518,6 +11511,13 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) lpfc_nvmet_destroy_targetport(phba); lpfc_nvme_destroy_localport(vport); + /* + * Bring down the SLI Layer. This step disables all interrupts, + * clears the rings, discards all mailbox commands, and resets + * the HBA FCoE function. + */ + lpfc_debugfs_terminate(vport); + lpfc_sli4_hba_unset(phba); lpfc_stop_hba_timers(phba); spin_lock_irq(&phba->hbalock); From 8ae337013674d5c1e803429356b85cba2ce12067 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:48 -0800 Subject: [PATCH 004/168] scsi: lpfc: correct debug counters for abort Existing code was using the wrong field for the completion status when comparing whether to increment abort statistics Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 8dbf5c9d51aa..7927ac46d345 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -130,7 +130,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, if (tgtp) { if (status) { atomic_inc(&tgtp->xmt_ls_rsp_error); - if (status == IOERR_ABORT_REQUESTED) + if (result == IOERR_ABORT_REQUESTED) atomic_inc(&tgtp->xmt_ls_rsp_aborted); if (bf_get(lpfc_wcqe_c_xb, wcqe)) atomic_inc(&tgtp->xmt_ls_rsp_xb_set); @@ -541,7 +541,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, rsp->transferred_length = 0; if (tgtp) { atomic_inc(&tgtp->xmt_fcp_rsp_error); - if (status == IOERR_ABORT_REQUESTED) + if (result == IOERR_ABORT_REQUESTED) atomic_inc(&tgtp->xmt_fcp_rsp_aborted); } From 6e8e1c14c61e54253098521127cd5ac0b959dd32 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:49 -0800 Subject: [PATCH 005/168] scsi: lpfc: Add WQ Full Logic for NVME Target I/O conditions on the nvme target may have the driver submitting to a full hardware wq. The hardware wq is a shared resource among all nvme controllers. When the driver hit a full wq, it failed the io posting back to the nvme-fc transport, which then escalated it into errors. Correct by maintaining a sideband queue within the driver that is added to when the WQ full condition is hit, and drained from as soon as new WQ space opens up. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_nvmet.c | 116 +++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_nvmet.h | 1 + drivers/scsi/lpfc/lpfc_sli.c | 3 + drivers/scsi/lpfc/lpfc_sli4.h | 5 +- 5 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 559f9aa0ed08..3ecf50df93f4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -254,6 +254,7 @@ void lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctxp); int lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport, struct fc_frame_header *fc_hdr); +void lpfc_nvmet_wqfull_process(struct lpfc_hba *phba, struct lpfc_queue *wq); void lpfc_sli_flush_nvme_rings(struct lpfc_hba *phba); void lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba); void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *, diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 7927ac46d345..9c2acf90212c 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -71,6 +71,8 @@ static int lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *, static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *, struct lpfc_nvmet_rcv_ctx *, uint32_t, uint16_t); +static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *, + struct lpfc_nvmet_rcv_ctx *); void lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp) @@ -741,7 +743,10 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, struct lpfc_nvmet_rcv_ctx *ctxp = container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req); struct lpfc_hba *phba = ctxp->phba; + struct lpfc_queue *wq; struct lpfc_iocbq *nvmewqeq; + struct lpfc_sli_ring *pring; + unsigned long iflags; int rc; if (phba->pport->load_flag & FC_UNLOADING) { @@ -820,6 +825,21 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, return 0; } + if (rc == -EBUSY) { + /* + * WQ was full, so queue nvmewqeq to be sent after + * WQE release CQE + */ + ctxp->flag |= LPFC_NVMET_DEFER_WQFULL; + wq = phba->sli4_hba.nvme_wq[rsp->hwqid]; + pring = wq->pring; + spin_lock_irqsave(&pring->ring_lock, iflags); + list_add_tail(&nvmewqeq->list, &wq->wqfull_list); + wq->q_flag |= HBA_NVMET_WQFULL; + spin_unlock_irqrestore(&pring->ring_lock, iflags); + return 0; + } + /* Give back resources */ atomic_inc(&lpfc_nvmep->xmt_fcp_drop); lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, @@ -851,6 +871,7 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport, struct lpfc_nvmet_rcv_ctx *ctxp = container_of(req, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req); struct lpfc_hba *phba = ctxp->phba; + struct lpfc_queue *wq; unsigned long flags; if (phba->pport->load_flag & FC_UNLOADING) @@ -880,6 +901,14 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport, } ctxp->flag |= LPFC_NVMET_ABORT_OP; + if (ctxp->flag & LPFC_NVMET_DEFER_WQFULL) { + lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid, + ctxp->oxid); + wq = phba->sli4_hba.nvme_wq[ctxp->wqeq->hba_wqidx]; + lpfc_nvmet_wqfull_flush(phba, wq, ctxp); + return; + } + /* An state of LPFC_NVMET_STE_RCV means we have just received * the NVME command and have not started processing it. * (by issuing any IO WQEs on this exchange yet) @@ -1435,16 +1464,103 @@ lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport, return 0; } +static void +lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq, + struct lpfc_nvmet_rcv_ctx *ctxp) +{ + struct lpfc_sli_ring *pring; + struct lpfc_iocbq *nvmewqeq; + struct lpfc_iocbq *next_nvmewqeq; + unsigned long iflags; + struct lpfc_wcqe_complete wcqe; + struct lpfc_wcqe_complete *wcqep; + + pring = wq->pring; + wcqep = &wcqe; + + /* Fake an ABORT error code back to cmpl routine */ + memset(wcqep, 0, sizeof(struct lpfc_wcqe_complete)); + bf_set(lpfc_wcqe_c_status, wcqep, IOSTAT_LOCAL_REJECT); + wcqep->parameter = IOERR_ABORT_REQUESTED; + + spin_lock_irqsave(&pring->ring_lock, iflags); + list_for_each_entry_safe(nvmewqeq, next_nvmewqeq, + &wq->wqfull_list, list) { + if (ctxp) { + /* Checking for a specific IO to flush */ + if (nvmewqeq->context2 == ctxp) { + list_del(&nvmewqeq->list); + spin_unlock_irqrestore(&pring->ring_lock, + iflags); + lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, + wcqep); + return; + } + continue; + } else { + /* Flush all IOs */ + list_del(&nvmewqeq->list); + spin_unlock_irqrestore(&pring->ring_lock, iflags); + lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep); + spin_lock_irqsave(&pring->ring_lock, iflags); + } + } + if (!ctxp) + wq->q_flag &= ~HBA_NVMET_WQFULL; + spin_unlock_irqrestore(&pring->ring_lock, iflags); +} + +void +lpfc_nvmet_wqfull_process(struct lpfc_hba *phba, + struct lpfc_queue *wq) +{ +#if (IS_ENABLED(CONFIG_NVME_TARGET_FC)) + struct lpfc_sli_ring *pring; + struct lpfc_iocbq *nvmewqeq; + unsigned long iflags; + int rc; + + /* + * Some WQE slots are available, so try to re-issue anything + * on the WQ wqfull_list. + */ + pring = wq->pring; + spin_lock_irqsave(&pring->ring_lock, iflags); + while (!list_empty(&wq->wqfull_list)) { + list_remove_head(&wq->wqfull_list, nvmewqeq, struct lpfc_iocbq, + list); + spin_unlock_irqrestore(&pring->ring_lock, iflags); + rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq); + spin_lock_irqsave(&pring->ring_lock, iflags); + if (rc == -EBUSY) { + /* WQ was full again, so put it back on the list */ + list_add(&nvmewqeq->list, &wq->wqfull_list); + spin_unlock_irqrestore(&pring->ring_lock, iflags); + return; + } + } + wq->q_flag &= ~HBA_NVMET_WQFULL; + spin_unlock_irqrestore(&pring->ring_lock, iflags); + +#endif +} + void lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) { #if (IS_ENABLED(CONFIG_NVME_TARGET_FC)) struct lpfc_nvmet_tgtport *tgtp; + struct lpfc_queue *wq; + uint32_t qidx; if (phba->nvmet_support == 0) return; if (phba->targetport) { tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; + for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++) { + wq = phba->sli4_hba.nvme_wq[qidx]; + lpfc_nvmet_wqfull_flush(phba, wq, NULL); + } init_completion(&tgtp->tport_unreg_done); nvmet_fc_unregister_targetport(phba->targetport); wait_for_completion_timeout(&tgtp->tport_unreg_done, 5); diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h index 5b32c9e4d4ef..354cce443c9f 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.h +++ b/drivers/scsi/lpfc/lpfc_nvmet.h @@ -132,6 +132,7 @@ struct lpfc_nvmet_rcv_ctx { #define LPFC_NVMET_CTX_RLS 0x8 /* ctx free requested */ #define LPFC_NVMET_ABTS_RCV 0x10 /* ABTS received on exchange */ #define LPFC_NVMET_DEFER_RCV_REPOST 0x20 /* repost to RQ on defer rcv */ +#define LPFC_NVMET_DEFER_WQFULL 0x40 /* Waiting on a free WQE */ struct rqb_dmabuf *rqb_buffer; struct lpfc_nvmet_ctxbuf *ctxbuf; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d08d9b48f6b1..fbda2fbcbfec 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -13232,6 +13232,8 @@ lpfc_sli4_fp_handle_rel_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, if (childwq->queue_id == hba_wqid) { lpfc_sli4_wq_release(childwq, bf_get(lpfc_wcqe_r_wqe_index, wcqe)); + if (childwq->q_flag & HBA_NVMET_WQFULL) + lpfc_nvmet_wqfull_process(phba, childwq); wqid_matched = true; break; } @@ -13950,6 +13952,7 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size, INIT_LIST_HEAD(&queue->list); INIT_LIST_HEAD(&queue->wq_list); + INIT_LIST_HEAD(&queue->wqfull_list); INIT_LIST_HEAD(&queue->page_list); INIT_LIST_HEAD(&queue->child_list); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index a9af9980fc43..ac81bfa59278 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -145,6 +145,7 @@ struct lpfc_rqb { struct lpfc_queue { struct list_head list; struct list_head wq_list; + struct list_head wqfull_list; enum lpfc_sli4_queue_type type; enum lpfc_sli4_queue_subtype subtype; struct lpfc_hba *phba; @@ -173,9 +174,11 @@ struct lpfc_queue { #define LPFC_EXPANDED_PAGE_SIZE 16384 #define LPFC_DEFAULT_PAGE_SIZE 4096 uint16_t chann; /* IO channel this queue is associated with */ - uint16_t db_format; + uint8_t db_format; #define LPFC_DB_RING_FORMAT 0x01 #define LPFC_DB_LIST_FORMAT 0x02 + uint8_t q_flag; +#define HBA_NVMET_WQFULL 0x1 /* We hit WQ Full condition for NVMET */ void __iomem *db_regaddr; /* For q stats */ uint32_t q_cnt_1; From 2c3b2a8f652566c5b35d945f0c8146555d2062ec Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:50 -0800 Subject: [PATCH 006/168] scsi: lpfc: Fix PRLI handling when topology type changes The lpfc driver does not discover a target when the topology changes from switched-fabric to direct-connect. The target rejects the PRLI from the initiator in direct-connect as the driver is using the old S_ID from the switched topology. The driver was inappropriately clearing the VP bit to register the VPI, which is what is associated with the S_ID. Fix by leaving the VP bit set (it was set earlier) and as the VFI is being re-registered, set the UPDT bit. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mbox.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 81fb92967b11..c32d4a323db2 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2170,10 +2170,8 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) /* Only FC supports upd bit */ if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) && (vport->fc_flag & FC_VFI_REGISTERED) && - (!phba->fc_topology_changed)) { - bf_set(lpfc_reg_vfi_vp, reg_vfi, 0); + (!phba->fc_topology_changed)) bf_set(lpfc_reg_vfi_upd, reg_vfi, 1); - } bf_set(lpfc_reg_vfi_bbcr, reg_vfi, 0); bf_set(lpfc_reg_vfi_bbscn, reg_vfi, 0); From 91455b850956bc13708a074bd1400f54aae74890 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:51 -0800 Subject: [PATCH 007/168] scsi: lpfc: Fix IO failure during hba reset testing with nvme io. A stress test repeatedly resetting the adapter while performing io would eventually report I/O failures and missing nvme namespaces. The driver was setting the nvmefc_fcp_req->private pointer to NULL during the IO completion routine before upcalling done(). If the transport was also running an abort for that IO, the driver would fail the abort with message 6140. Failing the abort is not allowed by the nvme-fc transport, as it mandates that the io must be returned back to the transport. As that does not happen, the transport controller delete has an outstanding reference and can't complete teardown. The NULL-ing of the private pointer should be done only when the io is considered complete. It's complete when the adapter returns the exchange with the "exchange busy" flag clear. Move the NULL'ing of the structure to the done case. This leaves the io contexts set while it is busy and until the subsequent XRI_ABORTED completion which returns the exchange is received. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 81e3a4f10c3c..c6e5b9972585 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -980,14 +980,14 @@ out_err: phba->cpucheck_cmpl_io[lpfc_ncmd->cpu]++; } #endif - freqpriv = nCmd->private; - freqpriv->nvme_buf = NULL; /* NVME targets need completion held off until the abort exchange * completes unless the NVME Rport is getting unregistered. */ if (!(lpfc_ncmd->flags & LPFC_SBUF_XBUSY)) { + freqpriv = nCmd->private; + freqpriv->nvme_buf = NULL; nCmd->done(nCmd); lpfc_ncmd->nvmeCmd = NULL; } From 411de511c6943554cdc4173c3f522029db2f75c7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:52 -0800 Subject: [PATCH 008/168] scsi: lpfc: Fix RQ empty firmware trap When nvme target deferred receive logic waits for exchange resources, the corresponding receive buffer is not replenished with the hardware. This can result in a lack of asynchronous receive buffer resources in the hardware, resulting in a "2885 Port Status Event: ... error 1=0x52004a01 ..." message. Correct by replenishing the buffer whenenver the deferred logic kicks in. Update corresponding debug messages and statistics as well. [mkp: applied by hand] Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 6 ++++++ drivers/scsi/lpfc/lpfc_mem.c | 10 +++++++--- drivers/scsi/lpfc/lpfc_nvmet.c | 31 +++++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_nvmet.h | 7 +++++-- drivers/scsi/lpfc/lpfc_sli.c | 12 ++++++++++++ 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ac77081e6e9e..c63a028385ab 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -259,6 +259,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, atomic_read(&tgtp->xmt_abort_rsp), atomic_read(&tgtp->xmt_abort_rsp_error)); + len += snprintf(buf + len, PAGE_SIZE - len, + "DELAY: ctx %08x fod %08x wqfull %08x\n", + atomic_read(&tgtp->defer_ctx), + atomic_read(&tgtp->defer_fod), + atomic_read(&tgtp->defer_wqfull)); + /* Calculate outstanding IOs */ tot = atomic_read(&tgtp->rcv_fcp_cmd_drop); tot += atomic_read(&tgtp->xmt_fcp_release); diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 87c08ff37ddd..60078e61da5e 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -753,12 +753,16 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys); rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe); if (rc < 0) { + (rqbp->rqb_free_buffer)(phba, rqb_entry); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "6409 Cannot post to RQ %d: %x %x\n", + "6409 Cannot post to HRQ %d: %x %x %x " + "DRQ %x %x\n", rqb_entry->hrq->queue_id, rqb_entry->hrq->host_index, - rqb_entry->hrq->hba_index); - (rqbp->rqb_free_buffer)(phba, rqb_entry); + rqb_entry->hrq->hba_index, + rqb_entry->hrq->entry_count, + rqb_entry->drq->host_index, + rqb_entry->drq->hba_index); } else { list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); rqbp->buffer_count++; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 9c2acf90212c..0539585d32d4 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -270,8 +270,6 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf) "NVMET RCV BUSY: xri x%x sz %d " "from %06x\n", oxid, size, sid); - /* defer repost rcv buffer till .defer_rcv callback */ - ctxp->flag &= ~LPFC_NVMET_DEFER_RCV_REPOST; atomic_inc(&tgtp->rcv_fcp_cmd_out); return; } @@ -837,6 +835,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, list_add_tail(&nvmewqeq->list, &wq->wqfull_list); wq->q_flag |= HBA_NVMET_WQFULL; spin_unlock_irqrestore(&pring->ring_lock, iflags); + atomic_inc(&lpfc_nvmep->defer_wqfull); return 0; } @@ -975,11 +974,9 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport, tgtp = phba->targetport->private; atomic_inc(&tgtp->rcv_fcp_cmd_defer); - if (ctxp->flag & LPFC_NVMET_DEFER_RCV_REPOST) - lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */ - else - nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf); - ctxp->flag &= ~LPFC_NVMET_DEFER_RCV_REPOST; + + /* Free the nvmebuf since a new buffer already replaced it */ + nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf); } static struct nvmet_fc_target_template lpfc_tgttemplate = { @@ -1309,6 +1306,9 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba) atomic_set(&tgtp->xmt_abort_sol, 0); atomic_set(&tgtp->xmt_abort_rsp, 0); atomic_set(&tgtp->xmt_abort_rsp_error, 0); + atomic_set(&tgtp->defer_ctx, 0); + atomic_set(&tgtp->defer_fod, 0); + atomic_set(&tgtp->defer_wqfull, 0); } return error; } @@ -1810,6 +1810,8 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, lpfc_nvmeio_data(phba, "NVMET FCP RCV: xri x%x sz %d CPU %02x\n", oxid, size, smp_processor_id()); + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; + if (!ctx_buf) { /* Queue this NVME IO to process later */ spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag); @@ -1825,10 +1827,11 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, lpfc_post_rq_buffer( phba, phba->sli4_hba.nvmet_mrq_hdr[qno], phba->sli4_hba.nvmet_mrq_data[qno], 1, qno); + + atomic_inc(&tgtp->defer_ctx); return; } - tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; payload = (uint32_t *)(nvmebuf->dbuf.virt); sid = sli4_sid_from_fc_hdr(fc_hdr); @@ -1892,12 +1895,20 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, /* Processing of FCP command is deferred */ if (rc == -EOVERFLOW) { + /* + * Post a brand new DMA buffer to RQ and defer + * freeing rcv buffer till .defer_rcv callback + */ + qno = nvmebuf->idx; + lpfc_post_rq_buffer( + phba, phba->sli4_hba.nvmet_mrq_hdr[qno], + phba->sli4_hba.nvmet_mrq_data[qno], 1, qno); + lpfc_nvmeio_data(phba, "NVMET RCV BUSY: xri x%x sz %d from %06x\n", oxid, size, sid); - /* defer reposting rcv buffer till .defer_rcv callback */ - ctxp->flag |= LPFC_NVMET_DEFER_RCV_REPOST; atomic_inc(&tgtp->rcv_fcp_cmd_out); + atomic_inc(&tgtp->defer_fod); return; } ctxp->rqb_buffer = nvmebuf; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h index 354cce443c9f..5da35de5ea45 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.h +++ b/drivers/scsi/lpfc/lpfc_nvmet.h @@ -72,7 +72,6 @@ struct lpfc_nvmet_tgtport { atomic_t xmt_fcp_rsp_aborted; atomic_t xmt_fcp_rsp_drop; - /* Stats counters - lpfc_nvmet_xmt_fcp_abort */ atomic_t xmt_fcp_xri_abort_cqe; atomic_t xmt_fcp_abort; @@ -81,6 +80,11 @@ struct lpfc_nvmet_tgtport { atomic_t xmt_abort_unsol; atomic_t xmt_abort_rsp; atomic_t xmt_abort_rsp_error; + + /* Stats counters - defer IO */ + atomic_t defer_ctx; + atomic_t defer_fod; + atomic_t defer_wqfull; }; struct lpfc_nvmet_ctx_info { @@ -131,7 +135,6 @@ struct lpfc_nvmet_rcv_ctx { #define LPFC_NVMET_XBUSY 0x4 /* XB bit set on IO cmpl */ #define LPFC_NVMET_CTX_RLS 0x8 /* ctx free requested */ #define LPFC_NVMET_ABTS_RCV 0x10 /* ABTS received on exchange */ -#define LPFC_NVMET_DEFER_RCV_REPOST 0x20 /* repost to RQ on defer rcv */ #define LPFC_NVMET_DEFER_WQFULL 0x40 /* Waiting on a free WQE */ struct rqb_dmabuf *rqb_buffer; struct lpfc_nvmet_ctxbuf *ctxbuf; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index fbda2fbcbfec..8b2919a553d6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -6535,9 +6535,11 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct lpfc_rqe hrqe; struct lpfc_rqe drqe; struct lpfc_rqb *rqbp; + unsigned long flags; struct rqb_dmabuf *rqb_buffer; LIST_HEAD(rqb_buf_list); + spin_lock_irqsave(&phba->hbalock, flags); rqbp = hrq->rqbp; for (i = 0; i < count; i++) { /* IF RQ is already full, don't bother */ @@ -6561,6 +6563,15 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys); rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe); if (rc < 0) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "6421 Cannot post to HRQ %d: %x %x %x " + "DRQ %x %x\n", + hrq->queue_id, + hrq->host_index, + hrq->hba_index, + hrq->entry_count, + drq->host_index, + drq->hba_index); rqbp->rqb_free_buffer(phba, rqb_buffer); } else { list_add_tail(&rqb_buffer->hbuf.list, @@ -6568,6 +6579,7 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, rqbp->buffer_count++; } } + spin_unlock_irqrestore(&phba->hbalock, flags); return 1; } From 64bf009933bc84a7fb44ff50f86af0201b8be0c3 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:53 -0800 Subject: [PATCH 009/168] scsi: lpfc: Allow set of maximum outstanding SCSI cmd limit for a target Make the attribute writeable. Remove the ramp up to logic as its unnecessary, simply set depth. Add debug message if depth changed, possibly reducing limit, yet our outstanding count has yet to catch up with it. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 4 ++-- drivers/scsi/lpfc/lpfc_scsi.c | 39 +++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c63a028385ab..06138b618220 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3464,8 +3464,8 @@ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512, # tgt_queue_depth: This parameter is used to limit the number of outstanding # commands per target port. Value range is [10,65535]. Default value is 65535. */ -LPFC_VPORT_ATTR_R(tgt_queue_depth, 65535, 10, 65535, - "Max number of FCP commands we can queue to a specific target port"); +LPFC_VPORT_ATTR_RW(tgt_queue_depth, 65535, 10, 65535, + "Max number of FCP commands we can queue to a specific target port"); /* # hba_queue_depth: This parameter is used to limit the number of outstanding diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c0cdaef4db24..dcc86936e6fc 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3926,7 +3926,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct lpfc_rport_data *rdata = lpfc_cmd->rdata; struct lpfc_nodelist *pnode = rdata->pnode; struct scsi_cmnd *cmd; - int depth; unsigned long flags; struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost; @@ -4132,16 +4131,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } spin_unlock_irqrestore(shost->host_lock, flags); } else if (pnode && NLP_CHK_NODE_ACT(pnode)) { - if ((pnode->cmd_qdepth < vport->cfg_tgt_queue_depth) && - time_after(jiffies, pnode->last_change_time + + if ((pnode->cmd_qdepth != vport->cfg_tgt_queue_depth) && + time_after(jiffies, pnode->last_change_time + msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) { spin_lock_irqsave(shost->host_lock, flags); - depth = pnode->cmd_qdepth * LPFC_TGTQ_RAMPUP_PCENT - / 100; - depth = depth ? depth : 1; - pnode->cmd_qdepth += depth; - if (pnode->cmd_qdepth > vport->cfg_tgt_queue_depth) - pnode->cmd_qdepth = vport->cfg_tgt_queue_depth; + pnode->cmd_qdepth = vport->cfg_tgt_queue_depth; pnode->last_change_time = jiffies; spin_unlock_irqrestore(shost->host_lock, flags); } @@ -4564,9 +4558,32 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) */ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) goto out_tgt_busy; - if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) + if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR, + "3377 Target Queue Full, scsi Id:%d Qdepth:%d" + " Pending command:%d" + " WWNN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, " + " WWPN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ndlp->nlp_sid, ndlp->cmd_qdepth, + atomic_read(&ndlp->cmd_pending), + ndlp->nlp_nodename.u.wwn[0], + ndlp->nlp_nodename.u.wwn[1], + ndlp->nlp_nodename.u.wwn[2], + ndlp->nlp_nodename.u.wwn[3], + ndlp->nlp_nodename.u.wwn[4], + ndlp->nlp_nodename.u.wwn[5], + ndlp->nlp_nodename.u.wwn[6], + ndlp->nlp_nodename.u.wwn[7], + ndlp->nlp_portname.u.wwn[0], + ndlp->nlp_portname.u.wwn[1], + ndlp->nlp_portname.u.wwn[2], + ndlp->nlp_portname.u.wwn[3], + ndlp->nlp_portname.u.wwn[4], + ndlp->nlp_portname.u.wwn[5], + ndlp->nlp_portname.u.wwn[6], + ndlp->nlp_portname.u.wwn[7]); goto out_tgt_busy; - + } lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); if (lpfc_cmd == NULL) { lpfc_rampdown_queue_depth(phba); From 161df4f09987ae2e9f0f97f0b38eee298b4a39ff Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:54 -0800 Subject: [PATCH 010/168] scsi: lpfc: Fix soft lockup in lpfc worker thread during LIP testing During link bounce testing in a point-to-point topology, the host may enter a soft lockup on the lpfc_worker thread: Call Trace: lpfc_work_done+0x1f3/0x1390 [lpfc] lpfc_do_work+0x16f/0x180 [lpfc] kthread+0xc7/0xe0 ret_from_fork+0x3f/0x70 The driver was simultaneously setting a combination of flags that caused lpfc_do_work()to effectively spin between slow path work and new event data, causing the lockup. Ensure in the typical wq completions, that new event data flags are set if the slow path flag is running. The slow path will eventually reschedule the wq handling. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b159a5c4e388..9265906d956e 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -696,8 +696,9 @@ lpfc_work_done(struct lpfc_hba *phba) phba->hba_flag & HBA_SP_QUEUE_EVT)) { if (pring->flag & LPFC_STOP_IOCB_EVENT) { pring->flag |= LPFC_DEFERRED_RING_EVENT; - /* Set the lpfc data pending flag */ - set_bit(LPFC_DATA_READY, &phba->data_flags); + /* Preserve legacy behavior. */ + if (!(phba->hba_flag & HBA_SP_QUEUE_EVT)) + set_bit(LPFC_DATA_READY, &phba->data_flags); } else { if (phba->link_state >= LPFC_LINK_UP || phba->link_flag & LS_MDS_LOOPBACK) { From 2289e9598dde9705400559ca2606fb8c145c34f0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:55 -0800 Subject: [PATCH 011/168] scsi: lpfc: Fix issue_lip if link is disabled The driver ignored checks on whether the link should be kept administratively down after a link bounce. Correct the checks. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 06138b618220..e25e63eb5a53 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -911,7 +911,12 @@ lpfc_issue_lip(struct Scsi_Host *shost) LPFC_MBOXQ_t *pmboxq; int mbxstatus = MBXERR_ERROR; + /* + * If the link is offline, disabled or BLOCK_MGMT_IO + * it doesn't make any sense to allow issue_lip + */ if ((vport->fc_flag & FC_OFFLINE_MODE) || + (phba->hba_flag & LINK_DISABLED) || (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)) return -EPERM; From a5ff06817eb86d022bc11993850a42732d7e6979 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:56 -0800 Subject: [PATCH 012/168] scsi: lpfc: Indicate CONF support in NVMe PRLI Revise the NVME PRLI to indicate CONF support. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 3 ++- drivers/scsi/lpfc/lpfc_hw4.h | 6 +++--- drivers/scsi/lpfc/lpfc_nportdisc.c | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 234c7c015982..404e1af5e2ab 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2293,10 +2293,11 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (phba->nvmet_support) { bf_set(prli_tgt, npr_nvme, 1); bf_set(prli_disc, npr_nvme, 1); - } else { bf_set(prli_init, npr_nvme, 1); + bf_set(prli_conf, npr_nvme, 1); } + npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index ef469129fb71..7c3afc3d3121 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4346,9 +4346,9 @@ struct lpfc_nvme_prli { #define prli_init_SHIFT 5 #define prli_init_MASK 0x00000001 #define prli_init_WORD word4 -#define prli_recov_SHIFT 8 -#define prli_recov_MASK 0x00000001 -#define prli_recov_WORD word4 +#define prli_conf_SHIFT 7 +#define prli_conf_MASK 0x00000001 +#define prli_conf_WORD word4 uint32_t word5; #define prli_fb_sz_SHIFT 0 #define prli_fb_sz_MASK 0x0000ffff diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d841aa42f607..bbf1e1342b09 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -2011,9 +2011,6 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } } - if (bf_get_be32(prli_recov, nvpr)) - ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6029 NVME PRLI Cmpl w1 x%08x " "w4 x%08x w5 x%08x flag x%x, " From c1dd9111b7f78a90bccd2e4abb9b9bb6319a4c64 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:57 -0800 Subject: [PATCH 013/168] scsi: lpfc: Fix SCSI io host reset causing kernel crash During SCSI error handling escalation to host reset, the SCSI io routines were moved off the txcmplq, but the individual io's ON_CMPLQ flag wasn't cleared. Thus, a background thread saw the io and attempted to access it as if on the txcmplq. Clear the flag upon removal. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 4 ++++ drivers/scsi/lpfc/lpfc_sli.c | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index bff5c95cf5df..aa7872a7b493 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -958,6 +958,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba) struct lpfc_sli_ring *pring; LIST_HEAD(completions); int i; + struct lpfc_iocbq *piocb, *next_iocb; if (phba->sli_rev != LPFC_SLI_REV4) { for (i = 0; i < psli->num_rings; i++) { @@ -983,6 +984,9 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba) if (!pring) continue; spin_lock_irq(&pring->ring_lock); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; list_splice_init(&pring->txcmplq, &completions); pring->txcmplq_cnt = 0; spin_unlock_irq(&pring->ring_lock); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8b2919a553d6..d597e15a1974 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3778,6 +3778,7 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; uint32_t i; + struct lpfc_iocbq *piocb, *next_iocb; spin_lock_irq(&phba->hbalock); /* Indicate the I/O queues are flushed */ @@ -3792,6 +3793,9 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) spin_lock_irq(&pring->ring_lock); /* Retrieve everything on txq */ list_splice_init(&pring->txq, &txq); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -3813,6 +3817,9 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); /* Retrieve everything on txq */ list_splice_init(&pring->txq, &txq); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -3844,6 +3851,7 @@ lpfc_sli_flush_nvme_rings(struct lpfc_hba *phba) LIST_HEAD(txcmplq); struct lpfc_sli_ring *pring; uint32_t i; + struct lpfc_iocbq *piocb, *next_iocb; if (phba->sli_rev < LPFC_SLI_REV4) return; @@ -3860,8 +3868,11 @@ lpfc_sli_flush_nvme_rings(struct lpfc_hba *phba) for (i = 0; i < phba->cfg_nvme_io_channel; i++) { pring = phba->sli4_hba.nvme_wq[i]->pring; - /* Retrieve everything on the txcmplq */ spin_lock_irq(&pring->ring_lock); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txcmplq_cnt = 0; spin_unlock_irq(&pring->ring_lock); From 20aefac3a9a23b56db43f1fe1b3ae72c87e39137 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:58 -0800 Subject: [PATCH 014/168] scsi: lpfc: Validate adapter support for SRIU option When using the special option to suppress the response iu, ensure the adapter fully supports the feature by checking feature flags from the adapter and validating the support when formatting the WQE. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 3 +++ drivers/scsi/lpfc/lpfc_init.c | 13 ++++++++++++- drivers/scsi/lpfc/lpfc_nvmet.c | 7 ++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 7c3afc3d3121..52fe28ae50fa 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3293,6 +3293,9 @@ struct lpfc_sli4_parameters { #define cfg_eqdr_SHIFT 8 #define cfg_eqdr_MASK 0x00000001 #define cfg_eqdr_WORD word19 +#define cfg_nosr_SHIFT 9 +#define cfg_nosr_MASK 0x00000001 +#define cfg_nosr_WORD word19 #define LPFC_NODELAY_MAX_IO 32 }; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index aa7872a7b493..f2d2faef8710 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10473,8 +10473,19 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP; } - if (bf_get(cfg_xib, mbx_sli4_parameters) && phba->cfg_suppress_rsp) + /* + * To support Suppress Response feature we must satisfy 3 conditions. + * lpfc_suppress_rsp module parameter must be set (default). + * In SLI4-Parameters Descriptor: + * Extended Inline Buffers (XIB) must be supported. + * Suppress Response IU Not Supported (SRIUNS) must NOT be supported + * (double negative). + */ + if (phba->cfg_suppress_rsp && bf_get(cfg_xib, mbx_sli4_parameters) && + !(bf_get(cfg_nosr, mbx_sli4_parameters))) phba->sli.sli_flag |= LPFC_SLI_SUPPRESS_RSP; + else + phba->cfg_suppress_rsp = 0; if (bf_get(cfg_eqdr, mbx_sli4_parameters)) phba->sli.sli_flag |= LPFC_SLI_USE_EQDR; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 0539585d32d4..6dd8535918f6 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -2290,9 +2290,10 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, if (rsp->op == NVMET_FCOP_READDATA_RSP) { atomic_inc(&tgtp->xmt_fcp_read_rsp); bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1); - if ((ndlp->nlp_flag & NLP_SUPPRESS_RSP) && - (rsp->rsplen == 12)) { - bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 1); + if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) { + if (ndlp->nlp_flag & NLP_SUPPRESS_RSP) + bf_set(wqe_sup, + &wqe->fcp_tsend.wqe_com, 1); bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0); bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0); From 8d731d1aa993c44fcf4de0dbd42059e00cf37102 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:58:59 -0800 Subject: [PATCH 015/168] scsi: lpfc: Fix header inclusion in lpfc_nvmet The driver was inappropriately pulling in the nvme host's nvme.h header. What it really needed was the standard header. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 6dd8535918f6..823b6df0aec7 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -36,7 +36,7 @@ #include #include -#include <../drivers/nvme/host/nvme.h> +#include #include #include From 45634a86ca6e98dbcaddb763f8e90ad243057789 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:59:00 -0800 Subject: [PATCH 016/168] scsi: lpfc: Treat SCSI Write operation Underruns as an error Currently, write underruns (mismatch of amount transferred vs scsi status and its residual) detected by the adapter are not being flagged as an error. Its expected the target controls the data transfer and would appropriately set the RSP values. Only read underruns are treated as errors. Revise the SCSI error handling to treat write underruns as an error as well. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index dcc86936e6fc..10c2dc0cf1fa 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3772,20 +3772,18 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER, - "9025 FCP Read Underrun, expected %d, " + "9025 FCP Underrun, expected %d, " "residual %d Data: x%x x%x x%x\n", fcpDl, scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0], cmnd->underflow); /* - * If there is an under run check if under run reported by + * If there is an under run, check if under run reported by * storage array is same as the under run reported by HBA. * If this is not same, there is a dropped frame. */ - if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && - fcpi_parm && - (scsi_get_resid(cmnd) != fcpi_parm)) { + if (fcpi_parm && (scsi_get_resid(cmnd) != fcpi_parm)) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, "9026 FCP Read Check Error " From 815a9c437617e221842d12b3366ff6911b3df628 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:59:01 -0800 Subject: [PATCH 017/168] scsi: lpfc: Fix nonrecovery of NVME controller after cable swap. In a test that is doing large numbers of cable swaps on the target, the nvme controllers wouldn't reconnect. During the cable swaps, the targets n_port_id would change. This information was passed to the nvme-fc transport, in the new remoteport registration. However, the nvme-fc transport didn't update the n_port_id value in the remoteport struct when it reused an existing structure. Later, when a new association was attempted on the remoteport, the driver's NVME LS routine would use the stale n_port_id from the remoteport struct to address the LS. As the device is no longer at that address, the LS would go into never never land. Separately, the nvme-fc transport will be corrected to update the n_port_id value on a re-registration. However, for now, there's no reason to use the transports values. The private pointer points to the drivers node structure and the node structure is up to date. Therefore, revise the LS routine to use the drivers data structures for the LS. Augmented the debug message for better debugging in the future. Also removed a duplicate if check that seems to have slipped in. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index c6e5b9972585..6327f858c4c8 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -241,10 +241,11 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, ndlp = (struct lpfc_nodelist *)cmdwqe->context1; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6047 nvme cmpl Enter " - "Data %p DID %x Xri: %x status %x cmd:%p lsreg:%p " - "bmp:%p ndlp:%p\n", + "Data %p DID %x Xri: %x status %x reason x%x cmd:%p " + "lsreg:%p bmp:%p ndlp:%p\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status, + (wcqe->parameter & 0xffff), cmdwqe, pnvme_lsreq, cmdwqe->context3, ndlp); lpfc_nvmeio_data(phba, "NVME LS CMPL: xri x%x stat x%x parm x%x\n", @@ -419,6 +420,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, { int ret = 0; struct lpfc_nvme_lport *lport; + struct lpfc_nvme_rport *rport; struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; struct ulp_bde64 *bpl; @@ -437,19 +439,18 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, */ lport = (struct lpfc_nvme_lport *)pnvme_lport->private; + rport = (struct lpfc_nvme_rport *)pnvme_rport->private; vport = lport->vport; if (vport->load_flag & FC_UNLOADING) return -ENODEV; - if (vport->load_flag & FC_UNLOADING) - return -ENODEV; - - ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id); + /* Need the ndlp. It is stored in the driver's rport. */ + ndlp = rport->ndlp; if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR, - "6051 DID x%06x not an active rport.\n", - pnvme_rport->port_id); + "6051 Remoteport %p, rport has invalid ndlp. " + "Failing LS Req\n", pnvme_rport); return -ENODEV; } @@ -500,8 +501,9 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, /* Expand print to include key fields. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6149 ENTER. lport %p, rport %p lsreq%p rqstlen:%d " - "rsplen:%d %pad %pad\n", + "6149 Issue LS Req to DID 0x%06x lport %p, rport %p " + "lsreq%p rqstlen:%d rsplen:%d %pad %pad\n", + ndlp->nlp_DID, pnvme_lport, pnvme_rport, pnvme_lsreq, pnvme_lsreq->rqstlen, pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma, @@ -517,7 +519,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, ndlp, 2, 30, 0); if (ret != WQE_SUCCESS) { atomic_inc(&lport->xmt_ls_err); - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, + lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, "6052 EXIT. issue ls wqe failed lport %p, " "rport %p lsreq%p Status %x DID %x\n", pnvme_lport, pnvme_rport, pnvme_lsreq, From 6e9d2f1667ea12bd2f997a7529fb41cce8e0036d Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:59:02 -0800 Subject: [PATCH 018/168] scsi: lpfc: update driver version to 11.4.0.7 Update the driver version to 11.4.0.7 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c232bf0e8998..6f4092cb903e 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.4.0.6" +#define LPFC_DRIVER_VERSION "11.4.0.7" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From 128bddacc4dd7c86070e1e0534687e3083a89d52 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 30 Jan 2018 15:59:03 -0800 Subject: [PATCH 019/168] scsi: lpfc: Update 11.4.0.7 modified files for 2018 Copyright Updated Copyright in files updated 11.4.0.7 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_mem.c | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 4 ++-- drivers/scsi/lpfc/lpfc_nvme.c | 2 +- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- drivers/scsi/lpfc/lpfc_nvmet.h | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 3 +-- drivers/scsi/lpfc/lpfc_sli4.h | 2 +- drivers/scsi/lpfc/lpfc_version.h | 6 +++--- 17 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index d042f9118e3b..9698b9635058 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e25e63eb5a53..7be4bdef4d42 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 3ecf50df93f4..14a86b5b51e4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 404e1af5e2ab..ba896554a14f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 9265906d956e..f5bbac3cadbb 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 52fe28ae50fa..8685d26e6929 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f2d2faef8710..465d890220d5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index c32d4a323db2..7313ceb0f23b 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 60078e61da5e..41361662ff08 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2014 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index bbf1e1342b09..b63179d895e2 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ - /******************************************************************* +/******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6327f858c4c8..3a103d0895a2 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 823b6df0aec7..a332a6638b1b 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channsel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h index 5da35de5ea45..c1bcef3f103c 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.h +++ b/drivers/scsi/lpfc/lpfc_nvmet.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 10c2dc0cf1fa..c595046a521b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d597e15a1974..e97d080e9f65 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,8 +1,7 @@ - /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index ac81bfa59278..4545c1fdcb55 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 6f4092cb903e..4adbf07880a2 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -32,6 +32,6 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright (C) 2017 Broadcom. All Rights Reserved. " \ - "The term \"Broadcom\" refers to Broadcom Limited " \ +#define LPFC_COPYRIGHT "Copyright (C) 2017-2018 Broadcom. All Rights " \ + "Reserved. The term \"Broadcom\" refers to Broadcom Limited " \ "and/or its subsidiaries." From da4704d941766ef61f125d57162eee4ba7f2deda Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Jan 2018 16:33:47 -0800 Subject: [PATCH 020/168] scsi: qla2xxx: Use %p for printing pointers Using %p instead of %lx to print a pointer allows to remove a cast. Signed-off-by: Bart Van Assche Cc: Himanshu Madhani Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index aececf664654..995579ea0f7f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2688,8 +2688,8 @@ qla2x00_chip_diag(scsi_qla_host_t *vha) /* Assume a failed state */ rval = QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_init, vha, 0x007b, - "Testing device at %lx.\n", (u_long)®->flash_address); + ql_dbg(ql_dbg_init, vha, 0x007b, "Testing device at %p.\n", + ®->flash_address); spin_lock_irqsave(&ha->hardware_lock, flags); From 7843327a236c4cf103a8b1d5da2b27e7bace0260 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Jan 2018 16:33:48 -0800 Subject: [PATCH 021/168] scsi: qla2xxx: Remove unused symbols Remove a few preprocessor macros that are not used anywhere. Signed-off-by: Bart Van Assche Cc: Himanshu Madhani Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx2.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nx2.h b/drivers/scsi/qla2xxx/qla_nx2.h index 83c1b7e17c80..8ba7c1db07c3 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.h +++ b/drivers/scsi/qla2xxx/qla_nx2.h @@ -23,10 +23,6 @@ #define MD_MIU_TEST_AGT_WRDATA_HI 0x410000A4 #define MD_MIU_TEST_AGT_WRDATA_ULO 0x410000B0 #define MD_MIU_TEST_AGT_WRDATA_UHI 0x410000B4 -#define MD_MIU_TEST_AGT_RDDATA_LO 0x410000A8 -#define MD_MIU_TEST_AGT_RDDATA_HI 0x410000AC -#define MD_MIU_TEST_AGT_RDDATA_ULO 0x410000B8 -#define MD_MIU_TEST_AGT_RDDATA_UHI 0x410000BC /* MIU_TEST_AGT_CTRL flags. work for SIU as well */ #define MIU_TA_CTL_WRITE_ENABLE (MIU_TA_CTL_WRITE | MIU_TA_CTL_ENABLE) From 454d0d41d2718f6dbc4b447c732040c0e4636c73 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Jan 2018 16:33:49 -0800 Subject: [PATCH 022/168] scsi: qla4xxx: Remove unused symbols Remove a few preprocessor macros that are not used anywhere. Signed-off-by: Bart Van Assche Cc: Himanshu Madhani Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_nx.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 337d9fcf6417..2c098cf9a1ac 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -1022,11 +1022,6 @@ struct qla8xxx_minidump_entry_queue { #define MD_MIU_TEST_AGT_WRDATA_ULO 0x410000B0 #define MD_MIU_TEST_AGT_WRDATA_UHI 0x410000B4 -#define MD_MIU_TEST_AGT_RDDATA_LO 0x410000A8 -#define MD_MIU_TEST_AGT_RDDATA_HI 0x410000AC -#define MD_MIU_TEST_AGT_RDDATA_ULO 0x410000B8 -#define MD_MIU_TEST_AGT_RDDATA_UHI 0x410000BC - static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC }; #endif From bb83e59dae2fd41d0b15dede7fa882c3089f78b0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Jan 2018 16:33:50 -0800 Subject: [PATCH 023/168] scsi: qla4xxx: Move an array from a .h into a .c file This patch does not change any functionality but slightly reduces the size of the compiled kernel module. Signed-off-by: Bart Van Assche Cc: Himanshu Madhani Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_nx.c | 2 ++ drivers/scsi/qla4xxx/ql4_nx.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 968bd85610f8..43f73583ef5c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -45,6 +45,8 @@ qla4_8xxx_pci_base_offsetfset(struct scsi_qla_host *ha, unsigned long off) return NULL; } +static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, + 0x410000AC, 0x410000B8, 0x410000BC }; #define MAX_CRB_XFORM 60 static unsigned long crb_addr_xform[MAX_CRB_XFORM]; static int qla4_8xxx_crb_table_initialized; diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 2c098cf9a1ac..98fe78613eb7 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -1022,6 +1022,4 @@ struct qla8xxx_minidump_entry_queue { #define MD_MIU_TEST_AGT_WRDATA_ULO 0x410000B0 #define MD_MIU_TEST_AGT_WRDATA_UHI 0x410000B4 -static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, - 0x410000AC, 0x410000B8, 0x410000BC }; #endif From 2db6228d9cd13bc3bb83bf3436998ea82b0d56ae Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Jan 2018 16:33:51 -0800 Subject: [PATCH 024/168] scsi: qla2xxx: Fix function argument descriptions Bring the kernel-doc headers in sync with the function argument lists. Signed-off-by: Bart Van Assche Cc: Himanshu Madhani Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 4 +- drivers/scsi/qla2xxx/qla_gs.c | 78 +++++++++++++++---------------- drivers/scsi/qla2xxx/qla_init.c | 33 ++++++------- drivers/scsi/qla2xxx/qla_inline.h | 1 + drivers/scsi/qla2xxx/qla_iocb.c | 15 ++++-- drivers/scsi/qla2xxx/qla_isr.c | 23 +++++---- drivers/scsi/qla2xxx/qla_mbx.c | 5 +- drivers/scsi/qla2xxx/qla_mr.c | 36 ++++++++------ drivers/scsi/qla2xxx/qla_nx.c | 7 ++- drivers/scsi/qla2xxx/qla_nx2.c | 19 ++++---- drivers/scsi/qla2xxx/qla_sup.c | 1 + drivers/scsi/qla2xxx/qla_target.c | 7 +-- 12 files changed, 125 insertions(+), 104 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 3e9dc54b89a3..7e9d8f08b9d5 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -717,7 +717,7 @@ qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval) /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. - * @ha: HA context + * @vha: HA context * @hardware_locked: Called with the hardware_lock */ void @@ -887,7 +887,7 @@ qla2300_fw_dump_failed: /** * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware. - * @ha: HA context + * @vha: HA context * @hardware_locked: Called with the hardware_lock */ void diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 5bf9a59432f6..e4d404c24506 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -21,11 +21,10 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *); /** * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. - * @ha: HA context - * @req_size: request size in bytes - * @rsp_size: response size in bytes + * @vha: HA context + * @arg: CT arguments * - * Returns a pointer to the @ha's ms_iocb. + * Returns a pointer to the @vha's ms_iocb. */ void * qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg) @@ -61,9 +60,8 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg) /** * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query. - * @ha: HA context - * @req_size: request size in bytes - * @rsp_size: response size in bytes + * @vha: HA context + * @arg: CT arguments * * Returns a pointer to the @ha's ms_iocb. */ @@ -101,7 +99,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg) /** * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. - * @ct_req: CT request buffer + * @p: CT request buffer * @cmd: GS command * @rsp_size: response size in bytes * @@ -196,7 +194,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt, /** * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command. - * @ha: HA context + * @vha: HA context * @fcport: fcport entry to updated * * Returns 0 on success. @@ -283,7 +281,7 @@ qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha) /** * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * NOTE: Non-Nx_Ports are not requested. @@ -371,7 +369,7 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * Returns 0 on success. @@ -441,7 +439,7 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * Returns 0 on success. @@ -583,7 +581,7 @@ err2: /** * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -675,7 +673,8 @@ done: /** * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA. - * @ha: HA context + * @vha: HA context + * @type: not used * * Returns 0 on success. */ @@ -769,7 +768,7 @@ done: /** * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -874,7 +873,7 @@ qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size) /** * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -970,7 +969,7 @@ done: /** * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query. - * @ha: HA context + * @vha: HA context * @cmd: GS command * @scmd_len: Subcommand length * @data_size: response size in bytes @@ -1003,7 +1002,7 @@ qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len, /** * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command. - * @ha: HA context + * @vha: HA context * @fcport: fcport entry to updated * * This command uses the old Exectute SNS Command mailbox routine. @@ -1067,7 +1066,7 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport) /** * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * This command uses the old Exectute SNS Command mailbox routine. @@ -1140,7 +1139,7 @@ qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * This command uses the old Exectute SNS Command mailbox routine. @@ -1196,7 +1195,7 @@ qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * This command uses the old Exectute SNS Command mailbox routine. @@ -1259,7 +1258,7 @@ qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA. - * @ha: HA context + * @vha: HA context * * This command uses the old Exectute SNS Command mailbox routine. * @@ -1308,8 +1307,7 @@ qla2x00_sns_rft_id(scsi_qla_host_t *vha) /** * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA. - * HBA. - * @ha: HA context + * @vha: HA context * * This command uses the old Exectute SNS Command mailbox routine. * @@ -1365,7 +1363,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha) /** * qla2x00_mgmt_svr_login() - Login to fabric Management Service. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -1401,7 +1399,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha) /** * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. - * @ha: HA context + * @vha: HA context * @req_size: request size in bytes * @rsp_size: response size in bytes * @@ -1439,7 +1437,7 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, /** * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. - * @ha: HA context + * @vha: HA context * @req_size: request size in bytes * @rsp_size: response size in bytes * @@ -1496,7 +1494,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size) /** * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. - * @ct_req: CT request buffer + * @p: CT request buffer * @cmd: GS command * @rsp_size: response size in bytes * @@ -1518,8 +1516,8 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd, } /** - * qla2x00_fdmi_rhba() - - * @ha: HA context + * qla2x00_fdmi_rhba() - perform RHBA FDMI registration + * @vha: HA context * * Returns 0 on success. */ @@ -1728,8 +1726,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) } /** - * qla2x00_fdmi_rpa() - - * @ha: HA context + * qla2x00_fdmi_rpa() - perform RPA registration + * @vha: HA context * * Returns 0 on success. */ @@ -1940,8 +1938,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) } /** - * qla2x00_fdmiv2_rhba() - - * @ha: HA context + * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration + * @vha: HA context * * Returns 0 on success. */ @@ -2257,7 +2255,7 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) /** * qla2x00_fdmi_dhba() - - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2305,7 +2303,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) /** * qla2x00_fdmiv2_rpa() - - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2635,7 +2633,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) /** * qla2x00_fdmi_register() - - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2693,7 +2691,7 @@ out: /** * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * Returns 0 on success. @@ -2778,7 +2776,7 @@ qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd, /** * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query. - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * * Returns 0 on success. @@ -2892,7 +2890,7 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list) /** * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query. * - * @ha: HA context + * @vha: HA context * @list: switch info entries to populate * */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 995579ea0f7f..590aa904fdef 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2046,7 +2046,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) /** * qla2100_pci_config() - Setup ISP21xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2077,7 +2077,7 @@ qla2100_pci_config(scsi_qla_host_t *vha) /** * qla2300_pci_config() - Setup ISP23xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2159,7 +2159,7 @@ qla2300_pci_config(scsi_qla_host_t *vha) /** * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2203,7 +2203,7 @@ qla24xx_pci_config(scsi_qla_host_t *vha) /** * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2234,7 +2234,7 @@ qla25xx_pci_config(scsi_qla_host_t *vha) /** * qla2x00_isp_firmware() - Choose firmware image. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2270,7 +2270,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha) /** * qla2x00_reset_chip() - Reset ISP chip. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2414,6 +2414,7 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) /** * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC. + * @vha: HA context * * Returns 0 on success. */ @@ -2430,7 +2431,7 @@ qla81xx_reset_mpi(scsi_qla_host_t *vha) /** * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2645,7 +2646,7 @@ acquired: /** * qla24xx_reset_chip() - Reset ISP24xx chip. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2669,7 +2670,7 @@ qla24xx_reset_chip(scsi_qla_host_t *vha) /** * qla2x00_chip_diag() - Test chip for proper operation. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2793,7 +2794,7 @@ chip_diag_failed: /** * qla24xx_chip_diag() - Test ISP24xx for proper operation. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -3261,7 +3262,7 @@ out: /** * qla2x00_setup_chip() - Load and start RISC firmware. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -3416,7 +3417,7 @@ failed: /** * qla2x00_init_response_q_entries() - Initializes response queue entries. - * @ha: HA context + * @rsp: response queue * * Beginning of request ring has initialization control block already built * by nvram config routine. @@ -3441,7 +3442,7 @@ qla2x00_init_response_q_entries(struct rsp_que *rsp) /** * qla2x00_update_fw_options() - Read and process firmware options. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -3704,7 +3705,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha) /** * qla2x00_init_rings() - Initializes firmware. - * @ha: HA context + * @vha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. @@ -3812,7 +3813,7 @@ next_check: /** * qla2x00_fw_ready() - Waits for firmware ready. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -4480,7 +4481,7 @@ qla2x00_rport_del(void *data) /** * qla2x00_alloc_fcport() - Allocate a generic fcport. - * @ha: HA context + * @vha: HA context * @flags: allocation flags * * Returns a pointer to the allocated fcport, or NULL, if none available. diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 4d32426393c7..b7a05aebf065 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -10,6 +10,7 @@ * qla24xx_calc_iocbs() - Determine number of Command Type 3 and * Continuation Type 1 IOCBs to allocate. * + * @vha: HA context * @dsds: number of data segment decriptors needed * * Returns the number of IOCB entries needed to store @dsds. diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 1b62e943ec49..e62ccd931853 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -14,7 +14,7 @@ /** * qla2x00_get_cmd_direction() - Determine control_flag data direction. - * @cmd: SCSI command + * @sp: SCSI command * * Returns the proper CF_* direction based on CDB. */ @@ -86,7 +86,7 @@ qla2x00_calc_iocbs_64(uint16_t dsds) /** * qla2x00_prep_cont_type0_iocb() - Initialize a Continuation Type 0 IOCB. - * @ha: HA context + * @vha: HA context * * Returns a pointer to the Continuation Type 0 IOCB packet. */ @@ -114,7 +114,8 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) /** * qla2x00_prep_cont_type1_iocb() - Initialize a Continuation Type 1 IOCB. - * @ha: HA context + * @vha: HA context + * @req: request queue * * Returns a pointer to the continuation type 1 IOCB packet. */ @@ -445,6 +446,8 @@ queuing_error: /** * qla2x00_start_iocbs() - Execute the IOCB command + * @vha: HA context + * @req: request queue */ void qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) @@ -486,7 +489,9 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) /** * qla2x00_marker() - Send a marker IOCB to the firmware. - * @ha: HA context + * @vha: HA context + * @req: request queue + * @rsp: response queue * @loop_id: loop ID * @lun: LUN * @type: marker modifier @@ -1190,6 +1195,8 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, * @sp: SRB command to process * @cmd_pkt: Command type 3 IOCB * @tot_dsds: Total number of segments to transfer + * @tot_prot_dsds: + * @fw_prot_opts: */ inline int qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 14109d86c3f6..16c43bd9bb83 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -259,7 +259,7 @@ qla2300_intr_handler(int irq, void *dev_id) /** * qla2x00_mbx_completion() - Process mailbox command completions. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context * @mb0: Mailbox0 register */ static void @@ -612,7 +612,8 @@ qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id, /** * qla2x00_async_event() - Process aynchronous events. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue * @mb: Mailbox registers (0 - 3) */ void @@ -1255,7 +1256,8 @@ global_port_update: /** * qla2x00_process_completed_request() - Process a Fast Post response. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @req: request queue * @index: SRB index */ void @@ -1969,7 +1971,7 @@ static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req, /** * qla2x00_process_response_queue() - Process response queue entries. - * @ha: SCSI driver HA context + * @rsp: response queue */ void qla2x00_process_response_queue(struct rsp_que *rsp) @@ -2373,7 +2375,8 @@ done: /** * qla2x00_status_entry() - Process a Status IOCB entry. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer */ static void @@ -2750,7 +2753,7 @@ out: /** * qla2x00_status_cont_entry() - Process a Status Continuations entry. - * @ha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer * * Extended sense data. @@ -2808,7 +2811,8 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) /** * qla2x00_error_entry() - Process an error entry. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer * return : 1=allow further error analysis. 0=no additional error analysis. */ @@ -2867,7 +2871,7 @@ fatal: /** * qla24xx_mbx_completion() - Process mailbox command completions. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context * @mb0: Mailbox0 register */ static void @@ -2935,7 +2939,8 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha, /** * qla24xx_process_response_queue() - Process response queue entries. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue */ void qla24xx_process_response_queue(struct scsi_qla_host *vha, struct rsp_que *rsp) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7397aeddd96c..41b0ee47c6a1 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3385,7 +3385,10 @@ qla8044_read_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data) /** * qla2x00_set_serdes_params() - - * @ha: HA context + * @vha: HA context + * @sw_em_1g: + * @sw_em_2g: + * @sw_em_4g: * * Returns */ diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index d5da3981cefe..7113acf42ff3 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -490,7 +490,7 @@ qlafx00_mbx_reg_test(scsi_qla_host_t *vha) /** * qlafx00_pci_config() - Setup ISPFx00 PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -519,9 +519,9 @@ qlafx00_pci_config(scsi_qla_host_t *vha) /** * qlafx00_warm_reset() - Perform warm reset of iSA(CPUs being reset on SOC). - * @ha: HA context + * @vha: HA context * - */ + */ static inline void qlafx00_soc_cpu_reset(scsi_qla_host_t *vha) { @@ -625,7 +625,7 @@ qlafx00_soc_cpu_reset(scsi_qla_host_t *vha) /** * qlafx00_soft_reset() - Soft Reset ISPFx00. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -644,7 +644,7 @@ qlafx00_soft_reset(scsi_qla_host_t *vha) /** * qlafx00_chip_diag() - Test ISPFx00 for proper operation. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -1408,7 +1408,7 @@ qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha, bool critemp) /** * qlafx00_init_response_q_entries() - Initializes response queue entries. - * @ha: HA context + * @rsp: response queue * * Beginning of request ring has initialization control block already built * by nvram config routine. @@ -2269,7 +2269,8 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, /** * qlafx00_status_entry() - Process a Status IOCB entry. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer */ static void @@ -2542,7 +2543,7 @@ check_scsi_status: /** * qlafx00_status_cont_entry() - Process a Status Continuations entry. - * @ha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer * * Extended sense data. @@ -2620,7 +2621,9 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) /** * qlafx00_multistatus_entry() - Process Multi response queue entries. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue + * @pkt: */ static void qlafx00_multistatus_entry(struct scsi_qla_host *vha, @@ -2674,8 +2677,11 @@ qlafx00_multistatus_entry(struct scsi_qla_host *vha, /** * qlafx00_error_entry() - Process an error entry. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue * @pkt: Entry pointer + * @estatus: + * @etype: */ static void qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, @@ -2705,7 +2711,8 @@ qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, /** * qlafx00_process_response_queue() - Process response queue entries. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context + * @rsp: response queue */ static void qlafx00_process_response_queue(struct scsi_qla_host *vha, @@ -2781,7 +2788,7 @@ qlafx00_process_response_queue(struct scsi_qla_host *vha, /** * qlafx00_async_event() - Process aynchronous events. - * @ha: SCSI driver HA context + * @vha: SCSI driver HA context */ static void qlafx00_async_event(scsi_qla_host_t *vha) @@ -2857,10 +2864,9 @@ qlafx00_async_event(scsi_qla_host_t *vha) } /** - * * qlafx00x_mbx_completion() - Process mailbox command completions. - * @ha: SCSI driver HA context - * @mb16: Mailbox16 register + * @vha: SCSI driver HA context + * @mb0: */ static void qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index a77c33987703..872d66dd79cd 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1732,7 +1732,7 @@ iospace_error_exit: /** * qla82xx_pci_config() - Setup ISP82xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -1753,7 +1753,7 @@ qla82xx_pci_config(scsi_qla_host_t *vha) /** * qla82xx_reset_chip() - Setup ISP82xx PCI configuration registers. - * @ha: HA context + * @vha: HA context * * Returns 0 on success. */ @@ -2008,11 +2008,10 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) "MBX pointer ERROR.\n"); } -/* +/** * qla82xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: * @dev_id: SCSI driver HA context - * @regs: * * Called by system whenever the host adapter generates an interrupt. * diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 525ac35a757b..3a2b0282df14 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -280,9 +280,8 @@ qla8044_clear_qsnt_ready(struct scsi_qla_host *vha) } /** - * * qla8044_lock_recovery - Recovers the idc_lock. - * @ha : Pointer to adapter structure + * @vha : Pointer to adapter structure * * Lock Recovery Register * 5-2 Lock recovery owner: Function ID of driver doing lock recovery, @@ -1639,10 +1638,10 @@ qla8044_set_rst_ready(struct scsi_qla_host *vha) /** * qla8044_need_reset_handler - Code to start reset sequence - * @ha: pointer to adapter structure + * @vha: pointer to adapter structure * * Note: IDC lock must be held upon entry - **/ + */ static void qla8044_need_reset_handler(struct scsi_qla_host *vha) { @@ -1859,8 +1858,8 @@ exit_update_idc_reg: /** * qla8044_need_qsnt_handler - Code to start qsnt - * @ha: pointer to adapter structure - **/ + * @vha: pointer to adapter structure + */ static void qla8044_need_qsnt_handler(struct scsi_qla_host *vha) { @@ -2031,10 +2030,10 @@ exit_error: /** * qla4_8xxx_check_temp - Check the ISP82XX temperature. - * @ha: adapter block pointer. + * @vha: adapter block pointer. * * Note: The caller should not hold the idc lock. - **/ + */ static int qla8044_check_temp(struct scsi_qla_host *vha) { @@ -2071,10 +2070,10 @@ int qla8044_read_temperature(scsi_qla_host_t *vha) /** * qla8044_check_fw_alive - Check firmware health - * @ha: Pointer to host adapter structure. + * @vha: Pointer to host adapter structure. * * Context: Interrupt - **/ + */ int qla8044_check_fw_alive(struct scsi_qla_host *vha) { diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index d2db86ea06b2..04458eb19d38 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2226,6 +2226,7 @@ qla2x00_erase_flash_sector(struct qla_hw_data *ha, uint32_t addr, /** * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. + * @ha: * @man_id: Flash manufacturer ID * @flash_id: Flash ID */ diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index fc89af8fe256..3735ebd83012 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6299,10 +6299,11 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, /** * qla_tgt_lport_register - register lport with external module * - * @qla_tgt_ops: Pointer for tcm_qla2xxx qla_tgt_ops - * @wwpn: Passwd FC target WWPN - * @callback: lport initialization callback for tcm_qla2xxx code * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data + * @phys_wwpn: + * @npiv_wwpn: + * @npiv_wwnn: + * @callback: lport initialization callback for tcm_qla2xxx code */ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, u64 npiv_wwpn, u64 npiv_wwnn, From 34e81f7a720d8a638f46b18b35678712dbafb42d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Jan 2018 09:07:58 +0100 Subject: [PATCH 025/168] scsi: raid_class: Add 'JBOD' RAID level Not a real RAID level, but some HBAs support JBOD in addition to the 'classical' RAID levels. Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/raid_class.c | 1 + include/linux/raid_class.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 2c146b44d95f..ea88906d2cc5 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -157,6 +157,7 @@ static struct { { RAID_LEVEL_5, "raid5" }, { RAID_LEVEL_50, "raid50" }, { RAID_LEVEL_6, "raid6" }, + { RAID_LEVEL_JBOD, "jbod" }, }; static const char *raid_level_name(enum raid_level level) diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h index 31e1ff69efc8..ec8655514283 100644 --- a/include/linux/raid_class.h +++ b/include/linux/raid_class.h @@ -38,6 +38,7 @@ enum raid_level { RAID_LEVEL_5, RAID_LEVEL_50, RAID_LEVEL_6, + RAID_LEVEL_JBOD, }; struct raid_data { From 458df78b1c513de9311afd913bdf93777af2d157 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 26 Jan 2018 08:52:19 -0800 Subject: [PATCH 026/168] scsi: scsi_debug: Simplify request tag decoding Since commit 64d513ac31bd ("scsi: use host wide tags by default") all SCSI requests have a tag, whether or not scsi-mq is enabled. Additionally, it is safe to use blk_mq_unique_tag() and blk_mq_unique_tag_to_hwq() for legacy SCSI queues. Since this means that the sdebug_mq_active variable is superfluous, remove it. Signed-off-by: Bart Van Assche Cc: Douglas Gilbert Cc: Christoph Hellwig Cc: Hannes Reinecke Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index a5986dae9020..7d2ce0cc915a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -649,7 +649,6 @@ static bool sdebug_any_injecting_opt; static bool sdebug_verbose; static bool have_dif_prot; static bool sdebug_statistics = DEF_STATISTICS; -static bool sdebug_mq_active; static unsigned int sdebug_store_sectors; static sector_t sdebug_capacity; /* in sectors */ @@ -3727,20 +3726,13 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp, static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) { - struct sdebug_queue *sqp = sdebug_q_arr; + u32 tag = blk_mq_unique_tag(cmnd->request); + u16 hwq = blk_mq_unique_tag_to_hwq(tag); - if (sdebug_mq_active) { - u32 tag = blk_mq_unique_tag(cmnd->request); - u16 hwq = blk_mq_unique_tag_to_hwq(tag); - - if (unlikely(hwq >= submit_queues)) { - pr_warn("Unexpected hwq=%d, apply modulo\n", hwq); - hwq %= submit_queues; - } - pr_debug("tag=%u, hwq=%d\n", tag, hwq); - return sqp + hwq; - } else - return sqp; + pr_debug("tag=%#x, hwq=%d\n", tag, hwq); + if (WARN_ON_ONCE(hwq >= submit_queues)) + hwq = 0; + return sdebug_q_arr + hwq; } /* Queued (deferred) command completions converge here. */ @@ -4587,9 +4579,8 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) num_host_resets); seq_printf(m, "dix_reads=%d, dix_writes=%d, dif_errors=%d\n", dix_reads, dix_writes, dif_errors); - seq_printf(m, "usec_in_jiffy=%lu, %s=%d, mq_active=%d\n", - TICK_NSEC / 1000, "statistics", sdebug_statistics, - sdebug_mq_active); + seq_printf(m, "usec_in_jiffy=%lu, statistics=%d\n", TICK_NSEC / 1000, + sdebug_statistics); seq_printf(m, "cmnd_count=%d, completions=%d, %s=%d, a_tsf=%d\n", atomic_read(&sdebug_cmnd_count), atomic_read(&sdebug_completions), @@ -5612,13 +5603,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, n += scnprintf(b + n, sb - n, "%02x ", (u32)cmd[k]); } - if (sdebug_mq_active) - sdev_printk(KERN_INFO, sdp, "%s: tag=%u, cmd %s\n", - my_name, blk_mq_unique_tag(scp->request), - b); - else - sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, - b); + sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name, + blk_mq_unique_tag(scp->request), b); } if (fake_host_busy(scp)) return SCSI_MLQUEUE_HOST_BUSY; @@ -5782,8 +5768,7 @@ static int sdebug_driver_probe(struct device * dev) } /* Decide whether to tell scsi subsystem that we want mq */ /* Following should give the same answer for each host */ - sdebug_mq_active = shost_use_blk_mq(hpnt) && (submit_queues > 1); - if (sdebug_mq_active) + if (shost_use_blk_mq(hpnt)) hpnt->nr_hw_queues = submit_queues; sdbg_host->shost = hpnt; From d9da891a892a38db4ec7abcc2df57f9ae3777d99 Mon Sep 17 00:00:00 2001 From: Laurence Oberman Date: Sat, 3 Feb 2018 13:38:35 -0500 Subject: [PATCH 027/168] scsi: scsi_debug: Add two new parameters to scsi_debug driver This patch adds two new parameters to the scsi_debug driver. During various fault injection scenarios it would be useful to be able to pick a specific starting sector and number of follow on sectors where a MEDIUM ERROR for reads would be returned against a scsi-debug device. Right now this only works against sector 0x1234 and OPT_MEDIUM_ERR_NUM follow on sectors. However during testing of md-raid and other scenarios I wanted more flexibility. The idea is add 2 new parameters: medium_error_start medium_error_count If medium_error_start is set then we don't use the default of OPT_MEDIUM_ERR_ADDR, but use that set value. If medium_error_count is set we use that value otherwise default to OPT_MEDIUM_ERR_NUM. Signed-off-by: Laurence Oberman Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 7d2ce0cc915a..8480e4849e29 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -616,6 +616,8 @@ static unsigned int sdebug_guard = DEF_GUARD; static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ +static unsigned int sdebug_medium_error_start = OPT_MEDIUM_ERR_ADDR; +static int sdebug_medium_error_count = OPT_MEDIUM_ERR_NUM; static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ static int sdebug_ndelay = DEF_NDELAY; /* if > 0 then unit is nanoseconds */ static int sdebug_no_lun_0 = DEF_NO_LUN_0; @@ -2711,8 +2713,8 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) } if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) && - (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && - ((lba + num) > OPT_MEDIUM_ERR_ADDR))) { + (lba <= (sdebug_medium_error_start + sdebug_medium_error_count - 1)) && + ((lba + num) > sdebug_medium_error_start))) { /* claim unrecoverable read error */ mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); /* set info field and valid bit for fixed descriptor */ @@ -4432,6 +4434,8 @@ module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO); module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO); module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR); module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR); +module_param_named(medium_error_start, sdebug_medium_error_start, int, S_IRUGO | S_IWUSR); +module_param_named(medium_error_count, sdebug_medium_error_count, int, S_IRUGO | S_IWUSR); module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR); module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR); module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO); @@ -4489,6 +4493,8 @@ MODULE_PARM_DESC(lbprz, MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); +MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error"); +MODULE_PARM_DESC(medium_error_count, "count of sectors to return follow on MEDIUM error"); MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)"); MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))"); From 779936faf4f1210a2a6c3a2ccc63cd74a61769ed Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 14:12:19 +0100 Subject: [PATCH 028/168] scsi: qedi: fix building with LTO When link-time optimizations are enabled, qedi fails to build because of mismatched prototypes: drivers/scsi/qedi/qedi_gbl.h:27:37: error: type of 'qedi_dbg_fops' does not match original declaration [-Werror=lto-type-mismatch] extern const struct file_operations qedi_dbg_fops; ^ drivers/scsi/qedi/qedi_debugfs.c:239:30: note: 'qedi_dbg_fops' was previously declared here const struct file_operations qedi_dbg_fops[] = { ^ drivers/scsi/qedi/qedi_gbl.h:26:32: error: type of 'qedi_debugfs_ops' does not match original declaration [-Werror=lto-type-mismatch] extern struct qedi_debugfs_ops qedi_debugfs_ops; ^ drivers/scsi/qedi/qedi_debugfs.c:102:25: note: 'qedi_debugfs_ops' was previously declared here struct qedi_debugfs_ops qedi_debugfs_ops[] = { This changes the declaration to match the definition, and adapts the users as necessary. Since both array can be constant here, I'm adding the 'const' everywhere for consistency. Signed-off-by: Arnd Bergmann Acked-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_dbg.h | 2 +- drivers/scsi/qedi/qedi_debugfs.c | 4 ++-- drivers/scsi/qedi/qedi_gbl.h | 4 ++-- drivers/scsi/qedi/qedi_main.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qedi/qedi_dbg.h b/drivers/scsi/qedi/qedi_dbg.h index c55572badfb0..358f40567849 100644 --- a/drivers/scsi/qedi/qedi_dbg.h +++ b/drivers/scsi/qedi/qedi_dbg.h @@ -134,7 +134,7 @@ struct qedi_debugfs_ops { } void qedi_dbg_host_init(struct qedi_dbg_ctx *qedi, - struct qedi_debugfs_ops *dops, + const struct qedi_debugfs_ops *dops, const struct file_operations *fops); void qedi_dbg_host_exit(struct qedi_dbg_ctx *qedi); void qedi_dbg_init(char *drv_name); diff --git a/drivers/scsi/qedi/qedi_debugfs.c b/drivers/scsi/qedi/qedi_debugfs.c index fd8a1eea3163..fd914ca4149a 100644 --- a/drivers/scsi/qedi/qedi_debugfs.c +++ b/drivers/scsi/qedi/qedi_debugfs.c @@ -19,7 +19,7 @@ static struct dentry *qedi_dbg_root; void qedi_dbg_host_init(struct qedi_dbg_ctx *qedi, - struct qedi_debugfs_ops *dops, + const struct qedi_debugfs_ops *dops, const struct file_operations *fops) { char host_dirname[32]; @@ -99,7 +99,7 @@ static struct qedi_list_of_funcs qedi_dbg_do_not_recover_ops[] = { { NULL, NULL } }; -struct qedi_debugfs_ops qedi_debugfs_ops[] = { +const struct qedi_debugfs_ops qedi_debugfs_ops[] = { { "gbl_ctx", NULL }, { "do_not_recover", qedi_dbg_do_not_recover_ops}, { "io_trace", NULL }, diff --git a/drivers/scsi/qedi/qedi_gbl.h b/drivers/scsi/qedi/qedi_gbl.h index f5b5a31999aa..a2aa06ed1620 100644 --- a/drivers/scsi/qedi/qedi_gbl.h +++ b/drivers/scsi/qedi/qedi_gbl.h @@ -23,8 +23,8 @@ extern uint qedi_io_tracing; extern struct scsi_host_template qedi_host_template; extern struct iscsi_transport qedi_iscsi_transport; extern const struct qed_iscsi_ops *qedi_ops; -extern struct qedi_debugfs_ops qedi_debugfs_ops; -extern const struct file_operations qedi_dbg_fops; +extern const struct qedi_debugfs_ops qedi_debugfs_ops[]; +extern const struct file_operations qedi_dbg_fops[]; extern struct device_attribute *qedi_shost_attrs[]; int qedi_alloc_sq(struct qedi_ctx *qedi, struct qedi_endpoint *ep); diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 029e2e69b29f..e992f9d3ef00 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -2303,8 +2303,8 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) } #ifdef CONFIG_DEBUG_FS - qedi_dbg_host_init(&qedi->dbg_ctx, &qedi_debugfs_ops, - &qedi_dbg_fops); + qedi_dbg_host_init(&qedi->dbg_ctx, qedi_debugfs_ops, + qedi_dbg_fops); #endif QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO, "QLogic FastLinQ iSCSI Module qedi %s, FW %d.%d.%d.%d\n", From 8d6febb0ccac88261fd50d425fceeca215551f11 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 6 Feb 2018 14:03:16 +0000 Subject: [PATCH 029/168] scsi: qedf: remove redundant initialization of 'fcport' Pointer fcport is initialized with a value that is never read, it is re-assigned a new value later on, hence the initialization is redundant and can be removed. Cleans up clang warning: drivers/scsi/qedf/qedf_io.c:920:21: warning: Value stored to 'fcport' during its initialization is never read Signed-off-by: Colin Ian King Acked-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index b15e69586a36..50a50c4249d0 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -917,7 +917,7 @@ qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd) struct qedf_ctx *qedf = lport_priv(lport); struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device)); struct fc_rport_libfc_priv *rp = rport->dd_data; - struct qedf_rport *fcport = rport->dd_data; + struct qedf_rport *fcport; struct qedf_ioreq *io_req; int rc = 0; int rval; From bc2e1299a828a13a44c3140a3c0a183c87872606 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 6 Feb 2018 14:21:57 +0000 Subject: [PATCH 030/168] scsi: libfc: remove redundant initialization of 'disc' Pointer disc is being intializated a value that is never read and then re-assigned the same value later on, hence the initialization is redundant and can be removed. Cleans up clang warning: drivers/scsi/libfc/fc_disc.c:734:18: warning: Value stored to 'disc' during its initialization is never read Signed-off-by: Colin Ian King Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 8660f923ace0..3f3569ec5ce3 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -731,7 +731,7 @@ static void fc_disc_stop_final(struct fc_lport *lport) */ void fc_disc_config(struct fc_lport *lport, void *priv) { - struct fc_disc *disc = &lport->disc; + struct fc_disc *disc; if (!lport->tt.disc_start) lport->tt.disc_start = fc_disc_start; From d9ea463a1cc7f0a6254cbd8228e1948c345a4acd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 14:12:18 +0100 Subject: [PATCH 031/168] scsi: qedf: fix LTO-enabled build The prototype for qedf_dbg_fops/qedf_debugfs_ops doesn't match the definition, which causes the final link to fail with link-time optimizations: drivers/scsi/qedf/qedf_main.c:34: error: type of 'qedf_dbg_fops' does not match original declaration [-Werror=lto-type-mismatch] extern struct file_operations qedf_dbg_fops; drivers/scsi/qedf/qedf_debugfs.c:443: note: 'qedf_dbg_fops' was previously declared here const struct file_operations qedf_dbg_fops[] = { drivers/scsi/qedf/qedf_main.c:33: error: type of 'qedf_debugfs_ops' does not match original declaration [-Werror=lto-type-mismatch] extern struct qedf_debugfs_ops qedf_debugfs_ops; drivers/scsi/qedf/qedf_debugfs.c:102: note: 'qedf_debugfs_ops' was previously declared here struct qedf_debugfs_ops qedf_debugfs_ops[] = { This corrects the prototype and moves it into a shared header file where it belongs. The file operations can also be marked 'const' like the qedf_debugfs_ops. Signed-off-by: Arnd Bergmann Acked-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_dbg.h | 17 ++++++++++------- drivers/scsi/qedf/qedf_debugfs.c | 6 +++--- drivers/scsi/qedf/qedf_main.c | 8 +++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h index 50083cae84c3..77c27e888969 100644 --- a/drivers/scsi/qedf/qedf_dbg.h +++ b/drivers/scsi/qedf/qedf_dbg.h @@ -116,6 +116,14 @@ extern int qedf_create_sysfs_attr(struct Scsi_Host *shost, extern void qedf_remove_sysfs_attr(struct Scsi_Host *shost, struct sysfs_bin_attrs *iter); +struct qedf_debugfs_ops { + char *name; + struct qedf_list_of_funcs *qedf_funcs; +}; + +extern const struct qedf_debugfs_ops qedf_debugfs_ops[]; +extern const struct file_operations qedf_dbg_fops[]; + #ifdef CONFIG_DEBUG_FS /* DebugFS related code */ struct qedf_list_of_funcs { @@ -123,11 +131,6 @@ struct qedf_list_of_funcs { ssize_t (*oper_func)(struct qedf_dbg_ctx *qedf); }; -struct qedf_debugfs_ops { - char *name; - struct qedf_list_of_funcs *qedf_funcs; -}; - #define qedf_dbg_fileops(drv, ops) \ { \ .owner = THIS_MODULE, \ @@ -147,8 +150,8 @@ struct qedf_debugfs_ops { } extern void qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, - struct qedf_debugfs_ops *dops, - struct file_operations *fops); + const struct qedf_debugfs_ops *dops, + const struct file_operations *fops); extern void qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf); extern void qedf_dbg_init(char *drv_name); extern void qedf_dbg_exit(void); diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c index 2b1ef3075e93..c539a7ae3a7e 100644 --- a/drivers/scsi/qedf/qedf_debugfs.c +++ b/drivers/scsi/qedf/qedf_debugfs.c @@ -23,8 +23,8 @@ static struct dentry *qedf_dbg_root; **/ void qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, - struct qedf_debugfs_ops *dops, - struct file_operations *fops) + const struct qedf_debugfs_ops *dops, + const struct file_operations *fops) { char host_dirname[32]; struct dentry *file_dentry = NULL; @@ -99,7 +99,7 @@ qedf_dbg_exit(void) qedf_dbg_root = NULL; } -struct qedf_debugfs_ops qedf_debugfs_ops[] = { +const struct qedf_debugfs_ops qedf_debugfs_ops[] = { { "fp_int", NULL }, { "io_trace", NULL }, { "debug", NULL }, diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index ccd9a08ea030..284ccb566b19 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -23,6 +23,7 @@ #include #include #include "qedf.h" +#include "qedf_dbg.h" #include const struct qed_fcoe_ops *qed_ops; @@ -30,9 +31,6 @@ const struct qed_fcoe_ops *qed_ops; static int qedf_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void qedf_remove(struct pci_dev *pdev); -extern struct qedf_debugfs_ops qedf_debugfs_ops; -extern struct file_operations qedf_dbg_fops; - /* * Driver module parameters. */ @@ -3155,8 +3153,8 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) } #ifdef CONFIG_DEBUG_FS - qedf_dbg_host_init(&(qedf->dbg_ctx), &qedf_debugfs_ops, - &qedf_dbg_fops); + qedf_dbg_host_init(&(qedf->dbg_ctx), qedf_debugfs_ops, + qedf_dbg_fops); #endif /* Start LL2 */ From a8db6140d7d5396263935a48f0bd7eca3b90f15d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 14:12:20 +0100 Subject: [PATCH 032/168] scsi: qedf: use correct strncpy() size gcc-8 warns during link-time optimization that the strncpy() call passes the size of the source buffer rather than the destination: drivers/scsi/qedf/qedf_dbg.c: In function 'qedf_uevent_emit': include/linux/string.h:253: error: 'strncpy' specified bound depends on the length of the source argument [-Werror=stringop-overflow=] This changes it to strscpy() with the correct length, guaranteeing a properly nul-terminated string of the right size. Signed-off-by: Arnd Bergmann Acked-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qedf/qedf_dbg.c b/drivers/scsi/qedf/qedf_dbg.c index e023f5d0dc12..bd1cef25a900 100644 --- a/drivers/scsi/qedf/qedf_dbg.c +++ b/drivers/scsi/qedf/qedf_dbg.c @@ -160,7 +160,7 @@ qedf_uevent_emit(struct Scsi_Host *shost, u32 code, char *msg) switch (code) { case QEDF_UEVENT_CODE_GRCDUMP: if (msg) - strncpy(event_string, msg, strlen(msg)); + strscpy(event_string, msg, sizeof(event_string)); else sprintf(event_string, "GRCDUMP=%u", shost->host_no); break; From 44f1ce7d2f4a90e8976ece898777e53337fd1bee Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Wed, 7 Feb 2018 08:40:56 -0800 Subject: [PATCH 033/168] scsi: aacraid: Implement DropIO sync command IOP_RESET takes a long time to complete. If controller is in a state where we can bring it back with init struct, send a DropIO sync command instead. - If controller is faulted perform standard IOP_RESET in aac_srcv_init. - If controller is not faulted get adapter properties and extended properties. - Update the sa_firmware variable and determine if DropIO request is supported. - Issue DropIO request, and get the number of outstanding commands. - If all commands are complete with success (CT_OK), consider IOP_RESET is complete. - If any commands timeout, Perform the IOP_RESET. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Dave Carroll Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 4 + drivers/scsi/aacraid/src.c | 161 +++++++++++++++++++++++++++++++-- 2 files changed, 159 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 0095fcbd1c88..c3fdec9d817a 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1528,6 +1528,7 @@ struct aac_bus_info_response { #define AAC_COMM_MESSAGE_TYPE3 5 #define AAC_EXTOPT_SA_FIRMWARE cpu_to_le32(1<<1) +#define AAC_EXTOPT_SOFT_RESET cpu_to_le32(1<<16) /* MSIX context */ struct aac_msix_ctx { @@ -1662,6 +1663,7 @@ struct aac_dev u8 raw_io_64; u8 printf_enabled; u8 in_reset; + u8 in_soft_reset; u8 msi; u8 sa_firmware; int management_fib_count; @@ -2504,6 +2506,7 @@ struct aac_hba_info { #define RCV_TEMP_READINGS 0x00000025 #define GET_COMM_PREFERRED_SETTINGS 0x00000026 #define IOP_RESET_FW_FIB_DUMP 0x00000034 +#define DROP_IO 0x00000035 #define IOP_RESET 0x00001000 #define IOP_RESET_ALWAYS 0x00001001 #define RE_INIT_ADAPTER 0x000000ee @@ -2539,6 +2542,7 @@ struct aac_hba_info { #define FLASH_UPD_PENDING 0x00002000 #define FLASH_UPD_SUCCESS 0x00004000 #define FLASH_UPD_FAILED 0x00008000 +#define INVALID_OMR 0xffffffff #define FWUPD_TIMEOUT (5 * 60) /* diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index fde6b6aa86e3..de4884577ad7 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -255,7 +255,8 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, */ src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); - if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) { + if ((!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) && + !dev->in_soft_reset) { ok = 0; start = jiffies; @@ -992,6 +993,148 @@ error_iounmap: return -1; } +static int aac_src_wait_sync(struct aac_dev *dev, int *status) +{ + unsigned long start = jiffies; + unsigned long usecs = 0; + int delay = 5 * HZ; + int rc = 1; + + while (time_before(jiffies, start+delay)) { + /* + * Delay 5 microseconds to let Mon960 get info. + */ + udelay(5); + + /* + * Mon960 will set doorbell0 bit when it has completed the + * command. + */ + if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) { + /* + * Clear: the doorbell. + */ + if (dev->msi_enabled) + aac_src_access_devreg(dev, AAC_CLEAR_SYNC_BIT); + else + src_writel(dev, MUnit.ODR_C, + OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); + rc = 0; + + break; + } + + /* + * Yield the processor in case we are slow + */ + usecs = 1 * USEC_PER_MSEC; + usleep_range(usecs, usecs + 50); + } + /* + * Pull the synch status from Mailbox 0. + */ + if (status && !rc) { + status[0] = readl(&dev->IndexRegs->Mailbox[0]); + status[1] = readl(&dev->IndexRegs->Mailbox[1]); + status[2] = readl(&dev->IndexRegs->Mailbox[2]); + status[3] = readl(&dev->IndexRegs->Mailbox[3]); + status[4] = readl(&dev->IndexRegs->Mailbox[4]); + } + + return rc; +} + +/** + * aac_src_soft_reset - perform soft reset to speed up + * access + * + * Assumptions: That the controller is in a state where we can + * bring it back to life with an init struct. We can only use + * fast sync commands, as the timeout is 5 seconds. + * + * @dev: device to configure + * + */ + +static int aac_src_soft_reset(struct aac_dev *dev) +{ + u32 status_omr = src_readl(dev, MUnit.OMR); + u32 status[5]; + int rc = 1; + int state = 0; + char *state_str[7] = { + "GET_ADAPTER_PROPERTIES Failed", + "GET_ADAPTER_PROPERTIES timeout", + "SOFT_RESET not supported", + "DROP_IO Failed", + "DROP_IO timeout", + "Check Health failed" + }; + + if (status_omr == INVALID_OMR) + return 1; // pcie hosed + + if (!(status_omr & KERNEL_UP_AND_RUNNING)) + return 1; // not up and running + + /* + * We go into soft reset mode to allow us to handle response + */ + dev->in_soft_reset = 1; + dev->msi_enabled = status_omr & AAC_INT_MODE_MSIX; + + /* Get adapter properties */ + rc = aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0, + 0, 0, 0, status+0, status+1, status+2, status+3, status+4); + if (rc) + goto out; + + state++; + if (aac_src_wait_sync(dev, status)) { + rc = 1; + goto out; + } + + state++; + if (!(status[1] & le32_to_cpu(AAC_OPT_EXTENDED) && + (status[4] & le32_to_cpu(AAC_EXTOPT_SOFT_RESET)))) { + rc = 2; + goto out; + } + + if ((status[1] & le32_to_cpu(AAC_OPT_EXTENDED)) && + (status[4] & le32_to_cpu(AAC_EXTOPT_SA_FIRMWARE))) + dev->sa_firmware = 1; + + state++; + rc = aac_adapter_sync_cmd(dev, DROP_IO, 0, 0, 0, 0, 0, 0, + status+0, status+1, status+2, status+3, status+4); + + if (rc) + goto out; + + state++; + if (aac_src_wait_sync(dev, status)) { + rc = 3; + goto out; + } + + if (status[1]) + dev_err(&dev->pdev->dev, "%s: %d outstanding I/O pending\n", + __func__, status[1]); + + state++; + rc = aac_src_check_health(dev); + +out: + dev->in_soft_reset = 0; + dev->msi_enabled = 0; + if (rc) + dev_err(&dev->pdev->dev, "%s: %s status = %d", __func__, + state_str[state], rc); + +return rc; +} /** * aac_srcv_init - initialize an SRCv card * @dev: device to configure @@ -1021,8 +1164,10 @@ int aac_srcv_init(struct aac_dev *dev) if (dev->init_reset) { dev->init_reset = false; - if (!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) + if (aac_src_soft_reset(dev)) { + aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET); ++restart; + } } /* @@ -1072,13 +1217,16 @@ int aac_srcv_init(struct aac_dev *dev) printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); goto error_iounmap; } + start = jiffies; /* * Wait for the adapter to be up and running. Wait up to 3 minutes */ - while (!((status = src_readl(dev, MUnit.OMR)) & - KERNEL_UP_AND_RUNNING) || - status == 0xffffffff) { + do { + status = src_readl(dev, MUnit.OMR); + if (status == INVALID_OMR) + status = 0; + if ((restart && (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || time_after(jiffies, start+HZ*startup_timeout)) { @@ -1098,7 +1246,8 @@ int aac_srcv_init(struct aac_dev *dev) ++restart; } msleep(1); - } + } while (!(status & KERNEL_UP_AND_RUNNING)); + if (restart && aac_commit) aac_commit = 1; /* From a5799d74d965c8a04812ae6a6b26cafb2c099981 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Wed, 7 Feb 2018 08:40:57 -0800 Subject: [PATCH 034/168] scsi: aacraid: Preserve MSIX mode in the OMR register Preserve the current MSIX mode value in the OMR before rewriting the OMR to initiate the IOP or Soft Reset. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Dave Carroll Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/src.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index de4884577ad7..09b82d3325fc 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -680,6 +680,25 @@ void aac_set_intx_mode(struct aac_dev *dev) } } +static void aac_clear_omr(struct aac_dev *dev) +{ + u32 omr_value = 0; + + omr_value = src_readl(dev, MUnit.OMR); + + /* + * Check for PCI Errors or Kernel Panic + */ + if ((omr_value == INVALID_OMR) || (omr_value & KERNEL_PANIC)) + omr_value = 0; + + /* + * Preserve MSIX Value if any + */ + src_writel(dev, MUnit.OMR, omr_value & AAC_INT_MODE_MSIX); + src_readl(dev, MUnit.OMR); +} + static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev) { __le32 supported_options3; @@ -740,6 +759,8 @@ static void aac_send_iop_reset(struct aac_dev *dev) aac_set_intx_mode(dev); + aac_clear_omr(dev); + src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK); msleep(5000); @@ -749,6 +770,7 @@ static void aac_send_hardware_soft_reset(struct aac_dev *dev) { u_int32_t val; + aac_clear_omr(dev); val = readl(((char *)(dev->base) + IBW_SWR_OFFSET)); val |= 0x01; writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET)); From eee549e1e3a4ec87353a5b85a51a7896394981d5 Mon Sep 17 00:00:00 2001 From: Raghava Aditya Renukunta Date: Wed, 7 Feb 2018 08:40:58 -0800 Subject: [PATCH 035/168] scsi: aacraid: Auto detect INTx or MSIx mode during sync cmd processing During sync command processing, if legacy INTx status indicates command is not completed, sample the MSIx register and check if it indicates command completion, set controller MSIx enabled flag. Signed-off-by: Prasad B Munirathnam Signed-off-by: Raghava Aditya Renukunta Reviewed-by: Dave Carroll Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aacraid.h | 1 + drivers/scsi/aacraid/src.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index c3fdec9d817a..29bf1e60f542 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1231,6 +1231,7 @@ struct src_registers { #define SRC_ODR_SHIFT 12 #define SRC_IDR_SHIFT 9 +#define SRC_MSI_READ_MASK 0x1000 typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 09b82d3325fc..3122389f380f 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -1405,13 +1405,23 @@ void aac_src_access_devreg(struct aac_dev *dev, int mode) static int aac_src_get_sync_status(struct aac_dev *dev) { + int msix_val = 0; + int legacy_val = 0; - int val; + msix_val = src_readl(dev, MUnit.ODR_MSI) & SRC_MSI_READ_MASK ? 1 : 0; - if (dev->msi_enabled) - val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0; - else - val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; + if (!dev->msi_enabled) { + /* + * if Legacy int status indicates cmd is not complete + * sample MSIx register to see if it indiactes cmd complete, + * if yes set the controller in MSIx mode and consider cmd + * completed + */ + legacy_val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; + if (!(legacy_val & 1) && msix_val) + dev->msi_enabled = 1; + return legacy_val; + } - return val; + return msix_val; } From 80e6e9c1dabb940dc7900f37c05f07280af90ac8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 14:12:16 +0100 Subject: [PATCH 036/168] scsi: NCR53c406a: avoid section mismatch with LTO Building with link time optimizations produces a false-positive section mismatch warning: WARNING: vmlinux.o(.data+0xf7e8): Section mismatch in reference from the variable driver_template.lto_priv.6914 to the function .init.text:NCR53c406a_detect() The variable driver_template.lto_priv.6914 references the function __init NCR53c406a_detect() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console The ->detect callback is always entered from the init_this_scsi_driver() init function, but apparently LTO turns the optimized direct function call into an indirect call through a non-__initdata pointer. All drivers using init_this_scsi_driver() are for ancient hardware, and most don't mark the detect() callback as __init(), so I'm just removing the annotation here to kill off the warning instead of doing a larger rework. [mkp: typo] Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR53c406a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 6e110c630d2c..44b09870bf51 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -448,7 +448,7 @@ static __inline__ int NCR53c406a_pio_write(unsigned char *request, unsigned int } #endif /* USE_PIO */ -static int __init NCR53c406a_detect(struct scsi_host_template * tpnt) +static int NCR53c406a_detect(struct scsi_host_template * tpnt) { int present = 0; struct Scsi_Host *shpnt = NULL; From 230816d48ed0213f25a1835f5e0e1bbef96bb896 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 14:12:17 +0100 Subject: [PATCH 037/168] scsi: sym53c416: avoid section mismatch with LTO Building with link time optimizations produces a false-positive section mismatch warning: WARNING: vmlinux.o(.data+0xf8c8): Section mismatch in reference from the variable driver_template.lto_priv.6915 to the function .init.text:sym53c416_detect() The variable driver_template.lto_priv.6915 references the function __init sym53c416_detect() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console The ->detect callback is always entered from the init_this_scsi_driver() init function, but apparently LTO turns the optimized direct function call into an indirect call through a non-__initdata pointer. All drivers using init_this_scsi_driver() are for ancient hardware, and most don't mark the detect() callback as __init(), so I'm just removing the annotation here to kill off the warning instead of doing a larger rework. [mkp: typo] Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/sym53c416.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index 5bdcbe8fa958..e68bcdc75bc3 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -608,7 +608,7 @@ static void sym53c416_probe(void) } } -int __init sym53c416_detect(struct scsi_host_template *tpnt) +int sym53c416_detect(struct scsi_host_template *tpnt) { unsigned long flags; struct Scsi_Host * shpnt = NULL; From 2976fbb6a7aff04076d13d2a37e4b8dbe0d6fd4c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 6 Feb 2018 14:12:36 +0000 Subject: [PATCH 038/168] scsi: isci: remove redundant initialization to 'bit' Variable bit is initialized with a value that is never read and is being updated immediately after the initialization, hence the initialization is redundant and can be removed. Cleans up clang warning: drivers/scsi/isci/host.c:2769:8: warning: Value stored to 'bit' during its initialization is never read Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 13b37cdffa8e..1ee3868ade07 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -2766,7 +2766,7 @@ static int sci_write_gpio_tx_gp(struct isci_host *ihost, u8 reg_index, u8 reg_co int i; for (i = 0; i < 3; i++) { - int bit = (i << 2) + 2; + int bit; bit = try_test_sas_gpio_gp_bit(to_sas_gpio_od(d, i), write_data, reg_index, From b22ee87d84296233886139654e8a125d8f79b44e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 6 Feb 2018 14:34:10 +0000 Subject: [PATCH 039/168] scsi: pmcraid: remove redundant initializations of pointer 'ioadl' There are several occurrances where pointer ioadl is initialized with a value that is never read and where it is re-assigned a new value later on, hence the initialization is redundant and can be removed. Cleans up clang warnings: drivers/scsi/pmcraid.c:1028:29: warning: Value stored to 'ioadl' during its initialization is never read drivers/scsi/pmcraid.c:3178:29: warning: Value stored to 'ioadl' during its initialization is never read drivers/scsi/pmcraid.c:5495:29: warning: Value stored to 'ioadl' during its initialization is never read drivers/scsi/pmcraid.c:5668:29: warning: Value stored to 'ioadl' during its initialization is never read Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 201c8de1853d..9330cc5ba34d 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -1025,7 +1025,7 @@ static void pmcraid_get_fwversion_done(struct pmcraid_cmd *cmd) static void pmcraid_get_fwversion(struct pmcraid_cmd *cmd) { struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; - struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; + struct pmcraid_ioadl_desc *ioadl; struct pmcraid_instance *pinstance = cmd->drv_inst; u16 data_size = sizeof(struct pmcraid_inquiry_data); @@ -3175,7 +3175,7 @@ static int pmcraid_build_ioadl( struct scsi_cmnd *scsi_cmd = cmd->scsi_cmd; struct pmcraid_ioarcb *ioarcb = &(cmd->ioa_cb->ioarcb); - struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; + struct pmcraid_ioadl_desc *ioadl; u32 length = scsi_bufflen(scsi_cmd); @@ -5492,7 +5492,7 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd) struct pmcraid_instance *pinstance = cmd->drv_inst; struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); - struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; + struct pmcraid_ioadl_desc *ioadl; u64 timestamp; timestamp = ktime_get_real_seconds() * 1000; @@ -5665,7 +5665,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) static void pmcraid_querycfg(struct pmcraid_cmd *cmd) { struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; - struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; + struct pmcraid_ioadl_desc *ioadl; struct pmcraid_instance *pinstance = cmd->drv_inst; __be32 cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); From f95dc1bb32d5eb9ff484f7f5a44f856d6fc39f20 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 08:58:17 -0800 Subject: [PATCH 040/168] scsi: ipr: Use sgl_alloc_order() and sgl_free_order() Use the sgl_alloc_order() and sgl_free_order() functions instead of open coding these functions. Signed-off-by: Bart Van Assche Acked-by: Brian King Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Cc: Martin K. Petersen Cc: linux-scsi@vger.kernel.org Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 1 + drivers/scsi/ipr.c | 49 ++++++++------------------------------------ drivers/scsi/ipr.h | 2 +- 3 files changed, 10 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8a739b74cfb7..7e3f6e37fb66 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1059,6 +1059,7 @@ config SCSI_IPR depends on PCI && SCSI && ATA select FW_LOADER select IRQ_POLL + select SGL_ALLOC ---help--- This driver supports the IBM Power Linux family RAID adapters. This includes IBM pSeries 5712, 5703, 5709, and 570A, as well diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e07dd990e585..52735162444f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3816,10 +3816,8 @@ static struct device_attribute ipr_iopoll_weight_attr = { **/ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) { - int sg_size, order, bsize_elem, num_elem, i, j; + int sg_size, order; struct ipr_sglist *sglist; - struct scatterlist *scatterlist; - struct page *page; /* Get the minimum size per scatter/gather element */ sg_size = buf_len / (IPR_MAX_SGLIST - 1); @@ -3827,45 +3825,18 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) /* Get the actual size per element */ order = get_order(sg_size); - /* Determine the actual number of bytes per element */ - bsize_elem = PAGE_SIZE * (1 << order); - - /* Determine the actual number of sg entries needed */ - if (buf_len % bsize_elem) - num_elem = (buf_len / bsize_elem) + 1; - else - num_elem = buf_len / bsize_elem; - /* Allocate a scatter/gather list for the DMA */ - sglist = kzalloc(sizeof(struct ipr_sglist) + - (sizeof(struct scatterlist) * (num_elem - 1)), - GFP_KERNEL); - + sglist = kzalloc(sizeof(struct ipr_sglist), GFP_KERNEL); if (sglist == NULL) { ipr_trace; return NULL; } - - scatterlist = sglist->scatterlist; - sg_init_table(scatterlist, num_elem); - sglist->order = order; - sglist->num_sg = num_elem; - - /* Allocate a bunch of sg elements */ - for (i = 0; i < num_elem; i++) { - page = alloc_pages(GFP_KERNEL, order); - if (!page) { - ipr_trace; - - /* Free up what we already allocated */ - for (j = i - 1; j >= 0; j--) - __free_pages(sg_page(&scatterlist[j]), order); - kfree(sglist); - return NULL; - } - - sg_set_page(&scatterlist[i], page, 0, 0); + sglist->scatterlist = sgl_alloc_order(buf_len, order, false, GFP_KERNEL, + &sglist->num_sg); + if (!sglist->scatterlist) { + kfree(sglist); + return NULL; } return sglist; @@ -3883,11 +3854,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) **/ static void ipr_free_ucode_buffer(struct ipr_sglist *sglist) { - int i; - - for (i = 0; i < sglist->num_sg; i++) - __free_pages(sg_page(&sglist->scatterlist[i]), sglist->order); - + sgl_free_order(sglist->scatterlist, sglist->order); kfree(sglist); } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index c7f0e9e3cd7d..93570734cbfb 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1454,7 +1454,7 @@ struct ipr_sglist { u32 num_sg; u32 num_dma_sg; u32 buffer_len; - struct scatterlist scatterlist[1]; + struct scatterlist *scatterlist; }; enum ipr_sdt_state { From f5594686f5f06637bea144159dfe147dae3040d2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 08:58:18 -0800 Subject: [PATCH 041/168] scsi: pmcraid: Remove an unused structure member Signed-off-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Cc: Anil Ravindranath Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 8bfac72a242b..44da91712115 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -542,7 +542,6 @@ struct pmcraid_sglist { u32 order; u32 num_sg; u32 num_dma_sg; - u32 buffer_len; struct scatterlist scatterlist[1]; }; From ed4414cef2ad0ad0afb3d77a6fdde425d7f7ec4d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 08:58:19 -0800 Subject: [PATCH 042/168] scsi: pmcraid: Use sgl_alloc_order() and sgl_free_order() Use the sgl_alloc_order() and sgl_free_order() functions instead of open coding these functions. Signed-off-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Cc: Anil Ravindranath Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 1 + drivers/scsi/pmcraid.c | 43 ++++-------------------------------------- drivers/scsi/pmcraid.h | 2 +- 3 files changed, 6 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7e3f6e37fb66..8647ca9199b3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1577,6 +1577,7 @@ config ZFCP config SCSI_PMCRAID tristate "PMC SIERRA Linux MaxRAID adapter support" depends on PCI && SCSI && NET + select SGL_ALLOC ---help--- This driver supports the PMC SIERRA MaxRAID adapters. diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 9330cc5ba34d..95530393872d 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3225,12 +3225,7 @@ static int pmcraid_build_ioadl( */ static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) { - int i; - - for (i = 0; i < sglist->num_sg; i++) - __free_pages(sg_page(&(sglist->scatterlist[i])), - sglist->order); - + sgl_free_order(sglist->scatterlist, sglist->order); kfree(sglist); } @@ -3247,50 +3242,20 @@ static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) { struct pmcraid_sglist *sglist; - struct scatterlist *scatterlist; - struct page *page; - int num_elem, i, j; int sg_size; int order; - int bsize_elem; sg_size = buflen / (PMCRAID_MAX_IOADLS - 1); order = (sg_size > 0) ? get_order(sg_size) : 0; - bsize_elem = PAGE_SIZE * (1 << order); - - /* Determine the actual number of sg entries needed */ - if (buflen % bsize_elem) - num_elem = (buflen / bsize_elem) + 1; - else - num_elem = buflen / bsize_elem; /* Allocate a scatter/gather list for the DMA */ - sglist = kzalloc(sizeof(struct pmcraid_sglist) + - (sizeof(struct scatterlist) * (num_elem - 1)), - GFP_KERNEL); - + sglist = kzalloc(sizeof(struct pmcraid_sglist), GFP_KERNEL); if (sglist == NULL) return NULL; - scatterlist = sglist->scatterlist; - sg_init_table(scatterlist, num_elem); sglist->order = order; - sglist->num_sg = num_elem; - sg_size = buflen; - - for (i = 0; i < num_elem; i++) { - page = alloc_pages(GFP_KERNEL|GFP_DMA|__GFP_ZERO, order); - if (!page) { - for (j = i - 1; j >= 0; j--) - __free_pages(sg_page(&scatterlist[j]), order); - kfree(sglist); - return NULL; - } - - sg_set_page(&scatterlist[i], page, - sg_size < bsize_elem ? sg_size : bsize_elem, 0); - sg_size -= bsize_elem; - } + sgl_alloc_order(buflen, order, false, + GFP_KERNEL | GFP_DMA | __GFP_ZERO, &sglist->num_sg); return sglist; } diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 44da91712115..754ef30927e2 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -542,7 +542,7 @@ struct pmcraid_sglist { u32 order; u32 num_sg; u32 num_dma_sg; - struct scatterlist scatterlist[1]; + struct scatterlist *scatterlist; }; /* page D0 inquiry data of focal point resource */ From 923f46f9e9b0a2352c93500cda989996ff875cbd Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 10:38:05 -0800 Subject: [PATCH 043/168] scsi: core: scmd_eh_abort_handler(): Add a comment After the patch that introduced this function was posted on the linux-scsi mailing list an explanation was posted why this patch is correct. Since that explanation contains important information, add a summary of it above the code that explanation applies to. See also http://www.spinics.net/lists/linux-scsi/msg106326.html. References: e494f6a72839 ("[SCSI] improved eh timeout handler") Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Cc: Christoph Hellwig Cc: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d042915ce895..96f988a7efda 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -117,6 +117,12 @@ static int scsi_host_eh_past_deadline(struct Scsi_Host *shost) /** * scmd_eh_abort_handler - Handle command aborts * @work: command to be aborted. + * + * Note: this function must be called only for a command that has timed out. + * Because the block layer marks a request as complete before it calls + * scsi_times_out(), a .scsi_done() call from the LLD for a command that has + * timed out do not have any effect. Hence it is safe to call + * scsi_finish_command() from this function. */ void scmd_eh_abort_handler(struct work_struct *work) From 9866306795c207b52d49ac5f8dc7cdec9363b67f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 10:41:29 -0800 Subject: [PATCH 044/168] scsi: core: Move the eh_deadline module parameter definition The eh_deadline definition occurs in the middle of the code for releasing a host. Avoid splitting the host release code by moving the definition of the eh_deadline parameter to the top of the hosts.c source file. Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 57bf43e34863..a0a7e4ff255c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -42,6 +42,12 @@ #include "scsi_logging.h" +static int shost_eh_deadline = -1; + +module_param_named(eh_deadline, shost_eh_deadline, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(eh_deadline, + "SCSI EH timeout in seconds (should be between 0 and 2^31-1)"); + static DEFINE_IDA(host_index_ida); @@ -358,12 +364,6 @@ static void scsi_host_dev_release(struct device *dev) kfree(shost); } -static int shost_eh_deadline = -1; - -module_param_named(eh_deadline, shost_eh_deadline, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(eh_deadline, - "SCSI EH timeout in seconds (should be between 0 and 2^31-1)"); - static struct device_type scsi_host_type = { .name = "scsi_host", .release = scsi_host_dev_release, From 9b91fd34b46ded81232de3ce41b9b662ec74b07f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 12 Feb 2018 10:57:52 -0800 Subject: [PATCH 045/168] scsi: core: Reduce number of scsi_test_unit_ready() retries Make scsi_test_unit_ready() send at most as many TURs as specified in the 'retries' argument instead of retries * (retries + 1) / 2. Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a86df9ca7d1c..aea5a1ae318b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2607,7 +2607,7 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, /* try to eat the UNIT_ATTENTION if there are enough retries */ do { result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr, - timeout, retries, NULL); + timeout, 1, NULL); if (sdev->removable && scsi_sense_valid(sshdr) && sshdr->sense_key == UNIT_ATTENTION) sdev->changed = 1; From 91d4c7520d0c514f404b9098b467184421cb9cc5 Mon Sep 17 00:00:00 2001 From: John Pittman Date: Fri, 9 Feb 2018 21:12:43 -0500 Subject: [PATCH 046/168] scsi: scsi_debug: Fix pointer styling issues Pointer styling issues exposed by checkpatch.pl in scsi_debug.c: ERROR: "foo * bar" should be "foo *bar" Fixed 37 total errors reported. [mkp: fixed typo noticed by Doug] Signed-off-by: John Pittman Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 8480e4849e29..108b1159d55d 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1156,8 +1156,8 @@ static int inquiry_vpd_84(unsigned char *arr) static int inquiry_vpd_85(unsigned char *arr) { int num = 0; - const char * na1 = "https://www.kernel.org/config"; - const char * na2 = "http://www.kernel.org/log"; + const char *na1 = "https://www.kernel.org/config"; + const char *na2 = "http://www.kernel.org/log"; int plen, olen; arr[num++] = 0x1; /* lu, storage config */ @@ -1373,7 +1373,7 @@ static int inquiry_vpd_b2(unsigned char *arr) static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { unsigned char pq_pdt; - unsigned char * arr; + unsigned char *arr; unsigned char *cmd = scp->cmnd; int alloc_len, n, ret; bool have_wlun, is_disk; @@ -1524,10 +1524,10 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; -static int resp_requests(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +static int resp_requests(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { - unsigned char * sbuff; + unsigned char *sbuff; unsigned char *cmd = scp->cmnd; unsigned char arr[SCSI_SENSE_BUFFERSIZE]; bool dsense; @@ -1585,8 +1585,8 @@ static int resp_requests(struct scsi_cmnd * scp, return fill_from_dev_buffer(scp, arr, len); } -static int resp_start_stop(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +static int resp_start_stop(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { unsigned char *cmd = scp->cmnd; int power_cond, stop; @@ -1613,8 +1613,8 @@ static sector_t get_sdebug_capacity(void) } #define SDEBUG_READCAP_ARR_SZ 8 -static int resp_readcap(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +static int resp_readcap(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { unsigned char arr[SDEBUG_READCAP_ARR_SZ]; unsigned int capac; @@ -1632,8 +1632,8 @@ static int resp_readcap(struct scsi_cmnd * scp, } #define SDEBUG_READCAP16_ARR_SZ 32 -static int resp_readcap16(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +static int resp_readcap16(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { unsigned char *cmd = scp->cmnd; unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; @@ -1671,11 +1671,11 @@ static int resp_readcap16(struct scsi_cmnd * scp, #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 -static int resp_report_tgtpgs(struct scsi_cmnd * scp, - struct sdebug_dev_info * devip) +static int resp_report_tgtpgs(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) { unsigned char *cmd = scp->cmnd; - unsigned char * arr; + unsigned char *arr; int host_no = devip->sdbg_host->shost->host_no; int n, ret, alen, rlen; int port_group_a, port_group_b, port_a, port_b; @@ -1927,7 +1927,7 @@ static int resp_rsup_tmfs(struct scsi_cmnd *scp, /* <> */ -static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) +static int resp_err_recov_pg(unsigned char *p, int pcontrol, int target) { /* Read-Write Error Recovery page for mode_sense */ unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0, 5, 0, 0xff, 0xff}; @@ -1938,7 +1938,7 @@ static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) return sizeof(err_recov_pg); } -static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) +static int resp_disconnect_pg(unsigned char *p, int pcontrol, int target) { /* Disconnect-Reconnect page for mode_sense */ unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -1949,7 +1949,7 @@ static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) return sizeof(disconnect_pg); } -static int resp_format_pg(unsigned char * p, int pcontrol, int target) +static int resp_format_pg(unsigned char *p, int pcontrol, int target) { /* Format device page for mode_sense */ unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1969,7 +1969,7 @@ static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; -static int resp_caching_pg(unsigned char * p, int pcontrol, int target) +static int resp_caching_pg(unsigned char *p, int pcontrol, int target) { /* Caching page for mode_sense */ unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -1989,7 +1989,7 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target) static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; -static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) +static int resp_ctrl_m_pg(unsigned char *p, int pcontrol, int target) { /* Control mode page for mode_sense */ unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -2013,7 +2013,7 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) } -static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target) +static int resp_iec_m_pg(unsigned char *p, int pcontrol, int target) { /* Informational Exceptions control mode page for mode_sense */ unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; @@ -2028,7 +2028,7 @@ static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target) return sizeof(iec_m_pg); } -static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target) +static int resp_sas_sf_m_pg(unsigned char *p, int pcontrol, int target) { /* SAS SSP mode page - short format for mode_sense */ unsigned char sas_sf_m_pg[] = {0x19, 0x6, 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0}; @@ -2040,7 +2040,7 @@ static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target) } -static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target, +static int resp_sas_pcd_m_spg(unsigned char *p, int pcontrol, int target, int target_dev_id) { /* SAS phy control and discover mode page for mode_sense */ unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2, @@ -2073,7 +2073,7 @@ static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target, return sizeof(sas_pcd_m_pg); } -static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) +static int resp_sas_sha_m_spg(unsigned char *p, int pcontrol) { /* SAS SSP shared protocol specific port mode subpage */ unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2094,7 +2094,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, unsigned char dev_spec; int alloc_len, offset, len, target_dev_id; int target = scp->device->id; - unsigned char * ap; + unsigned char *ap; unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; unsigned char *cmd = scp->cmnd; bool dbd, llbaa, msense_6, is_disk, bad_pcode; @@ -2325,7 +2325,7 @@ set_mode_changed_ua: return 0; } -static int resp_temp_l_pg(unsigned char * arr) +static int resp_temp_l_pg(unsigned char *arr) { unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38, 0x0, 0x1, 0x3, 0x2, 0x0, 65, @@ -2335,7 +2335,7 @@ static int resp_temp_l_pg(unsigned char * arr) return sizeof(temp_l_pg); } -static int resp_ie_l_pg(unsigned char * arr) +static int resp_ie_l_pg(unsigned char *arr) { unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38, }; @@ -4060,7 +4060,7 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt) return SUCCESS; } -static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) +static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt) { ++num_dev_resets; if (SCpnt && SCpnt->device) { @@ -4112,7 +4112,7 @@ lie: return SUCCESS; } -static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) +static int scsi_debug_bus_reset(struct scsi_cmnd *SCpnt) { struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *devip; @@ -4145,9 +4145,9 @@ lie: return SUCCESS; } -static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) +static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt) { - struct sdebug_host_info * sdbg_host; + struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *devip; int k = 0; @@ -4173,7 +4173,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) static void __init sdebug_build_parts(unsigned char *ramp, unsigned long store_size) { - struct partition * pp; + struct partition *pp; int starts[SDEBUG_MAX_PARTS + 2]; int sectors_per_part, num_sectors, k; int heads_by_sects, start_sec, end_sec; @@ -4524,7 +4524,7 @@ MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xff #define SDEBUG_INFO_LEN 256 static char sdebug_info[SDEBUG_INFO_LEN]; -static const char * scsi_debug_info(struct Scsi_Host * shp) +static const char *scsi_debug_info(struct Scsi_Host *shp) { int k; @@ -5447,7 +5447,7 @@ static void __exit scsi_debug_exit(void) device_initcall(scsi_debug_init); module_exit(scsi_debug_exit); -static void sdebug_release_adapter(struct device * dev) +static void sdebug_release_adapter(struct device *dev) { struct sdebug_host_info *sdbg_host; @@ -5749,7 +5749,7 @@ static struct scsi_host_template sdebug_driver_template = { .track_queue_depth = 1, }; -static int sdebug_driver_probe(struct device * dev) +static int sdebug_driver_probe(struct device *dev) { int error = 0; struct sdebug_host_info *sdbg_host; @@ -5846,7 +5846,7 @@ static int sdebug_driver_probe(struct device * dev) return error; } -static int sdebug_driver_remove(struct device * dev) +static int sdebug_driver_remove(struct device *dev) { struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *sdbg_devinfo, *tmp; From 80c49563e2506731372c04eec6f8c853d8b0151f Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 9 Feb 2018 21:36:39 -0500 Subject: [PATCH 047/168] scsi: scsi_debug: implement IMMED bit The Start Stop Unit (SSU) command takes in the order of a second to complete on some SAS SSDs and longer on hard disks. Synchronize Cache (SC) can also take some time. Both commands have an IMMED bit in their cdbs for those apps that don't want to wait. This patch introduces a long delay for those commands when the IMMED bit is clear. Since SC is a media access command then when the fake_rw option is active, its cdb processing is skipped and it returns immediately. The SSU command is not altered by the setting of the fake_rw option. These actions are not changed by this patch. Changes since v1: - clear the cdb mask of SYNCHRONIZE CACHE(16) cdb in byte 1, bit 0 Changes: - add the SYNCHRONIZE CACHE(16) command - together with the existing START STOP UNIT and SYNCHRONIZE CACHE(10) commands process the IMMED bit in their cdbs - if the IMMED bit is set, return immediately - if the IMMED bit is clear, treat the delay parameter as having a unit of one second - in the SYNCHRONIZE CACHE processing do a bounds check Signed-off-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 76 +++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 108b1159d55d..52ccf4f3da70 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -6,7 +6,7 @@ * anything out of the ordinary is seen. * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - * Copyright (C) 2001 - 2017 Douglas Gilbert + * Copyright (C) 2001 - 2018 Douglas Gilbert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,8 +61,8 @@ #include "scsi_logging.h" /* make sure inq_product_rev string corresponds to this version */ -#define SDEBUG_VERSION "0187" /* format to fit INQUIRY revision field */ -static const char *sdebug_version_date = "20171202"; +#define SDEBUG_VERSION "0188" /* format to fit INQUIRY revision field */ +static const char *sdebug_version_date = "20180128"; #define MY_NAME "scsi_debug" @@ -234,6 +234,7 @@ static const char *sdebug_version_date = "20171202"; #define F_INV_OP 0x200 #define F_FAKE_RW 0x400 #define F_M_ACCESS 0x800 /* media access */ +#define F_LONG_DELAY 0x1000 #define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR) #define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW) @@ -349,7 +350,7 @@ enum sdeb_opcode_index { SDEB_I_XDWRITEREAD = 25, /* 10 only */ SDEB_I_WRITE_BUFFER = 26, SDEB_I_WRITE_SAME = 27, /* 10, 16 */ - SDEB_I_SYNC_CACHE = 28, /* 10 only */ + SDEB_I_SYNC_CACHE = 28, /* 10, 16 */ SDEB_I_COMP_WRITE = 29, SDEB_I_LAST_ELEMENT = 30, /* keep this last (previous + 1) */ }; @@ -382,7 +383,7 @@ static const unsigned char opcode_ind_arr[256] = { /* 0x80; 0x80->0x9f: 16 byte cdbs */ 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0, SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0, - 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0, + 0, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16, /* 0xa0; 0xa0->0xbf: 12 byte cdbs */ SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN, @@ -398,6 +399,14 @@ static const unsigned char opcode_ind_arr[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +/* + * The following "response" functions return the SCSI mid-level's 4 byte + * tuple-in-an-int. To handle commands with an IMMED bit, for a faster + * command completion, they can mask their return value with + * SDEG_RES_IMMED_MASK . + */ +#define SDEG_RES_IMMED_MASK 0x40000000 + static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *); @@ -420,6 +429,7 @@ static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *); /* * The following are overflow arrays for cdbs that "hit" the same index in @@ -499,6 +509,12 @@ static const struct opcode_info_t release_iarr[] = { {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, }; +static const struct opcode_info_t sync_cache_iarr[] = { + {0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL, + {16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* SYNC_CACHE (16) */ +}; + /* This array is accessed via SDEB_I_* values. Make sure all are mapped, * plus the terminating elements for logic that scans this table such as @@ -536,8 +552,8 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = { {ARRAY_SIZE(write_iarr), 0x8a, 0, F_D_OUT | FF_MEDIA_IO, resp_write_dt0, write_iarr, /* WRITE(16) */ {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7} }, /* WRITE(16) */ - {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7} }, + {0, 0x1b, 0, F_LONG_DELAY, resp_start_stop, NULL,/* START STOP UNIT */ {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {ARRAY_SIZE(sa_in_16_iarr), 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_16_iarr, /* SA_IN(16), READ CAPACITY(16) */ @@ -590,9 +606,10 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = { resp_write_same_10, write_same_iarr, /* WRITE SAME(10) */ {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, - {0, 0x35, 0, F_DELAY_OVERR | FF_MEDIA_IO, NULL, NULL, /* SYNC_CACHE */ + {ARRAY_SIZE(sync_cache_iarr), 0x35, 0, F_LONG_DELAY | F_M_ACCESS, + resp_sync_cache, sync_cache_iarr, {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0, - 0, 0, 0, 0} }, + 0, 0, 0, 0} }, /* SYNC_CACHE (10) */ {0, 0x89, 0, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL, {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0x3f, 0xc7} }, /* COMPARE AND WRITE */ @@ -1598,7 +1615,7 @@ static int resp_start_stop(struct scsi_cmnd *scp, } stop = !(cmd[4] & 1); atomic_xchg(&devip->stopped, stop); - return 0; + return (cmd[1] & 0x1) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */ } static sector_t get_sdebug_capacity(void) @@ -3563,6 +3580,27 @@ static int resp_get_lba_status(struct scsi_cmnd *scp, return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN); } +static int resp_sync_cache(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) +{ + u64 lba; + u32 num_blocks; + u8 *cmd = scp->cmnd; + + if (cmd[0] == SYNCHRONIZE_CACHE) { /* 10 byte cdb */ + lba = get_unaligned_be32(cmd + 2); + num_blocks = get_unaligned_be16(cmd + 7); + } else { /* SYNCHRONIZE_CACHE(16) */ + lba = get_unaligned_be64(cmd + 2); + num_blocks = get_unaligned_be32(cmd + 10); + } + if (lba + num_blocks > sdebug_capacity) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); + return check_condition_result; + } + return (cmd[1] & 0x2) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */ +} + #define RL_BUCKET_ELEMS 8 /* Even though each pseudo target has a REPORT LUNS "well known logical unit" @@ -5709,11 +5747,27 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, errsts = oip->pfp(scp, devip); /* calls a resp_* function */ else if (r_pfp) /* if leaf function ptr NULL, try the root's */ errsts = r_pfp(scp, devip); + if (errsts & SDEG_RES_IMMED_MASK) { + errsts &= ~SDEG_RES_IMMED_MASK; + flags |= F_DELAY_OVERR; + flags &= ~F_LONG_DELAY; + } + fini: if (F_DELAY_OVERR & flags) return schedule_resp(scp, devip, errsts, 0, 0); - else + else if ((sdebug_jdelay || sdebug_ndelay) && (flags & F_LONG_DELAY)) { + /* + * If any delay is active, want F_LONG_DELAY to be at least 1 + * second and if sdebug_jdelay>0 want a long delay of that + * many seconds. + */ + int jdelay = (sdebug_jdelay < 2) ? 1 : sdebug_jdelay; + + jdelay = mult_frac(USER_HZ * jdelay, HZ, USER_HZ); + return schedule_resp(scp, devip, errsts, jdelay, 0); + } else return schedule_resp(scp, devip, errsts, sdebug_jdelay, sdebug_ndelay); check_cond: From f9ba7af8105f792d2204742810f9647aa32699cd Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Tue, 30 Jan 2018 00:35:52 +0100 Subject: [PATCH 048/168] scsi: scsi_debug: reset injection flags for every_nth > 0 If every_nth > 0, the injection flags must be reset for commands that aren't supposed to fail (i.e. that aren't "nth"). Otherwise, commands will continue to fail, like in the every_nth < 0 case. Signed-off-by: Martin Wilck Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 52ccf4f3da70..905501075ec6 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4294,8 +4294,13 @@ static void clear_queue_stats(void) static void setup_inject(struct sdebug_queue *sqp, struct sdebug_queued_cmd *sqcp) { - if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) + if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) { + if (sdebug_every_nth > 0) + sqcp->inj_recovered = sqcp->inj_transport + = sqcp->inj_dif + = sqcp->inj_dix = sqcp->inj_short = 0; return; + } sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts); sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts); sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts); From c62f40bfb26356bb289267f3b802ec0434fdc118 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 14 Feb 2018 22:35:43 +0000 Subject: [PATCH 049/168] scsi: scsi_transport_spi: make two const arrays static, shrinks object size Don't populate the const read-only arrays spi_test_unit_ready and spi_test_unit_ready on the stack but instead make them static. Makes the object code smaller by over 100 bytes: Before: text data bss dec hex filename 40171 12832 128 53131 cf8b drivers/scsi/scsi_transport_spi.o After: text data bss dec hex filename 39922 12976 128 53026 cf22 drivers/scsi/scsi_transport_spi.o (gcc version 7.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 871ea582029e..2ca150b16764 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -822,11 +822,11 @@ spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer) * fails, the device won't let us write to the echo buffer * so just return failure */ - const char spi_test_unit_ready[] = { + static const char spi_test_unit_ready[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 }; - const char spi_read_buffer_descriptor[] = { + static const char spi_read_buffer_descriptor[] = { READ_BUFFER, 0x0b, 0, 0, 0, 0, 0, 0, 4, 0 }; From f66b85171a0ebd55a7efc3e82575ae187d62322c Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 14 Feb 2018 11:05:57 +0100 Subject: [PATCH 050/168] scsi: scsi_debug: call resp_*() function after setting host_scribble Error injection in scsi_debug (e.g. opts=16, SDEBUG_OPT_TRANSPORT_ERR) currently doesn't work correctly because the test for sqcp in resp_read_dt0() and similar resp_*() functions always fails. sqcp is set from cmnd->host_scribble, which is set in schedule_resp(), which is called from scsi_debug_queuecommand() after calling the resp_* function. Defer calling resp_*() until after cmnd->host_scribble is set in schedule_resp(). Fixes: c483739430f1 "scsi_debug: add multiple queue support" Signed-off-by: Martin Wilck Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 53 ++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 905501075ec6..26ce022dd6f4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4315,7 +4315,10 @@ static void setup_inject(struct sdebug_queue *sqp, * SCSI_MLQUEUE_HOST_BUSY if temporarily out of resources. */ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, - int scsi_result, int delta_jiff, int ndelay) + int scsi_result, + int (*pfp)(struct scsi_cmnd *, + struct sdebug_dev_info *), + int delta_jiff, int ndelay) { unsigned long iflags; int k, num_in_q, qdepth, inject; @@ -4331,9 +4334,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, } sdp = cmnd->device; - if (unlikely(sdebug_verbose && scsi_result)) - sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", - __func__, scsi_result); if (delta_jiff == 0) goto respond_in_thread; @@ -4388,7 +4388,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, sqcp = &sqp->qc_arr[k]; sqcp->a_cmnd = cmnd; cmnd->host_scribble = (unsigned char *)sqcp; - cmnd->result = scsi_result; sd_dp = sqcp->sd_dp; spin_unlock_irqrestore(&sqp->qc_lock, iflags); if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt)) @@ -4398,6 +4397,22 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if (sd_dp == NULL) return SCSI_MLQUEUE_HOST_BUSY; } + + cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0; + if (cmnd->result & SDEG_RES_IMMED_MASK) { + /* + * This is the F_DELAY_OVERR case. No delay. + */ + cmnd->result &= ~SDEG_RES_IMMED_MASK; + delta_jiff = ndelay = 0; + } + if (cmnd->result == 0 && scsi_result != 0) + cmnd->result = scsi_result; + + if (unlikely(sdebug_verbose && cmnd->result)) + sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", + __func__, cmnd->result); + if (delta_jiff > 0 || ndelay > 0) { ktime_t kt; @@ -4440,7 +4455,10 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, return 0; respond_in_thread: /* call back to mid-layer using invocation thread */ - cmnd->result = scsi_result; + cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0; + cmnd->result &= ~SDEG_RES_IMMED_MASK; + if (cmnd->result == 0 && scsi_result != 0) + cmnd->result = scsi_result; cmnd->scsi_done(cmnd); return 0; } @@ -5628,6 +5646,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, struct sdebug_dev_info *devip; u8 *cmd = scp->cmnd; int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); + int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *) = NULL; int k, na; int errsts = 0; u32 flags; @@ -5749,19 +5768,13 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, return 0; /* ignore command: make trouble */ } if (likely(oip->pfp)) - errsts = oip->pfp(scp, devip); /* calls a resp_* function */ - else if (r_pfp) /* if leaf function ptr NULL, try the root's */ - errsts = r_pfp(scp, devip); - if (errsts & SDEG_RES_IMMED_MASK) { - errsts &= ~SDEG_RES_IMMED_MASK; - flags |= F_DELAY_OVERR; - flags &= ~F_LONG_DELAY; - } - + pfp = oip->pfp; /* calls a resp_* function */ + else + pfp = r_pfp; /* if leaf function ptr NULL, try the root's */ fini: if (F_DELAY_OVERR & flags) - return schedule_resp(scp, devip, errsts, 0, 0); + return schedule_resp(scp, devip, errsts, pfp, 0, 0); else if ((sdebug_jdelay || sdebug_ndelay) && (flags & F_LONG_DELAY)) { /* * If any delay is active, want F_LONG_DELAY to be at least 1 @@ -5771,14 +5784,14 @@ fini: int jdelay = (sdebug_jdelay < 2) ? 1 : sdebug_jdelay; jdelay = mult_frac(USER_HZ * jdelay, HZ, USER_HZ); - return schedule_resp(scp, devip, errsts, jdelay, 0); + return schedule_resp(scp, devip, errsts, pfp, jdelay, 0); } else - return schedule_resp(scp, devip, errsts, sdebug_jdelay, + return schedule_resp(scp, devip, errsts, pfp, sdebug_jdelay, sdebug_ndelay); check_cond: - return schedule_resp(scp, devip, check_condition_result, 0, 0); + return schedule_resp(scp, devip, check_condition_result, NULL, 0, 0); err_out: - return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0, 0); + return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, NULL, 0, 0); } static struct scsi_host_template sdebug_driver_template = { From cbb6813ee771abc17a713432f31820581eafd4ae Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:01 +0200 Subject: [PATCH 051/168] scsi: ufs: sysfs: attribute group for existing sysfs entries. This patch introduces attribute group to show existing sysfs entries. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/Makefile | 3 +- drivers/scsi/ufs/ufs-sysfs.c | 156 +++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.h | 14 ++++ drivers/scsi/ufs/ufshcd.c | 156 +---------------------------------- drivers/scsi/ufs/ufshcd.h | 2 + 5 files changed, 178 insertions(+), 153 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-sysfs.c create mode 100644 drivers/scsi/ufs/ufs-sysfs.h diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 9310c6c83041..918f5791202d 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o +ufshcd-core-objs := ufshcd.o ufs-sysfs.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c new file mode 100644 index 000000000000..77624d0adee6 --- /dev/null +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Western Digital Corporation + +#include +#include + +#include "ufs-sysfs.h" + +static const char *ufschd_uic_link_state_to_string( + enum uic_link_state state) +{ + switch (state) { + case UIC_LINK_OFF_STATE: return "OFF"; + case UIC_LINK_ACTIVE_STATE: return "ACTIVE"; + case UIC_LINK_HIBERN8_STATE: return "HIBERN8"; + default: return "UNKNOWN"; + } +} + +static const char *ufschd_ufs_dev_pwr_mode_to_string( + enum ufs_dev_pwr_mode state) +{ + switch (state) { + case UFS_ACTIVE_PWR_MODE: return "ACTIVE"; + case UFS_SLEEP_PWR_MODE: return "SLEEP"; + case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN"; + default: return "UNKNOWN"; + } +} + +static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count, + bool rpm) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned long flags, value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value >= UFS_PM_LVL_MAX) + return -EINVAL; + + spin_lock_irqsave(hba->host->host_lock, flags); + if (rpm) + hba->rpm_lvl = value; + else + hba->spm_lvl = value; + spin_unlock_irqrestore(hba->host->host_lock, flags); + return count; +} + +static ssize_t rpm_lvl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int curr_len; + u8 lvl; + + curr_len = snprintf(buf, PAGE_SIZE, + "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n", + hba->rpm_lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].link_state)); + + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\nAll available Runtime PM levels info:\n"); + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n", + lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[lvl].link_state)); + + return curr_len; +} + +static ssize_t rpm_lvl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true); +} + +static ssize_t spm_lvl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int curr_len; + u8 lvl; + + curr_len = snprintf(buf, PAGE_SIZE, + "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n", + hba->spm_lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->spm_lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->spm_lvl].link_state)); + + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\nAll available System PM levels info:\n"); + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n", + lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[lvl].link_state)); + + return curr_len; +} + +static ssize_t spm_lvl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false); +} + +static DEVICE_ATTR_RW(rpm_lvl); +static DEVICE_ATTR_RW(spm_lvl); + +static struct attribute *ufs_sysfs_ufshcd_attrs[] = { + &dev_attr_rpm_lvl.attr, + &dev_attr_spm_lvl.attr, + NULL +}; + +static const struct attribute_group ufs_sysfs_default_group = { + .attrs = ufs_sysfs_ufshcd_attrs, +}; + +static const struct attribute_group *ufs_sysfs_groups[] = { + &ufs_sysfs_default_group, + NULL, +}; + +void ufs_sysfs_add_nodes(struct device *dev) +{ + int ret; + + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups); + if (ret) + dev_err(dev, + "%s: sysfs groups creation failed (err = %d)\n", + __func__, ret); +} + +void ufs_sysfs_remove_nodes(struct device *dev) +{ + sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups); +} diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h new file mode 100644 index 000000000000..ce58861f548a --- /dev/null +++ b/drivers/scsi/ufs/ufs-sysfs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright (C) 2018 Western Digital Corporation + */ + +#ifndef __UFS_SYSFS_H__ +#define __UFS_SYSFS_H__ + +#include + +#include "ufshcd.h" + +void ufs_sysfs_add_nodes(struct device *dev); +void ufs_sysfs_remove_nodes(struct device *dev); +#endif diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a355d989b414..e7621a0a54b8 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -44,6 +44,7 @@ #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" +#include "ufs-sysfs.h" #define CREATE_TRACE_POINTS #include @@ -150,7 +151,7 @@ enum { #define ufshcd_is_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) -static struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { +struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE}, {UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE}, @@ -813,28 +814,6 @@ static inline bool ufshcd_is_hba_active(struct ufs_hba *hba) ? false : true; } -static const char *ufschd_uic_link_state_to_string( - enum uic_link_state state) -{ - switch (state) { - case UIC_LINK_OFF_STATE: return "OFF"; - case UIC_LINK_ACTIVE_STATE: return "ACTIVE"; - case UIC_LINK_HIBERN8_STATE: return "HIBERN8"; - default: return "UNKNOWN"; - } -} - -static const char *ufschd_ufs_dev_pwr_mode_to_string( - enum ufs_dev_pwr_mode state) -{ - switch (state) { - case UFS_ACTIVE_PWR_MODE: return "ACTIVE"; - case UFS_SLEEP_PWR_MODE: return "SLEEP"; - case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN"; - default: return "UNKNOWN"; - } -} - u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba) { /* HCI version 1.0 and 1.1 supports UniPro 1.41 */ @@ -7585,133 +7564,6 @@ int ufshcd_runtime_idle(struct ufs_hba *hba) } EXPORT_SYMBOL(ufshcd_runtime_idle); -static inline ssize_t ufshcd_pm_lvl_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count, - bool rpm) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - unsigned long flags, value; - - if (kstrtoul(buf, 0, &value)) - return -EINVAL; - - if (value >= UFS_PM_LVL_MAX) - return -EINVAL; - - spin_lock_irqsave(hba->host->host_lock, flags); - if (rpm) - hba->rpm_lvl = value; - else - hba->spm_lvl = value; - spin_unlock_irqrestore(hba->host->host_lock, flags); - return count; -} - -static ssize_t ufshcd_rpm_lvl_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->rpm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available Runtime PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; -} - -static ssize_t ufshcd_rpm_lvl_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return ufshcd_pm_lvl_store(dev, attr, buf, count, true); -} - -static void ufshcd_add_rpm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->rpm_lvl_attr.show = ufshcd_rpm_lvl_show; - hba->rpm_lvl_attr.store = ufshcd_rpm_lvl_store; - sysfs_attr_init(&hba->rpm_lvl_attr.attr); - hba->rpm_lvl_attr.attr.name = "rpm_lvl"; - hba->rpm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, &hba->rpm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for rpm_lvl\n"); -} - -static ssize_t ufshcd_spm_lvl_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->spm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->spm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->spm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available System PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; -} - -static ssize_t ufshcd_spm_lvl_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return ufshcd_pm_lvl_store(dev, attr, buf, count, false); -} - -static void ufshcd_add_spm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->spm_lvl_attr.show = ufshcd_spm_lvl_show; - hba->spm_lvl_attr.store = ufshcd_spm_lvl_store; - sysfs_attr_init(&hba->spm_lvl_attr.attr); - hba->spm_lvl_attr.attr.name = "spm_lvl"; - hba->spm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, &hba->spm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for spm_lvl\n"); -} - -static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba) -{ - ufshcd_add_rpm_lvl_sysfs_nodes(hba); - ufshcd_add_spm_lvl_sysfs_nodes(hba); -} - -static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba) -{ - device_remove_file(hba->dev, &hba->rpm_lvl_attr); - device_remove_file(hba->dev, &hba->spm_lvl_attr); -} - /** * ufshcd_shutdown - shutdown routine * @hba: per adapter instance @@ -7749,7 +7601,7 @@ EXPORT_SYMBOL(ufshcd_shutdown); */ void ufshcd_remove(struct ufs_hba *hba) { - ufshcd_remove_sysfs_nodes(hba); + ufs_sysfs_remove_nodes(hba->dev); scsi_remove_host(hba->host); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); @@ -7996,7 +7848,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_set_ufs_dev_active(hba); async_schedule(ufshcd_async_scan, hba); - ufshcd_add_sysfs_nodes(hba); + ufs_sysfs_add_nodes(hba->dev); return 0; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 1332e544da92..53e2779f9d06 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -985,4 +985,6 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) hba->vops->dbg_register_dump(hba); } +extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; + #endif /* End of Header */ From 45bced87e79316ecd868aee8f187284025792c5f Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:02 +0200 Subject: [PATCH 052/168] scsi: ufs: sysfs: device descriptor This patch introduces a sysfs group entry for the UFS device descriptor parameters. The group adds "device_descriptor" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 223 +++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 116 +++++++++++ drivers/scsi/ufs/ufs.h | 8 + drivers/scsi/ufs/ufshcd.c | 12 +- drivers/scsi/ufs/ufshcd.h | 6 + 5 files changed, 359 insertions(+), 6 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs new file mode 100644 index 000000000000..8da7b8448f13 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -0,0 +1,223 @@ +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the device type. This is one of the UFS + device descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_class +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the device class. This is one of the UFS + device descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_sub_class +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the UFS storage subclass. This is one of + the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/protocol +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the protocol supported by an UFS device. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_luns +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows number of logical units. This is one of + the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_wluns +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows number of well known logical units. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/boot_enable +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows value that indicates whether the device is + enabled for boot. This is one of the UFS device descriptor + parameters. The full information about the descriptor could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/descriptor_access_enable +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows value that indicates whether the device + descriptor could be read after partial initialization phase + of the boot sequence. This is one of the UFS device descriptor + parameters. The full information about the descriptor could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_power_mode +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows value that defines the power mode after + device initialization or hardware reset. This is one of + the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/high_priority_lun +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the high priority lun. This is one of + the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/secure_removal_type +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the secure removal type. This is one of + the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/support_security_lun +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the security lun is supported. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/bkops_termination_latency +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the background operations termination + latency. This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_active_icc_level +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the initial active ICC level. This is one + of the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/specification_version +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the specification version. This is one + of the UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturing_date +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the manufacturing date in BCD format. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturer_id +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the manufacturee ID. This is one of the + UFS device descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtt_capability +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum number of outstanding RTTs + supported by the device. This is one of the UFS device + descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtc_update +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the frequency and method of the realtime + clock update. This is one of the UFS device descriptor + parameters. The full information about the descriptor + could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ufs_features +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows which features are supported by the device. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be + found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ffu_timeout +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the FFU timeout. This is one of the + UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/queue_depth +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the device queue depth. This is one of the + UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_version +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the device version. This is one of the + UFS device descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_secure_wpa +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows number of secure write protect areas + supported by the device. This is one of the UFS device + descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_max_data_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum amount of data that may be + written during the pre-soldering phase of the PSA flow. + This is one of the UFS device descriptor parameters. + The full information about the descriptor could be found + at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_state_timeout +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the command maximum timeout for a change + in PSA state. This is one of the UFS device descriptor + parameters. The full information about the descriptor could + be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 77624d0adee6..440b94e453bf 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -3,7 +3,9 @@ #include #include +#include +#include "ufs.h" #include "ufs-sysfs.h" static const char *ufschd_uic_link_state_to_string( @@ -134,8 +136,122 @@ static const struct attribute_group ufs_sysfs_default_group = { .attrs = ufs_sysfs_ufshcd_attrs, }; +static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, + enum desc_idn desc_id, + u8 desc_index, + u8 param_offset, + u8 *sysfs_buf, + u8 param_size) +{ + u8 desc_buf[8] = {0}; + int ret; + + if (param_size > 8) + return -EINVAL; + + ret = ufshcd_read_desc_param(hba, desc_id, desc_index, + param_offset, desc_buf, param_size); + if (ret) + return -EINVAL; + switch (param_size) { + case 1: + ret = sprintf(sysfs_buf, "0x%02X\n", *desc_buf); + break; + case 2: + ret = sprintf(sysfs_buf, "0x%04X\n", + get_unaligned_be16(desc_buf)); + break; + case 4: + ret = sprintf(sysfs_buf, "0x%08X\n", + get_unaligned_be32(desc_buf)); + break; + case 8: + ret = sprintf(sysfs_buf, "0x%016llX\n", + get_unaligned_be64(desc_buf)); + break; + } + + return ret; +} + +#define UFS_DESC_PARAM(_name, _puname, _duname, _size) \ +static ssize_t _name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \ + 0, _duname##_DESC_PARAM##_puname, buf, _size); \ +} \ +static DEVICE_ATTR_RO(_name) + +#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \ + UFS_DESC_PARAM(_name, _uname, DEVICE, _size) + +UFS_DEVICE_DESC_PARAM(device_type, _DEVICE_TYPE, 1); +UFS_DEVICE_DESC_PARAM(device_class, _DEVICE_CLASS, 1); +UFS_DEVICE_DESC_PARAM(device_sub_class, _DEVICE_SUB_CLASS, 1); +UFS_DEVICE_DESC_PARAM(protocol, _PRTCL, 1); +UFS_DEVICE_DESC_PARAM(number_of_luns, _NUM_LU, 1); +UFS_DEVICE_DESC_PARAM(number_of_wluns, _NUM_WLU, 1); +UFS_DEVICE_DESC_PARAM(boot_enable, _BOOT_ENBL, 1); +UFS_DEVICE_DESC_PARAM(descriptor_access_enable, _DESC_ACCSS_ENBL, 1); +UFS_DEVICE_DESC_PARAM(initial_power_mode, _INIT_PWR_MODE, 1); +UFS_DEVICE_DESC_PARAM(high_priority_lun, _HIGH_PR_LUN, 1); +UFS_DEVICE_DESC_PARAM(secure_removal_type, _SEC_RMV_TYPE, 1); +UFS_DEVICE_DESC_PARAM(support_security_lun, _SEC_LU, 1); +UFS_DEVICE_DESC_PARAM(bkops_termination_latency, _BKOP_TERM_LT, 1); +UFS_DEVICE_DESC_PARAM(initial_active_icc_level, _ACTVE_ICC_LVL, 1); +UFS_DEVICE_DESC_PARAM(specification_version, _SPEC_VER, 2); +UFS_DEVICE_DESC_PARAM(manufacturing_date, _MANF_DATE, 2); +UFS_DEVICE_DESC_PARAM(manufacturer_id, _MANF_ID, 2); +UFS_DEVICE_DESC_PARAM(rtt_capability, _RTT_CAP, 1); +UFS_DEVICE_DESC_PARAM(rtc_update, _FRQ_RTC, 2); +UFS_DEVICE_DESC_PARAM(ufs_features, _UFS_FEAT, 1); +UFS_DEVICE_DESC_PARAM(ffu_timeout, _FFU_TMT, 1); +UFS_DEVICE_DESC_PARAM(queue_depth, _Q_DPTH, 1); +UFS_DEVICE_DESC_PARAM(device_version, _DEV_VER, 2); +UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, _NUM_SEC_WPA, 1); +UFS_DEVICE_DESC_PARAM(psa_max_data_size, _PSA_MAX_DATA, 4); +UFS_DEVICE_DESC_PARAM(psa_state_timeout, _PSA_TMT, 1); + +static struct attribute *ufs_sysfs_device_descriptor[] = { + &dev_attr_device_type.attr, + &dev_attr_device_class.attr, + &dev_attr_device_sub_class.attr, + &dev_attr_protocol.attr, + &dev_attr_number_of_luns.attr, + &dev_attr_number_of_wluns.attr, + &dev_attr_boot_enable.attr, + &dev_attr_descriptor_access_enable.attr, + &dev_attr_initial_power_mode.attr, + &dev_attr_high_priority_lun.attr, + &dev_attr_secure_removal_type.attr, + &dev_attr_support_security_lun.attr, + &dev_attr_bkops_termination_latency.attr, + &dev_attr_initial_active_icc_level.attr, + &dev_attr_specification_version.attr, + &dev_attr_manufacturing_date.attr, + &dev_attr_manufacturer_id.attr, + &dev_attr_rtt_capability.attr, + &dev_attr_rtc_update.attr, + &dev_attr_ufs_features.attr, + &dev_attr_ffu_timeout.attr, + &dev_attr_queue_depth.attr, + &dev_attr_device_version.attr, + &dev_attr_number_of_secure_wpa.attr, + &dev_attr_psa_max_data_size.attr, + &dev_attr_psa_state_timeout.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_device_descriptor_group = { + .name = "device_descriptor", + .attrs = ufs_sysfs_device_descriptor, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, + &ufs_sysfs_device_descriptor_group, NULL, }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 54deeb754db5..6ae1e08329cc 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -220,6 +220,14 @@ enum device_desc_param { DEVICE_DESC_PARAM_UD_LEN = 0x1B, DEVICE_DESC_PARAM_RTT_CAP = 0x1C, DEVICE_DESC_PARAM_FRQ_RTC = 0x1D, + DEVICE_DESC_PARAM_UFS_FEAT = 0x1F, + DEVICE_DESC_PARAM_FFU_TMT = 0x20, + DEVICE_DESC_PARAM_Q_DPTH = 0x21, + DEVICE_DESC_PARAM_DEV_VER = 0x22, + DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24, + DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25, + DEVICE_DESC_PARAM_PSA_TMT = 0x29, + DEVICE_DESC_PARAM_PRDCT_REV = 0x2A, }; /* diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index e7621a0a54b8..540a431e38ce 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2989,12 +2989,12 @@ EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); * * Return 0 in case of success, non-zero otherwise */ -static int ufshcd_read_desc_param(struct ufs_hba *hba, - enum desc_idn desc_id, - int desc_index, - u8 param_offset, - u8 *param_read_buf, - u8 param_size) +int ufshcd_read_desc_param(struct ufs_hba *hba, + enum desc_idn desc_id, + int desc_index, + u8 param_offset, + u8 *param_read_buf, + u8 param_size) { int ret; u8 *desc_buf; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 53e2779f9d06..38c307d053c7 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -841,6 +841,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) } /* Expose Query-Request API */ +int ufshcd_read_desc_param(struct ufs_hba *hba, + enum desc_idn desc_id, + int desc_index, + u8 param_offset, + u8 *param_read_buf, + u8 param_size); int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res); int ufshcd_hold(struct ufs_hba *hba, bool async); From 8c2582bfbd9abe84b9cf435996aa720a84f908c4 Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:03 +0200 Subject: [PATCH 053/168] scsi: ufs: sysfs: interconnect descriptor This patch introduces a sysfs group entry for the UFS interconnect descriptor parameters. The group adds "interconnect_descriptor" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 19 +++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 18 ++++++++++++++++++ drivers/scsi/ufs/ufs.h | 8 ++++++++ 3 files changed, 45 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 8da7b8448f13..099e6fa0e301 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -221,3 +221,22 @@ Description: This file shows the command maximum timeout for a change parameters. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/unipro_version +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the MIPI UniPro version number in BCD format. + This is one of the UFS interconnect descriptor parameters. + The full information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/mphy_version +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the MIPI M-PHY version number in BCD format. + This is one of the UFS interconnect descriptor parameters. + The full information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 440b94e453bf..ba229d9f326b 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -249,9 +249,27 @@ static const struct attribute_group ufs_sysfs_device_descriptor_group = { .attrs = ufs_sysfs_device_descriptor, }; +#define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size) \ + UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size) + +UFS_INTERCONNECT_DESC_PARAM(unipro_version, _UNIPRO_VER, 2); +UFS_INTERCONNECT_DESC_PARAM(mphy_version, _MPHY_VER, 2); + +static struct attribute *ufs_sysfs_interconnect_descriptor[] = { + &dev_attr_unipro_version.attr, + &dev_attr_mphy_version.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = { + .name = "interconnect_descriptor", + .attrs = ufs_sysfs_interconnect_descriptor, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, + &ufs_sysfs_interconnect_descriptor_group, NULL, }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 6ae1e08329cc..773c0495c542 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -230,6 +230,14 @@ enum device_desc_param { DEVICE_DESC_PARAM_PRDCT_REV = 0x2A, }; +/* Interconnect descriptor parameters offsets in bytes*/ +enum interconnect_desc_param { + INTERCONNECT_DESC_PARAM_LEN = 0x0, + INTERCONNECT_DESC_PARAM_TYPE = 0x1, + INTERCONNECT_DESC_PARAM_UNIPRO_VER = 0x2, + INTERCONNECT_DESC_PARAM_MPHY_VER = 0x4, +}; + /* * Logical Unit Write Protect * 00h: LU not write protected From c720c091222e26d46c0fd9c70144a0f916bf3993 Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:04 +0200 Subject: [PATCH 054/168] scsi: ufs: sysfs: geometry descriptor This patch introduces a sysfs group entry for the UFS geometry descriptor parameters. The group adds "geometry_descriptor" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 173 +++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 84 ++++++++++ drivers/scsi/ufs/ufs.h | 36 +++++ 3 files changed, 293 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 099e6fa0e301..6ea7613a3f3e 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -240,3 +240,176 @@ Description: This file shows the MIPI M-PHY version number in BCD format. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/raw_device_capacity +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the total memory quantity available to + the user to configure the device logical units. This is one + of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_luns +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum number of logical units + supported by the UFS device. This is one of the UFS + geometry descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/segment_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the segment size. This is one of the UFS + geometry descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/allocation_unit_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the allocation unit size. This is one of + the UFS geometry descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/min_addressable_block_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the minimum addressable block size. This + is one of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at UFS + specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_read_block_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the optimal read block size. This is one + of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at UFS + specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_write_block_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the optimal write block size. This is one + of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at UFS + specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_in_buffer_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum data-in buffer size. This + is one of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at UFS + specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_out_buffer_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum data-out buffer size. This + is one of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at UFS + specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/rpmb_rw_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum number of RPMB frames allowed + in Security Protocol In/Out. This is one of the UFS geometry + descriptor parameters. The full information about the + descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/dyn_capacity_resource_policy +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the dynamic capacity resource policy. This + is one of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/data_ordering +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows support for out-of-order data transfer. + This is one of the UFS geometry descriptor parameters. + The full information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_contexts +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows maximum available number of contexts which + are supported by the device. This is one of the UFS geometry + descriptor parameters. The full information about the + descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_unit_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows system data tag unit size. This is one of + the UFS geometry descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_resource_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows maximum storage area size allocated by + the device to handle system data by the tagging mechanism. + This is one of the UFS geometry descriptor parameters. + The full information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/secure_removal_types +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows supported secure removal types. This is + one of the UFS geometry descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/memory_types +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows supported memory types. This is one of + the UFS geometry descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_max_alloc_units +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum number of allocation units for + different memory types (system code, non persistent, + enhanced type 1-4). This is one of the UFS geometry + descriptor parameters. The full information about the + descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_capacity_adjustment_factor +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the memory capacity adjustment factor for + different memory types (system code, non persistent, + enhanced type 1-4). This is one of the UFS geometry + descriptor parameters. The full information about the + descriptor could be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index ba229d9f326b..ecd3dcb05f67 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -266,10 +266,94 @@ static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = { .attrs = ufs_sysfs_interconnect_descriptor, }; +#define UFS_GEOMETRY_DESC_PARAM(_name, _uname, _size) \ + UFS_DESC_PARAM(_name, _uname, GEOMETRY, _size) + +UFS_GEOMETRY_DESC_PARAM(raw_device_capacity, _DEV_CAP, 8); +UFS_GEOMETRY_DESC_PARAM(max_number_of_luns, _MAX_NUM_LUN, 1); +UFS_GEOMETRY_DESC_PARAM(segment_size, _SEG_SIZE, 4); +UFS_GEOMETRY_DESC_PARAM(allocation_unit_size, _ALLOC_UNIT_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(min_addressable_block_size, _MIN_BLK_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(optimal_read_block_size, _OPT_RD_BLK_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(optimal_write_block_size, _OPT_WR_BLK_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(max_in_buffer_size, _MAX_IN_BUF_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(max_out_buffer_size, _MAX_OUT_BUF_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(rpmb_rw_size, _RPMB_RW_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(dyn_capacity_resource_policy, _DYN_CAP_RSRC_PLC, 1); +UFS_GEOMETRY_DESC_PARAM(data_ordering, _DATA_ORDER, 1); +UFS_GEOMETRY_DESC_PARAM(max_number_of_contexts, _MAX_NUM_CTX, 1); +UFS_GEOMETRY_DESC_PARAM(sys_data_tag_unit_size, _TAG_UNIT_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(sys_data_tag_resource_size, _TAG_RSRC_SIZE, 1); +UFS_GEOMETRY_DESC_PARAM(secure_removal_types, _SEC_RM_TYPES, 1); +UFS_GEOMETRY_DESC_PARAM(memory_types, _MEM_TYPES, 2); +UFS_GEOMETRY_DESC_PARAM(sys_code_memory_max_alloc_units, + _SCM_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(sys_code_memory_capacity_adjustment_factor, + _SCM_CAP_ADJ_FCTR, 2); +UFS_GEOMETRY_DESC_PARAM(non_persist_memory_max_alloc_units, + _NPM_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(non_persist_memory_capacity_adjustment_factor, + _NPM_CAP_ADJ_FCTR, 2); +UFS_GEOMETRY_DESC_PARAM(enh1_memory_max_alloc_units, + _ENM1_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(enh1_memory_capacity_adjustment_factor, + _ENM1_CAP_ADJ_FCTR, 2); +UFS_GEOMETRY_DESC_PARAM(enh2_memory_max_alloc_units, + _ENM2_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(enh2_memory_capacity_adjustment_factor, + _ENM2_CAP_ADJ_FCTR, 2); +UFS_GEOMETRY_DESC_PARAM(enh3_memory_max_alloc_units, + _ENM3_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(enh3_memory_capacity_adjustment_factor, + _ENM3_CAP_ADJ_FCTR, 2); +UFS_GEOMETRY_DESC_PARAM(enh4_memory_max_alloc_units, + _ENM4_MAX_NUM_UNITS, 4); +UFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor, + _ENM4_CAP_ADJ_FCTR, 2); + +static struct attribute *ufs_sysfs_geometry_descriptor[] = { + &dev_attr_raw_device_capacity.attr, + &dev_attr_max_number_of_luns.attr, + &dev_attr_segment_size.attr, + &dev_attr_allocation_unit_size.attr, + &dev_attr_min_addressable_block_size.attr, + &dev_attr_optimal_read_block_size.attr, + &dev_attr_optimal_write_block_size.attr, + &dev_attr_max_in_buffer_size.attr, + &dev_attr_max_out_buffer_size.attr, + &dev_attr_rpmb_rw_size.attr, + &dev_attr_dyn_capacity_resource_policy.attr, + &dev_attr_data_ordering.attr, + &dev_attr_max_number_of_contexts.attr, + &dev_attr_sys_data_tag_unit_size.attr, + &dev_attr_sys_data_tag_resource_size.attr, + &dev_attr_secure_removal_types.attr, + &dev_attr_memory_types.attr, + &dev_attr_sys_code_memory_max_alloc_units.attr, + &dev_attr_sys_code_memory_capacity_adjustment_factor.attr, + &dev_attr_non_persist_memory_max_alloc_units.attr, + &dev_attr_non_persist_memory_capacity_adjustment_factor.attr, + &dev_attr_enh1_memory_max_alloc_units.attr, + &dev_attr_enh1_memory_capacity_adjustment_factor.attr, + &dev_attr_enh2_memory_max_alloc_units.attr, + &dev_attr_enh2_memory_capacity_adjustment_factor.attr, + &dev_attr_enh3_memory_max_alloc_units.attr, + &dev_attr_enh3_memory_capacity_adjustment_factor.attr, + &dev_attr_enh4_memory_max_alloc_units.attr, + &dev_attr_enh4_memory_capacity_adjustment_factor.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_geometry_descriptor_group = { + .name = "geometry_descriptor", + .attrs = ufs_sysfs_geometry_descriptor, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, &ufs_sysfs_interconnect_descriptor_group, + &ufs_sysfs_geometry_descriptor_group, NULL, }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 773c0495c542..04d41c8d3dc1 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -238,6 +238,42 @@ enum interconnect_desc_param { INTERCONNECT_DESC_PARAM_MPHY_VER = 0x4, }; +/* Geometry descriptor parameters offsets in bytes*/ +enum geometry_desc_param { + GEOMETRY_DESC_PARAM_LEN = 0x0, + GEOMETRY_DESC_PARAM_TYPE = 0x1, + GEOMETRY_DESC_PARAM_DEV_CAP = 0x4, + GEOMETRY_DESC_PARAM_MAX_NUM_LUN = 0xC, + GEOMETRY_DESC_PARAM_SEG_SIZE = 0xD, + GEOMETRY_DESC_PARAM_ALLOC_UNIT_SIZE = 0x11, + GEOMETRY_DESC_PARAM_MIN_BLK_SIZE = 0x12, + GEOMETRY_DESC_PARAM_OPT_RD_BLK_SIZE = 0x13, + GEOMETRY_DESC_PARAM_OPT_WR_BLK_SIZE = 0x14, + GEOMETRY_DESC_PARAM_MAX_IN_BUF_SIZE = 0x15, + GEOMETRY_DESC_PARAM_MAX_OUT_BUF_SIZE = 0x16, + GEOMETRY_DESC_PARAM_RPMB_RW_SIZE = 0x17, + GEOMETRY_DESC_PARAM_DYN_CAP_RSRC_PLC = 0x18, + GEOMETRY_DESC_PARAM_DATA_ORDER = 0x19, + GEOMETRY_DESC_PARAM_MAX_NUM_CTX = 0x1A, + GEOMETRY_DESC_PARAM_TAG_UNIT_SIZE = 0x1B, + GEOMETRY_DESC_PARAM_TAG_RSRC_SIZE = 0x1C, + GEOMETRY_DESC_PARAM_SEC_RM_TYPES = 0x1D, + GEOMETRY_DESC_PARAM_MEM_TYPES = 0x1E, + GEOMETRY_DESC_PARAM_SCM_MAX_NUM_UNITS = 0x20, + GEOMETRY_DESC_PARAM_SCM_CAP_ADJ_FCTR = 0x24, + GEOMETRY_DESC_PARAM_NPM_MAX_NUM_UNITS = 0x26, + GEOMETRY_DESC_PARAM_NPM_CAP_ADJ_FCTR = 0x2A, + GEOMETRY_DESC_PARAM_ENM1_MAX_NUM_UNITS = 0x2C, + GEOMETRY_DESC_PARAM_ENM1_CAP_ADJ_FCTR = 0x30, + GEOMETRY_DESC_PARAM_ENM2_MAX_NUM_UNITS = 0x32, + GEOMETRY_DESC_PARAM_ENM2_CAP_ADJ_FCTR = 0x36, + GEOMETRY_DESC_PARAM_ENM3_MAX_NUM_UNITS = 0x38, + GEOMETRY_DESC_PARAM_ENM3_CAP_ADJ_FCTR = 0x3C, + GEOMETRY_DESC_PARAM_ENM4_MAX_NUM_UNITS = 0x3E, + GEOMETRY_DESC_PARAM_ENM4_CAP_ADJ_FCTR = 0x42, + GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44, +}; + /* * Logical Unit Write Protect * 00h: LU not write protected From c648c2d27f168ae4faeb43f8c3074226aae3862c Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:05 +0200 Subject: [PATCH 055/168] scsi: ufs: sysfs: health descriptor This patch introduces a sysfs group entry for the UFS health descriptor parameters. The group adds "health_descriptor" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 28 ++++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 20 ++++++++++++++++ drivers/scsi/ufs/ufs.h | 11 +++++++++ drivers/scsi/ufs/ufshcd.c | 8 +++++++ drivers/scsi/ufs/ufshcd.h | 1 + 5 files changed, 68 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 6ea7613a3f3e..ddb012b05f0d 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -413,3 +413,31 @@ Description: This file shows the memory capacity adjustment factor for descriptor parameters. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/eol_info +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows preend of life information. This is one + of the UFS health descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_a +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows indication of the device life time + (method a). This is one of the UFS health descriptor + parameters. The full information about the descriptor + could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_b +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows indication of the device life time + (method b). This is one of the UFS health descriptor + parameters. The full information about the descriptor + could be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index ecd3dcb05f67..c4f18b0970db 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -349,11 +349,31 @@ static const struct attribute_group ufs_sysfs_geometry_descriptor_group = { .attrs = ufs_sysfs_geometry_descriptor, }; +#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size) \ + UFS_DESC_PARAM(_name, _uname, HEALTH, _size) + +UFS_HEALTH_DESC_PARAM(eol_info, _EOL_INFO, 1); +UFS_HEALTH_DESC_PARAM(life_time_estimation_a, _LIFE_TIME_EST_A, 1); +UFS_HEALTH_DESC_PARAM(life_time_estimation_b, _LIFE_TIME_EST_B, 1); + +static struct attribute *ufs_sysfs_health_descriptor[] = { + &dev_attr_eol_info.attr, + &dev_attr_life_time_estimation_a.attr, + &dev_attr_life_time_estimation_b.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_health_descriptor_group = { + .name = "health_descriptor", + .attrs = ufs_sysfs_health_descriptor, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, &ufs_sysfs_interconnect_descriptor_group, &ufs_sysfs_geometry_descriptor_group, + &ufs_sysfs_health_descriptor_group, NULL, }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 04d41c8d3dc1..6bfeedb934f1 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -154,6 +154,7 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1 = 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER = 0x8, + QUERY_DESC_IDN_HEALTH = 0x9, QUERY_DESC_IDN_MAX, }; @@ -169,6 +170,7 @@ enum ufs_desc_def_size { QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, QUERY_DESC_POWER_DEF_SIZE = 0x62, + QUERY_DESC_HEALTH_DEF_SIZE = 0x25, }; /* Unit descriptor parameters offsets in bytes*/ @@ -274,6 +276,15 @@ enum geometry_desc_param { GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44, }; +/* Health descriptor parameters offsets in bytes*/ +enum health_desc_param { + HEALTH_DESC_PARAM_LEN = 0x0, + HEALTH_DESC_PARAM_TYPE = 0x1, + HEALTH_DESC_PARAM_EOL_INFO = 0x2, + HEALTH_DESC_PARAM_LIFE_TIME_EST_A = 0x3, + HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4, +}; + /* * Logical Unit Write Protect * 00h: LU not write protected diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 540a431e38ce..b88fcf7be47b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2966,6 +2966,9 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, case QUERY_DESC_IDN_STRING: *desc_len = QUERY_DESC_MAX_SIZE; break; + case QUERY_DESC_IDN_HEALTH: + *desc_len = hba->desc_size.hlth_desc; + break; case QUERY_DESC_IDN_RFU_0: case QUERY_DESC_IDN_RFU_1: *desc_len = 0; @@ -6277,6 +6280,10 @@ static void ufshcd_init_desc_sizes(struct ufs_hba *hba) &hba->desc_size.geom_desc); if (err) hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0, + &hba->desc_size.hlth_desc); + if (err) + hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE; } static void ufshcd_def_desc_sizes(struct ufs_hba *hba) @@ -6287,6 +6294,7 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba) hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; + hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE; } /** diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 38c307d053c7..515c6e6244be 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -229,6 +229,7 @@ struct ufs_desc_size { int interc_desc; int unit_desc; int conf_desc; + int hlth_desc; }; /** From c2e6e283c52f3a2c4a99774b36bcc88e7cbd5eb7 Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:06 +0200 Subject: [PATCH 056/168] scsi: ufs: sysfs: power descriptor This patch introduces a sysfs group entry for the UFS power descriptor parameters. The group adds "power_descriptor" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 10 ++ drivers/scsi/ufs/ufs-sysfs.c | 117 +++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index ddb012b05f0d..7460566f557d 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -441,3 +441,13 @@ Description: This file shows indication of the device life time parameters. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/power_descriptor/active_icc_levels_vcc* +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows maximum VCC, VCCQ and VCCQ2 value for + active ICC levels from 0 to 15. This is one of the UFS + power descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index c4f18b0970db..16e357a95b6b 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -368,12 +368,129 @@ static const struct attribute_group ufs_sysfs_health_descriptor_group = { .attrs = ufs_sysfs_health_descriptor, }; +#define UFS_POWER_DESC_PARAM(_name, _uname, _index) \ +static ssize_t _name##_index##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, \ + PWR_DESC##_uname##_0 + _index * 2, buf, 2); \ +} \ +static DEVICE_ATTR_RO(_name##_index) + +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 0); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 1); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 2); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 3); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 4); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 5); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 6); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 7); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 8); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 9); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 10); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 11); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 12); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 13); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 14); +UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 15); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 0); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 1); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 2); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 3); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 4); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 5); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 6); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 7); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 8); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 9); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 10); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 11); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 12); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 13); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 14); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 15); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 0); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 1); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 2); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 3); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 4); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 5); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 6); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 7); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 8); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 9); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 10); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 11); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 12); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 13); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 14); +UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 15); + +static struct attribute *ufs_sysfs_power_descriptor[] = { + &dev_attr_active_icc_levels_vcc0.attr, + &dev_attr_active_icc_levels_vcc1.attr, + &dev_attr_active_icc_levels_vcc2.attr, + &dev_attr_active_icc_levels_vcc3.attr, + &dev_attr_active_icc_levels_vcc4.attr, + &dev_attr_active_icc_levels_vcc5.attr, + &dev_attr_active_icc_levels_vcc6.attr, + &dev_attr_active_icc_levels_vcc7.attr, + &dev_attr_active_icc_levels_vcc8.attr, + &dev_attr_active_icc_levels_vcc9.attr, + &dev_attr_active_icc_levels_vcc10.attr, + &dev_attr_active_icc_levels_vcc11.attr, + &dev_attr_active_icc_levels_vcc12.attr, + &dev_attr_active_icc_levels_vcc13.attr, + &dev_attr_active_icc_levels_vcc14.attr, + &dev_attr_active_icc_levels_vcc15.attr, + &dev_attr_active_icc_levels_vccq0.attr, + &dev_attr_active_icc_levels_vccq1.attr, + &dev_attr_active_icc_levels_vccq2.attr, + &dev_attr_active_icc_levels_vccq3.attr, + &dev_attr_active_icc_levels_vccq4.attr, + &dev_attr_active_icc_levels_vccq5.attr, + &dev_attr_active_icc_levels_vccq6.attr, + &dev_attr_active_icc_levels_vccq7.attr, + &dev_attr_active_icc_levels_vccq8.attr, + &dev_attr_active_icc_levels_vccq9.attr, + &dev_attr_active_icc_levels_vccq10.attr, + &dev_attr_active_icc_levels_vccq11.attr, + &dev_attr_active_icc_levels_vccq12.attr, + &dev_attr_active_icc_levels_vccq13.attr, + &dev_attr_active_icc_levels_vccq14.attr, + &dev_attr_active_icc_levels_vccq15.attr, + &dev_attr_active_icc_levels_vccq20.attr, + &dev_attr_active_icc_levels_vccq21.attr, + &dev_attr_active_icc_levels_vccq22.attr, + &dev_attr_active_icc_levels_vccq23.attr, + &dev_attr_active_icc_levels_vccq24.attr, + &dev_attr_active_icc_levels_vccq25.attr, + &dev_attr_active_icc_levels_vccq26.attr, + &dev_attr_active_icc_levels_vccq27.attr, + &dev_attr_active_icc_levels_vccq28.attr, + &dev_attr_active_icc_levels_vccq29.attr, + &dev_attr_active_icc_levels_vccq210.attr, + &dev_attr_active_icc_levels_vccq211.attr, + &dev_attr_active_icc_levels_vccq212.attr, + &dev_attr_active_icc_levels_vccq213.attr, + &dev_attr_active_icc_levels_vccq214.attr, + &dev_attr_active_icc_levels_vccq215.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_power_descriptor_group = { + .name = "power_descriptor", + .attrs = ufs_sysfs_power_descriptor, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, &ufs_sysfs_interconnect_descriptor_group, &ufs_sysfs_geometry_descriptor_group, &ufs_sysfs_health_descriptor_group, + &ufs_sysfs_power_descriptor_group, NULL, }; From 2238d31cdeabc585de5869efd11856815aa4dd13 Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:07 +0200 Subject: [PATCH 057/168] scsi: ufs: sysfs: string descriptors This patch introduces a sysfs group entry for the UFS string descriptors. The group adds "string_descriptors" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The folder will contain 5 files that will show string values defined by the UFS spec: a manufacturer name, a product name, an OEM id, a serial number and a product revision. The full information about the string descriptors could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 39 +++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 56 ++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 14 +++--- drivers/scsi/ufs/ufshcd.h | 9 ++++ 4 files changed, 111 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 7460566f557d..c17a9685048b 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -451,3 +451,42 @@ Description: This file shows maximum VCC, VCCQ and VCCQ2 value for power descriptor parameters. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/manufacturer_name +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file contains a device manufactureer name string. + The full information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_name +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file contains a product name string. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/oem_id +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file contains a OEM ID string. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/serial_number +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file contains a device serial number string. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_revision +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file contains a product revision string. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 16e357a95b6b..c1aeb8aa3160 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -484,6 +484,61 @@ static const struct attribute_group ufs_sysfs_power_descriptor_group = { .attrs = ufs_sysfs_power_descriptor, }; +#define UFS_STRING_DESCRIPTOR(_name, _pname) \ +static ssize_t _name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + u8 index; \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + int ret; \ + int desc_len = QUERY_DESC_MAX_SIZE; \ + u8 *desc_buf; \ + desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \ + if (!desc_buf) \ + return -ENOMEM; \ + ret = ufshcd_query_descriptor_retry(hba, \ + UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \ + 0, 0, desc_buf, &desc_len); \ + if (ret) { \ + ret = -EINVAL; \ + goto out; \ + } \ + index = desc_buf[DEVICE_DESC_PARAM##_pname]; \ + memset(desc_buf, 0, QUERY_DESC_MAX_SIZE); \ + if (ufshcd_read_string_desc(hba, index, desc_buf, \ + QUERY_DESC_MAX_SIZE, true)) { \ + ret = -EINVAL; \ + goto out; \ + } \ + ret = snprintf(buf, PAGE_SIZE, "%s\n", \ + desc_buf + QUERY_DESC_HDR_SIZE); \ +out: \ + kfree(desc_buf); \ + return ret; \ +} \ +static DEVICE_ATTR_RO(_name) + +UFS_STRING_DESCRIPTOR(manufacturer_name, _MANF_NAME); +UFS_STRING_DESCRIPTOR(product_name, _PRDCT_NAME); +UFS_STRING_DESCRIPTOR(oem_id, _OEM_ID); +UFS_STRING_DESCRIPTOR(serial_number, _SN); +UFS_STRING_DESCRIPTOR(product_revision, _PRDCT_REV); + +static struct attribute *ufs_sysfs_string_descriptors[] = { + &dev_attr_manufacturer_name.attr, + &dev_attr_product_name.attr, + &dev_attr_oem_id.attr, + &dev_attr_serial_number.attr, + &dev_attr_product_revision.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_string_descriptors_group = { + .name = "string_descriptors", + .attrs = ufs_sysfs_string_descriptors, +}; + + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, @@ -491,6 +546,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_geometry_descriptor_group, &ufs_sysfs_health_descriptor_group, &ufs_sysfs_power_descriptor_group, + &ufs_sysfs_string_descriptors_group, NULL, }; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b88fcf7be47b..9cfdd8ed198a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2873,11 +2873,11 @@ out: * The buf_len parameter will contain, on return, the length parameter * received on the response. */ -static int ufshcd_query_descriptor_retry(struct ufs_hba *hba, - enum query_opcode opcode, - enum desc_idn idn, u8 index, - u8 selector, - u8 *desc_buf, int *buf_len) +int ufshcd_query_descriptor_retry(struct ufs_hba *hba, + enum query_opcode opcode, + enum desc_idn idn, u8 index, + u8 selector, + u8 *desc_buf, int *buf_len) { int err; int retries; @@ -3093,8 +3093,8 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size) * Return 0 in case of success, non-zero otherwise */ #define ASCII_STD true -static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, - u8 *buf, u32 size, bool ascii) +int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, + u8 *buf, u32 size, bool ascii) { int err = 0; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 515c6e6244be..2dad9dada86a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -842,6 +842,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) } /* Expose Query-Request API */ +int ufshcd_query_descriptor_retry(struct ufs_hba *hba, + enum query_opcode opcode, + enum desc_idn idn, u8 index, + u8 selector, + u8 *desc_buf, int *buf_len); + int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, @@ -850,6 +856,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, u8 param_size); int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res); +int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, + u8 *buf, u32 size, bool ascii); + int ufshcd_hold(struct ufs_hba *hba, bool async); void ufshcd_release(struct ufs_hba *hba); From 86b87cde0b5581cdb1a7babeb9c4c387761f151b Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:08 +0200 Subject: [PATCH 058/168] scsi: core: host template attribute groups The patch introduces an additional field in the scsi_host_template structure - struct attribute_group **sdev_group. This field allows to define groups of attributes. It will provide an ability to use binary attributes as well as device attributes and to group them under subfolders if necessary. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 11 +++++++++++ include/scsi/scsi_host.h | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 91b90f672d23..e56a4ac990c0 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1310,6 +1310,13 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) } } + if (sdev->host->hostt->sdev_groups) { + error = sysfs_create_groups(&sdev->sdev_gendev.kobj, + sdev->host->hostt->sdev_groups); + if (error) + return error; + } + scsi_autopm_put_device(sdev); return error; } @@ -1349,6 +1356,10 @@ void __scsi_remove_device(struct scsi_device *sdev) if (res != 0) return; + if (sdev->host->hostt->sdev_groups) + sysfs_remove_groups(&sdev->sdev_gendev.kobj, + sdev->host->hostt->sdev_groups); + bsg_unregister_queue(sdev->request_queue); device_unregister(&sdev->sdev_dev); transport_remove_device(dev); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 1a1df0d21ee3..19317585ae48 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -476,6 +476,12 @@ struct scsi_host_template { */ struct device_attribute **sdev_attrs; + /* + * Pointer to the SCSI device attribute groups for this host, + * NULL terminated. + */ + const struct attribute_group **sdev_groups; + /* * List of hosts per template. * From d829fc8a1058851f1058b4a29ea02da125c1684a Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:09 +0200 Subject: [PATCH 059/168] scsi: ufs: sysfs: unit descriptor This patch introduces a sysfs group entry for the UFS unit descriptor parameters. The group adds "unit_descriptor" folder under the corresponding SCSI device sysfs entry (/sys/class/scsi_device/*/device/). The parameters are shown as hexadecimal numbers. The full information about the parameters could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 108 +++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 53 ++++++++++ drivers/scsi/ufs/ufs-sysfs.h | 2 + drivers/scsi/ufs/ufs.h | 11 +++ drivers/scsi/ufs/ufshcd.c | 23 ++--- drivers/scsi/ufs/ufshcd.h | 15 +++ 6 files changed, 196 insertions(+), 16 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index c17a9685048b..57c6a9028108 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -490,3 +490,111 @@ Description: This file contains a product revision string. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/class/scsi_device/*/device/unit_descriptor/boot_lun_id +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows boot LUN information. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/lun_write_protect +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows LUN write protection status. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/lun_queue_depth +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows LUN queue depth. This is one of the UFS + unit descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/psa_sensitive +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows PSA sensitivity. This is one of the UFS + unit descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/lun_memory_type +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows LUN memory type. This is one of the UFS + unit descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/data_reliability +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file defines the device behavior when a power failure + occurs during a write operation. This is one of the UFS + unit descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the size of addressable logical blocks + (calculated as an exponent with base 2). This is one of + the UFS unit descriptor parameters. The full information about + the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_count +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows total number of addressable logical blocks. + This is one of the UFS unit descriptor parameters. The full + information about the descriptor could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/erase_block_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the erase block size. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/provisioning_type +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the thin provisioning type. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the total physical memory resources. This is + one of the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/context_capabilities +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the context capabilities. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/large_unit_granularity +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the granularity of the LUN. This is one of + the UFS unit descriptor parameters. The full information + about the descriptor could be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index c1aeb8aa3160..cd4d9d039ee9 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -550,6 +550,59 @@ static const struct attribute_group *ufs_sysfs_groups[] = { NULL, }; +#define UFS_LUN_DESC_PARAM(_pname, _puname, _duname, _size) \ +static ssize_t _pname##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct scsi_device *sdev = to_scsi_device(dev); \ + struct ufs_hba *hba = shost_priv(sdev->host); \ + u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \ + if (!ufs_is_valid_unit_desc_lun(lun)) \ + return -EINVAL; \ + return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \ + lun, _duname##_DESC_PARAM##_puname, buf, _size); \ +} \ +static DEVICE_ATTR_RO(_pname) + +#define UFS_UNIT_DESC_PARAM(_name, _uname, _size) \ + UFS_LUN_DESC_PARAM(_name, _uname, UNIT, _size) + +UFS_UNIT_DESC_PARAM(boot_lun_id, _BOOT_LUN_ID, 1); +UFS_UNIT_DESC_PARAM(lun_write_protect, _LU_WR_PROTECT, 1); +UFS_UNIT_DESC_PARAM(lun_queue_depth, _LU_Q_DEPTH, 1); +UFS_UNIT_DESC_PARAM(psa_sensitive, _PSA_SENSITIVE, 1); +UFS_UNIT_DESC_PARAM(lun_memory_type, _MEM_TYPE, 1); +UFS_UNIT_DESC_PARAM(data_reliability, _DATA_RELIABILITY, 1); +UFS_UNIT_DESC_PARAM(logical_block_size, _LOGICAL_BLK_SIZE, 1); +UFS_UNIT_DESC_PARAM(logical_block_count, _LOGICAL_BLK_COUNT, 8); +UFS_UNIT_DESC_PARAM(erase_block_size, _ERASE_BLK_SIZE, 4); +UFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1); +UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8); +UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2); +UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1); + +static struct attribute *ufs_sysfs_unit_descriptor[] = { + &dev_attr_boot_lun_id.attr, + &dev_attr_lun_write_protect.attr, + &dev_attr_lun_queue_depth.attr, + &dev_attr_psa_sensitive.attr, + &dev_attr_lun_memory_type.attr, + &dev_attr_data_reliability.attr, + &dev_attr_logical_block_size.attr, + &dev_attr_logical_block_count.attr, + &dev_attr_erase_block_size.attr, + &dev_attr_provisioning_type.attr, + &dev_attr_physical_memory_resourse_count.attr, + &dev_attr_context_capabilities.attr, + &dev_attr_large_unit_granularity.attr, + NULL, +}; + +const struct attribute_group ufs_sysfs_unit_descriptor_group = { + .name = "unit_descriptor", + .attrs = ufs_sysfs_unit_descriptor, +}; + void ufs_sysfs_add_nodes(struct device *dev) { int ret; diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h index ce58861f548a..2afce169a9f0 100644 --- a/drivers/scsi/ufs/ufs-sysfs.h +++ b/drivers/scsi/ufs/ufs-sysfs.h @@ -11,4 +11,6 @@ void ufs_sysfs_add_nodes(struct device *dev); void ufs_sysfs_remove_nodes(struct device *dev); + +extern const struct attribute_group ufs_sysfs_unit_descriptor_group; #endif diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 6bfeedb934f1..73870597e34c 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -182,6 +182,7 @@ enum unit_desc_param { UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4, UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5, UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6, + UNIT_DESC_PARAM_PSA_SENSITIVE = 0x7, UNIT_DESC_PARAM_MEM_TYPE = 0x8, UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9, UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, @@ -592,4 +593,14 @@ struct ufs_dev_desc { char model[MAX_MODEL_LEN + 1]; }; +/** + * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor + * @lun: LU number to check + * @return: true if the lun has a matching unit descriptor, false otherwise + */ +static inline bool ufs_is_valid_unit_desc_lun(u8 lun) +{ + return lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN); +} + #endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9cfdd8ed198a..ace3acdc9a5b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2222,21 +2222,6 @@ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) return ret; } -/* - * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN - * @scsi_lun: scsi LUN id - * - * Returns UPIU LUN id - */ -static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun) -{ - if (scsi_is_wlun(scsi_lun)) - return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID) - | UFS_UPIU_WLUN_ID; - else - return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID; -} - /** * ufshcd_upiu_wlun_to_scsi_wlun - maps UPIU W-LUN id to SCSI W-LUN ID * @scsi_lun: UPIU W-LUN id @@ -3171,7 +3156,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, * Unit descriptors are only available for general purpose LUs (LUN id * from 0 to 7) and RPMB Well known LU. */ - if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN)) + if (!ufs_is_valid_unit_desc_lun(lun)) return -EOPNOTSUPP; return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun, @@ -6481,6 +6466,11 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) return found ? BLK_EH_NOT_HANDLED : BLK_EH_RESET_TIMER; } +static const struct attribute_group *ufshcd_driver_groups[] = { + &ufs_sysfs_unit_descriptor_group, + NULL, +}; + static struct scsi_host_template ufshcd_driver_template = { .module = THIS_MODULE, .name = UFSHCD, @@ -6500,6 +6490,7 @@ static struct scsi_host_template ufshcd_driver_template = { .can_queue = UFSHCD_CAN_QUEUE, .max_host_blocked = 1, .track_queue_depth = 1, + .sdev_groups = ufshcd_driver_groups, }; static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 2dad9dada86a..f4cb31b23728 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1003,4 +1003,19 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; +/* + * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN + * @scsi_lun: scsi LUN id + * + * Returns UPIU LUN id + */ +static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun) +{ + if (scsi_is_wlun(scsi_lun)) + return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID) + | UFS_UPIU_WLUN_ID; + else + return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID; +} + #endif /* End of Header */ From d10b2a8ea8fd0d6c8a667dc1950c8c061bfbbcdd Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:10 +0200 Subject: [PATCH 060/168] scsi: ufs: sysfs: flags This patch introduces a sysfs group entry for the UFS flags. The group adds "flags" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The flags are shown as boolean value ("true" or "false"). The full information about the UFS flags could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 65 ++++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 39 +++++++++++++ drivers/scsi/ufs/ufs.h | 14 ++++- 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 57c6a9028108..f4f49e29e225 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -598,3 +598,68 @@ Description: This file shows the granularity of the LUN. This is one of the UFS unit descriptor parameters. The full information about the descriptor could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/flags/device_init +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the device init status. The full information + about the flag could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether permanent write protection is enabled. + The full information about the flag could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether write protection is enabled on all + logical units configured as power on write protected. The + full information about the flag could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the device background operations are + enabled. The full information about the flag could be + found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the device life span mode is enabled. + The full information about the flag could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether physical resource removal is enable. + The full information about the flag could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the device is executing internal + operation related to real time clock. The full information + about the flag could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the device FW update is permanently + disabled. The full information about the flag could be found + at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index cd4d9d039ee9..a09a8a2ed46c 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -538,6 +538,44 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = { .attrs = ufs_sysfs_string_descriptors, }; +#define UFS_FLAG(_name, _uname) \ +static ssize_t _name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + bool flag; \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + if (ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ + QUERY_FLAG_IDN##_uname, &flag)) \ + return -EINVAL; \ + return sprintf(buf, "%s\n", flag ? "true" : "false"); \ +} \ +static DEVICE_ATTR_RO(_name) + +UFS_FLAG(device_init, _FDEVICEINIT); +UFS_FLAG(permanent_wpe, _PERMANENT_WPE); +UFS_FLAG(power_on_wpe, _PWR_ON_WPE); +UFS_FLAG(bkops_enable, _BKOPS_EN); +UFS_FLAG(life_span_mode_enable, _LIFE_SPAN_MODE_ENABLE); +UFS_FLAG(phy_resource_removal, _FPHYRESOURCEREMOVAL); +UFS_FLAG(busy_rtc, _BUSY_RTC); +UFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE); + +static struct attribute *ufs_sysfs_device_flags[] = { + &dev_attr_device_init.attr, + &dev_attr_permanent_wpe.attr, + &dev_attr_power_on_wpe.attr, + &dev_attr_bkops_enable.attr, + &dev_attr_life_span_mode_enable.attr, + &dev_attr_phy_resource_removal.attr, + &dev_attr_busy_rtc.attr, + &dev_attr_disable_fw_update.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_flags_group = { + .name = "flags", + .attrs = ufs_sysfs_device_flags, +}; static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, @@ -547,6 +585,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_health_descriptor_group, &ufs_sysfs_power_descriptor_group, &ufs_sysfs_string_descriptors_group, + &ufs_sysfs_flags_group, NULL, }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 73870597e34c..df5e73e7de3e 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -130,9 +130,17 @@ enum { /* Flag idn for Query Requests*/ enum flag_idn { - QUERY_FLAG_IDN_FDEVICEINIT = 0x01, - QUERY_FLAG_IDN_PWR_ON_WPE = 0x03, - QUERY_FLAG_IDN_BKOPS_EN = 0x04, + QUERY_FLAG_IDN_FDEVICEINIT = 0x01, + QUERY_FLAG_IDN_PERMANENT_WPE = 0x02, + QUERY_FLAG_IDN_PWR_ON_WPE = 0x03, + QUERY_FLAG_IDN_BKOPS_EN = 0x04, + QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE = 0x05, + QUERY_FLAG_IDN_PURGE_ENABLE = 0x06, + QUERY_FLAG_IDN_RESERVED2 = 0x07, + QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL = 0x08, + QUERY_FLAG_IDN_BUSY_RTC = 0x09, + QUERY_FLAG_IDN_RESERVED3 = 0x0A, + QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE = 0x0B, }; /* Attribute idn for Query requests */ From ec92b59cc03c3d5757449c1c9344524e088df2bd Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 15 Feb 2018 14:14:11 +0200 Subject: [PATCH 061/168] scsi: ufs: sysfs: attributes This patch introduces a sysfs group entry for the UFS attributes. The group adds "attributes" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The attributes are shown as hexadecimal numbers. The full information about the attributes could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov Reviewed-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 139 +++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 80 ++++++++++++ drivers/scsi/ufs/ufs-sysfs.h | 1 + drivers/scsi/ufs/ufs.h | 27 +++- drivers/scsi/ufs/ufshcd.c | 5 +- drivers/scsi/ufs/ufshcd.h | 3 +- 6 files changed, 248 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index f4f49e29e225..07f1c2f8dbfc 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -663,3 +663,142 @@ Description: This file shows whether the device FW update is permanently disabled. The full information about the flag could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/boot_lun_enabled +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the boot lun enabled UFS device attribute. + The full information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/current_power_mode +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the current power mode UFS device attribute. + The full information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/active_icc_level +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the active icc level UFS device attribute. + The full information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/ooo_data_enabled +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the out of order data transfer enabled UFS + device attribute. The full information about the attribute + could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/bkops_status +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the background operations status UFS device + attribute. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/purge_status +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the purge operation status UFS device + attribute. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_in_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum data size in a DATA IN + UPIU. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_out_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the maximum number of bytes that can be + requested with a READY TO TRANSFER UPIU. The full information + about the attribute could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/reference_clock_frequency +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the reference clock frequency UFS device + attribute. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/configuration_descriptor_lock +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows whether the configuration descriptor is locked. + The full information about the attribute could be found at + UFS specifications 2.1. The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_number_of_rtt +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the maximum current number of + outstanding RTTs in device that is allowed. The full + information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the exception event control UFS device + attribute. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_status +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the exception event status UFS device + attribute. The full information about the attribute could + be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file provides the ffu status UFS device attribute. + The full information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_state +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file show the PSA feature status. The full information + about the attribute could be found at UFS specifications 2.1. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_data_size +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the amount of data that the host plans to + load to all logical units in pre-soldering state. + The full information about the attribute could be found at + UFS specifications 2.1. + The file is read only. + + +What: /sys/class/scsi_device/*/device/dyn_cap_needed +Date: February 2018 +Contact: Stanislav Nijnikov +Description: This file shows the The amount of physical memory needed + to be removed from the physical memory resources pool of + the particular logical unit. The full information about + the attribute could be found at UFS specifications 2.1. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index a09a8a2ed46c..cd7174d2d225 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -577,6 +577,61 @@ static const struct attribute_group ufs_sysfs_flags_group = { .attrs = ufs_sysfs_device_flags, }; +#define UFS_ATTRIBUTE(_name, _uname) \ +static ssize_t _name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + u32 value; \ + if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \ + QUERY_ATTR_IDN##_uname, 0, 0, &value)) \ + return -EINVAL; \ + return sprintf(buf, "0x%08X\n", value); \ +} \ +static DEVICE_ATTR_RO(_name) + +UFS_ATTRIBUTE(boot_lun_enabled, _BOOT_LU_EN); +UFS_ATTRIBUTE(current_power_mode, _POWER_MODE); +UFS_ATTRIBUTE(active_icc_level, _ACTIVE_ICC_LVL); +UFS_ATTRIBUTE(ooo_data_enabled, _OOO_DATA_EN); +UFS_ATTRIBUTE(bkops_status, _BKOPS_STATUS); +UFS_ATTRIBUTE(purge_status, _PURGE_STATUS); +UFS_ATTRIBUTE(max_data_in_size, _MAX_DATA_IN); +UFS_ATTRIBUTE(max_data_out_size, _MAX_DATA_OUT); +UFS_ATTRIBUTE(reference_clock_frequency, _REF_CLK_FREQ); +UFS_ATTRIBUTE(configuration_descriptor_lock, _CONF_DESC_LOCK); +UFS_ATTRIBUTE(max_number_of_rtt, _MAX_NUM_OF_RTT); +UFS_ATTRIBUTE(exception_event_control, _EE_CONTROL); +UFS_ATTRIBUTE(exception_event_status, _EE_STATUS); +UFS_ATTRIBUTE(ffu_status, _FFU_STATUS); +UFS_ATTRIBUTE(psa_state, _PSA_STATE); +UFS_ATTRIBUTE(psa_data_size, _PSA_DATA_SIZE); + +static struct attribute *ufs_sysfs_attributes[] = { + &dev_attr_boot_lun_enabled.attr, + &dev_attr_current_power_mode.attr, + &dev_attr_active_icc_level.attr, + &dev_attr_ooo_data_enabled.attr, + &dev_attr_bkops_status.attr, + &dev_attr_purge_status.attr, + &dev_attr_max_data_in_size.attr, + &dev_attr_max_data_out_size.attr, + &dev_attr_reference_clock_frequency.attr, + &dev_attr_configuration_descriptor_lock.attr, + &dev_attr_max_number_of_rtt.attr, + &dev_attr_exception_event_control.attr, + &dev_attr_exception_event_status.attr, + &dev_attr_ffu_status.attr, + &dev_attr_psa_state.attr, + &dev_attr_psa_data_size.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_attributes_group = { + .name = "attributes", + .attrs = ufs_sysfs_attributes, +}; + static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, @@ -586,6 +641,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_power_descriptor_group, &ufs_sysfs_string_descriptors_group, &ufs_sysfs_flags_group, + &ufs_sysfs_attributes_group, NULL, }; @@ -642,6 +698,30 @@ const struct attribute_group ufs_sysfs_unit_descriptor_group = { .attrs = ufs_sysfs_unit_descriptor, }; +static ssize_t dyn_cap_needed_attribute_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 value; + struct scsi_device *sdev = to_scsi_device(dev); + struct ufs_hba *hba = shost_priv(sdev->host); + u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); + + if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value)) + return -EINVAL; + return sprintf(buf, "0x%08X\n", value); +} +static DEVICE_ATTR_RO(dyn_cap_needed_attribute); + +static struct attribute *ufs_sysfs_lun_attributes[] = { + &dev_attr_dyn_cap_needed_attribute.attr, + NULL, +}; + +const struct attribute_group ufs_sysfs_lun_attributes_group = { + .attrs = ufs_sysfs_lun_attributes, +}; + void ufs_sysfs_add_nodes(struct device *dev) { int ret; diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h index 2afce169a9f0..e5621e59a432 100644 --- a/drivers/scsi/ufs/ufs-sysfs.h +++ b/drivers/scsi/ufs/ufs-sysfs.h @@ -13,4 +13,5 @@ void ufs_sysfs_add_nodes(struct device *dev); void ufs_sysfs_remove_nodes(struct device *dev); extern const struct attribute_group ufs_sysfs_unit_descriptor_group; +extern const struct attribute_group ufs_sysfs_lun_attributes_group; #endif diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index df5e73e7de3e..14e5bf7af0bb 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -145,10 +145,29 @@ enum flag_idn { /* Attribute idn for Query requests */ enum attr_idn { - QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03, - QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, - QUERY_ATTR_IDN_EE_CONTROL = 0x0D, - QUERY_ATTR_IDN_EE_STATUS = 0x0E, + QUERY_ATTR_IDN_BOOT_LU_EN = 0x00, + QUERY_ATTR_IDN_RESERVED = 0x01, + QUERY_ATTR_IDN_POWER_MODE = 0x02, + QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03, + QUERY_ATTR_IDN_OOO_DATA_EN = 0x04, + QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, + QUERY_ATTR_IDN_PURGE_STATUS = 0x06, + QUERY_ATTR_IDN_MAX_DATA_IN = 0x07, + QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08, + QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09, + QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A, + QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B, + QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C, + QUERY_ATTR_IDN_EE_CONTROL = 0x0D, + QUERY_ATTR_IDN_EE_STATUS = 0x0E, + QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F, + QUERY_ATTR_IDN_CNTX_CONF = 0x10, + QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11, + QUERY_ATTR_IDN_RESERVED2 = 0x12, + QUERY_ATTR_IDN_RESERVED3 = 0x13, + QUERY_ATTR_IDN_FFU_STATUS = 0x14, + QUERY_ATTR_IDN_PSA_STATE = 0x15, + QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16, }; /* Descriptor idn for Query requests */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ace3acdc9a5b..1fbb17bb175b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2689,8 +2689,8 @@ out_unlock: * * Returns 0 for success, non-zero in case of failure */ -static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, - enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) +int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) { struct ufs_query_req *request = NULL; struct ufs_query_res *response = NULL; @@ -6468,6 +6468,7 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) static const struct attribute_group *ufshcd_driver_groups[] = { &ufs_sysfs_unit_descriptor_group, + &ufs_sysfs_lun_attributes_group, NULL, }; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index f4cb31b23728..deb3c5d382e9 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -847,13 +847,14 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum desc_idn idn, u8 index, u8 selector, u8 *desc_buf, int *buf_len); - int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u8 param_offset, u8 *param_read_buf, u8 param_size); +int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val); int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res); int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, From 8d35a9dc42448c4f3cd208f8f4d5c5e72af83309 Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Thu, 15 Feb 2018 00:30:20 +0530 Subject: [PATCH 062/168] scsi: qla4xxx: Use dma_pool_zalloc() Use dma_pool_zalloc() instead of dma_pool_alloc + memset Signed-off-by: Souptick Joarder Acked-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_mbx.c | 6 ++---- drivers/scsi/qla4xxx/ql4_os.c | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index bda2e64ee5ca..5d56904687b9 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1584,12 +1584,11 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, struct ql4_chap_table *chap_table; dma_addr_t chap_dma; - chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); + chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); if (chap_table == NULL) return -ENOMEM; chap_size = sizeof(struct ql4_chap_table); - memset(chap_table, 0, chap_size); if (is_qla40XX(ha)) offset = FLASH_CHAP_OFFSET | (idx * chap_size); @@ -1648,13 +1647,12 @@ int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, uint32_t chap_size = 0; dma_addr_t chap_dma; - chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); + chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); if (chap_table == NULL) { ret = -ENOMEM; goto exit_set_chap; } - memset(chap_table, 0, sizeof(struct ql4_chap_table)); if (bidi) chap_table->flags |= BIT_6; /* peer */ else diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 82e889bbe0ed..589634358c83 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -825,12 +825,10 @@ static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx) uint32_t chap_size; int ret = 0; - chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); + chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); if (chap_table == NULL) return -ENOMEM; - memset(chap_table, 0, sizeof(struct ql4_chap_table)); - if (is_qla80XX(ha)) max_chap_entries = (ha->hw.flt_chap_size / 2) / sizeof(struct ql4_chap_table); From 501017f6d4e1feaa9ce3ff49c1190bc0588b3f02 Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Thu, 15 Feb 2018 01:40:38 +0530 Subject: [PATCH 063/168] scsi: qla2xxx: Use dma_pool_zalloc() Use dma_pool_zalloc() instead of dma_pool_alloc + memset Signed-off-by: Souptick Joarder Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 3 +-- drivers/scsi/qla2xxx/qla_iocb.c | 10 ++-------- drivers/scsi/qla2xxx/qla_target.c | 7 +------ 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index e2d5d3ca0f57..c11a89be292c 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1035,7 +1035,7 @@ qla84xx_updatefw(struct bsg_job *bsg_job) sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, fw_buf, data_len); - mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); + mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); if (!mn) { ql_log(ql_log_warn, vha, 0x7036, "DMA alloc failed for fw buffer.\n"); @@ -1046,7 +1046,6 @@ qla84xx_updatefw(struct bsg_job *bsg_job) flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); - memset(mn, 0, sizeof(struct access_chip_84xx)); mn->entry_type = VERIFY_CHIP_IOCB_TYPE; mn->entry_count = 1; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index e62ccd931853..a4edbecfaf96 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1210,7 +1210,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, uint32_t dif_bytes; uint8_t bundling = 1; uint16_t blk_size; - uint8_t *clr_ptr; struct crc_context *crc_ctx_pkt = NULL; struct qla_hw_data *ha; uint8_t additional_fcpcdb_len; @@ -1252,15 +1251,11 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, /* Allocate CRC context from global pool */ crc_ctx_pkt = sp->u.scmd.ctx = - dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma); + dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma); if (!crc_ctx_pkt) goto crc_queuing_error; - /* Zero out CTX area. */ - clr_ptr = (uint8_t *)crc_ctx_pkt; - memset(clr_ptr, 0, sizeof(*crc_ctx_pkt)); - crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma; sp->flags |= SRB_CRC_CTX_DMA_VALID; @@ -3074,7 +3069,7 @@ sufficient_dsds: } memset(ctx, 0, sizeof(struct ct6_dsd)); - ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool, + ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool, GFP_ATOMIC, &ctx->fcp_cmnd_dma); if (!ctx->fcp_cmnd) { ql_log(ql_log_fatal, vha, 0x3011, @@ -3127,7 +3122,6 @@ sufficient_dsds: host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); /* build FCP_CMND IU */ - memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd)); int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun); ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 3735ebd83012..755d7a2a3eea 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2871,7 +2871,6 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) uint32_t data_bytes; uint32_t dif_bytes; uint8_t bundling = 1; - uint8_t *clr_ptr; struct crc_context *crc_ctx_pkt = NULL; struct qla_hw_data *ha; struct ctio_crc2_to_fw *pkt; @@ -3000,15 +2999,11 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) /* Allocate CRC context from global pool */ crc_ctx_pkt = cmd->ctx = - dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma); + dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma); if (!crc_ctx_pkt) goto crc_queuing_error; - /* Zero out CTX area. */ - clr_ptr = (uint8_t *)crc_ctx_pkt; - memset(clr_ptr, 0, sizeof(*crc_ctx_pkt)); - crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma; INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list); From b71413dd01bbf302236cfb61df44702ea838dd75 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:40 -0800 Subject: [PATCH 064/168] scsi: lpfc: Rework lpfc to allow different sli4 cq and eq handlers Up until now, an SLI-4 device had no variance in the way it handled its EQs and CQs. With newer hardware, there are now differences in doorbells and some differences in how entries are valid. Prepare the code for new hardware by creating a sli4-based callout table that can be set based on if_type. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 7 ++++ drivers/scsi/lpfc/lpfc_sli.c | 63 ++++++++++++++++++----------------- drivers/scsi/lpfc/lpfc_sli4.h | 5 +++ 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 465d890220d5..e24dca2b3f2f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -9540,6 +9540,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } } + /* Set up the EQ/CQ register handeling functions now */ + if (if_type <= LPFC_SLI_INTF_IF_TYPE_2) { + phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_eq_clr_intr; + phba->sli4_hba.sli4_eq_release = lpfc_sli4_eq_release; + phba->sli4_hba.sli4_cq_release = lpfc_sli4_cq_release; + } + return 0; out_iounmap_all: diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e97d080e9f65..f91caae6489a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -299,7 +299,7 @@ lpfc_sli4_eq_get(struct lpfc_queue *q) * @q: The Event Queue to disable interrupts * **/ -static inline void +inline void lpfc_sli4_eq_clr_intr(struct lpfc_queue *q) { struct lpfc_register doorbell; @@ -5302,41 +5302,42 @@ static void lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) { int qidx; + struct lpfc_sli4_hba *sli4_hba = &phba->sli4_hba; - lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); - lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); - if (phba->sli4_hba.nvmels_cq) - lpfc_sli4_cq_release(phba->sli4_hba.nvmels_cq, + sli4_hba->sli4_cq_release(sli4_hba->mbx_cq, LPFC_QUEUE_REARM); + sli4_hba->sli4_cq_release(sli4_hba->els_cq, LPFC_QUEUE_REARM); + if (sli4_hba->nvmels_cq) + sli4_hba->sli4_cq_release(sli4_hba->nvmels_cq, LPFC_QUEUE_REARM); - if (phba->sli4_hba.fcp_cq) + if (sli4_hba->fcp_cq) for (qidx = 0; qidx < phba->cfg_fcp_io_channel; qidx++) - lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[qidx], + sli4_hba->sli4_cq_release(sli4_hba->fcp_cq[qidx], LPFC_QUEUE_REARM); - if (phba->sli4_hba.nvme_cq) + if (sli4_hba->nvme_cq) for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++) - lpfc_sli4_cq_release(phba->sli4_hba.nvme_cq[qidx], + sli4_hba->sli4_cq_release(sli4_hba->nvme_cq[qidx], LPFC_QUEUE_REARM); if (phba->cfg_fof) - lpfc_sli4_cq_release(phba->sli4_hba.oas_cq, LPFC_QUEUE_REARM); + sli4_hba->sli4_cq_release(sli4_hba->oas_cq, LPFC_QUEUE_REARM); - if (phba->sli4_hba.hba_eq) + if (sli4_hba->hba_eq) for (qidx = 0; qidx < phba->io_channel_irqs; qidx++) - lpfc_sli4_eq_release(phba->sli4_hba.hba_eq[qidx], - LPFC_QUEUE_REARM); + sli4_hba->sli4_eq_release(sli4_hba->hba_eq[qidx], + LPFC_QUEUE_REARM); if (phba->nvmet_support) { for (qidx = 0; qidx < phba->cfg_nvmet_mrq; qidx++) { - lpfc_sli4_cq_release( - phba->sli4_hba.nvmet_cqset[qidx], + sli4_hba->sli4_cq_release( + sli4_hba->nvmet_cqset[qidx], LPFC_QUEUE_REARM); } } if (phba->cfg_fof) - lpfc_sli4_eq_release(phba->sli4_hba.fof_eq, LPFC_QUEUE_REARM); + sli4_hba->sli4_eq_release(sli4_hba->fof_eq, LPFC_QUEUE_REARM); } /** @@ -7270,7 +7271,7 @@ lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) { - + struct lpfc_sli4_hba *sli4_hba = &phba->sli4_hba; uint32_t eqidx; struct lpfc_queue *fpeq = NULL; struct lpfc_eqe *eqe; @@ -7281,11 +7282,11 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) /* Find the eq associated with the mcq */ - if (phba->sli4_hba.hba_eq) + if (sli4_hba->hba_eq) for (eqidx = 0; eqidx < phba->io_channel_irqs; eqidx++) - if (phba->sli4_hba.hba_eq[eqidx]->queue_id == - phba->sli4_hba.mbx_cq->assoc_qid) { - fpeq = phba->sli4_hba.hba_eq[eqidx]; + if (sli4_hba->hba_eq[eqidx]->queue_id == + sli4_hba->mbx_cq->assoc_qid) { + fpeq = sli4_hba->hba_eq[eqidx]; break; } if (!fpeq) @@ -7293,7 +7294,7 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) /* Turn off interrupts from this EQ */ - lpfc_sli4_eq_clr_intr(fpeq); + sli4_hba->sli4_eq_clr_intr(fpeq); /* Check to see if a mbox completion is pending */ @@ -7314,7 +7315,7 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) /* Always clear and re-arm the EQ */ - lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); + sli4_hba->sli4_eq_release(fpeq, LPFC_QUEUE_REARM); return mbox_pending; @@ -9494,7 +9495,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, fpeq = phba->sli4_hba.hba_eq[idx]; /* Turn off interrupts from this EQ */ - lpfc_sli4_eq_clr_intr(fpeq); + phba->sli4_hba.sli4_eq_clr_intr(fpeq); /* * Process all the events on FCP EQ @@ -9506,7 +9507,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, } /* Always clear and re-arm the EQ */ - lpfc_sli4_eq_release(fpeq, + phba->sli4_hba.sli4_eq_release(fpeq, LPFC_QUEUE_REARM); } atomic_inc(&hba_eq_hdl->hba_eq_in_use); @@ -13136,7 +13137,7 @@ lpfc_sli4_sp_process_cq(struct work_struct *work) "(x%x), type (%d)\n", cq->queue_id, cq->type); /* In any case, flash and re-arm the RCQ */ - lpfc_sli4_cq_release(cq, LPFC_QUEUE_REARM); + phba->sli4_hba.sli4_cq_release(cq, LPFC_QUEUE_REARM); /* wake up worker thread if there are works to be done */ if (workposted) @@ -13568,7 +13569,7 @@ lpfc_sli4_hba_process_cq(struct work_struct *work) "queue fcpcqid=%d\n", cq->queue_id); /* In any case, flash and re-arm the CQ */ - lpfc_sli4_cq_release(cq, LPFC_QUEUE_REARM); + phba->sli4_hba.sli4_cq_release(cq, LPFC_QUEUE_REARM); /* wake up worker thread if there are works to be done */ if (workposted) @@ -13585,7 +13586,7 @@ lpfc_sli4_eq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq) ; /* Clear and re-arm the EQ */ - lpfc_sli4_eq_release(eq, LPFC_QUEUE_REARM); + phba->sli4_hba.sli4_eq_release(eq, LPFC_QUEUE_REARM); } @@ -13733,7 +13734,7 @@ lpfc_sli4_fof_intr_handler(int irq, void *dev_id) } } /* Always clear and re-arm the fast-path EQ */ - lpfc_sli4_eq_release(eq, LPFC_QUEUE_REARM); + phba->sli4_hba.sli4_eq_release(eq, LPFC_QUEUE_REARM); return IRQ_HANDLED; } @@ -13791,7 +13792,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) if (lpfc_fcp_look_ahead) { if (atomic_dec_and_test(&hba_eq_hdl->hba_eq_in_use)) - lpfc_sli4_eq_clr_intr(fpeq); + phba->sli4_hba.sli4_eq_clr_intr(fpeq); else { atomic_inc(&hba_eq_hdl->hba_eq_in_use); return IRQ_NONE; @@ -13826,7 +13827,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) fpeq->EQ_max_eqe = ecount; /* Always clear and re-arm the fast-path EQ */ - lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); + phba->sli4_hba.sli4_eq_release(fpeq, LPFC_QUEUE_REARM); if (unlikely(ecount == 0)) { fpeq->EQ_no_entry++; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 4545c1fdcb55..0c0cbe296fed 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -582,6 +582,10 @@ struct lpfc_sli4_hba { struct lpfc_bbscn_params bbscn_params; struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */ + void (*sli4_eq_clr_intr)(struct lpfc_queue *q); + uint32_t (*sli4_eq_release)(struct lpfc_queue *q, bool arm); + uint32_t (*sli4_cq_release)(struct lpfc_queue *q, bool arm); + /* Pointers to the constructed SLI4 queues */ struct lpfc_queue **hba_eq; /* Event queues for HBA */ struct lpfc_queue **fcp_cq; /* Fast-path FCP compl queue */ @@ -848,6 +852,7 @@ void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *); int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *); int lpfc_sli4_get_iocb_cnt(struct lpfc_hba *phba); int lpfc_sli4_init_vpi(struct lpfc_vport *); +inline void lpfc_sli4_eq_clr_intr(struct lpfc_queue *); uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool); uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool); void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t); From 9dd35425a50c667ae2b6c2cda201425ed2d3fd25 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:41 -0800 Subject: [PATCH 065/168] scsi: lpfc: Rework sli4 doorbell infrastructure Up until now, all SLI-4 devices had the same doorbells at the same bar locations. With newer hardware, there are now independent EQ and CQ doorbells and the bar locations differ. Prepare the code for new hardware by separating the eq/cq doorbell into separate components. The components can be set based on if_type. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_debugfs.c | 20 ++++++++++++++------ drivers/scsi/lpfc/lpfc_debugfs.h | 11 ++++++----- drivers/scsi/lpfc/lpfc_init.c | 9 ++++++--- drivers/scsi/lpfc/lpfc_sli.c | 8 ++++---- drivers/scsi/lpfc/lpfc_sli4.h | 3 ++- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 17ea3bb04266..308303d501cf 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -3944,10 +3944,15 @@ lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer, return 0; switch (drbregid) { - case LPFC_DRB_EQCQ: - len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, - "EQCQ-DRB-REG: 0x%08x\n", - readl(phba->sli4_hba.EQCQDBregaddr)); + case LPFC_DRB_EQ: + len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len, + "EQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.EQDBregaddr)); + break; + case LPFC_DRB_CQ: + len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len, + "CQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.CQDBregaddr)); break; case LPFC_DRB_MQ: len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, @@ -4086,8 +4091,11 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf, idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { switch (drb_reg_id) { - case LPFC_DRB_EQCQ: - drb_reg = phba->sli4_hba.EQCQDBregaddr; + case LPFC_DRB_EQ: + drb_reg = phba->sli4_hba.EQDBregaddr; + break; + case LPFC_DRB_CQ: + drb_reg = phba->sli4_hba.CQDBregaddr; break; case LPFC_DRB_MQ: drb_reg = phba->sli4_hba.MQDBregaddr; diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index c4edd87bfc65..12fbf498a7ce 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h @@ -126,12 +126,13 @@ #define LPFC_DRB_ACC_WR_CMD_ARG 2 #define LPFC_DRB_ACC_BUF_SIZE 256 -#define LPFC_DRB_EQCQ 1 -#define LPFC_DRB_MQ 2 -#define LPFC_DRB_WQ 3 -#define LPFC_DRB_RQ 4 +#define LPFC_DRB_EQ 1 +#define LPFC_DRB_CQ 2 +#define LPFC_DRB_MQ 3 +#define LPFC_DRB_WQ 4 +#define LPFC_DRB_RQ 5 -#define LPFC_DRB_MAX 4 +#define LPFC_DRB_MAX 5 #define IDIAG_DRBACC_REGID_INDX 0 #define IDIAG_DRBACC_VALUE_INDX 1 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e24dca2b3f2f..b2cf8eb99008 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7430,8 +7430,9 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) phba->sli4_hba.WQDBregaddr = phba->sli4_hba.conf_regs_memmap_p + LPFC_ULP0_WQ_DOORBELL; - phba->sli4_hba.EQCQDBregaddr = + phba->sli4_hba.CQDBregaddr = phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL; + phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr; phba->sli4_hba.MQDBregaddr = phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL; phba->sli4_hba.BMBXregaddr = @@ -7488,8 +7489,10 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf) phba->sli4_hba.WQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + vf * LPFC_VFR_PAGE_SIZE + LPFC_ULP0_WQ_DOORBELL); - phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + - vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL); + phba->sli4_hba.CQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + + vf * LPFC_VFR_PAGE_SIZE + + LPFC_EQCQ_DOORBELL); + phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr; phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p + vf * LPFC_VFR_PAGE_SIZE + LPFC_MQ_DOORBELL); phba->sli4_hba.BMBXregaddr = (phba->sli4_hba.drbl_regs_memmap_p + diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f91caae6489a..f4db7d486431 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -310,7 +310,7 @@ lpfc_sli4_eq_clr_intr(struct lpfc_queue *q) bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell, (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT)); bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id); - writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); + writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr); } /** @@ -360,10 +360,10 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm) bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell, (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT)); bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id); - writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); + writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr); /* PCI read to flush PCI pipeline on re-arming for INTx mode */ if ((q->phba->intr_type == INTx) && (arm == LPFC_QUEUE_REARM)) - readl(q->phba->sli4_hba.EQCQDBregaddr); + readl(q->phba->sli4_hba.EQDBregaddr); return released; } @@ -453,7 +453,7 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm) bf_set(lpfc_eqcq_doorbell_cqid_hi, &doorbell, (q->queue_id >> LPFC_CQID_HI_FIELD_SHIFT)); bf_set(lpfc_eqcq_doorbell_cqid_lo, &doorbell, q->queue_id); - writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); + writel(doorbell.word0, q->phba->sli4_hba.CQDBregaddr); return released; } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 0c0cbe296fed..e2f06c92c4dd 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -569,7 +569,8 @@ struct lpfc_sli4_hba { /* IF type 0, BAR 0 and if type 2, BAR 0 doorbell register memory map */ void __iomem *RQDBregaddr; /* RQ_DOORBELL register */ void __iomem *WQDBregaddr; /* WQ_DOORBELL register */ - void __iomem *EQCQDBregaddr; /* EQCQ_DOORBELL register */ + void __iomem *CQDBregaddr; /* CQ_DOORBELL register */ + void __iomem *EQDBregaddr; /* EQ_DOORBELL register */ void __iomem *MQDBregaddr; /* MQ_DOORBELL register */ void __iomem *BMBXregaddr; /* BootStrap MBX register */ From 27d6ac0a6e830043bd5db89fee8adddb41ada2f7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:42 -0800 Subject: [PATCH 066/168] scsi: lpfc: Add SLI-4 if_type=6 support to the code base New hardware supports a SLI-4 interface, but with a new if_type variant of 6. If_type=6 has a different PCI BAR map, separate EQ/CQ doorbells, and some changes in doorbell formats. Add the changes for the if_type into headers, adapter initialization and control flows. Add new eq and cq handlers. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 4 +- drivers/scsi/lpfc/lpfc_hw4.h | 54 ++++++++++++++- drivers/scsi/lpfc/lpfc_init.c | 120 ++++++++++++++++++++++++++++------ drivers/scsi/lpfc/lpfc_sli.c | 120 +++++++++++++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_sli4.h | 3 + 5 files changed, 275 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d89816222b23..8b33b652226b 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -3867,7 +3867,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job, "ext_buf_cnt:%d\n", ext_buf_cnt); } else { /* sanity check on interface type for support */ - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < LPFC_SLI_INTF_IF_TYPE_2) { rc = -ENODEV; goto job_error; @@ -4053,7 +4053,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job, "ext_buf_cnt:%d\n", ext_buf_cnt); } else { /* sanity check on interface type for support */ - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < LPFC_SLI_INTF_IF_TYPE_2) return -ENODEV; /* nemb_tp == nemb_hbd */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 8685d26e6929..93fd9fd10a0f 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -84,6 +84,7 @@ struct lpfc_sli_intf { #define LPFC_SLI_INTF_IF_TYPE_0 0 #define LPFC_SLI_INTF_IF_TYPE_1 1 #define LPFC_SLI_INTF_IF_TYPE_2 2 +#define LPFC_SLI_INTF_IF_TYPE_6 6 #define lpfc_sli_intf_sli_family_SHIFT 8 #define lpfc_sli_intf_sli_family_MASK 0x0000000F #define lpfc_sli_intf_sli_family_WORD word0 @@ -731,11 +732,13 @@ struct lpfc_register { * register sets depending on the UCNA Port's reported if_type * value. For UCNA ports running SLI4 and if_type 0, they reside in * BAR4. For UCNA ports running SLI4 and if_type 2, they reside in - * BAR0. The offsets are the same so the driver must account for - * any base address difference. + * BAR0. For FC ports running SLI4 and if_type 6, they reside in + * BAR2. The offsets and base address are different, so the driver + * has to compute the register addresses accordingly */ #define LPFC_ULP0_RQ_DOORBELL 0x00A0 #define LPFC_ULP1_RQ_DOORBELL 0x00C0 +#define LPFC_IF6_RQ_DOORBELL 0x0080 #define lpfc_rq_db_list_fm_num_posted_SHIFT 24 #define lpfc_rq_db_list_fm_num_posted_MASK 0x00FF #define lpfc_rq_db_list_fm_num_posted_WORD word0 @@ -770,6 +773,20 @@ struct lpfc_register { #define lpfc_wq_db_ring_fm_id_MASK 0xFFFF #define lpfc_wq_db_ring_fm_id_WORD word0 +#define LPFC_IF6_WQ_DOORBELL 0x0040 +#define lpfc_if6_wq_db_list_fm_num_posted_SHIFT 24 +#define lpfc_if6_wq_db_list_fm_num_posted_MASK 0x00FF +#define lpfc_if6_wq_db_list_fm_num_posted_WORD word0 +#define lpfc_if6_wq_db_list_fm_dpp_SHIFT 23 +#define lpfc_if6_wq_db_list_fm_dpp_MASK 0x0001 +#define lpfc_if6_wq_db_list_fm_dpp_WORD word0 +#define lpfc_if6_wq_db_list_fm_dpp_id_SHIFT 16 +#define lpfc_if6_wq_db_list_fm_dpp_id_MASK 0x001F +#define lpfc_if6_wq_db_list_fm_dpp_id_WORD word0 +#define lpfc_if6_wq_db_list_fm_id_SHIFT 0 +#define lpfc_if6_wq_db_list_fm_id_MASK 0xFFFF +#define lpfc_if6_wq_db_list_fm_id_WORD word0 + #define LPFC_EQCQ_DOORBELL 0x0120 #define lpfc_eqcq_doorbell_se_SHIFT 31 #define lpfc_eqcq_doorbell_se_MASK 0x0001 @@ -805,6 +822,38 @@ struct lpfc_register { #define LPFC_CQID_HI_FIELD_SHIFT 10 #define LPFC_EQID_HI_FIELD_SHIFT 9 +#define LPFC_IF6_CQ_DOORBELL 0x00C0 +#define lpfc_if6_cq_doorbell_se_SHIFT 31 +#define lpfc_if6_cq_doorbell_se_MASK 0x0001 +#define lpfc_if6_cq_doorbell_se_WORD word0 +#define LPFC_IF6_CQ_SOLICIT_ENABLE_OFF 0 +#define LPFC_IF6_CQ_SOLICIT_ENABLE_ON 1 +#define lpfc_if6_cq_doorbell_arm_SHIFT 29 +#define lpfc_if6_cq_doorbell_arm_MASK 0x0001 +#define lpfc_if6_cq_doorbell_arm_WORD word0 +#define lpfc_if6_cq_doorbell_num_released_SHIFT 16 +#define lpfc_if6_cq_doorbell_num_released_MASK 0x1FFF +#define lpfc_if6_cq_doorbell_num_released_WORD word0 +#define lpfc_if6_cq_doorbell_cqid_SHIFT 0 +#define lpfc_if6_cq_doorbell_cqid_MASK 0xFFFF +#define lpfc_if6_cq_doorbell_cqid_WORD word0 + +#define LPFC_IF6_EQ_DOORBELL 0x0120 +#define lpfc_if6_eq_doorbell_io_SHIFT 31 +#define lpfc_if6_eq_doorbell_io_MASK 0x0001 +#define lpfc_if6_eq_doorbell_io_WORD word0 +#define LPFC_IF6_EQ_INTR_OVERRIDE_OFF 0 +#define LPFC_IF6_EQ_INTR_OVERRIDE_ON 1 +#define lpfc_if6_eq_doorbell_arm_SHIFT 29 +#define lpfc_if6_eq_doorbell_arm_MASK 0x0001 +#define lpfc_if6_eq_doorbell_arm_WORD word0 +#define lpfc_if6_eq_doorbell_num_released_SHIFT 16 +#define lpfc_if6_eq_doorbell_num_released_MASK 0x1FFF +#define lpfc_if6_eq_doorbell_num_released_WORD word0 +#define lpfc_if6_eq_doorbell_eqid_SHIFT 0 +#define lpfc_if6_eq_doorbell_eqid_MASK 0x0FFF +#define lpfc_if6_eq_doorbell_eqid_WORD word0 + #define LPFC_BMBX 0x0160 #define lpfc_bmbx_addr_SHIFT 2 #define lpfc_bmbx_addr_MASK 0x3FFFFFFF @@ -817,6 +866,7 @@ struct lpfc_register { #define lpfc_bmbx_rdy_WORD word0 #define LPFC_MQ_DOORBELL 0x0140 +#define LPFC_IF6_MQ_DOORBELL 0x0160 #define lpfc_mq_doorbell_num_posted_SHIFT 16 #define lpfc_mq_doorbell_num_posted_MASK 0x3FFF #define lpfc_mq_doorbell_num_posted_WORD word0 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b2cf8eb99008..0d51ecb7317f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1761,7 +1761,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, int rc; uint32_t intr_mode; - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >= LPFC_SLI_INTF_IF_TYPE_2) { /* * On error status condition, driver need to wait for port @@ -1892,6 +1892,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) break; case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_6: pci_rd_rc1 = lpfc_readl( phba->sli4_hba.u.if_type2.STATUSregaddr, &portstat_reg.word0); @@ -6018,7 +6019,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) return -ENOMEM; /* IF Type 2 ports get initialized now. */ - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >= LPFC_SLI_INTF_IF_TYPE_2) { rc = lpfc_pci_function_reset(phba); if (unlikely(rc)) { @@ -7348,6 +7349,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) } break; case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_6: /* Final checks. The port status should be clean. */ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, ®_data.word0) || @@ -7438,6 +7440,28 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) phba->sli4_hba.BMBXregaddr = phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX; break; + case LPFC_SLI_INTF_IF_TYPE_6: + phba->sli4_hba.u.if_type2.EQDregaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_EQ_DELAY_OFFSET; + phba->sli4_hba.u.if_type2.ERR1regaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_ER1_OFFSET; + phba->sli4_hba.u.if_type2.ERR2regaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_ER2_OFFSET; + phba->sli4_hba.u.if_type2.CTRLregaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_CTL_OFFSET; + phba->sli4_hba.u.if_type2.STATUSregaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_STA_OFFSET; + phba->sli4_hba.PSMPHRregaddr = + phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_SEM_OFFSET; + phba->sli4_hba.BMBXregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX; + break; case LPFC_SLI_INTF_IF_TYPE_1: default: dev_printk(KERN_ERR, &phba->pcidev->dev, @@ -7451,20 +7475,43 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) * lpfc_sli4_bar1_register_memmap - Set up SLI4 BAR1 register memory map. * @phba: pointer to lpfc hba data structure. * - * This routine is invoked to set up SLI4 BAR1 control status register (CSR) - * memory map. + * This routine is invoked to set up SLI4 BAR1 register memory map. **/ static void -lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba) +lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba, uint32_t if_type) { - phba->sli4_hba.PSMPHRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_SLIPORT_IF0_SMPHR; - phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_ISR0; - phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_IMR0; - phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_ISCR0; + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + phba->sli4_hba.PSMPHRregaddr = + phba->sli4_hba.ctrl_regs_memmap_p + + LPFC_SLIPORT_IF0_SMPHR; + phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + + LPFC_HST_ISR0; + phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + + LPFC_HST_IMR0; + phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + + LPFC_HST_ISCR0; + break; + case LPFC_SLI_INTF_IF_TYPE_6: + phba->sli4_hba.RQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p + + LPFC_IF6_RQ_DOORBELL; + phba->sli4_hba.WQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p + + LPFC_IF6_WQ_DOORBELL; + phba->sli4_hba.CQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p + + LPFC_IF6_CQ_DOORBELL; + phba->sli4_hba.EQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p + + LPFC_IF6_EQ_DOORBELL; + phba->sli4_hba.MQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p + + LPFC_IF6_MQ_DOORBELL; + break; + case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_1: + default: + dev_err(&phba->pcidev->dev, + "FATAL - unsupported SLI4 interface type - %d\n", + if_type); + break; + } } /** @@ -7729,7 +7776,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) /* Update link speed if forced link speed is supported */ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); - if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { forced_link_speed = bf_get(lpfc_mbx_rd_conf_link_speed, rd_config); if (forced_link_speed) { @@ -7789,7 +7836,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) phba->cfg_hba_queue_depth = length; } - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < LPFC_SLI_INTF_IF_TYPE_2) goto read_cfg_out; @@ -7903,6 +7950,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba) } mempool_free(mboxq, phba->mbox_mem_pool); break; + case LPFC_SLI_INTF_IF_TYPE_6: case LPFC_SLI_INTF_IF_TYPE_2: case LPFC_SLI_INTF_IF_TYPE_1: default: @@ -9314,6 +9362,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) } break; case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_6: wait: /* * Poll the Port Status Register and wait for RDY for @@ -9469,7 +9518,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } else { phba->pci_bar0_map = pci_resource_start(pdev, 1); bar0map_len = pci_resource_len(pdev, 1); - if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { dev_printk(KERN_ERR, &pdev->dev, "FATAL - No BAR0 mapping for SLI4, if_type 2\n"); goto out; @@ -9506,13 +9555,32 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } phba->pci_bar2_memmap_p = phba->sli4_hba.ctrl_regs_memmap_p; - lpfc_sli4_bar1_register_memmap(phba); + lpfc_sli4_bar1_register_memmap(phba, if_type); } else { error = -ENOMEM; goto out_iounmap_conf; } } + if ((if_type == LPFC_SLI_INTF_IF_TYPE_6) && + (pci_resource_start(pdev, PCI_64BIT_BAR2))) { + /* + * Map SLI4 if type 6 HBA Doorbell Register base to a kernel + * virtual address and setup the registers. + */ + phba->pci_bar1_map = pci_resource_start(pdev, PCI_64BIT_BAR2); + bar1map_len = pci_resource_len(pdev, PCI_64BIT_BAR2); + phba->sli4_hba.drbl_regs_memmap_p = + ioremap(phba->pci_bar1_map, bar1map_len); + if (!phba->sli4_hba.drbl_regs_memmap_p) { + dev_err(&pdev->dev, + "ioremap failed for SLI4 HBA doorbell registers.\n"); + goto out_iounmap_conf; + } + phba->pci_bar2_memmap_p = phba->sli4_hba.drbl_regs_memmap_p; + lpfc_sli4_bar1_register_memmap(phba, if_type); + } + if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { if (pci_resource_start(pdev, PCI_64BIT_BAR4)) { /* @@ -9544,10 +9612,20 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } /* Set up the EQ/CQ register handeling functions now */ - if (if_type <= LPFC_SLI_INTF_IF_TYPE_2) { + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + case LPFC_SLI_INTF_IF_TYPE_2: phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_eq_clr_intr; phba->sli4_hba.sli4_eq_release = lpfc_sli4_eq_release; phba->sli4_hba.sli4_cq_release = lpfc_sli4_cq_release; + break; + case LPFC_SLI_INTF_IF_TYPE_6: + phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_if6_eq_clr_intr; + phba->sli4_hba.sli4_eq_release = lpfc_sli4_if6_eq_release; + phba->sli4_hba.sli4_cq_release = lpfc_sli4_if6_cq_release; + break; + default: + break; } return 0; @@ -9584,6 +9662,10 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba) case LPFC_SLI_INTF_IF_TYPE_2: iounmap(phba->sli4_hba.conf_regs_memmap_p); break; + case LPFC_SLI_INTF_IF_TYPE_6: + iounmap(phba->sli4_hba.drbl_regs_memmap_p); + iounmap(phba->sli4_hba.conf_regs_memmap_p); + break; case LPFC_SLI_INTF_IF_TYPE_1: default: dev_printk(KERN_ERR, &phba->pcidev->dev, @@ -11288,7 +11370,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade) const struct firmware *fw; /* Only supported on SLI4 interface type 2 for now */ - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < LPFC_SLI_INTF_IF_TYPE_2) return -EPERM; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f4db7d486431..3bff1f9c5df7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -313,6 +313,25 @@ lpfc_sli4_eq_clr_intr(struct lpfc_queue *q) writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr); } +/** + * lpfc_sli4_if6_eq_clr_intr - Turn off interrupts from this EQ + * @q: The Event Queue to disable interrupts + * + **/ +inline void +lpfc_sli4_if6_eq_clr_intr(struct lpfc_queue *q) +{ + struct lpfc_register doorbell; + + doorbell.word0 = 0; + bf_set(lpfc_eqcq_doorbell_eqci, &doorbell, 1); + bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_EVENT); + bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell, + (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT)); + bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id); + writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr); +} + /** * lpfc_sli4_eq_release - Indicates the host has finished processing an EQ * @q: The Event Queue that the host has completed processing for. @@ -367,6 +386,55 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm) return released; } +/** + * lpfc_sli4_if6_eq_release - Indicates the host has finished processing an EQ + * @q: The Event Queue that the host has completed processing for. + * @arm: Indicates whether the host wants to arms this CQ. + * + * This routine will mark all Event Queue Entries on @q, from the last + * known completed entry to the last entry that was processed, as completed + * by clearing the valid bit for each completion queue entry. Then it will + * notify the HBA, by ringing the doorbell, that the EQEs have been processed. + * The internal host index in the @q will be updated by this routine to indicate + * that the host has finished processing the entries. The @arm parameter + * indicates that the queue should be rearmed when ringing the doorbell. + * + * This function will return the number of EQEs that were popped. + **/ +uint32_t +lpfc_sli4_if6_eq_release(struct lpfc_queue *q, bool arm) +{ + uint32_t released = 0; + struct lpfc_eqe *temp_eqe; + struct lpfc_register doorbell; + + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; + + /* while there are valid entries */ + while (q->hba_index != q->host_index) { + temp_eqe = q->qe[q->host_index].eqe; + bf_set_le32(lpfc_eqe_valid, temp_eqe, 0); + released++; + q->host_index = ((q->host_index + 1) % q->entry_count); + } + if (unlikely(released == 0 && !arm)) + return 0; + + /* ring doorbell for number popped */ + doorbell.word0 = 0; + if (arm) + bf_set(lpfc_if6_eq_doorbell_arm, &doorbell, 1); + bf_set(lpfc_if6_eq_doorbell_num_released, &doorbell, released); + bf_set(lpfc_if6_eq_doorbell_eqid, &doorbell, q->queue_id); + writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr); + /* PCI read to flush PCI pipeline on re-arming for INTx mode */ + if ((q->phba->intr_type == INTx) && (arm == LPFC_QUEUE_REARM)) + readl(q->phba->sli4_hba.EQDBregaddr); + return released; +} + /** * lpfc_sli4_cq_get - Gets the next valid CQE from a CQ * @q: The Completion Queue to get the first valid CQE from @@ -457,6 +525,51 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm) return released; } +/** + * lpfc_sli4_if6_cq_release - Indicates the host has finished processing a CQ + * @q: The Completion Queue that the host has completed processing for. + * @arm: Indicates whether the host wants to arms this CQ. + * + * This routine will mark all Completion queue entries on @q, from the last + * known completed entry to the last entry that was processed, as completed + * by clearing the valid bit for each completion queue entry. Then it will + * notify the HBA, by ringing the doorbell, that the CQEs have been processed. + * The internal host index in the @q will be updated by this routine to indicate + * that the host has finished processing the entries. The @arm parameter + * indicates that the queue should be rearmed when ringing the doorbell. + * + * This function will return the number of CQEs that were released. + **/ +uint32_t +lpfc_sli4_if6_cq_release(struct lpfc_queue *q, bool arm) +{ + uint32_t released = 0; + struct lpfc_cqe *temp_qe; + struct lpfc_register doorbell; + + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; + /* while there are valid entries */ + while (q->hba_index != q->host_index) { + temp_qe = q->qe[q->host_index].cqe; + bf_set_le32(lpfc_cqe_valid, temp_qe, 0); + released++; + q->host_index = ((q->host_index + 1) % q->entry_count); + } + if (unlikely(released == 0 && !arm)) + return 0; + + /* ring doorbell for number popped */ + doorbell.word0 = 0; + if (arm) + bf_set(lpfc_if6_cq_doorbell_arm, &doorbell, 1); + bf_set(lpfc_if6_cq_doorbell_num_released, &doorbell, released); + bf_set(lpfc_if6_cq_doorbell_cqid, &doorbell, q->queue_id); + writel(doorbell.word0, q->phba->sli4_hba.CQDBregaddr); + return released; +} + /** * lpfc_sli4_rq_put - Put a Receive Buffer Queue Entry on a Receive Queue * @q: The Header Receive Queue to operate on. @@ -2331,7 +2444,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) { if (phba->sli_rev == LPFC_SLI_REV4 && (bf_get(lpfc_sli_intf_if_type, - &phba->sli4_hba.sli_intf) == + &phba->sli4_hba.sli_intf) >= LPFC_SLI_INTF_IF_TYPE_2)) { if (ndlp) { lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, @@ -8792,7 +8905,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->context2)->virt); if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); - if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { if (pcmd && (*pcmd == ELS_CMD_FLOGI || *pcmd == ELS_CMD_SCR || *pcmd == ELS_CMD_FDISC || @@ -9089,7 +9202,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); - if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { if (iocbq->vport->fc_flag & FC_PT2PT) { bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1); bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, @@ -11673,6 +11786,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) } break; case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_6: if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, &portstat_reg.word0) || lpfc_readl(phba->sli4_hba.PSMPHRregaddr, diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index e2f06c92c4dd..33838b4b28d9 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -856,6 +856,9 @@ int lpfc_sli4_init_vpi(struct lpfc_vport *); inline void lpfc_sli4_eq_clr_intr(struct lpfc_queue *); uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool); uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool); +inline void lpfc_sli4_if6_eq_clr_intr(struct lpfc_queue *q); +uint32_t lpfc_sli4_if6_cq_release(struct lpfc_queue *q, bool arm); +uint32_t lpfc_sli4_if6_eq_release(struct lpfc_queue *q, bool arm); void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t); int lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *, uint16_t); int lpfc_sli4_fcf_rr_read_fcf_rec(struct lpfc_hba *, uint16_t); From 1351e69fc6db30e186295f1c9495d03cef6a01a2 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:43 -0800 Subject: [PATCH 067/168] scsi: lpfc: Add push-to-adapter support to sli4 New if_type=6 adapters support an additional BAR that provides apertures to allow direct WQE to adapter push support - termed Direct Packet Push (DPP). WQ creation differs slightly to ask for a WQ to be DPP-ized. When submitting a WQE to a DPP WQ, it is submitted to the host memory for the WQ normally, but is also written by the host cpu directly to a BAR aperture. Write buffer coalescing in hardware is (hopefully) turned on, enabling single pci write operation support. The doorbell is thing rung to indicate the WQE is available and was pushed to the aperture. This patch: - Updates the WQ Create commands for the DPP options - Adds the bar mapping for if_type=6 DPP bar - Adds the WQE pushing to the DDP aperture received from WQ create - Adds a new module parameter to disable DPP operation if desired. Default is enabled. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 3 +- drivers/scsi/lpfc/lpfc_attr.c | 10 ++ drivers/scsi/lpfc/lpfc_hw4.h | 31 +++++ drivers/scsi/lpfc/lpfc_init.c | 18 +++ drivers/scsi/lpfc/lpfc_sli.c | 229 ++++++++++++++++++++++------------ drivers/scsi/lpfc/lpfc_sli4.h | 16 ++- 6 files changed, 220 insertions(+), 87 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 9698b9635058..86ffb9756e65 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -840,7 +840,8 @@ struct lpfc_hba { uint32_t cfg_enable_SmartSAN; uint32_t cfg_enable_mds_diags; uint32_t cfg_enable_fc4_type; - uint32_t cfg_enable_bbcr; /*Enable BB Credit Recovery*/ + uint32_t cfg_enable_bbcr; /* Enable BB Credit Recovery */ + uint32_t cfg_enable_dpp; /* Enable Direct Packet Push */ uint32_t cfg_xri_split; #define LPFC_ENABLE_FCP 1 #define LPFC_ENABLE_NVME 2 diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 7be4bdef4d42..32f17e19e123 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5186,6 +5186,14 @@ LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics"); */ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery"); +/* + * lpfc_enable_dpp: Enable DPP on G7 + * 0 = DPP on G7 disabled + * 1 = DPP on G7 enabled (default) + * Value range is [0,1]. Default value is 1. + */ +LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push"); + struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_nvme_info, &dev_attr_bg_info, @@ -5294,6 +5302,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_xlane_supported, &dev_attr_lpfc_enable_mds_diags, &dev_attr_lpfc_enable_bbcr, + &dev_attr_lpfc_enable_dpp, NULL, }; @@ -6306,6 +6315,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel); lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr); + lpfc_enable_dpp_init(phba, lpfc_enable_dpp); if (phba->sli_rev != LPFC_SLI_REV4) { /* NVME only supported on SLI4 */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 93fd9fd10a0f..60ccff6fa8b0 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1372,6 +1372,15 @@ struct lpfc_mbx_wq_create { #define lpfc_mbx_wq_create_page_size_MASK 0x000000FF #define lpfc_mbx_wq_create_page_size_WORD word1 #define LPFC_WQ_PAGE_SIZE_4096 0x1 +#define lpfc_mbx_wq_create_dpp_req_SHIFT 15 +#define lpfc_mbx_wq_create_dpp_req_MASK 0x00000001 +#define lpfc_mbx_wq_create_dpp_req_WORD word1 +#define lpfc_mbx_wq_create_doe_SHIFT 14 +#define lpfc_mbx_wq_create_doe_MASK 0x00000001 +#define lpfc_mbx_wq_create_doe_WORD word1 +#define lpfc_mbx_wq_create_toe_SHIFT 13 +#define lpfc_mbx_wq_create_toe_MASK 0x00000001 +#define lpfc_mbx_wq_create_toe_WORD word1 #define lpfc_mbx_wq_create_wqe_size_SHIFT 8 #define lpfc_mbx_wq_create_wqe_size_MASK 0x0000000F #define lpfc_mbx_wq_create_wqe_size_WORD word1 @@ -1400,6 +1409,28 @@ struct lpfc_mbx_wq_create { #define lpfc_mbx_wq_create_db_format_MASK 0x0000FFFF #define lpfc_mbx_wq_create_db_format_WORD word2 } response; + struct { + uint32_t word0; +#define lpfc_mbx_wq_create_dpp_rsp_SHIFT 31 +#define lpfc_mbx_wq_create_dpp_rsp_MASK 0x00000001 +#define lpfc_mbx_wq_create_dpp_rsp_WORD word0 +#define lpfc_mbx_wq_create_v1_q_id_SHIFT 0 +#define lpfc_mbx_wq_create_v1_q_id_MASK 0x0000FFFF +#define lpfc_mbx_wq_create_v1_q_id_WORD word0 + uint32_t word1; +#define lpfc_mbx_wq_create_v1_bar_set_SHIFT 0 +#define lpfc_mbx_wq_create_v1_bar_set_MASK 0x0000000F +#define lpfc_mbx_wq_create_v1_bar_set_WORD word1 + uint32_t doorbell_offset; + uint32_t word3; +#define lpfc_mbx_wq_create_dpp_id_SHIFT 16 +#define lpfc_mbx_wq_create_dpp_id_MASK 0x0000001F +#define lpfc_mbx_wq_create_dpp_id_WORD word3 +#define lpfc_mbx_wq_create_dpp_bar_SHIFT 0 +#define lpfc_mbx_wq_create_dpp_bar_MASK 0x0000000F +#define lpfc_mbx_wq_create_dpp_bar_WORD word3 + uint32_t dpp_offset; + } response_1; } u; }; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 0d51ecb7317f..5f0c63bb0a4d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -9611,6 +9611,24 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } } + if (if_type == LPFC_SLI_INTF_IF_TYPE_6 && + pci_resource_start(pdev, PCI_64BIT_BAR4)) { + /* + * Map SLI4 if type 6 HBA DPP Register base to a kernel + * virtual address and setup the registers. + */ + phba->pci_bar2_map = pci_resource_start(pdev, PCI_64BIT_BAR4); + bar2map_len = pci_resource_len(pdev, PCI_64BIT_BAR4); + phba->sli4_hba.dpp_regs_memmap_p = + ioremap(phba->pci_bar2_map, bar2map_len); + if (!phba->sli4_hba.dpp_regs_memmap_p) { + dev_err(&pdev->dev, + "ioremap failed for SLI4 HBA dpp registers.\n"); + goto out_iounmap_ctrl; + } + phba->pci_bar4_memmap_p = phba->sli4_hba.dpp_regs_memmap_p; + } + /* Set up the EQ/CQ register handeling functions now */ switch (if_type) { case LPFC_SLI_INTF_IF_TYPE_0: diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 3bff1f9c5df7..265f1fab2f39 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_X86 +#include +#endif #include @@ -112,6 +115,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) struct lpfc_register doorbell; uint32_t host_index; uint32_t idx; + uint32_t i = 0; + uint8_t *tmp; /* sanity check on queue memory */ if (unlikely(!q)) @@ -133,7 +138,13 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); - /* ensure WQE bcopy flushed before doorbell write */ + if (q->dpp_enable && q->phba->cfg_enable_dpp) { + /* write to DPP aperture taking advatage of Combined Writes */ + tmp = (uint8_t *)wqe; + for (i = 0; i < q->entry_size; i += sizeof(uint64_t)) + writeq(*((uint64_t *)(tmp + i)), q->dpp_regaddr + i); + } + /* ensure WQE bcopy and DPP flushed before doorbell write */ wmb(); /* Update the host index before invoking device */ @@ -144,9 +155,18 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) /* Ring Doorbell */ doorbell.word0 = 0; if (q->db_format == LPFC_DB_LIST_FORMAT) { - bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1); - bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index); - bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id); + if (q->dpp_enable && q->phba->cfg_enable_dpp) { + bf_set(lpfc_if6_wq_db_list_fm_num_posted, &doorbell, 1); + bf_set(lpfc_if6_wq_db_list_fm_dpp, &doorbell, 1); + bf_set(lpfc_if6_wq_db_list_fm_dpp_id, &doorbell, + q->dpp_id); + bf_set(lpfc_if6_wq_db_list_fm_id, &doorbell, + q->queue_id); + } else { + bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1); + bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index); + bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id); + } } else if (q->db_format == LPFC_DB_RING_FORMAT) { bf_set(lpfc_wq_db_ring_fm_num_posted, &doorbell, 1); bf_set(lpfc_wq_db_ring_fm_id, &doorbell, q->queue_id); @@ -15023,6 +15043,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, void __iomem *bar_memmap_p; uint32_t db_offset; uint16_t pci_barset; + uint8_t dpp_barset; + uint32_t dpp_offset; + unsigned long pg_addr; uint8_t wq_create_version; /* sanity check on queue memory */ @@ -15056,38 +15079,13 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, else wq_create_version = LPFC_Q_CREATE_VERSION_0; - switch (wq_create_version) { - case LPFC_Q_CREATE_VERSION_0: - switch (wq->entry_size) { - default: - case 64: - /* Nothing to do, version 0 ONLY supports 64 byte */ - page = wq_create->u.request.page; - break; - case 128: - if (!(phba->sli4_hba.pc_sli4_params.wqsize & - LPFC_WQ_SZ128_SUPPORT)) { - status = -ERANGE; - goto out; - } - /* If we get here the HBA MUST also support V1 and - * we MUST use it - */ - bf_set(lpfc_mbox_hdr_version, &shdr->request, - LPFC_Q_CREATE_VERSION_1); - bf_set(lpfc_mbx_wq_create_wqe_count, - &wq_create->u.request_1, wq->entry_count); - bf_set(lpfc_mbx_wq_create_wqe_size, - &wq_create->u.request_1, - LPFC_WQ_WQE_SIZE_128); - bf_set(lpfc_mbx_wq_create_page_size, - &wq_create->u.request_1, - LPFC_WQ_PAGE_SIZE_4096); - page = wq_create->u.request_1.page; - break; - } - break; + if (phba->sli4_hba.pc_sli4_params.wqsize & LPFC_WQ_SZ128_SUPPORT) + wq_create_version = LPFC_Q_CREATE_VERSION_1; + else + wq_create_version = LPFC_Q_CREATE_VERSION_0; + + switch (wq_create_version) { case LPFC_Q_CREATE_VERSION_1: bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1, wq->entry_count); @@ -15102,24 +15100,21 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, LPFC_WQ_WQE_SIZE_64); break; case 128: - if (!(phba->sli4_hba.pc_sli4_params.wqsize & - LPFC_WQ_SZ128_SUPPORT)) { - status = -ERANGE; - goto out; - } bf_set(lpfc_mbx_wq_create_wqe_size, &wq_create->u.request_1, LPFC_WQ_WQE_SIZE_128); break; } + /* Request DPP by default */ + bf_set(lpfc_mbx_wq_create_dpp_req, &wq_create->u.request_1, 1); bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1, (wq->page_size / SLI4_PAGE_SIZE)); page = wq_create->u.request_1.page; break; default: - status = -ERANGE; - goto out; + page = wq_create->u.request.page; + break; } list_for_each_entry(dmabuf, &wq->page_list, list) { @@ -15143,52 +15138,120 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, status = -ENXIO; goto out; } - wq->queue_id = bf_get(lpfc_mbx_wq_create_q_id, &wq_create->u.response); + + if (wq_create_version == LPFC_Q_CREATE_VERSION_0) + wq->queue_id = bf_get(lpfc_mbx_wq_create_q_id, + &wq_create->u.response); + else + wq->queue_id = bf_get(lpfc_mbx_wq_create_v1_q_id, + &wq_create->u.response_1); + if (wq->queue_id == 0xFFFF) { status = -ENXIO; goto out; } - if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { - wq->db_format = bf_get(lpfc_mbx_wq_create_db_format, - &wq_create->u.response); - if ((wq->db_format != LPFC_DB_LIST_FORMAT) && - (wq->db_format != LPFC_DB_RING_FORMAT)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3265 WQ[%d] doorbell format not " - "supported: x%x\n", wq->queue_id, - wq->db_format); - status = -EINVAL; - goto out; - } - pci_barset = bf_get(lpfc_mbx_wq_create_bar_set, - &wq_create->u.response); - bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); - if (!bar_memmap_p) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3263 WQ[%d] failed to memmap pci " - "barset:x%x\n", wq->queue_id, - pci_barset); - status = -ENOMEM; - goto out; - } - db_offset = wq_create->u.response.doorbell_offset; - if ((db_offset != LPFC_ULP0_WQ_DOORBELL) && - (db_offset != LPFC_ULP1_WQ_DOORBELL)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3252 WQ[%d] doorbell offset not " - "supported: x%x\n", wq->queue_id, - db_offset); - status = -EINVAL; - goto out; - } - wq->db_regaddr = bar_memmap_p + db_offset; - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "3264 WQ[%d]: barset:x%x, offset:x%x, " - "format:x%x\n", wq->queue_id, pci_barset, - db_offset, wq->db_format); + + wq->db_format = LPFC_DB_LIST_FORMAT; + if (wq_create_version == LPFC_Q_CREATE_VERSION_0) { + if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { + wq->db_format = bf_get(lpfc_mbx_wq_create_db_format, + &wq_create->u.response); + if ((wq->db_format != LPFC_DB_LIST_FORMAT) && + (wq->db_format != LPFC_DB_RING_FORMAT)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3265 WQ[%d] doorbell format " + "not supported: x%x\n", + wq->queue_id, wq->db_format); + status = -EINVAL; + goto out; + } + pci_barset = bf_get(lpfc_mbx_wq_create_bar_set, + &wq_create->u.response); + bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, + pci_barset); + if (!bar_memmap_p) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3263 WQ[%d] failed to memmap " + "pci barset:x%x\n", + wq->queue_id, pci_barset); + status = -ENOMEM; + goto out; + } + db_offset = wq_create->u.response.doorbell_offset; + if ((db_offset != LPFC_ULP0_WQ_DOORBELL) && + (db_offset != LPFC_ULP1_WQ_DOORBELL)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3252 WQ[%d] doorbell offset " + "not supported: x%x\n", + wq->queue_id, db_offset); + status = -EINVAL; + goto out; + } + wq->db_regaddr = bar_memmap_p + db_offset; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "3264 WQ[%d]: barset:x%x, offset:x%x, " + "format:x%x\n", wq->queue_id, + pci_barset, db_offset, wq->db_format); + } else + wq->db_regaddr = phba->sli4_hba.WQDBregaddr; } else { - wq->db_format = LPFC_DB_LIST_FORMAT; - wq->db_regaddr = phba->sli4_hba.WQDBregaddr; + /* Check if DPP was honored by the firmware */ + wq->dpp_enable = bf_get(lpfc_mbx_wq_create_dpp_rsp, + &wq_create->u.response_1); + if (wq->dpp_enable) { + pci_barset = bf_get(lpfc_mbx_wq_create_v1_bar_set, + &wq_create->u.response_1); + bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, + pci_barset); + if (!bar_memmap_p) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3267 WQ[%d] failed to memmap " + "pci barset:x%x\n", + wq->queue_id, pci_barset); + status = -ENOMEM; + goto out; + } + db_offset = wq_create->u.response_1.doorbell_offset; + wq->db_regaddr = bar_memmap_p + db_offset; + wq->dpp_id = bf_get(lpfc_mbx_wq_create_dpp_id, + &wq_create->u.response_1); + dpp_barset = bf_get(lpfc_mbx_wq_create_dpp_bar, + &wq_create->u.response_1); + bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, + dpp_barset); + if (!bar_memmap_p) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3268 WQ[%d] failed to memmap " + "pci barset:x%x\n", + wq->queue_id, dpp_barset); + status = -ENOMEM; + goto out; + } + dpp_offset = wq_create->u.response_1.dpp_offset; + wq->dpp_regaddr = bar_memmap_p + dpp_offset; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "3271 WQ[%d]: barset:x%x, offset:x%x, " + "dpp_id:x%x dpp_barset:x%x " + "dpp_offset:x%x\n", + wq->queue_id, pci_barset, db_offset, + wq->dpp_id, dpp_barset, dpp_offset); + + /* Enable combined writes for DPP aperture */ + pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK; +#ifdef CONFIG_X86 + rc = set_memory_wc(pg_addr, 1); + if (rc) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3272 Cannot setup Combined " + "Write on WQ[%d] - disable DPP\n", + wq->queue_id); + phba->cfg_enable_dpp = 0; + } +#else + phba->cfg_enable_dpp = 0; +#endif + } else + wq->db_regaddr = phba->sli4_hba.WQDBregaddr; } wq->pring = kzalloc(sizeof(struct lpfc_sli_ring), GFP_KERNEL); if (wq->pring == NULL) { diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 33838b4b28d9..708167b309bd 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -180,6 +180,10 @@ struct lpfc_queue { uint8_t q_flag; #define HBA_NVMET_WQFULL 0x1 /* We hit WQ Full condition for NVMET */ void __iomem *db_regaddr; + uint16_t dpp_enable; + uint16_t dpp_id; + void __iomem *dpp_regaddr; + /* For q stats */ uint32_t q_cnt_1; uint32_t q_cnt_2; @@ -524,11 +528,17 @@ struct lpfc_vector_map_info { /* SLI4 HBA data structure entries */ struct lpfc_sli4_hba { void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for - PCI BAR0, config space registers */ + * config space registers + */ void __iomem *ctrl_regs_memmap_p; /* Kernel memory mapped address for - PCI BAR1, control registers */ + * control registers + */ void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for - PCI BAR2, doorbell registers */ + * doorbell registers + */ + void __iomem *dpp_regs_memmap_p; /* Kernel memory mapped address for + * dpp registers + */ union { struct { /* IF Type 0, BAR 0 PCI cfg space reg mem map */ From c238b9b6eae399e81d36382b09c2e969c154b7ee Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:44 -0800 Subject: [PATCH 068/168] scsi: lpfc: Add PCI Ids for if_type=6 hardware Add PCI ids for the new G7 adapter Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw.h | 1 + drivers/scsi/lpfc/lpfc_ids.h | 2 ++ drivers/scsi/lpfc/lpfc_init.c | 3 +++ 3 files changed, 6 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index bdc1f184f67a..d07d2fcbea34 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1580,6 +1580,7 @@ struct lpfc_fdmi_reg_portattr { #define PCI_DEVICE_ID_LANCER_FCOE 0xe260 #define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268 #define PCI_DEVICE_ID_LANCER_G6_FC 0xe300 +#define PCI_DEVICE_ID_LANCER_G7_FC 0xf400 #define PCI_DEVICE_ID_SAT_SMB 0xf011 #define PCI_DEVICE_ID_SAT_MID 0xf015 #define PCI_DEVICE_ID_RFLY 0xf095 diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h index 0ba3733eb36d..329c8d28869c 100644 --- a/drivers/scsi/lpfc/lpfc_ids.h +++ b/drivers/scsi/lpfc/lpfc_ids.h @@ -116,6 +116,8 @@ const struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC, PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7_FC, + PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK, PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF, diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5f0c63bb0a4d..2e723cdd2c1a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2473,6 +2473,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) case PCI_DEVICE_ID_LANCER_G6_FC: m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"}; break; + case PCI_DEVICE_ID_LANCER_G7_FC: + m = (typeof(m)){"LPe36000", "PCIe", "Fibre Channel Adapter"}; + break; case PCI_DEVICE_ID_SKYHAWK: case PCI_DEVICE_ID_SKYHAWK_VF: oneConnect = 1; From fbd8a6ba65443a8a79183edd9c2e1ad302339063 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:45 -0800 Subject: [PATCH 069/168] scsi: lpfc: Add 64G link speed support The G7 adapter supports 64G link speeds. Add support to the driver. In addition, a small cleanup to replace the odd bitmap logic with a switch case. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 14 +++----- drivers/scsi/lpfc/lpfc_attr.c | 62 ++++++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_ct.c | 5 +++ drivers/scsi/lpfc/lpfc_els.c | 5 +++ drivers/scsi/lpfc/lpfc_hbadisc.c | 1 + drivers/scsi/lpfc/lpfc_hw.h | 12 +++++++ drivers/scsi/lpfc/lpfc_hw4.h | 3 ++ drivers/scsi/lpfc/lpfc_init.c | 17 +++++++-- drivers/scsi/lpfc/lpfc_mbox.c | 4 +++ 9 files changed, 93 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 86ffb9756e65..7aad4a717f13 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -544,16 +544,10 @@ struct unsol_rcv_ct_ctx { #define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */ #define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */ #define LPFC_USER_LINK_SPEED_32G 32 /* 32 Gigabaud */ -#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_32G -#define LPFC_USER_LINK_SPEED_BITMAP ((1ULL << LPFC_USER_LINK_SPEED_32G) | \ - (1 << LPFC_USER_LINK_SPEED_16G) | \ - (1 << LPFC_USER_LINK_SPEED_10G) | \ - (1 << LPFC_USER_LINK_SPEED_8G) | \ - (1 << LPFC_USER_LINK_SPEED_4G) | \ - (1 << LPFC_USER_LINK_SPEED_2G) | \ - (1 << LPFC_USER_LINK_SPEED_1G) | \ - (1 << LPFC_USER_LINK_SPEED_AUTO)) -#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32" +#define LPFC_USER_LINK_SPEED_64G 64 /* 64 Gigabaud */ +#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_64G + +#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32, 64" enum nemb_type { nemb_mse = 1, diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 32f17e19e123..14f6efcf8f0b 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4115,23 +4115,32 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) || ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) || - ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb))) { + ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) || + ((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2879 lpfc_link_speed attribute cannot be set " "to %d. Speed is not supported by this port.\n", val); return -EINVAL; } - if (val == LPFC_USER_LINK_SPEED_16G && - phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + if (val >= LPFC_USER_LINK_SPEED_16G && + phba->fc_topology == LPFC_TOPOLOGY_LOOP) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3112 lpfc_link_speed attribute cannot be set " "to %d. Speed is not supported in loop mode.\n", val); return -EINVAL; } - if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && - (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { + + switch (val) { + case LPFC_USER_LINK_SPEED_AUTO: + case LPFC_USER_LINK_SPEED_1G: + case LPFC_USER_LINK_SPEED_2G: + case LPFC_USER_LINK_SPEED_4G: + case LPFC_USER_LINK_SPEED_8G: + case LPFC_USER_LINK_SPEED_16G: + case LPFC_USER_LINK_SPEED_32G: + case LPFC_USER_LINK_SPEED_64G: prev_val = phba->cfg_link_speed; phba->cfg_link_speed = val; if (nolip) @@ -4141,13 +4150,18 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, if (err) { phba->cfg_link_speed = prev_val; return -EINVAL; - } else - return strlen(buf); + } + return strlen(buf); + default: + break; } + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0469 lpfc_link_speed attribute cannot be set to %d, " - "allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val); + "0469 lpfc_link_speed attribute cannot be set to %d, " + "allowed values are [%s]\n", + val, LPFC_LINK_SPEED_STRING); return -EINVAL; + } static int lpfc_link_speed = 0; @@ -4174,24 +4188,33 @@ lpfc_param_show(link_speed) static int lpfc_link_speed_init(struct lpfc_hba *phba, int val) { - if (val == LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) { + if (val >= LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3111 lpfc_link_speed of %d cannot " "support loop mode, setting topology to default.\n", val); phba->cfg_topology = 0; } - if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && - (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { + + switch (val) { + case LPFC_USER_LINK_SPEED_AUTO: + case LPFC_USER_LINK_SPEED_1G: + case LPFC_USER_LINK_SPEED_2G: + case LPFC_USER_LINK_SPEED_4G: + case LPFC_USER_LINK_SPEED_8G: + case LPFC_USER_LINK_SPEED_16G: + case LPFC_USER_LINK_SPEED_32G: + case LPFC_USER_LINK_SPEED_64G: phba->cfg_link_speed = val; return 0; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0405 lpfc_link_speed attribute cannot " + "be set to %d, allowed values are " + "["LPFC_LINK_SPEED_STRING"]\n", val); + phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; + return -EINVAL; } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0405 lpfc_link_speed attribute cannot " - "be set to %d, allowed values are " - "["LPFC_LINK_SPEED_STRING"]\n", val); - phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; - return -EINVAL; } static DEVICE_ATTR_RW(lpfc_link_speed); @@ -5716,6 +5739,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost) case LPFC_LINK_SPEED_32GHZ: fc_host_speed(shost) = FC_PORTSPEED_32GBIT; break; + case LPFC_LINK_SPEED_64GHZ: + fc_host_speed(shost) = FC_PORTSPEED_64GBIT; + break; default: fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 9d20d2c208c7..03a7e13a049d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2130,6 +2130,8 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, ae->un.AttrInt = 0; if (!(phba->hba_flag & HBA_FCOE_MODE)) { + if (phba->lmt & LMT_64Gb) + ae->un.AttrInt |= HBA_PORTSPEED_64GFC; if (phba->lmt & LMT_32Gb) ae->un.AttrInt |= HBA_PORTSPEED_32GFC; if (phba->lmt & LMT_16Gb) @@ -2201,6 +2203,9 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, case LPFC_LINK_SPEED_32GHZ: ae->un.AttrInt = HBA_PORTSPEED_32GFC; break; + case LPFC_LINK_SPEED_64GHZ: + ae->un.AttrInt = HBA_PORTSPEED_64GFC; + break; default: ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN; break; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index ba896554a14f..09e4eb9fbc69 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5270,6 +5270,9 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) case LPFC_LINK_SPEED_32GHZ: rdp_speed = RDP_PS_32GB; break; + case LPFC_LINK_SPEED_64GHZ: + rdp_speed = RDP_PS_64GB; + break; default: rdp_speed = RDP_PS_UNKNOWN; break; @@ -5277,6 +5280,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) desc->info.port_speed.speed = cpu_to_be16(rdp_speed); + if (phba->lmt & LMT_64Gb) + rdp_cap |= RDP_PS_64GB; if (phba->lmt & LMT_32Gb) rdp_cap |= RDP_PS_32GB; if (phba->lmt & LMT_16Gb) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f5bbac3cadbb..7855afa13568 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -3084,6 +3084,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) case LPFC_LINK_SPEED_10GHZ: case LPFC_LINK_SPEED_16GHZ: case LPFC_LINK_SPEED_32GHZ: + case LPFC_LINK_SPEED_64GHZ: break; default: phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN; diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index d07d2fcbea34..cf83322cd4fe 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1177,6 +1177,9 @@ struct fc_rdp_link_error_status_desc { #define RDP_PS_8GB 0x0800 #define RDP_PS_16GB 0x0400 #define RDP_PS_32GB 0x0200 +#define RDP_PS_64GB 0x0100 +#define RDP_PS_128GB 0x0080 +#define RDP_PS_256GB 0x0040 #define RDP_CAP_USER_CONFIGURED 0x0002 #define RDP_CAP_UNKNOWN 0x0001 @@ -2258,6 +2261,9 @@ typedef struct { #define LINK_SPEED_10G 0x10 /* 10 Gigabaud */ #define LINK_SPEED_16G 0x11 /* 16 Gigabaud */ #define LINK_SPEED_32G 0x14 /* 32 Gigabaud */ +#define LINK_SPEED_64G 0x17 /* 64 Gigabaud */ +#define LINK_SPEED_128G 0x1A /* 128 Gigabaud */ +#define LINK_SPEED_256G 0x1D /* 256 Gigabaud */ } INIT_LINK_VAR; @@ -2442,6 +2448,9 @@ typedef struct { #define LMT_10Gb 0x100 #define LMT_16Gb 0x200 #define LMT_32Gb 0x400 +#define LMT_64Gb 0x800 +#define LMT_128Gb 0x1000 +#define LMT_256Gb 0x2000 uint32_t rsvd2; uint32_t rsvd3; uint32_t max_xri; @@ -2966,6 +2975,9 @@ struct lpfc_mbx_read_top { #define LPFC_LINK_SPEED_10GHZ 0x40 #define LPFC_LINK_SPEED_16GHZ 0x80 #define LPFC_LINK_SPEED_32GHZ 0x90 +#define LPFC_LINK_SPEED_64GHZ 0xA0 +#define LPFC_LINK_SPEED_128GHZ 0xB0 +#define LPFC_LINK_SPEED_256GHZ 0xC0 }; /* Structure for MB Command CLEAR_LA (22) */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 60ccff6fa8b0..0c33510fe75c 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3961,6 +3961,9 @@ struct lpfc_acqe_fc_la { #define LPFC_FC_LA_SPEED_10G 0xA #define LPFC_FC_LA_SPEED_16G 0x10 #define LPFC_FC_LA_SPEED_32G 0x20 +#define LPFC_FC_LA_SPEED_64G 0x21 +#define LPFC_FC_LA_SPEED_128G 0x22 +#define LPFC_FC_LA_SPEED_256G 0x23 #define lpfc_acqe_fc_la_topology_SHIFT 16 #define lpfc_acqe_fc_la_topology_MASK 0x000000FF #define lpfc_acqe_fc_la_topology_WORD word0 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2e723cdd2c1a..576ab7ec7e9d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -731,7 +731,9 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology, ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_32G) && - !(phba->lmt & LMT_32Gb))) { + !(phba->lmt & LMT_32Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_64G) && + !(phba->lmt & LMT_64Gb))) { /* Reset link speed to auto */ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1302 Invalid speed for this board:%d " @@ -2274,7 +2276,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) && descp && descp[0] != '\0') return; - if (phba->lmt & LMT_32Gb) + if (phba->lmt & LMT_64Gb) + max_speed = 64; + else if (phba->lmt & LMT_32Gb) max_speed = 32; else if (phba->lmt & LMT_16Gb) max_speed = 16; @@ -4112,6 +4116,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) sizeof fc_host_symbolic_name(shost)); fc_host_supported_speeds(shost) = 0; + if (phba->lmt & LMT_64Gb) + fc_host_supported_speeds(shost) |= FC_PORTSPEED_64GBIT; if (phba->lmt & LMT_32Gb) fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT; if (phba->lmt & LMT_16Gb) @@ -4448,6 +4454,9 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code, case LPFC_FC_LA_SPEED_32G: port_speed = 32000; break; + case LPFC_FC_LA_SPEED_64G: + port_speed = 64000; + break; default: port_speed = 0; } @@ -7814,6 +7823,10 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) phba->cfg_link_speed = LPFC_USER_LINK_SPEED_32G; break; + case LINK_SPEED_64G: + phba->cfg_link_speed = + LPFC_USER_LINK_SPEED_64G; + break; case 0xffff: phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 7313ceb0f23b..47c02da11f01 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -557,6 +557,10 @@ lpfc_init_link(struct lpfc_hba * phba, mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; mb->un.varInitLnk.link_speed = LINK_SPEED_32G; break; + case LPFC_USER_LINK_SPEED_64G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_64G; + break; case LPFC_USER_LINK_SPEED_AUTO: default: mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO; From 7365f6fdbba559f7e814519fafe6e4956f68b6be Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:46 -0800 Subject: [PATCH 070/168] scsi: lpfc: Add if_type=6 support for cycling valid bits Traditional SLI4 required the driver to clear Valid bits on EQEs and CQEs after consuming them. The new if_type=6 hardware will cycle the value for what is valid on each queue itteration. The driver no longer has to touch the valid bits. This also means all the cpu cache dirtying and perhaps flush/refill's done by the hardware in accessing the EQ/CQ elements is eliminated. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 18 ++++++-- drivers/scsi/lpfc/lpfc_init.c | 11 +++++ drivers/scsi/lpfc/lpfc_sli.c | 77 ++++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_sli4.h | 3 ++ 4 files changed, 92 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 0c33510fe75c..dba724e1f5ee 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1040,6 +1040,9 @@ struct eq_context { #define lpfc_eq_context_valid_SHIFT 29 #define lpfc_eq_context_valid_MASK 0x00000001 #define lpfc_eq_context_valid_WORD word0 +#define lpfc_eq_context_autovalid_SHIFT 28 +#define lpfc_eq_context_autovalid_MASK 0x00000001 +#define lpfc_eq_context_autovalid_WORD word0 uint32_t word1; #define lpfc_eq_context_count_SHIFT 26 #define lpfc_eq_context_count_MASK 0x00000003 @@ -1173,6 +1176,9 @@ struct cq_context { #define LPFC_CQ_CNT_512 0x1 #define LPFC_CQ_CNT_1024 0x2 #define LPFC_CQ_CNT_WORD7 0x3 +#define lpfc_cq_context_autovalid_SHIFT 15 +#define lpfc_cq_context_autovalid_MASK 0x00000001 +#define lpfc_cq_context_autovalid_WORD word0 uint32_t word1; #define lpfc_cq_eq_id_SHIFT 22 /* Version 0 Only */ #define lpfc_cq_eq_id_MASK 0x000000FF @@ -1231,9 +1237,9 @@ struct lpfc_mbx_cq_create_set { #define lpfc_mbx_cq_create_set_cqe_size_SHIFT 25 #define lpfc_mbx_cq_create_set_cqe_size_MASK 0x00000003 #define lpfc_mbx_cq_create_set_cqe_size_WORD word1 -#define lpfc_mbx_cq_create_set_auto_SHIFT 15 -#define lpfc_mbx_cq_create_set_auto_MASK 0x0000001 -#define lpfc_mbx_cq_create_set_auto_WORD word1 +#define lpfc_mbx_cq_create_set_autovalid_SHIFT 15 +#define lpfc_mbx_cq_create_set_autovalid_MASK 0x0000001 +#define lpfc_mbx_cq_create_set_autovalid_WORD word1 #define lpfc_mbx_cq_create_set_nodelay_SHIFT 14 #define lpfc_mbx_cq_create_set_nodelay_MASK 0x00000001 #define lpfc_mbx_cq_create_set_nodelay_WORD word1 @@ -3288,6 +3294,9 @@ struct lpfc_sli4_parameters { #define cfg_sli_hint_2_MASK 0x0000001f #define cfg_sli_hint_2_WORD word1 uint32_t word2; +#define cfg_eqav_SHIFT 31 +#define cfg_eqav_MASK 0x00000001 +#define cfg_eqav_WORD word2 uint32_t word3; uint32_t word4; #define cfg_cqv_SHIFT 14 @@ -3296,6 +3305,9 @@ struct lpfc_sli4_parameters { #define cfg_cqpsize_SHIFT 16 #define cfg_cqpsize_MASK 0x000000ff #define cfg_cqpsize_WORD word4 +#define cfg_cqav_SHIFT 31 +#define cfg_cqav_MASK 0x00000001 +#define cfg_cqav_WORD word4 uint32_t word5; uint32_t word6; #define cfg_mqv_SHIFT 14 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 576ab7ec7e9d..96a37e4e127d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8063,6 +8063,7 @@ lpfc_alloc_nvme_wq_cq(struct lpfc_hba *phba, int wqidx) wqidx); return 1; } + qdesc->qe_valid = 1; phba->sli4_hba.nvme_cq[wqidx] = qdesc; qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, @@ -8100,6 +8101,7 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) "0499 Failed allocate fast-path FCP CQ (%d)\n", wqidx); return 1; } + qdesc->qe_valid = 1; phba->sli4_hba.fcp_cq[wqidx] = qdesc; /* Create Fast Path FCP WQs */ @@ -8293,6 +8295,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "0497 Failed allocate EQ (%d)\n", idx); goto out_error; } + qdesc->qe_valid = 1; phba->sli4_hba.hba_eq[idx] = qdesc; } @@ -8318,6 +8321,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "CQ Set (%d)\n", idx); goto out_error; } + qdesc->qe_valid = 1; phba->sli4_hba.nvmet_cqset[idx] = qdesc; } } @@ -8335,6 +8339,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "0500 Failed allocate slow-path mailbox CQ\n"); goto out_error; } + qdesc->qe_valid = 1; phba->sli4_hba.mbx_cq = qdesc; /* Create slow-path ELS Complete Queue */ @@ -8346,6 +8351,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "0501 Failed allocate slow-path ELS CQ\n"); goto out_error; } + qdesc->qe_valid = 1; phba->sli4_hba.els_cq = qdesc; @@ -8391,6 +8397,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "6079 Failed allocate NVME LS CQ\n"); goto out_error; } + qdesc->qe_valid = 1; phba->sli4_hba.nvmels_cq = qdesc; /* Create NVME LS Work Queue */ @@ -10569,6 +10576,8 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters); sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters); sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters); + sli4_params->eqav = bf_get(cfg_eqav, mbx_sli4_parameters); + sli4_params->cqav = bf_get(cfg_cqav, mbx_sli4_parameters); sli4_params->wqsize = bf_get(cfg_wqsize, mbx_sli4_parameters); sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt, mbx_sli4_parameters); @@ -12387,6 +12396,7 @@ lpfc_fof_queue_create(struct lpfc_hba *phba) if (!qdesc) goto out_error; + qdesc->qe_valid = 1; phba->sli4_hba.fof_eq = qdesc; if (phba->cfg_fof) { @@ -12405,6 +12415,7 @@ lpfc_fof_queue_create(struct lpfc_hba *phba) if (!qdesc) goto out_error; + qdesc->qe_valid = 1; phba->sli4_hba.oas_cq = qdesc; /* Create OAS WQ */ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 265f1fab2f39..925a40deeb49 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -283,16 +283,18 @@ lpfc_sli4_mq_release(struct lpfc_queue *q) static struct lpfc_eqe * lpfc_sli4_eq_get(struct lpfc_queue *q) { + struct lpfc_hba *phba; struct lpfc_eqe *eqe; uint32_t idx; /* sanity check on queue memory */ if (unlikely(!q)) return NULL; + phba = q->phba; eqe = q->qe[q->hba_index].eqe; /* If the next EQE is not valid then we are done */ - if (!bf_get_le32(lpfc_eqe_valid, eqe)) + if (bf_get_le32(lpfc_eqe_valid, eqe) != q->qe_valid) return NULL; /* If the host has not yet processed the next entry then we are done */ idx = ((q->hba_index + 1) % q->entry_count); @@ -300,6 +302,10 @@ lpfc_sli4_eq_get(struct lpfc_queue *q) return NULL; q->hba_index = idx; + /* if the index wrapped around, toggle the valid bit */ + if (phba->sli4_hba.pc_sli4_params.eqav && !q->hba_index) + q->qe_valid = (q->qe_valid) ? 0 : 1; + /* * insert barrier for instruction interlock : data from the hardware @@ -371,17 +377,21 @@ uint32_t lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm) { uint32_t released = 0; + struct lpfc_hba *phba; struct lpfc_eqe *temp_eqe; struct lpfc_register doorbell; /* sanity check on queue memory */ if (unlikely(!q)) return 0; + phba = q->phba; /* while there are valid entries */ while (q->hba_index != q->host_index) { - temp_eqe = q->qe[q->host_index].eqe; - bf_set_le32(lpfc_eqe_valid, temp_eqe, 0); + if (!phba->sli4_hba.pc_sli4_params.eqav) { + temp_eqe = q->qe[q->host_index].eqe; + bf_set_le32(lpfc_eqe_valid, temp_eqe, 0); + } released++; q->host_index = ((q->host_index + 1) % q->entry_count); } @@ -425,17 +435,21 @@ uint32_t lpfc_sli4_if6_eq_release(struct lpfc_queue *q, bool arm) { uint32_t released = 0; + struct lpfc_hba *phba; struct lpfc_eqe *temp_eqe; struct lpfc_register doorbell; /* sanity check on queue memory */ if (unlikely(!q)) return 0; + phba = q->phba; /* while there are valid entries */ while (q->hba_index != q->host_index) { - temp_eqe = q->qe[q->host_index].eqe; - bf_set_le32(lpfc_eqe_valid, temp_eqe, 0); + if (!phba->sli4_hba.pc_sli4_params.eqav) { + temp_eqe = q->qe[q->host_index].eqe; + bf_set_le32(lpfc_eqe_valid, temp_eqe, 0); + } released++; q->host_index = ((q->host_index + 1) % q->entry_count); } @@ -467,23 +481,28 @@ lpfc_sli4_if6_eq_release(struct lpfc_queue *q, bool arm) static struct lpfc_cqe * lpfc_sli4_cq_get(struct lpfc_queue *q) { + struct lpfc_hba *phba; struct lpfc_cqe *cqe; uint32_t idx; /* sanity check on queue memory */ if (unlikely(!q)) return NULL; + phba = q->phba; + cqe = q->qe[q->hba_index].cqe; /* If the next CQE is not valid then we are done */ - if (!bf_get_le32(lpfc_cqe_valid, q->qe[q->hba_index].cqe)) + if (bf_get_le32(lpfc_cqe_valid, cqe) != q->qe_valid) return NULL; /* If the host has not yet processed the next entry then we are done */ idx = ((q->hba_index + 1) % q->entry_count); if (idx == q->host_index) return NULL; - cqe = q->qe[q->hba_index].cqe; q->hba_index = idx; + /* if the index wrapped around, toggle the valid bit */ + if (phba->sli4_hba.pc_sli4_params.cqav && !q->hba_index) + q->qe_valid = (q->qe_valid) ? 0 : 1; /* * insert barrier for instruction interlock : data from the hardware @@ -516,16 +535,21 @@ uint32_t lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm) { uint32_t released = 0; + struct lpfc_hba *phba; struct lpfc_cqe *temp_qe; struct lpfc_register doorbell; /* sanity check on queue memory */ if (unlikely(!q)) return 0; + phba = q->phba; + /* while there are valid entries */ while (q->hba_index != q->host_index) { - temp_qe = q->qe[q->host_index].cqe; - bf_set_le32(lpfc_cqe_valid, temp_qe, 0); + if (!phba->sli4_hba.pc_sli4_params.cqav) { + temp_qe = q->qe[q->host_index].cqe; + bf_set_le32(lpfc_cqe_valid, temp_qe, 0); + } released++; q->host_index = ((q->host_index + 1) % q->entry_count); } @@ -564,16 +588,21 @@ uint32_t lpfc_sli4_if6_cq_release(struct lpfc_queue *q, bool arm) { uint32_t released = 0; + struct lpfc_hba *phba; struct lpfc_cqe *temp_qe; struct lpfc_register doorbell; /* sanity check on queue memory */ if (unlikely(!q)) return 0; + phba = q->phba; + /* while there are valid entries */ while (q->hba_index != q->host_index) { - temp_qe = q->qe[q->host_index].cqe; - bf_set_le32(lpfc_cqe_valid, temp_qe, 0); + if (!phba->sli4_hba.pc_sli4_params.cqav) { + temp_qe = q->qe[q->host_index].cqe; + bf_set_le32(lpfc_cqe_valid, temp_qe, 0); + } released++; q->host_index = ((q->host_index + 1) % q->entry_count); } @@ -7367,6 +7396,7 @@ lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) struct lpfc_queue *mcq; struct lpfc_mcqe *mcqe; bool pending_completions = false; + uint8_t qe_valid; if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) return false; @@ -7375,7 +7405,8 @@ lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) mcq = phba->sli4_hba.mbx_cq; idx = mcq->hba_index; - while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe)) { + qe_valid = mcq->qe_valid; + while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe) == qe_valid) { mcqe = (struct lpfc_mcqe *)mcq->qe[idx].cqe; if (bf_get_le32(lpfc_trailer_completed, mcqe) && (!bf_get_le32(lpfc_trailer_async, mcqe))) { @@ -7385,6 +7416,10 @@ lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) idx = (idx + 1) % mcq->entry_count; if (mcq->hba_index == idx) break; + + /* if the index wrapped around, toggle the valid bit */ + if (phba->sli4_hba.pc_sli4_params.cqav && !idx) + qe_valid = (qe_valid) ? 0 : 1; } return pending_completions; @@ -8258,7 +8293,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, } else if (flag == MBX_POLL) { lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, "(%d):2542 Try to issue mailbox command " - "x%x (x%x/x%x) synchronously ahead of async" + "x%x (x%x/x%x) synchronously ahead of async " "mailbox command queue: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, @@ -14335,11 +14370,21 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) LPFC_MBOX_OPCODE_EQ_CREATE, length, LPFC_SLI4_MBX_EMBED); eq_create = &mbox->u.mqe.un.eq_create; + shdr = (union lpfc_sli4_cfg_shdr *) &eq_create->header.cfg_shdr; bf_set(lpfc_mbx_eq_create_num_pages, &eq_create->u.request, eq->page_count); bf_set(lpfc_eq_context_size, &eq_create->u.request.context, LPFC_EQE_SIZE); bf_set(lpfc_eq_context_valid, &eq_create->u.request.context, 1); + + /* Use version 2 of CREATE_EQ if eqav is set */ + if (phba->sli4_hba.pc_sli4_params.eqav) { + bf_set(lpfc_mbox_hdr_version, &shdr->request, + LPFC_Q_CREATE_VERSION_2); + bf_set(lpfc_eq_context_autovalid, &eq_create->u.request.context, + phba->sli4_hba.pc_sli4_params.eqav); + } + /* don't setup delay multiplier using EQ_CREATE */ dmult = 0; bf_set(lpfc_eq_context_delay_multi, &eq_create->u.request.context, @@ -14384,7 +14429,6 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->context1 = NULL; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); - shdr = (union lpfc_sli4_cfg_shdr *) &eq_create->header.cfg_shdr; shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { @@ -14467,6 +14511,8 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, (cq->page_size / SLI4_PAGE_SIZE)); bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context, eq->queue_id); + bf_set(lpfc_cq_context_autovalid, &cq_create->u.request.context, + phba->sli4_hba.pc_sli4_params.cqav); } else { bf_set(lpfc_cq_eq_id, &cq_create->u.request.context, eq->queue_id); @@ -14638,6 +14684,9 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, &cq_set->u.request, 0); bf_set(lpfc_mbx_cq_create_set_num_cq, &cq_set->u.request, numcq); + bf_set(lpfc_mbx_cq_create_set_autovalid, + &cq_set->u.request, + phba->sli4_hba.pc_sli4_params.cqav); switch (cq->entry_count) { case 2048: case 4096: diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 708167b309bd..cf64aca82bd0 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -216,6 +216,7 @@ struct lpfc_queue { struct work_struct spwork; uint64_t isr_timestamp; + uint8_t qe_valid; struct lpfc_queue *assoc_qp; union sli4_qe qe[1]; /* array to index entries (must be last) */ }; @@ -486,6 +487,8 @@ struct lpfc_pc_sli4_params { uint8_t mqv; uint8_t wqv; uint8_t rqv; + uint8_t eqav; + uint8_t cqav; uint8_t wqsize; #define LPFC_WQ_SZ64_SUPPORT 1 #define LPFC_WQ_SZ128_SUPPORT 2 From 1feb8204a12ed7987bffa75311754edc1367680f Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:47 -0800 Subject: [PATCH 071/168] scsi: lpfc: Enable fw download on if_type=6 devices Current code is very explicit in what it allows to be downloaded. The driver checking prevented G7 firmware download. The driver checking is unnecessary as the device will validate what it receives. Revise the firmware download interface checking. Added a little debug support in case there is still a failure. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 5 +--- drivers/scsi/lpfc/lpfc_init.c | 44 ++++++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_sli.c | 1 + 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index dba724e1f5ee..be8227dfa086 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2241,6 +2241,7 @@ struct lpfc_mbx_redisc_fcf_tbl { * command. */ #define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67 +#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB struct lpfc_mbx_sli4_config { struct mbox_header header; @@ -4603,10 +4604,6 @@ union lpfc_wqe128 { struct gen_req64_wqe gen_req; }; -#define LPFC_GROUP_OJECT_MAGIC_G5 0xfeaa0001 -#define LPFC_GROUP_OJECT_MAGIC_G6 0xfeaa0003 -#define LPFC_FILE_TYPE_GROUP 0xf7 -#define LPFC_FILE_ID_GROUP 0xa2 struct lpfc_grp_hdr { uint32_t size; uint32_t magic_number; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 96a37e4e127d..af92c3c681f7 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11297,6 +11297,27 @@ lpfc_sli4_get_iocb_cnt(struct lpfc_hba *phba) } +static void +lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset, + uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize, + const struct firmware *fw) +{ + if (offset == ADD_STATUS_FW_NOT_SUPPORTED) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3030 This firmware version is not supported on " + "this HBA model. Device:%x Magic:%x Type:%x " + "ID:%x Size %d %zd\n", + phba->pcidev->device, magic_number, ftype, fid, + fsize, fw->size); + else + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3022 FW Download failed. Device:%x Magic:%x Type:%x " + "ID:%x Size %d %zd\n", + phba->pcidev->device, magic_number, ftype, fid, + fsize, fw->size); +} + + /** * lpfc_write_firmware - attempt to write a firmware image to the port * @fw: pointer to firmware image returned from request_firmware. @@ -11324,20 +11345,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) magic_number = be32_to_cpu(image->magic_number); ftype = bf_get_be32(lpfc_grp_hdr_file_type, image); - fid = bf_get_be32(lpfc_grp_hdr_id, image), + fid = bf_get_be32(lpfc_grp_hdr_id, image); fsize = be32_to_cpu(image->size); INIT_LIST_HEAD(&dma_buffer_list); - if ((magic_number != LPFC_GROUP_OJECT_MAGIC_G5 && - magic_number != LPFC_GROUP_OJECT_MAGIC_G6) || - ftype != LPFC_FILE_TYPE_GROUP || fsize != fw->size) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3022 Invalid FW image found. " - "Magic:%x Type:%x ID:%x Size %d %zd\n", - magic_number, ftype, fid, fsize, fw->size); - rc = -EINVAL; - goto release_out; - } lpfc_decode_firmware_rev(phba, fwrev, 1); if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -11378,11 +11389,18 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } rc = lpfc_wr_object(phba, &dma_buffer_list, (fw->size - offset), &offset); - if (rc) + if (rc) { + lpfc_log_write_firmware_error(phba, offset, + magic_number, ftype, fid, fsize, fw); goto release_out; + } } rc = offset; - } + } else + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3029 Skipped Firmware update, Current " + "Version:%s New Version:%s\n", + fwrev, image->revision); release_out: list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 925a40deeb49..8fc11baa88a9 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -18871,6 +18871,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); rc = -ENXIO; + *offset = shdr_add_status; } else *offset += wr_object->u.response.actual_write_length; return rc; From 0bc2b7c5317bd51df571e9d1131547901215f6c9 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:48 -0800 Subject: [PATCH 072/168] scsi: lpfc: Add embedded data pointers for enhanced performance The current driver isn't taking advantage of a performance hint whereby the initial data buffer descriptor can be placed in the WQE as well as the SGL. Add the logic to detect support for the feature and to use it when supported. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 ++ drivers/scsi/lpfc/lpfc_hw4.h | 3 +++ drivers/scsi/lpfc/lpfc_init.c | 20 ++++++++++++++++++++ drivers/scsi/lpfc/lpfc_nvme.c | 18 ++++++++++++++++++ drivers/scsi/lpfc/lpfc_nvmet.c | 24 ++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_scsi.c | 8 ++++++-- drivers/scsi/lpfc/lpfc_sli.c | 25 +++++++++++++++++++++---- 7 files changed, 94 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 7aad4a717f13..9136a59b1c5b 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -840,6 +840,8 @@ struct lpfc_hba { #define LPFC_ENABLE_FCP 1 #define LPFC_ENABLE_NVME 2 #define LPFC_ENABLE_BOTH 3 + uint32_t nvme_embed_pbde; + uint32_t fcp_embed_pbde; uint32_t io_channel_irqs; /* number of irqs for io channels */ struct nvmet_fc_target_port *targetport; lpfc_vpd_t vpd; /* vital product data */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index be8227dfa086..ed5e870c58c3 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4226,6 +4226,9 @@ struct wqe_common { #define wqe_irsp_SHIFT 4 #define wqe_irsp_MASK 0x00000001 #define wqe_irsp_WORD word11 +#define wqe_pbde_SHIFT 5 +#define wqe_pbde_MASK 0x00000001 +#define wqe_pbde_WORD word11 #define wqe_sup_SHIFT 6 #define wqe_sup_MASK 0x00000001 #define wqe_sup_WORD word11 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index af92c3c681f7..ecb42cae71f2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10608,6 +10608,19 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP; } + /* Only embed PBDE for if_type 6 */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_6) { + phba->fcp_embed_pbde = 1; + phba->nvme_embed_pbde = 1; + } + + /* PBDE support requires xib be set */ + if (!bf_get(cfg_xib, mbx_sli4_parameters)) { + phba->fcp_embed_pbde = 0; + phba->nvme_embed_pbde = 0; + } + /* * To support Suppress Response feature we must satisfy 3 conditions. * lpfc_suppress_rsp module parameter must be set (default). @@ -10639,6 +10652,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) else phba->fcp_embed_io = 0; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME, + "6422 XIB %d: FCP %d %d NVME %d %d %d\n", + bf_get(cfg_xib, mbx_sli4_parameters), + phba->fcp_embed_pbde, phba->fcp_embed_io, + phba->nvme_support, phba->nvme_embed_pbde, + phba->cfg_suppress_rsp); + if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) && (bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) && (sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT)) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 3a103d0895a2..5a1a6e24a27f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1170,6 +1170,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, struct sli4_sge *sgl = lpfc_ncmd->nvme_sgl; struct scatterlist *data_sg; struct sli4_sge *first_data_sgl; + struct ulp_bde64 *bde; dma_addr_t physaddr; uint32_t num_bde = 0; uint32_t dma_len; @@ -1237,7 +1238,24 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, data_sg = sg_next(data_sg); sgl++; } + if (phba->nvme_embed_pbde) { + /* Use PBDE support for first SGL only, offset == 0 */ + /* Words 13-15 */ + bde = (struct ulp_bde64 *) + &wqe->words[13]; + bde->addrLow = first_data_sgl->addr_lo; + bde->addrHigh = first_data_sgl->addr_hi; + bde->tus.f.bdeSize = + le32_to_cpu(first_data_sgl->sge_len); + bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; + bde->tus.w = cpu_to_le32(bde->tus.w); + bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); + } else + bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); + } else { + bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); + /* For this clause to be valid, the payload_length * and sg_cnt must zero. */ diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index a332a6638b1b..a4a32d7ec248 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -2150,9 +2150,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *nvmewqe; struct scatterlist *sgel; union lpfc_wqe128 *wqe; + struct ulp_bde64 *bde; uint32_t *txrdy; dma_addr_t physaddr; int i, cnt; + int do_pbde; int xc = 1; if (!lpfc_is_link_up(phba)) { @@ -2243,6 +2245,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, /* Word 7 */ bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, 1); bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE); + do_pbde = 0; /* Word 8 */ wqe->fcp_tsend.wqe_com.abort_tag = nvmewqe->iotag; @@ -2355,6 +2358,10 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0); bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com, CMD_FCP_TRECEIVE64_WQE); + if (phba->nvme_embed_pbde) + do_pbde = 1; + else + do_pbde = 0; /* Word 8 */ wqe->fcp_treceive.wqe_com.abort_tag = nvmewqe->iotag; @@ -2438,6 +2445,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_pu, &wqe->fcp_trsp.wqe_com, 0); bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1); bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE); + do_pbde = 0; /* Word 8 */ wqe->fcp_trsp.wqe_com.abort_tag = nvmewqe->iotag; @@ -2508,9 +2516,25 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(lpfc_sli4_sge_last, sgl, 1); sgl->word2 = cpu_to_le32(sgl->word2); sgl->sge_len = cpu_to_le32(cnt); + if (do_pbde && i == 0) { + bde = (struct ulp_bde64 *)&wqe->words[13]; + memset(bde, 0, sizeof(struct ulp_bde64)); + /* Words 13-15 (PBDE)*/ + bde->addrLow = sgl->addr_lo; + bde->addrHigh = sgl->addr_hi; + bde->tus.f.bdeSize = + le32_to_cpu(sgl->sge_len); + bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; + bde->tus.w = cpu_to_le32(bde->tus.w); + } sgl++; ctxp->offset += cnt; } + + if (do_pbde) + bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); + else + bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); ctxp->state = LPFC_NVMET_STE_DATA; ctxp->entry_cnt++; return nvmewqe; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c595046a521b..fb81e8a8fb1c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3304,8 +3304,12 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) dma_offset += dma_len; sgl++; } - /* setup the performance hint (first data BDE) if enabled */ - if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) { + /* + * Setup the first Payload BDE. For FCoE we just key off + * Performance Hints, for FC we utilize fcp_embed_pbde. + */ + if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) || + phba->fcp_embed_pbde) { bde = (struct ulp_bde64 *) &(iocb_cmd->unsli3.sli3Words[5]); bde->addrLow = first_data_sgl->addr_lo; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8fc11baa88a9..416ba8f8e295 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -6958,10 +6958,15 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "0378 No support for fcpi mode.\n"); ftr_rsp++; } - if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs)) - phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED; - else - phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED; + + /* Performance Hints are ONLY for FCoE */ + if (phba->hba_flag & HBA_FCOE_MODE) { + if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs)) + phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED; + else + phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED; + } + /* * If the port cannot support the host's requested features * then turn off the global config parameters to disable the @@ -9063,6 +9068,12 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, } /* Note, word 10 is already initialized to 0 */ + /* Don't set PBDE for Perf hints, just fcp_embed_pbde */ + if (phba->fcp_embed_pbde) + bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1); + else + bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0); + if (phba->fcp_embed_io) { struct lpfc_scsi_buf *lpfc_cmd; struct sli4_sge *sgl; @@ -9122,6 +9133,12 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, } /* Note, word 10 is already initialized to 0 */ + /* Don't set PBDE for Perf hints, just fcp_embed_pbde */ + if (phba->fcp_embed_pbde) + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1); + else + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0); + if (phba->fcp_embed_io) { struct lpfc_scsi_buf *lpfc_cmd; struct sli4_sge *sgl; From 63452e144662a90b77fcdb27bd33c8b43655b850 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:49 -0800 Subject: [PATCH 073/168] scsi: lpfc: Fix nvme embedded io length on new hardware Newer hardware more strictly enforces buffer lenghts, causing an mis-set value to be identified. Older hardware won't catch it. The difference is benign on old hardware. Set the right embedded buffer length for nvme ios. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 5a1a6e24a27f..c75958daf799 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -655,7 +655,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, /* Word 0-2 - NVME CMND IU (embedded payload) */ wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; - wqe->generic.bde.tus.f.bdeSize = 60; + wqe->generic.bde.tus.f.bdeSize = 56; wqe->generic.bde.addrHigh = 0; wqe->generic.bde.addrLow = 64; /* Word 16 */ From 4e565cf04138fca6ffeb884044febf922b2306d0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:50 -0800 Subject: [PATCH 074/168] scsi: lpfc: Work around NVME cmd iu SGL type The hardware offload for NVME commands was created when the FC-NVME standard was setting SGL Descriptor Type to SGL Data Block Descriptor (0h) and SGL Descriptor Sub Type to Address (0h). A late change in NVMe-over-Fabrics obsoleted these values, creating a transport SGL descriptor type with new values to go into these fields. For initial hardware support, in order to be compliant to the spec, use host-supplied cmd IU buffers instead of the adapter generated values. Later hardware will correct this. Add a module parameter to override this offload disablement if looking for lowest latency. This is reasonable as nothing in FC-NVME uses the SQE SGL values. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_attr.c | 14 ++++++++++ drivers/scsi/lpfc/lpfc_hw4.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 4 +-- drivers/scsi/lpfc/lpfc_nvme.c | 51 ++++++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_sli.c | 15 +++++++++++ 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 9136a59b1c5b..6c0d351c0d0d 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -782,6 +782,7 @@ struct lpfc_hba { uint32_t cfg_fcp_io_channel; uint32_t cfg_suppress_rsp; uint32_t cfg_nvme_oas; + uint32_t cfg_nvme_embed_cmd; uint32_t cfg_nvme_io_channel; uint32_t cfg_nvmet_mrq; uint32_t cfg_enable_nvmet; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 14f6efcf8f0b..46f6d97d21d6 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5041,6 +5041,18 @@ LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or " LPFC_ATTR_RW(nvme_oas, 0, 0, 1, "Use OAS bit on NVME IOs"); +/* + * lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs + * + * 0 = Put NVME Command in SGL + * 1 = Embed NVME Command in WQE (unless G7) + * 2 = Embed NVME Command in WQE (force) + * + * Value range is [0,2]. Default value is 1. + */ +LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2, + "Embed NVME Command in WQE"); + /* * lpfc_fcp_io_channel: Set the number of FCP IO channels the driver * will advertise it supports to the SCSI layer. This also will map to @@ -5282,6 +5294,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_task_mgmt_tmo, &dev_attr_lpfc_use_msi, &dev_attr_lpfc_nvme_oas, + &dev_attr_lpfc_nvme_embed_cmd, &dev_attr_lpfc_auto_imax, &dev_attr_lpfc_fcp_imax, &dev_attr_lpfc_fcp_cpu_map, @@ -6306,6 +6319,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN); lpfc_use_msi_init(phba, lpfc_use_msi); lpfc_nvme_oas_init(phba, lpfc_nvme_oas); + lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd); lpfc_auto_imax_init(phba, lpfc_auto_imax); lpfc_fcp_imax_init(phba, lpfc_fcp_imax); lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map); diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index ed5e870c58c3..37c547b4bc78 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2678,6 +2678,7 @@ struct lpfc_mbx_read_rev { #define lpfc_mbx_rd_rev_vpd_MASK 0x00000001 #define lpfc_mbx_rd_rev_vpd_WORD word1 uint32_t first_hw_rev; +#define LPFC_G7_ASIC_1 0xd uint32_t second_hw_rev; uint32_t word4_rsvd; uint32_t third_hw_rev; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ecb42cae71f2..50bc6c6efa87 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10653,11 +10653,11 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->fcp_embed_io = 0; lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME, - "6422 XIB %d: FCP %d %d NVME %d %d %d\n", + "6422 XIB %d: FCP %d %d NVME %d %d %d %d\n", bf_get(cfg_xib, mbx_sli4_parameters), phba->fcp_embed_pbde, phba->fcp_embed_io, phba->nvme_support, phba->nvme_embed_pbde, - phba->cfg_suppress_rsp); + phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp); if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) && (bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) && diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index c75958daf799..6ea6cc372647 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -617,10 +617,20 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, struct lpfc_nvme_buf *lpfc_ncmd, struct nvmefc_fcp_req *nCmd) { + struct lpfc_hba *phba = vport->phba; struct sli4_sge *sgl; union lpfc_wqe128 *wqe; uint32_t *wptr, *dptr; + /* + * Get a local pointer to the built-in wqe and correct + * the cmd size to match NVME's 96 bytes and fix + * the dma address. + */ + + /* 128 byte wqe support here */ + wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; + /* * Adjust the FCP_CMD and FCP_RSP DMA data and sge_len to * match NVME. NVME sends 96 bytes. Also, use the @@ -630,6 +640,25 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, */ sgl = lpfc_ncmd->nvme_sgl; sgl->sge_len = cpu_to_le32(nCmd->cmdlen); + if (phba->cfg_nvme_embed_cmd) { + sgl->addr_hi = 0; + sgl->addr_lo = 0; + + /* Word 0-2 - NVME CMND IU (embedded payload) */ + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; + wqe->generic.bde.tus.f.bdeSize = 56; + wqe->generic.bde.addrHigh = 0; + wqe->generic.bde.addrLow = 64; /* Word 16 */ + } else { + sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->cmddma)); + sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->cmddma)); + + /* Word 0-2 - NVME CMND IU Inline BDE */ + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + wqe->generic.bde.tus.f.bdeSize = nCmd->cmdlen; + wqe->generic.bde.addrHigh = sgl->addr_hi; + wqe->generic.bde.addrLow = sgl->addr_lo; + } sgl++; @@ -644,27 +673,19 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, sgl->word2 = cpu_to_le32(sgl->word2); sgl->sge_len = cpu_to_le32(nCmd->rsplen); - /* - * Get a local pointer to the built-in wqe and correct - * the cmd size to match NVME's 96 bytes and fix - * the dma address. - */ - - /* 128 byte wqe support here */ - wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; - - /* Word 0-2 - NVME CMND IU (embedded payload) */ - wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; - wqe->generic.bde.tus.f.bdeSize = 56; - wqe->generic.bde.addrHigh = 0; - wqe->generic.bde.addrLow = 64; /* Word 16 */ - /* Word 3 */ bf_set(payload_offset_len, &wqe->fcp_icmd, (nCmd->rsplen + nCmd->cmdlen)); /* Word 10 */ bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1); + + if (!phba->cfg_nvme_embed_cmd) { + bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 0); + return; + } + bf_set(wqe_dbde, &wqe->generic.wqe_com, 0); bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); /* diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 416ba8f8e295..4ce3ca6f4b79 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -6880,6 +6880,18 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Save information as VPD data */ phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev; phba->vpd.rev.smRev = mqe->un.read_rev.second_hw_rev; + + /* + * This is because first G7 ASIC doesn't support the standard + * 0x5a NVME cmd descriptor type/subtype + */ + if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_6) && + (phba->vpd.rev.biuRev == LPFC_G7_ASIC_1) && + (phba->vpd.rev.smRev == 0) && + (phba->cfg_nvme_embed_cmd == 1)) + phba->cfg_nvme_embed_cmd = 0; + phba->vpd.rev.endecRev = mqe->un.read_rev.third_hw_rev; phba->vpd.rev.fcphHigh = bf_get(lpfc_mbx_rd_rev_fcph_high, &mqe->un.read_rev); @@ -9096,6 +9108,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, wqe128->generic.bde.addrLow = 88; /* Word 22 */ bf_set(wqe_wqes, &wqe128->fcp_iwrite.wqe_com, 1); + bf_set(wqe_dbde, &wqe128->fcp_iwrite.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ ptr = &wqe128->words[22]; @@ -9161,6 +9174,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, wqe128->generic.bde.addrLow = 88; /* Word 22 */ bf_set(wqe_wqes, &wqe128->fcp_iread.wqe_com, 1); + bf_set(wqe_dbde, &wqe128->fcp_iread.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ ptr = &wqe128->words[22]; @@ -9219,6 +9233,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, wqe128->generic.bde.addrLow = 88; /* Word 22 */ bf_set(wqe_wqes, &wqe128->fcp_icmd.wqe_com, 1); + bf_set(wqe_dbde, &wqe128->fcp_icmd.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ ptr = &wqe128->words[22]; From 6efb23804153fac93bc49ef6e76707f35fbe2163 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:51 -0800 Subject: [PATCH 075/168] scsi: lpfc: update driver version to 12.0.0.0 Update the driver version to 12.0.0.0 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 4adbf07880a2..b1ae62a44aae 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.4.0.7" +#define LPFC_DRIVER_VERSION "12.0.0.0" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From cf8037f8d08a078d263a9b725e3ae7603ad0d42e Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 22 Feb 2018 08:18:52 -0800 Subject: [PATCH 076/168] scsi: lpfc: Change Copyright of 12.0.0.0 modified files to 2018 Updated Copyright in files updated as part of 12.0.0.0 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 2 +- drivers/scsi/lpfc/lpfc_debugfs.c | 2 +- drivers/scsi/lpfc/lpfc_debugfs.h | 2 +- drivers/scsi/lpfc/lpfc_hw.h | 2 +- drivers/scsi/lpfc/lpfc_ids.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 8b33b652226b..0f174ca80f67 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2009-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 03a7e13a049d..ebe8ac1b88e7 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 308303d501cf..fb0dc2aeed91 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2007-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 12fbf498a7ce..f32eaeb2225a 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2007-2011 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index cf83322cd4fe..08a3f1520159 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h index 329c8d28869c..07ee34017d88 100644 --- a/drivers/scsi/lpfc/lpfc_ids.h +++ b/drivers/scsi/lpfc/lpfc_ids.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * From 121246ae93a1ef37b358da43155c1cc4f33eab37 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 22 Feb 2018 13:49:59 -0800 Subject: [PATCH 077/168] scsi: libsas: Fix kernel-doc headers Avoid that building with W=1 causes the kernel-doc tool to complain about function arguments that have not been documented in the libsas kernel-doc headers. Avoid that the short description starts with a hyphen by changing "--" into "-" in the first line of the kernel-doc headers. Signed-off-by: Bart Van Assche Cc: John Garry Reviewed-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_discover.c | 13 +++++++------ drivers/scsi/libsas/sas_expander.c | 29 +++++++++++++++-------------- drivers/scsi/libsas/sas_init.c | 2 +- drivers/scsi/libsas/sas_port.c | 5 +++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 2b3637b40dde..0cc1567eacc1 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -709,7 +709,7 @@ void sas_resume_sata(struct asd_sas_port *port) } /** - * sas_discover_sata -- discover an STP/SATA domain device + * sas_discover_sata - discover an STP/SATA domain device * @dev: pointer to struct domain_device of interest * * Devices directly attached to a HA port, have no parents. All other diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index e4fd078e4175..a0fa7ef3a071 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -55,7 +55,7 @@ void sas_init_dev(struct domain_device *dev) /* ---------- Domain device discovery ---------- */ /** - * sas_get_port_device -- Discover devices which caused port creation + * sas_get_port_device - Discover devices which caused port creation * @port: pointer to struct sas_port of interest * * Devices directly attached to a HA port, have no parent. This is @@ -278,8 +278,8 @@ static void sas_resume_devices(struct work_struct *work) } /** - * sas_discover_end_dev -- discover an end device (SSP, etc) - * @end: pointer to domain device of interest + * sas_discover_end_dev - discover an end device (SSP, etc) + * @dev: pointer to domain device of interest * * See comment in sas_discover_sata(). */ @@ -428,8 +428,8 @@ void sas_device_set_phy(struct domain_device *dev, struct sas_port *port) /* ---------- Discovery and Revalidation ---------- */ /** - * sas_discover_domain -- discover the domain - * @port: port to the domain of interest + * sas_discover_domain - discover the domain + * @work: work structure embedded in port domain device. * * NOTE: this process _must_ quit (return) as soon as any connection * errors are encountered. Connection recovery is done elsewhere. @@ -572,7 +572,8 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) } /** - * sas_init_disc -- initialize the discovery struct in the port + * sas_init_disc - initialize the discovery struct in the port + * @disc: port discovery structure * @port: pointer to struct port * * Called when the ports are being initialized. diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 6a4f8198b78e..8b7114348def 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1170,9 +1170,9 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev) return 0; } /** - * sas_ex_discover_devices -- discover devices attached to this expander - * dev: pointer to the expander domain device - * single: if you want to do a single phy, else set to -1; + * sas_ex_discover_devices - discover devices attached to this expander + * @dev: pointer to the expander domain device + * @single: if you want to do a single phy, else set to -1; * * Configure this expander for use with its devices and register the * devices of this expander. @@ -1528,10 +1528,11 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, } /** - * sas_configure_parent -- configure routing table of parent - * parent: parent expander - * child: child expander - * sas_addr: SAS port identifier of device directly attached to child + * sas_configure_parent - configure routing table of parent + * @parent: parent expander + * @child: child expander + * @sas_addr: SAS port identifier of device directly attached to child + * @include: whether or not to include @child in the expander routing table */ static int sas_configure_parent(struct domain_device *parent, struct domain_device *child, @@ -1570,9 +1571,9 @@ static int sas_configure_parent(struct domain_device *parent, } /** - * sas_configure_routing -- configure routing - * dev: expander device - * sas_addr: port identifier of device directly attached to the expander device + * sas_configure_routing - configure routing + * @dev: expander device + * @sas_addr: port identifier of device directly attached to the expander device */ static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr) { @@ -1589,8 +1590,8 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) } /** - * sas_discover_expander -- expander discovery - * @ex: pointer to expander domain device + * sas_discover_expander - expander discovery + * @dev: pointer to expander domain device * * See comment in sas_discover_sata(). */ @@ -2111,8 +2112,8 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id) } /** - * sas_revalidate_domain -- revalidate the domain - * @port: port to the domain of interest + * sas_ex_revalidate_domain - revalidate the domain + * @port_dev: port domain device. * * NOTE: this process _must_ quit (return) as soon as any connection * errors are encountered. Connection recovery is done elsewhere. diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index c81a63b5dc71..ede0af78144f 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -234,7 +234,7 @@ int sas_try_ata_reset(struct asd_sas_phy *asd_phy) return -ENODEV; } -/** +/* * transport_sas_phy_reset - reset a phy and permit libata to manage the link * * phy reset request via sysfs in host workqueue context so we know we diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index f07e55d3aa73..fad23dd39114 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -84,7 +84,7 @@ static void sas_resume_port(struct asd_sas_phy *phy) } /** - * sas_form_port -- add this phy to a port + * sas_form_port - add this phy to a port * @phy: the phy of interest * * This function adds this phy to an existing port, thus creating a wide @@ -197,8 +197,9 @@ static void sas_form_port(struct asd_sas_phy *phy) } /** - * sas_deform_port -- remove this phy from the port it belongs to + * sas_deform_port - remove this phy from the port it belongs to * @phy: the phy of interest + * @gone: whether or not the PHY is gone * * This is called when the physical link to the other phy has been * lost (on this phy), in Event thread context. We cannot delay here. From edd066a10090773e18a2095455ad793c73d022b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 26 Feb 2018 10:44:14 +0100 Subject: [PATCH 078/168] scsi: qedi: fix build regression A bugfix I did caused a build regression in some other randconfig builds in a rare combination of options: In file included from drivers/scsi/qedi/qedi_fw.c:16: drivers/scsi/qedi/qedi_gbl.h:26:38: error: array type has incomplete element type 'struct qedi_debugfs_ops' extern const struct qedi_debugfs_ops qedi_debugfs_ops[]; ^~~~~~~~~~~~~~~~ This removes the useless #ifdef around the declarations in qedi_dbg.h to make it always build. Fixes: 779936faf4f1 ("scsi: qedi: fix building with LTO") Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_dbg.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/qedi/qedi_dbg.h b/drivers/scsi/qedi/qedi_dbg.h index 358f40567849..0bc9c31d5a4f 100644 --- a/drivers/scsi/qedi/qedi_dbg.h +++ b/drivers/scsi/qedi/qedi_dbg.h @@ -103,7 +103,6 @@ int qedi_create_sysfs_attr(struct Scsi_Host *shost, void qedi_remove_sysfs_attr(struct Scsi_Host *shost, struct sysfs_bin_attrs *iter); -#ifdef CONFIG_DEBUG_FS /* DebugFS related code */ struct qedi_list_of_funcs { char *oper_str; @@ -139,6 +138,5 @@ void qedi_dbg_host_init(struct qedi_dbg_ctx *qedi, void qedi_dbg_host_exit(struct qedi_dbg_ctx *qedi); void qedi_dbg_init(char *drv_name); void qedi_dbg_exit(void); -#endif /* CONFIG_DEBUG_FS */ #endif /* _QEDI_DBG_H_ */ From 8ef7fe4b2bee7ba88dd24d781f82e98b0b461bbc Mon Sep 17 00:00:00 2001 From: Jianchao Wang Date: Mon, 26 Feb 2018 15:59:16 +0800 Subject: [PATCH 079/168] scsi: core: fix two wrong indentation cases No functional changes. Just fix two wrong indentation cases in scsi_finish_command and scsi_decide_disposition. Signed-off-by: Jianchao Wang Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi_error.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a7e4fba724b7..4c60c260c5da 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -231,7 +231,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "(result %x)\n", cmd->result)); good_bytes = scsi_bufflen(cmd); - if (!blk_rq_is_passthrough(cmd->request)) { + if (!blk_rq_is_passthrough(cmd->request)) { int old_good_bytes = good_bytes; drv = scsi_cmd_to_driver(cmd); if (drv->done) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 96f988a7efda..ac3b1c36c478 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1894,7 +1894,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) } return FAILED; - maybe_retry: +maybe_retry: /* we requeue for retry because the error was retryable, and * the request was not marked fast fail. Note that above, From c520691b38cde1d94f53e5782feba892f5645043 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:45 -0800 Subject: [PATCH 080/168] scsi: mpt3sas: Add PCI device ID for Andromeda. Add device ID and flag for Andromeda/MPI Endpoint. [mkp: typo] Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 1 + drivers/scsi/mpt3sas/mpt3sas_base.h | 1 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index ee117106d0f7..0ad88deb3176 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -524,6 +524,7 @@ typedef struct _MPI2_CONFIG_REPLY { #define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) #define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) #define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) +#define MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP (0x02B0) /*MPI v2.5 SAS products */ #define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 789bc421424b..897394dc8c62 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1336,6 +1336,7 @@ struct MPT3SAS_ADAPTER { u32 ring_buffer_offset; u32 ring_buffer_sz; u8 is_warpdrive; + u8 is_mcpu_endpoint; u8 hide_ir_msg; u8 mfg_pg10_hide_flag; u8 hide_drives; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 74fca184dba9..bde3c6fc8ee3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -10335,6 +10335,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev) case MPI2_MFGPAGE_DEVID_SAS2308_1: case MPI2_MFGPAGE_DEVID_SAS2308_2: case MPI2_MFGPAGE_DEVID_SAS2308_3: + case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP: return MPI2_VERSION; case MPI25_MFGPAGE_DEVID_SAS3004: case MPI25_MFGPAGE_DEVID_SAS3008: @@ -10412,11 +10413,18 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->hba_mpi_version_belonged = hba_mpi_version; ioc->id = mpt2_ids++; sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME); - if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) { + switch (pdev->device) { + case MPI2_MFGPAGE_DEVID_SSS6200: ioc->is_warpdrive = 1; ioc->hide_ir_msg = 1; - } else + break; + case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP: + ioc->is_mcpu_endpoint = 1; + break; + default: ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; + break; + } break; case MPI25_VERSION: case MPI26_VERSION: @@ -10845,6 +10853,8 @@ static const struct pci_device_id mpt3sas_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP, + PCI_ANY_ID, PCI_ANY_ID }, /* SSS6200 */ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, PCI_ANY_ID, PCI_ANY_ID }, From 0448f0195124e33f11d15b7d1e1cab959989eee7 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:46 -0800 Subject: [PATCH 081/168] scsi: mpt3sas: Configure reply post queue depth, DMA and sgl tablesize. This configures shost max sector to 128, single reply descriptor post queue, sgl table size to 16 and 32 bit DMA for MPI Endpoint and it supports 64K as max IO. Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 47 ++++++++++++++++++---------- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 40 +++++++++++++---------- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 13d6e4ec3022..f45da9a4bb50 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2214,6 +2214,9 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) struct sysinfo s; u64 consistent_dma_mask; + if (ioc->is_mcpu_endpoint) + goto try_32bit; + if (ioc->dma_mask) consistent_dma_mask = DMA_BIT_MASK(64); else @@ -2232,6 +2235,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) } } + try_32bit: if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { ioc->base_add_sg_single = &_base_add_sg_single_32; @@ -3887,17 +3891,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) sg_tablesize = min_t(unsigned short, sg_tablesize, MPT_KDUMP_MIN_PHYS_SEGMENTS); - if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) - sg_tablesize = MPT_MIN_PHYS_SEGMENTS; - else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { - sg_tablesize = min_t(unsigned short, sg_tablesize, - SG_MAX_SEGMENTS); - pr_warn(MPT3SAS_FMT - "sg_tablesize(%u) is bigger than kernel" - " defined SG_CHUNK_SIZE(%u)\n", ioc->name, - sg_tablesize, MPT_MAX_PHYS_SEGMENTS); + if (ioc->is_mcpu_endpoint) + ioc->shost->sg_tablesize = MPT_MIN_PHYS_SEGMENTS; + else { + if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) + sg_tablesize = MPT_MIN_PHYS_SEGMENTS; + else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { + sg_tablesize = min_t(unsigned short, sg_tablesize, + SG_MAX_SEGMENTS); + pr_warn(MPT3SAS_FMT + "sg_tablesize(%u) is bigger than kernel " + "defined SG_CHUNK_SIZE(%u)\n", ioc->name, + sg_tablesize, MPT_MAX_PHYS_SEGMENTS); + } + ioc->shost->sg_tablesize = sg_tablesize; } - ioc->shost->sg_tablesize = sg_tablesize; ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)), (facts->RequestCredit / 4)); @@ -3982,13 +3990,18 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) /* reply free queue sizing - taking into account for 64 FW events */ ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - /* calculate reply descriptor post queue depth */ - ioc->reply_post_queue_depth = ioc->hba_queue_depth + - ioc->reply_free_queue_depth + 1 ; - /* align the reply post queue on the next 16 count boundary */ - if (ioc->reply_post_queue_depth % 16) - ioc->reply_post_queue_depth += 16 - - (ioc->reply_post_queue_depth % 16); + /* mCPU manage single counters for simplicity */ + if (ioc->is_mcpu_endpoint) + ioc->reply_post_queue_depth = ioc->reply_free_queue_depth; + else { + /* calculate reply descriptor post queue depth */ + ioc->reply_post_queue_depth = ioc->hba_queue_depth + + ioc->reply_free_queue_depth + 1; + /* align the reply post queue on the next 16 count boundary */ + if (ioc->reply_post_queue_depth % 16) + ioc->reply_post_queue_depth += 16 - + (ioc->reply_post_queue_depth % 16); + } if (ioc->reply_post_queue_depth > facts->MaxReplyDescriptorPostQueueDepth) { diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index bde3c6fc8ee3..5e526799552c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -10521,26 +10521,34 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->transportt = mpt3sas_transport_template; shost->unique_id = ioc->id; - if (max_sectors != 0xFFFF) { - if (max_sectors < 64) { - shost->max_sectors = 64; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "value of 64.\n", ioc->name, max_sectors); - } else if (max_sectors > 32767) { - shost->max_sectors = 32767; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "default value of 32767.\n", ioc->name, - max_sectors); - } else { - shost->max_sectors = max_sectors & 0xFFFE; - pr_info(MPT3SAS_FMT + if (ioc->is_mcpu_endpoint) { + /* mCPU MPI support 64K max IO */ + shost->max_sectors = 128; + pr_info(MPT3SAS_FMT "The max_sectors value is set to %d\n", ioc->name, shost->max_sectors); + } else { + if (max_sectors != 0xFFFF) { + if (max_sectors < 64) { + shost->max_sectors = 64; + pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ + "for max_sectors, range is 64 to 32767. " \ + "Assigning value of 64.\n", \ + ioc->name, max_sectors); + } else if (max_sectors > 32767) { + shost->max_sectors = 32767; + pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ + "for max_sectors, range is 64 to 32767." \ + "Assigning default value of 32767.\n", \ + ioc->name, max_sectors); + } else { + shost->max_sectors = max_sectors & 0xFFFE; + pr_info(MPT3SAS_FMT + "The max_sectors value is set to %d\n", + ioc->name, shost->max_sectors); + } } } - /* register EEDP capabilities with SCSI layer */ if (prot_mask > 0) scsi_host_set_prot(shost, prot_mask); From 22ae5a3c2599381cf7aaa5aca25c515a3166adcc Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:47 -0800 Subject: [PATCH 082/168] scsi: mpt3sas: Introduce API to get BAR0 mapped buffer address For MPI Endpoint/Mcpu, driver should double buffer data buffer/SGLs. This is normally copied from host to internal memory of IOC by DMA engine of PCI device. Since the interface to DMA from host to mCPU is not present for Mcpu/MPI Endpoint device, driver does double copy of those buffers directly to the mCPU memory region via BAR0 region. Introduced API to calculate and return BAR0 mapped host buffer's physical and virtual address for the provided smid. Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 93 +++++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + 2 files changed, 95 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index f45da9a4bb50..36f12426ea53 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -125,6 +125,99 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); +/** + * _base_get_chain - Calculates and Returns virtual chain address + * for the provided smid in BAR0 space. + * + * @ioc: per adapter object + * @smid: system request message index + * @sge_chain_count: Scatter gather chain count. + * + * @Return: chain address. + */ +static inline void __iomem* +_base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u8 sge_chain_count) +{ + void __iomem *base_chain, *chain_virt; + u16 cmd_credit = ioc->facts.RequestCredit + 1; + + base_chain = (void __iomem *)ioc->chip + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + + REPLY_FREE_POOL_SIZE; + chain_virt = base_chain + (smid * ioc->facts.MaxChainDepth * + ioc->request_sz) + (sge_chain_count * ioc->request_sz); + return chain_virt; +} + +/** + * _base_get_chain_phys - Calculates and Returns physical address + * in BAR0 for scatter gather chains, for + * the provided smid. + * + * @ioc: per adapter object + * @smid: system request message index + * @sge_chain_count: Scatter gather chain count. + * + * @Return - Physical chain address. + */ +static inline void * +_base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u8 sge_chain_count) +{ + void *base_chain_phys, *chain_phys; + u16 cmd_credit = ioc->facts.RequestCredit + 1; + + base_chain_phys = (void *)ioc->chip_phys + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + + REPLY_FREE_POOL_SIZE; + chain_phys = base_chain_phys + (smid * ioc->facts.MaxChainDepth * + ioc->request_sz) + (sge_chain_count * ioc->request_sz); + return chain_phys; +} + +/** + * _base_get_buffer_bar0 - Calculates and Returns BAR0 mapped Host + * buffer address for the provided smid. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @smid: system request message index + * + * @Returns - Pointer to buffer location in BAR0. + */ + +static void __iomem * +_base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) +{ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + // Added extra 1 to reach end of chain. + void __iomem *chain_end = _base_get_chain(ioc, + cmd_credit + 1, + ioc->facts.MaxChainDepth); + return chain_end + (smid * 64 * 1024); +} + +/** + * _base_get_buffer_phys_bar0 - Calculates and Returns BAR0 mapped + * Host buffer Physical address for the provided smid. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @smid: system request message index + * + * @Returns - Pointer to buffer location in BAR0. + */ +static void * +_base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) +{ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + void *chain_end_phys = _base_get_chain_phys(ioc, + cmd_credit + 1, + ioc->facts.MaxChainDepth); + return chain_end_phys + (smid * 64 * 1024); +} + /** * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc * @arg: input argument, used to derive ioc diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 897394dc8c62..2529d252a8f1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -120,6 +120,8 @@ #define MPT3SAS_NVME_QUEUE_DEPTH 128 #define MPT_NAME_LENGTH 32 /* generic length of strings */ #define MPT_STRING_LENGTH 64 +#define MPI_FRAME_START_OFFSET 256 +#define REPLY_FREE_POOL_SIZE 512 /*(32 maxcredix *4)*(4 times)*/ #define MPT_MAX_CALLBACKS 32 From 182ac784b41faee02e8b44cd7149575258ad6858 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:48 -0800 Subject: [PATCH 083/168] scsi: mpt3sas: Introduce Base function for cloning. All scsi IO's and config request's data buffer and sgl are cloned to system memory in _clone_sg_entries before submitting it to firmware. Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 215 +++++++++++++++++++++++++- drivers/scsi/mpt3sas/mpt3sas_base.h | 3 + drivers/scsi/mpt3sas/mpt3sas_config.c | 1 + 3 files changed, 218 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 36f12426ea53..484bb987afb4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -125,6 +125,24 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); +/** + * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region + * + * @dst_iomem: Pointer to the destination location in BAR0 space. + * @src: Pointer to the Source data. + * @size: Size of data to be copied. + */ +static void +_base_clone_to_sys_mem(void __iomem *dst_iomem, void *src, u32 size) +{ + int i; + u32 *src_virt_mem = (u32 *)(src); + + for (i = 0; i < size/4; i++) + writel((u32)src_virt_mem[i], + (void __iomem *)dst_iomem + (i * 4)); +} + /** * _base_get_chain - Calculates and Returns virtual chain address * for the provided smid in BAR0 space. @@ -218,6 +236,201 @@ _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) return chain_end_phys + (smid * 64 * 1024); } +/** + * _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain + * lookup list and Provides chain_buffer + * address for the matching dma address. + * (Each smid can have 64K starts from 17024) + * + * @ioc: per adapter object + * @chain_buffer_dma: Chain buffer dma address. + * + * @Returns - Pointer to chain buffer. Or Null on Failure. + */ +static void * +_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc, + dma_addr_t chain_buffer_dma) +{ + u16 index; + + for (index = 0; index < ioc->chain_depth; index++) { + if (ioc->chain_lookup[index].chain_buffer_dma == + chain_buffer_dma) + return ioc->chain_lookup[index].chain_buffer; + } + pr_info(MPT3SAS_FMT + "Provided chain_buffer_dma address is not in the lookup list\n", + ioc->name); + return NULL; +} + +/** + * _clone_sg_entries - MPI EP's scsiio and config requests + * are handled here. Base function for + * double buffering, before submitting + * the requests. + * + * @ioc: per adapter object. + * @mpi_request: mf request pointer. + * @smid: system request message index. + * + * @Returns: Nothing. + */ +static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, + void *mpi_request, u16 smid) +{ + Mpi2SGESimple32_t *sgel, *sgel_next; + u32 sgl_flags, sge_chain_count = 0; + bool is_write = 0; + u16 i = 0; + void __iomem *buffer_iomem; + void *buffer_iomem_phys; + void __iomem *buff_ptr; + void *buff_ptr_phys; + void __iomem *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO]; + void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO], *dst_addr_phys; + MPI2RequestHeader_t *request_hdr; + struct scsi_cmnd *scmd; + struct scatterlist *sg_scmd = NULL; + int is_scsiio_req = 0; + + request_hdr = (MPI2RequestHeader_t *) mpi_request; + + if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) { + Mpi25SCSIIORequest_t *scsiio_request = + (Mpi25SCSIIORequest_t *)mpi_request; + sgel = (Mpi2SGESimple32_t *) &scsiio_request->SGL; + is_scsiio_req = 1; + } else if (request_hdr->Function == MPI2_FUNCTION_CONFIG) { + Mpi2ConfigRequest_t *config_req = + (Mpi2ConfigRequest_t *)mpi_request; + sgel = (Mpi2SGESimple32_t *) &config_req->PageBufferSGE; + } else + return; + + /* From smid we can get scsi_cmd, once we have sg_scmd, + * we just need to get sg_virt and sg_next to get virual + * address associated with sgel->Address. + */ + + if (is_scsiio_req) { + /* Get scsi_cmd using smid */ + scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid); + if (scmd == NULL) { + pr_err(MPT3SAS_FMT "scmd is NULL\n", ioc->name); + return; + } + + /* Get sg_scmd from scmd provided */ + sg_scmd = scsi_sglist(scmd); + } + + /* + * 0 - 255 System register + * 256 - 4352 MPI Frame. (This is based on maxCredit 32) + * 4352 - 4864 Reply_free pool (512 byte is reserved + * considering maxCredit 32. Reply need extra + * room, for mCPU case kept four times of + * maxCredit). + * 4864 - 17152 SGE chain element. (32cmd * 3 chain of + * 128 byte size = 12288) + * 17152 - x Host buffer mapped with smid. + * (Each smid can have 64K Max IO.) + * BAR0+Last 1K MSIX Addr and Data + * Total size in use 2113664 bytes of 4MB BAR0 + */ + + buffer_iomem = _base_get_buffer_bar0(ioc, smid); + buffer_iomem_phys = _base_get_buffer_phys_bar0(ioc, smid); + + buff_ptr = buffer_iomem; + buff_ptr_phys = buffer_iomem_phys; + + if (sgel->FlagsLength & + (MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT)) + is_write = 1; + + for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) { + + sgl_flags = (sgel->FlagsLength >> MPI2_SGE_FLAGS_SHIFT); + + switch (sgl_flags & MPI2_SGE_FLAGS_ELEMENT_MASK) { + case MPI2_SGE_FLAGS_CHAIN_ELEMENT: + /* + * Helper function which on passing + * chain_buffer_dma returns chain_buffer. Get + * the virtual address for sgel->Address + */ + sgel_next = + _base_get_chain_buffer_dma_to_chain_buffer(ioc, + sgel->Address); + if (sgel_next == NULL) + return; + /* + * This is coping 128 byte chain + * frame (not a host buffer) + */ + dst_chain_addr[sge_chain_count] = + _base_get_chain(ioc, + smid, sge_chain_count); + src_chain_addr[sge_chain_count] = + (void *) sgel_next; + dst_addr_phys = + _base_get_chain_phys(ioc, + smid, sge_chain_count); + sgel->Address = (dma_addr_t)dst_addr_phys; + sgel = sgel_next; + sge_chain_count++; + break; + case MPI2_SGE_FLAGS_SIMPLE_ELEMENT: + if (is_write) { + if (is_scsiio_req) { + _base_clone_to_sys_mem(buff_ptr, + sg_virt(sg_scmd), + (sgel->FlagsLength & 0x00ffffff)); + sgel->Address = + (dma_addr_t)buff_ptr_phys; + } else { + _base_clone_to_sys_mem(buff_ptr, + ioc->config_vaddr, + (sgel->FlagsLength & 0x00ffffff)); + sgel->Address = + (dma_addr_t)buff_ptr_phys; + } + } + buff_ptr += (sgel->FlagsLength & 0x00ffffff); + buff_ptr_phys += (sgel->FlagsLength & 0x00ffffff); + if ((sgel->FlagsLength & + (MPI2_SGE_FLAGS_END_OF_BUFFER + << MPI2_SGE_FLAGS_SHIFT))) + goto eob_clone_chain; + else { + /* + * Every single element in MPT will have + * associated sg_next. Better to sanity that + * sg_next is not NULL, but it will be a bug + * if it is null. + */ + if (is_scsiio_req) { + sg_scmd = sg_next(sg_scmd); + if (sg_scmd) + sgel++; + else + goto eob_clone_chain; + } + } + break; + } + } + +eob_clone_chain: + for (i = 0; i < sge_chain_count; i++) { + if (is_scsiio_req) + _base_clone_to_sys_mem(dst_chain_addr[i], + src_chain_addr[i], ioc->request_sz); + } +} + /** * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc * @arg: input argument, used to derive ioc @@ -3295,7 +3508,7 @@ _base_put_smid_nvme_encap_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) /** * _base_put_smid_default - Default, primarily used for config pages - * use Atomic Request Descriptor + * use Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 2529d252a8f1..4fd582bd14b3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -95,6 +95,8 @@ #define MPT_MIN_PHYS_SEGMENTS 16 #define MPT_KDUMP_MIN_PHYS_SEGMENTS 32 +#define MCPU_MAX_CHAINS_PER_IO 3 + #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE #define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE #else @@ -1238,6 +1240,7 @@ struct MPT3SAS_ADAPTER { u16 config_page_sz; void *config_page; dma_addr_t config_page_dma; + void *config_vaddr; /* scsiio request */ u16 hba_queue_depth; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 1c747cf419d5..0dba3c480b24 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -219,6 +219,7 @@ _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, mem->page = ioc->config_page; mem->page_dma = ioc->config_page_dma; } + ioc->config_vaddr = mem->page; return r; } From e5747439366c1079257083f231f5dd9a84bf0fd7 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:49 -0800 Subject: [PATCH 084/168] scsi: mpt3sas: Introduce function to clone mpi request. 1) Added function _base_clone_mpi_to_sys_mem to clone MPI request into system BAR0 mapped region. 2) Separate out MPI Endpoint IO submissions to function _base_put_smid_mpi_ep_scsi_io. 3) MPI EP requests are submitted in two 32 bit MMIO writes. from _base_mpi_ep_writeq. For 32 bit Arch,_base_writeq function is identical to _base_mpi_ep_writeq, Removed duplicate code as suggested. Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 140 +++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 484bb987afb4..bb2f2a4156a9 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -125,6 +125,25 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); +/** + * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames + * to system/BAR0 region. + * + * @dst_iomem: Pointer to the destinaltion location in BAR0 space. + * @src: Pointer to the Source data. + * @size: Size of data to be copied. + */ +static void +_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size) +{ + int i; + u32 *src_virt_mem = (u32 *)src; + + for (i = 0; i < size/4; i++) + writel((u32)src_virt_mem[i], + (void __iomem *)dst_iomem + (i * 4)); +} + /** * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region * @@ -3267,6 +3286,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); } +/** + * _base_mpi_ep_writeq - 32 bit write to MMIO + * @b: data payload + * @addr: address in MMIO space + * @writeq_lock: spin lock + * + * This special handling for MPI EP to take care of 32 bit + * environment where its not quarenteed to send the entire word + * in one transfer. + */ +static inline void +_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr, + spinlock_t *writeq_lock) +{ + unsigned long flags; + __u64 data_out = cpu_to_le64(b); + + spin_lock_irqsave(writeq_lock, flags); + writel((u32)(data_out), addr); + writel((u32)(data_out >> 32), (addr + 4)); + spin_unlock_irqrestore(writeq_lock, flags); +} + /** * _base_writeq - 64 bit write to MMIO * @ioc: per adapter object @@ -3288,16 +3330,40 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) static inline void _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) { - unsigned long flags; - __u64 data_out = cpu_to_le64(b); - - spin_lock_irqsave(writeq_lock, flags); - writel((u32)(data_out), addr); - writel((u32)(data_out >> 32), (addr + 4)); - spin_unlock_irqrestore(writeq_lock, flags); + _base_mpi_ep_writeq(b, addr, writeq_lock); } #endif +/** + * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware + * @ioc: per adapter object + * @smid: system request message index + * @handle: device handle + * + * Return nothing. + */ +static void +_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + void *mpi_req_iomem; + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid); + + _clone_sg_entries(ioc, (void *) mfp, smid); + mpi_req_iomem = (void *)ioc->chip + + MPI_FRAME_START_OFFSET + (smid * ioc->request_sz); + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp, + ioc->request_sz); + descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; + descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); + descriptor.SCSIIO.SMID = cpu_to_le16(smid); + descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); + descriptor.SCSIIO.LMID = 0; + _base_mpi_ep_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + /** * _base_put_smid_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object @@ -3359,7 +3425,23 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; + void *mpi_req_iomem; + u64 *request; + + if (ioc->is_mcpu_endpoint) { + MPI2RequestHeader_t *request_hdr; + + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid); + + request_hdr = (MPI2RequestHeader_t *)mfp; + /* TBD 256 is offset within sys register. */ + mpi_req_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET + + (smid * ioc->request_sz); + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp, + ioc->request_sz); + } + + request = (u64 *)&descriptor; descriptor.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; @@ -3367,8 +3449,13 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, descriptor.HighPriority.SMID = cpu_to_le16(smid); descriptor.HighPriority.LMID = 0; descriptor.HighPriority.Reserved1 = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); + if (ioc->is_mcpu_endpoint) + _base_mpi_ep_writeq(*request, + &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); + else + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); } /** @@ -3406,15 +3493,35 @@ static void _base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) { Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; + void *mpi_req_iomem; + u64 *request; + MPI2RequestHeader_t *request_hdr; + if (ioc->is_mcpu_endpoint) { + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid); + + request_hdr = (MPI2RequestHeader_t *)mfp; + + _clone_sg_entries(ioc, (void *) mfp, smid); + /* TBD 256 is offset within sys register */ + mpi_req_iomem = (void *)ioc->chip + + MPI_FRAME_START_OFFSET + (smid * ioc->request_sz); + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp, + ioc->request_sz); + } + request = (u64 *)&descriptor; descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; descriptor.Default.MSIxIndex = _base_get_msix_index(ioc); descriptor.Default.SMID = cpu_to_le16(smid); descriptor.Default.LMID = 0; descriptor.Default.DescriptorTypeDependent = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); + if (ioc->is_mcpu_endpoint) + _base_mpi_ep_writeq(*request, + &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); + else + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); } /** @@ -3508,7 +3615,7 @@ _base_put_smid_nvme_encap_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) /** * _base_put_smid_default - Default, primarily used for config pages - * use Atomic Request Descriptor + * use Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * @@ -6333,7 +6440,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap_atomic; } else { ioc->put_smid_default = &_base_put_smid_default; - ioc->put_smid_scsi_io = &_base_put_smid_scsi_io; + if (ioc->is_mcpu_endpoint) + ioc->put_smid_scsi_io = &_base_put_smid_mpi_ep_scsi_io; + else + ioc->put_smid_scsi_io = &_base_put_smid_scsi_io; ioc->put_smid_fast_path = &_base_put_smid_fast_path; ioc->put_smid_hi_priority = &_base_put_smid_hi_priority; ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap; From b4472d7180894c96b6133ef5ff3df50836591eaa Mon Sep 17 00:00:00 2001 From: Suganath Prabu Subramani Date: Wed, 7 Feb 2018 02:51:50 -0800 Subject: [PATCH 085/168] scsi: mpt3sas: Introduce function to clone mpi reply. If the posted request has an error of any type, the IOC writes a Reply message into a host-based system reply message frame. This functions clone it in the BAR0 mapped region. Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index bb2f2a4156a9..7858c2d4a14a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -125,6 +125,33 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt3sas_fwfault_debug, 0644); +/** + * _base_clone_reply_to_sys_mem - copies reply to reply free iomem + * in BAR0 space. + * + * @ioc: per adapter object + * @reply: reply message frame(lower 32bit addr) + * @index: System request message index. + * + * @Returns - Nothing + */ +static void +_base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, u32 reply, + u32 index) +{ + /* + * 256 is offset within sys register. + * 256 offset MPI frame starts. Max MPI frame supported is 32. + * 32 * 128 = 4K. From here, Clone of reply free for mcpu starts + */ + u16 cmd_credit = ioc->facts.RequestCredit + 1; + void __iomem *reply_free_iomem = (void __iomem *)ioc->chip + + MPI_FRAME_START_OFFSET + + (cmd_credit * ioc->request_sz) + (index * sizeof(u32)); + + writel(reply, reply_free_iomem); +} + /** * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames * to system/BAR0 region. @@ -1400,6 +1427,10 @@ _base_interrupt(int irq, void *bus_id) 0 : ioc->reply_free_host_index + 1; ioc->reply_free[ioc->reply_free_host_index] = cpu_to_le32(reply); + if (ioc->is_mcpu_endpoint) + _base_clone_reply_to_sys_mem(ioc, + cpu_to_le32(reply), + ioc->reply_free_host_index); writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); } @@ -6242,8 +6273,12 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) /* initialize Reply Free Queue */ for (i = 0, reply_address = (u32)ioc->reply_dma ; i < ioc->reply_free_queue_depth ; i++, reply_address += - ioc->reply_sz) + ioc->reply_sz) { ioc->reply_free[i] = cpu_to_le32(reply_address); + if (ioc->is_mcpu_endpoint) + _base_clone_reply_to_sys_mem(ioc, + (__le32)reply_address, i); + } /* initialize reply queues */ if (ioc->is_driver_loading) From 40114bde9773ccaf9ad77233ac2cc9039f0f2941 Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Wed, 14 Feb 2018 02:16:37 -0800 Subject: [PATCH 086/168] scsi: mpt3sas: Do not use 32-bit atomic request descriptor for Ventura controllers. Sending I/O through 32 bit descriptors to Ventura series of controller results in IO timeout on certain conditions. This error only occurs on systems with high I/O activity. Changes in this patch will prevent driver from using 32 bit descriptor and use 64 bit Descriptors Signed-off-by: Suganath Prabu S Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 169 +++-------------------- drivers/scsi/mpt3sas/mpt3sas_base.h | 11 +- drivers/scsi/mpt3sas/mpt3sas_config.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 22 +-- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 20 +-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 8 +- 6 files changed, 54 insertions(+), 178 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 7858c2d4a14a..84a79ea9caa2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1227,7 +1227,7 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) ack_request->EventContext = mpi_reply->EventContext; ack_request->VF_ID = 0; /* TODO */ ack_request->VP_ID = 0; - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); out: @@ -3420,15 +3420,15 @@ _base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) } /** - * _base_put_smid_fast_path - send fast path request to firmware + * mpt3sas_base_put_smid_fast_path - send fast path request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle * * Return nothing. */ -static void -_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, +void +mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { Mpi2RequestDescriptorUnion_t descriptor; @@ -3445,14 +3445,14 @@ _base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, } /** - * _base_put_smid_hi_priority - send Task Management request to firmware + * mpt3sas_base_put_smid_hi_priority - send Task Management request to firmware * @ioc: per adapter object * @smid: system request message index * @msix_task: msix_task will be same as msix of IO incase of task abort else 0. * Return nothing. */ -static void -_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, +void +mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { Mpi2RequestDescriptorUnion_t descriptor; @@ -3490,15 +3490,15 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, } /** - * _base_put_smid_nvme_encap - send NVMe encapsulated request to + * mpt3sas_base_put_smid_nvme_encap - send NVMe encapsulated request to * firmware * @ioc: per adapter object * @smid: system request message index * * Return nothing. */ -static void -_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid) +void +mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid) { Mpi2RequestDescriptorUnion_t descriptor; u64 *request = (u64 *)&descriptor; @@ -3514,14 +3514,14 @@ _base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid) } /** - * _base_put_smid_default - Default, primarily used for config pages + * mpt3sas_base_put_smid_default - Default, primarily used for config pages * @ioc: per adapter object * @smid: system request message index * * Return nothing. */ -static void -_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) +void +mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) { Mpi2RequestDescriptorUnion_t descriptor; void *mpi_req_iomem; @@ -3555,116 +3555,6 @@ _base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) &ioc->scsi_lookup_lock); } -/** -* _base_put_smid_scsi_io_atomic - send SCSI_IO request to firmware using -* Atomic Request Descriptor -* @ioc: per adapter object -* @smid: system request message index -* @handle: device handle, unused in this function, for function type match -* -* Return nothing. -*/ -static void -_base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle) -{ - Mpi26AtomicRequestDescriptor_t descriptor; - u32 *request = (u32 *)&descriptor; - - descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; - descriptor.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SMID = cpu_to_le16(smid); - - writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); -} - -/** - * _base_put_smid_fast_path_atomic - send fast path request to firmware - * using Atomic Request Descriptor - * @ioc: per adapter object - * @smid: system request message index - * @handle: device handle, unused in this function, for function type match - * Return nothing - */ -static void -_base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle) -{ - Mpi26AtomicRequestDescriptor_t descriptor; - u32 *request = (u32 *)&descriptor; - - descriptor.RequestFlags = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; - descriptor.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SMID = cpu_to_le16(smid); - - writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); -} - -/** - * _base_put_smid_hi_priority_atomic - send Task Management request to - * firmware using Atomic Request Descriptor - * @ioc: per adapter object - * @smid: system request message index - * @msix_task: msix_task will be same as msix of IO incase of task abort else 0 - * - * Return nothing. - */ -static void -_base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 msix_task) -{ - Mpi26AtomicRequestDescriptor_t descriptor; - u32 *request = (u32 *)&descriptor; - - descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; - descriptor.MSIxIndex = msix_task; - descriptor.SMID = cpu_to_le16(smid); - - writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); -} - -/** - * _base_put_smid_nvme_encap_atomic - send NVMe encapsulated request to - * firmware using Atomic Request Descriptor - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -static void -_base_put_smid_nvme_encap_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - Mpi26AtomicRequestDescriptor_t descriptor; - u32 *request = (u32 *)&descriptor; - - descriptor.RequestFlags = MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED; - descriptor.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SMID = cpu_to_le16(smid); - - writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); -} - -/** - * _base_put_smid_default - Default, primarily used for config pages - * use Atomic Request Descriptor - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -static void -_base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - Mpi26AtomicRequestDescriptor_t descriptor; - u32 *request = (u32 *)&descriptor; - - descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - descriptor.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SMID = cpu_to_le16(smid); - - writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost); -} - /** * _base_display_OEMs_branding - Display branding string * @ioc: per adapter object @@ -5243,7 +5133,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) ioc->ioc_link_reset_in_progress = 1; init_completion(&ioc->base_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || @@ -5343,7 +5233,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, ioc->base_cmds.smid = smid; memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); init_completion(&ioc->base_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { @@ -5528,8 +5418,6 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc) if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE) && (!reset_devices)) ioc->rdpq_array_capable = 1; - if (facts->IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ) - ioc->atomic_desc_capable = 1; facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); facts->IOCRequestFrameSize = le16_to_cpu(mpi_reply.IOCRequestFrameSize); @@ -5771,7 +5659,7 @@ _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc) mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; init_completion(&ioc->port_enable_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ); if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -5834,7 +5722,7 @@ mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); return 0; } @@ -5953,7 +5841,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc) mpi_request->EventMasks[i] = cpu_to_le32(ioc->event_masks[i]); init_completion(&ioc->base_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -6467,23 +6355,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) break; } - if (ioc->atomic_desc_capable) { - ioc->put_smid_default = &_base_put_smid_default_atomic; - ioc->put_smid_scsi_io = &_base_put_smid_scsi_io_atomic; - ioc->put_smid_fast_path = &_base_put_smid_fast_path_atomic; - ioc->put_smid_hi_priority = &_base_put_smid_hi_priority_atomic; - ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap_atomic; - } else { - ioc->put_smid_default = &_base_put_smid_default; - if (ioc->is_mcpu_endpoint) - ioc->put_smid_scsi_io = &_base_put_smid_mpi_ep_scsi_io; - else - ioc->put_smid_scsi_io = &_base_put_smid_scsi_io; - ioc->put_smid_fast_path = &_base_put_smid_fast_path; - ioc->put_smid_hi_priority = &_base_put_smid_hi_priority; - ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap; - } - + if (ioc->is_mcpu_endpoint) + ioc->put_smid_scsi_io = &_base_put_smid_mpi_ep_scsi_io; + else + ioc->put_smid_scsi_io = &_base_put_smid_scsi_io; /* * These function pointers for other requests that don't diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 4fd582bd14b3..68bffaebe900 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1354,12 +1354,7 @@ struct MPT3SAS_ADAPTER { void *device_remove_in_progress; u16 device_remove_in_progress_sz; u8 is_gen35_ioc; - u8 atomic_desc_capable; PUT_SMID_IO_FP_HIP put_smid_scsi_io; - PUT_SMID_IO_FP_HIP put_smid_fast_path; - PUT_SMID_IO_FP_HIP put_smid_hi_priority; - PUT_SMID_DEFAULT put_smid_default; - PUT_SMID_DEFAULT put_smid_nvme_encap; }; @@ -1400,6 +1395,12 @@ void *mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid); dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid); void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc); +void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 handle); +void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, + u16 msix_task); +void mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid); +void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid); /* hi-priority queue */ u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 0dba3c480b24..e87c76a832f6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -403,7 +403,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); _config_display_some_debug(ioc, smid, "config_request", NULL); init_completion(&ioc->config_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ); if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 523971aeb4c1..d3cb387ba9f4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -820,7 +820,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ret = -EINVAL; goto out; } - ioc->put_smid_nvme_encap(ioc, smid); + mpt3sas_base_put_smid_nvme_encap(ioc, smid); break; } case MPI2_FUNCTION_SCSI_IO_REQUEST: @@ -845,7 +845,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) ioc->put_smid_scsi_io(ioc, smid, device_handle); else - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SCSI_TASK_MGMT: @@ -882,7 +882,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, tm_request->DevHandle)); ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - ioc->put_smid_hi_priority(ioc, smid, 0); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); break; } case MPI2_FUNCTION_SMP_PASSTHROUGH: @@ -913,7 +913,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SATA_PASSTHROUGH: @@ -928,7 +928,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_FW_DOWNLOAD: @@ -936,7 +936,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, { ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_TOOLBOX: @@ -951,7 +951,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); } - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: @@ -970,7 +970,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, default: ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); break; } @@ -1601,7 +1601,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, cpu_to_le32(ioc->product_specific[buffer_type][i]); init_completion(&ioc->ctl_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -1948,7 +1948,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, mpi_request->VP_ID = 0; init_completion(&ioc->ctl_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -2215,7 +2215,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) mpi_request->VP_ID = 0; init_completion(&ioc->ctl_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 5e526799552c..50efccd73cb1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2679,7 +2679,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); mpt3sas_scsih_set_tm_flag(ioc, handle); init_completion(&ioc->tm_cmds.done); - ioc->put_smid_hi_priority(ioc, smid, msix_task); + mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { pr_err(MPT3SAS_FMT "%s: timeout\n", @@ -3638,7 +3638,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; set_bit(handle, ioc->device_remove_in_progress); - ioc->put_smid_hi_priority(ioc, smid, 0); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); out: @@ -3739,7 +3739,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; mpi_request->DevHandle = mpi_request_tm->DevHandle; - ioc->put_smid_default(ioc, smid_sas_ctrl); + mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl); return _scsih_check_for_pending_tm(ioc, smid); } @@ -3834,7 +3834,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - ioc->put_smid_hi_priority(ioc, smid, 0); + mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); } /** @@ -3926,7 +3926,7 @@ _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, ack_request->EventContext = event_context; ack_request->VF_ID = 0; /* TODO */ ack_request->VP_ID = 0; - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); } /** @@ -3983,7 +3983,7 @@ _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; mpi_request->DevHandle = handle; - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); } /** @@ -4712,12 +4712,12 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | MPI25_SCSIIO_IOFLAGS_FAST_PATH); - ioc->put_smid_fast_path(ioc, smid, handle); + mpt3sas_base_put_smid_fast_path(ioc, smid, handle); } else ioc->put_smid_scsi_io(ioc, smid, le16_to_cpu(mpi_request->DevHandle)); } else - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); return 0; out: @@ -7606,7 +7606,7 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) handle, phys_disk_num)); init_completion(&ioc->scsih_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { @@ -9697,7 +9697,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) if (!ioc->hide_ir_msg) pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); init_completion(&ioc->scsih_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index d3940c5d079d..3a143bb5ca72 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -392,7 +392,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, "report_manufacture - send to sas_addr(0x%016llx)\n", ioc->name, (unsigned long long)sas_address)); init_completion(&ioc->transport_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -1198,7 +1198,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, ioc->name, (unsigned long long)phy->identify.sas_address, phy->number)); init_completion(&ioc->transport_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -1514,7 +1514,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, ioc->name, (unsigned long long)phy->identify.sas_address, phy->number, phy_operation)); init_completion(&ioc->transport_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { @@ -2014,7 +2014,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, "%s - sending smp request\n", ioc->name, __func__)); init_completion(&ioc->transport_cmds.done); - ioc->put_smid_default(ioc, smid); + mpt3sas_base_put_smid_default(ioc, smid); wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { From e0b14a4ad57801063065cfe2129b0ea9ad95e59a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Mar 2018 15:07:19 -0800 Subject: [PATCH 087/168] scsi: sd_zbc: Fix sd_zbc_get_seq_zones() kernel-doc header Avoid that the kernel-doc tool complains about a mismatch between the kernel-doc header and the function argument list. Signed-off-by: Bart Van Assche Cc: Damien Le Moal Cc: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/sd_zbc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 6c348a211ebb..8f3669fd490d 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -520,7 +520,8 @@ static inline unsigned long *sd_zbc_alloc_zone_bitmap(struct scsi_disk *sdkp) * sd_zbc_get_seq_zones - Parse report zones reply to identify sequential zones * @sdkp: disk used * @buf: report reply buffer - * @seq_zone_bitamp: bitmap of sequential zones to set + * @buflen: length of @buf + * @seq_zones_bitmap: bitmap of sequential zones to set * * Parse reported zone descriptors in @buf to identify sequential zones and * set the reported zone bit in @seq_zones_bitmap accordingly. From 8aa29f192ca675746ab4f39e46a5fd712a76faa6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Mar 2018 15:07:20 -0800 Subject: [PATCH 088/168] scsi: ufs: Fix kernel-doc errors and warnings Avoid that the kernel-doc tool complains about mismatches between kernel-doc headers and function definitions. Avoid that errors like the following are reported when building the UFS driver with W=1: drivers/scsi/ufs/tc-dwc-g210-pci.c:60: error: Cannot parse struct or union! drivers/scsi/ufs/tc-dwc-g210-pltfrm.c:26: warning: cannot understand function prototype: 'struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = ' Signed-off-by: Bart Van Assche Cc: Vivek Gautam Cc: Stanislav Nijnikov Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/tc-dwc-g210-pci.c | 4 +- drivers/scsi/ufs/tc-dwc-g210-pltfrm.c | 2 +- drivers/scsi/ufs/ufshcd-pci.c | 7 +- drivers/scsi/ufs/ufshcd.c | 94 +++++++++++++-------------- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c index 325d5e14fc0d..2f41722a8c28 100644 --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c @@ -51,7 +51,7 @@ static int tc_dwc_g210_pci_runtime_idle(struct device *dev) return ufshcd_runtime_idle(dev_get_drvdata(dev)); } -/** +/* * struct ufs_hba_dwc_vops - UFS DWC specific variant operations */ static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = { @@ -71,7 +71,7 @@ static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev) /** * tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory - * @pdev - pointer to PCI handle + * @pdev: pointer to PCI handle */ static void tc_dwc_g210_pci_remove(struct pci_dev *pdev) { diff --git a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c index 2d3f5270f875..6dfe5a9206e9 100644 --- a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c +++ b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c @@ -20,7 +20,7 @@ #include "ufshcd-dwc.h" #include "tc-dwc-g210.h" -/** +/* * UFS DWC specific variant operations */ static struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = { diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 925b0ec7ec54..ffe6f82182ba 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -75,8 +75,7 @@ static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { #ifdef CONFIG_PM_SLEEP /** * ufshcd_pci_suspend - suspend power management function - * @pdev: pointer to PCI device handle - * @state: power state + * @dev: pointer to PCI device handle * * Returns 0 if successful * Returns non-zero otherwise @@ -88,7 +87,7 @@ static int ufshcd_pci_suspend(struct device *dev) /** * ufshcd_pci_resume - resume power management function - * @pdev: pointer to PCI device handle + * @dev: pointer to PCI device handle * * Returns 0 if successful * Returns non-zero otherwise @@ -126,7 +125,7 @@ static void ufshcd_pci_shutdown(struct pci_dev *pdev) /** * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory - * @pdev - pointer to PCI handle + * @pdev: pointer to PCI handle */ static void ufshcd_pci_remove(struct pci_dev *pdev) { diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 1fbb17bb175b..3abcd31646eb 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -524,7 +524,7 @@ int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, /** * ufshcd_get_intr_mask - Get the interrupt bit mask - * @hba - Pointer to adapter instance + * @hba: Pointer to adapter instance * * Returns interrupt bit mask per version */ @@ -551,7 +551,7 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba) /** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA - * @hba - Pointer to adapter instance + * @hba: Pointer to adapter instance * * Returns UFSHCI version supported by the controller */ @@ -578,7 +578,7 @@ static inline bool ufshcd_is_device_present(struct ufs_hba *hba) /** * ufshcd_get_tr_ocs - Get the UTRD Overall Command Status - * @lrb: pointer to local command reference block + * @lrbp: pointer to local command reference block * * This function is used to get the OCS field from UTRD * Returns the OCS field in the UTRD @@ -1738,7 +1738,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) /** * ufshcd_copy_sense_data - Copy sense data in case of check condition - * @lrb - pointer to local reference block + * @lrbp: pointer to local reference block */ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) { @@ -1760,7 +1760,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) * ufshcd_copy_query_response() - Copy the Query Response and the data * descriptor * @hba: per adapter instance - * @lrb - pointer to local reference block + * @lrbp: pointer to local reference block */ static int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) @@ -1861,7 +1861,7 @@ ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) /** * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command * @hba: per adapter instance - * @uic_command: UIC command + * @uic_cmd: UIC command * * Must be called with mutex held. * Returns 0 only if success. @@ -1944,7 +1944,8 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) /** * ufshcd_map_sg - Map scatter-gather list to prdt - * @lrbp - pointer to local reference block + * @hba: per adapter instance + * @lrbp: pointer to local reference block * * Returns 0 in case of success, non-zero value in case of failure */ @@ -2080,8 +2081,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, /** * ufshcd_prepare_utp_scsi_cmd_upiu() - fills the utp_transfer_req_desc, * for scsi commands - * @lrbp - local reference block pointer - * @upiu_flags - flags + * @lrbp: local reference block pointer + * @upiu_flags: flags */ static void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags) @@ -2169,8 +2170,8 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp) /** * ufshcd_comp_devman_upiu - UFS Protocol Information Unit(UPIU) * for Device Management Purposes - * @hba - per adapter instance - * @lrb - pointer to local reference block + * @hba: per adapter instance + * @lrbp: pointer to local reference block */ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { @@ -2197,8 +2198,8 @@ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) /** * ufshcd_comp_scsi_upiu - UFS Protocol Information Unit(UPIU) * for SCSI Purposes - * @hba - per adapter instance - * @lrb - pointer to local reference block + * @hba: per adapter instance + * @lrbp: pointer to local reference block */ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { @@ -2224,7 +2225,7 @@ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) /** * ufshcd_upiu_wlun_to_scsi_wlun - maps UPIU W-LUN id to SCSI W-LUN ID - * @scsi_lun: UPIU W-LUN id + * @upiu_wlun_id: UPIU W-LUN id * * Returns SCSI W-LUN id */ @@ -2235,8 +2236,8 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id) /** * ufshcd_queuecommand - main entry point for SCSI requests + * @host: SCSI host pointer * @cmd: command from SCSI Midlayer - * @done: call back function * * Returns 0 for success, non-zero in case of failure */ @@ -2477,7 +2478,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, /** * ufshcd_get_dev_cmd_tag - Get device management command tag * @hba: per-adapter instance - * @tag: pointer to variable with available slot value + * @tag_out: pointer to variable with available slot value * * Get a free slot and lock it until device management command * completes. @@ -2514,9 +2515,9 @@ static inline void ufshcd_put_dev_cmd_tag(struct ufs_hba *hba, int tag) /** * ufshcd_exec_dev_cmd - API for sending device management requests - * @hba - UFS hba - * @cmd_type - specifies the type (NOP, Query...) - * @timeout - time in seconds + * @hba: UFS hba + * @cmd_type: specifies the type (NOP, Query...) + * @timeout: time in seconds * * NOTE: Since there is only one available tag for device management commands, * it is expected you hold the hba->dev_cmd.lock mutex. @@ -2613,10 +2614,10 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, /** * ufshcd_query_flag() - API function for sending flag query requests - * hba: per-adapter instance - * query_opcode: flag query to perform - * idn: flag idn to access - * flag_res: the flag value after the query request completes + * @hba: per-adapter instance + * @opcode: flag query to perform + * @idn: flag idn to access + * @flag_res: the flag value after the query request completes * * Returns 0 for success, non-zero in case of failure */ @@ -2680,12 +2681,12 @@ out_unlock: /** * ufshcd_query_attr - API function for sending attribute requests - * hba: per-adapter instance - * opcode: attribute opcode - * idn: attribute idn to access - * index: index field - * selector: selector field - * attr_val: the attribute value after the query request completes + * @hba: per-adapter instance + * @opcode: attribute opcode + * @idn: attribute idn to access + * @index: index field + * @selector: selector field + * @attr_val: the attribute value after the query request completes * * Returns 0 for success, non-zero in case of failure */ @@ -2844,15 +2845,14 @@ out: } /** - * ufshcd_query_descriptor_retry - API function for sending descriptor - * requests - * hba: per-adapter instance - * opcode: attribute opcode - * idn: attribute idn to access - * index: index field - * selector: selector field - * desc_buf: the buffer that contains the descriptor - * buf_len: length parameter passed to the device + * ufshcd_query_descriptor_retry - API function for sending descriptor requests + * @hba: per-adapter instance + * @opcode: attribute opcode + * @idn: attribute idn to access + * @index: index field + * @selector: selector field + * @desc_buf: the buffer that contains the descriptor + * @buf_len: length parameter passed to the device * * Returns 0 for success, non-zero in case of failure. * The buf_len parameter will contain, on return, the length parameter @@ -3077,7 +3077,6 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size) * * Return 0 in case of success, non-zero otherwise */ -#define ASCII_STD true int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf, u32 size, bool ascii) { @@ -3879,7 +3878,7 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba, /** * ufshcd_complete_dev_init() - checks device readiness - * hba: per-adapter instance + * @hba: per-adapter instance * * Set fDeviceInit flag and poll until device toggles it. */ @@ -4418,7 +4417,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) /** * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status - * @lrb: pointer to local reference block of completed command + * @lrbp: pointer to local reference block of completed command * @scsi_status: SCSI command status * * Returns value base on SCSI command status @@ -4453,7 +4452,7 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status) /** * ufshcd_transfer_rsp_status - Get overall status of the response * @hba: per adapter instance - * @lrb: pointer to local reference block of completed command + * @lrbp: pointer to local reference block of completed command * * Returns result of the command to notify SCSI midlayer */ @@ -5761,7 +5760,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba) /** * ufshcd_eh_host_reset_handler - host reset handler registered to scsi layer - * @cmd - SCSI command pointer + * @cmd: SCSI command pointer * * Returns SUCCESS/FAILED */ @@ -5946,11 +5945,11 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) * will take effect only when its sent to "UFS device" well known logical unit * hence we require the scsi_device instance to represent this logical unit in * order for the UFS host driver to send the SSU command for power management. - + * * We also require the scsi_device instance for "RPMB" (Replay Protected Memory * Block) LU so user space process can control this LU. User space may also * want to have access to BOOT LU. - + * * This function adds scsi device instances for each of all well known LUs * (except "REPORT LUNS" LU). * @@ -6019,7 +6018,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba, model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; err = ufshcd_read_string_desc(hba, model_index, str_desc_buf, - QUERY_DESC_MAX_SIZE, ASCII_STD); + QUERY_DESC_MAX_SIZE, true/*ASCII*/); if (err) { dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n", __func__, err); @@ -7413,7 +7412,6 @@ out: /** * ufshcd_system_suspend - system suspend routine * @hba: per adapter instance - * @pm_op: runtime PM or system PM * * Check the description of ufshcd_suspend() function for more details. * @@ -7597,7 +7595,7 @@ EXPORT_SYMBOL(ufshcd_shutdown); /** * ufshcd_remove - de-allocate SCSI host and host memory space * data structure memory - * @hba - per adapter instance + * @hba: per adapter instance */ void ufshcd_remove(struct ufs_hba *hba) { From e75fba9c0668b3767f608ea07485f48d33c270cf Mon Sep 17 00:00:00 2001 From: Wilfried Weissmann Date: Fri, 23 Feb 2018 20:52:34 +0100 Subject: [PATCH 089/168] scsi: mvsas: fix wrong endianness of sgpio api This patch fixes the byte order of the SGPIO api and brings it back in sync with ledmon v0.80 and above. [mkp: added missing SoB and fixed whitespace] Signed-off-by: Wilfried Weissmann Signed-off-by: Martin K. Petersen --- drivers/scsi/mvsas/mv_94xx.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 7de5d8d75480..eb5471bc7263 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -1080,16 +1080,16 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv, void __iomem *regs = mvi->regs_ex - 0x10200; int drive = (i/3) & (4-1); /* drive number on host */ - u32 block = mr32(MVS_SGPIO_DCTRL + + int driveshift = drive * 8; /* bit offset of drive */ + u32 block = ioread32be(regs + MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id); - /* * if bit is set then create a mask with the first * bit of the drive set in the mask ... */ - u32 bit = (write_data[i/8] & (1 << (i&(8-1)))) ? - 1<<(24-drive*8) : 0; + u32 bit = get_unaligned_be32(write_data) & (1 << i) ? + 1 << driveshift : 0; /* * ... and then shift it to the right position based @@ -1098,26 +1098,27 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv, switch (i%3) { case 0: /* activity */ block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT) - << (24-drive*8)); + << driveshift); /* hardwire activity bit to SOF */ block |= LED_BLINKA_SOF << ( MVS_SGPIO_DCTRL_ACT_SHIFT + - (24-drive*8)); + driveshift); break; case 1: /* id */ block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT) - << (24-drive*8)); + << driveshift); block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT; break; case 2: /* fail */ block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT) - << (24-drive*8)); + << driveshift); block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT; break; } - mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, - block); + iowrite32be(block, + regs + MVS_SGPIO_DCTRL + + MVS_SGPIO_HOST_OFFSET * mvi->id); } @@ -1132,7 +1133,7 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv, void __iomem *regs = mvi->regs_ex - 0x10200; mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, - be32_to_cpu(((u32 *) write_data)[i])); + ((u32 *) write_data)[i]); } return reg_count; } From 29e79e0fa9b86535c2f1442d080c8cb5dec8606b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 14 Feb 2018 15:02:31 +0300 Subject: [PATCH 090/168] scsi: atp870u: 64 bit bug in atp885_init() On 64 bit CPUs there is a memory corruption bug on probe(). It should be a u32 pointer instead of an unsigned long pointer or we write past the end of the setupdata[] array. Signed-off-by: Dan Carpenter Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/atp870u.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 8b52a9dbb9cf..b46997cf77e2 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1413,11 +1413,11 @@ static void atp885_init(struct Scsi_Host *shpnt) atpdev->global_map[m] = 0; for (k = 0; k < 4; k++) { atp_writew_base(atpdev, 0x3c, n++); - ((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38); + ((u32 *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38); } for (k = 0; k < 4; k++) { atp_writew_base(atpdev, 0x3c, n++); - ((unsigned long *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38); + ((u32 *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38); } n += 8; } From 18d595bf9de99a0f092d8522da42df8b09ef5c2f Mon Sep 17 00:00:00 2001 From: Weiping Zhang Date: Mon, 26 Feb 2018 22:08:28 +0800 Subject: [PATCH 091/168] scsi: sd: Documentation: add sd-parameters.txt Add a file for documenting SCSI sd module parameters and describe the cache_type setting. [mkp: tweaked text a bit] Signed-off-by: Weiping Zhang Signed-off-by: Martin K. Petersen --- Documentation/scsi/sd-parameters.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/scsi/sd-parameters.txt diff --git a/Documentation/scsi/sd-parameters.txt b/Documentation/scsi/sd-parameters.txt new file mode 100644 index 000000000000..8e5af00d88e7 --- /dev/null +++ b/Documentation/scsi/sd-parameters.txt @@ -0,0 +1,22 @@ +Linux SCSI Disk Driver (sd) Parameters +====================================== + +cache_type (RW) +--------------- +Enable/disable drive write & read cache. + + cache_type string | WCE RCD | Write cache | Read cache +----------------------------+---------+-------------+------------ + write through | 0 0 | off | on + none | 0 1 | off | off + write back | 1 0 | on | on + write back, no read (daft) | 1 1 | on | off + +To set cache type to "write back" and save this setting to the drive: + + # echo "write back" > cache_type + +To modify the caching mode without making the change persistent, prepend +"temporary " to the cache type string. E.g.: + + # echo "temporary write back" > cache_type From 6f9e09fd6488de7661ee20efb5d8ab4e05a59735 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 1 Mar 2018 14:07:07 +0100 Subject: [PATCH 092/168] scsi: mpt3sas: clarify mmio pointer types The newly added code mixes up phys_addr_t/resource_size_t with dma_addr_t and void pointers, as seen from these compiler warning: drivers/scsi/mpt3sas/mpt3sas_base.c: In function '_base_get_chain_phys': drivers/scsi/mpt3sas/mpt3sas_base.c:235:21: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] base_chain_phys = (void *)ioc->chip_phys + MPI_FRAME_START_OFFSET + ^ drivers/scsi/mpt3sas/mpt3sas_base.c: In function '_clone_sg_entries': drivers/scsi/mpt3sas/mpt3sas_base.c:427:20: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] sgel->Address = (dma_addr_t)dst_addr_phys; ^ drivers/scsi/mpt3sas/mpt3sas_base.c:438:7: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] (dma_addr_t)buff_ptr_phys; ^ drivers/scsi/mpt3sas/mpt3sas_base.c:444:10: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] (dma_addr_t)buff_ptr_phys; Both dma_addr_t and phys_addr_t may be wider than a pointer, so we must avoid the conversion to pointer types. This also helps readability. A second problem is treating MMIO addresses from a 'struct resource' as addresses that can be used for DMA on that device. In almost all cases, those are the same, but on some of the more obscure architectures, PCI memory address 0 is mapped into the CPU address space at a nonzero offset. I don't have a good fix for that, so I'm adding a comment here, plus a WARN_ON() that triggers whenever the phys_addr_t number is outside of the low 32-bit address space and causes a straight overflow when assigned to the 32-bit sgel->Address. Fixes: 182ac784b41f ("scsi: mpt3sas: Introduce Base function for cloning.") Signed-off-by: Arnd Bergmann Acked-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 42 ++++++++++++++++------------- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 84a79ea9caa2..0a0e7aad0ca4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -225,14 +225,14 @@ _base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid, * * @Return - Physical chain address. */ -static inline void * +static inline phys_addr_t _base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 sge_chain_count) { - void *base_chain_phys, *chain_phys; + phys_addr_t base_chain_phys, chain_phys; u16 cmd_credit = ioc->facts.RequestCredit + 1; - base_chain_phys = (void *)ioc->chip_phys + MPI_FRAME_START_OFFSET + + base_chain_phys = ioc->chip_phys + MPI_FRAME_START_OFFSET + (cmd_credit * ioc->request_sz) + REPLY_FREE_POOL_SIZE; chain_phys = base_chain_phys + (smid * ioc->facts.MaxChainDepth * @@ -272,11 +272,11 @@ _base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) * * @Returns - Pointer to buffer location in BAR0. */ -static void * +static phys_addr_t _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) { u16 cmd_credit = ioc->facts.RequestCredit + 1; - void *chain_end_phys = _base_get_chain_phys(ioc, + phys_addr_t chain_end_phys = _base_get_chain_phys(ioc, cmd_credit + 1, ioc->facts.MaxChainDepth); return chain_end_phys + (smid * 64 * 1024); @@ -330,11 +330,12 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, bool is_write = 0; u16 i = 0; void __iomem *buffer_iomem; - void *buffer_iomem_phys; + phys_addr_t buffer_iomem_phys; void __iomem *buff_ptr; - void *buff_ptr_phys; + phys_addr_t buff_ptr_phys; void __iomem *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO]; - void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO], *dst_addr_phys; + void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO]; + phys_addr_t dst_addr_phys; MPI2RequestHeader_t *request_hdr; struct scsi_cmnd *scmd; struct scatterlist *sg_scmd = NULL; @@ -391,6 +392,7 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, buff_ptr = buffer_iomem; buff_ptr_phys = buffer_iomem_phys; + WARN_ON(buff_ptr_phys > U32_MAX); if (sgel->FlagsLength & (MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT)) @@ -421,10 +423,10 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, smid, sge_chain_count); src_chain_addr[sge_chain_count] = (void *) sgel_next; - dst_addr_phys = - _base_get_chain_phys(ioc, + dst_addr_phys = _base_get_chain_phys(ioc, smid, sge_chain_count); - sgel->Address = (dma_addr_t)dst_addr_phys; + WARN_ON(dst_addr_phys > U32_MAX); + sgel->Address = (u32)dst_addr_phys; sgel = sgel_next; sge_chain_count++; break; @@ -434,14 +436,16 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, _base_clone_to_sys_mem(buff_ptr, sg_virt(sg_scmd), (sgel->FlagsLength & 0x00ffffff)); - sgel->Address = - (dma_addr_t)buff_ptr_phys; + /* + * FIXME: this relies on a a zero + * PCI mem_offset. + */ + sgel->Address = (u32)buff_ptr_phys; } else { _base_clone_to_sys_mem(buff_ptr, ioc->config_vaddr, (sgel->FlagsLength & 0x00ffffff)); - sgel->Address = - (dma_addr_t)buff_ptr_phys; + sgel->Address = (u32)buff_ptr_phys; } } buff_ptr += (sgel->FlagsLength & 0x00ffffff); @@ -2938,7 +2942,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) u32 pio_sz; int i, r = 0; u64 pio_chip = 0; - u64 chip_phys = 0; + phys_addr_t chip_phys = 0; struct adapter_reply_queue *reply_q; dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", @@ -2986,7 +2990,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) if (memap_sz) continue; ioc->chip_phys = pci_resource_start(pdev, i); - chip_phys = (u64)ioc->chip_phys; + chip_phys = ioc->chip_phys; memap_sz = pci_resource_len(pdev, i); ioc->chip = ioremap(ioc->chip_phys, memap_sz); } @@ -3061,8 +3065,8 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) "IO-APIC enabled"), pci_irq_vector(ioc->pdev, reply_q->msix_index)); - pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", - ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); + pr_info(MPT3SAS_FMT "iomem(%pap), mapped(0x%p), size(%d)\n", + ioc->name, &chip_phys, ioc->chip, memap_sz); pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n", ioc->name, (unsigned long long)pio_chip, pio_sz); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 68bffaebe900..4de0251e158e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1103,7 +1103,7 @@ struct MPT3SAS_ADAPTER { char tmp_string[MPT_STRING_LENGTH]; struct pci_dev *pdev; Mpi2SystemInterfaceRegs_t __iomem *chip; - resource_size_t chip_phys; + phys_addr_t chip_phys; int logging_level; int fwfault_debug; u8 ir_firmware; From b0f9408b14838566b2a9b26434fab667c2afb0ea Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Mon, 5 Mar 2018 09:01:00 -0600 Subject: [PATCH 093/168] scsi: smartpqi: add in new supported controllers Reviewed-by: Scott Benesh Signed-off-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index b2880c7709e6..b3aeb88456d8 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -6795,6 +6795,14 @@ static __maybe_unused int pqi_resume(struct pci_dev *pci_dev) /* Define the PCI IDs for the controllers that we support. */ static const struct pci_device_id pqi_pci_id_table[] = { + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x105b, 0x1211) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x105b, 0x1321) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x152d, 0x8a22) @@ -6815,6 +6823,38 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x152d, 0x8a37) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x8460) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x8461) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0xf460) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0xf461) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0045) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0046) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0047) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0048) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x0110) @@ -6915,6 +6955,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1281) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1282) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1300) From 61b142afb2e28d4f06e158399409d181ad91949c Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Thu, 15 Feb 2018 21:55:06 +0530 Subject: [PATCH 094/168] scsi: megaraid: Use dma_pool_zalloc() Use dma_pool_zalloc() instead of dma_pool_alloc + memset Signed-off-by: Souptick Joarder Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index a71ee67df084..905ea36da646 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4022,7 +4022,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) cmd = instance->cmd_list[i]; - cmd->frame = dma_pool_alloc(instance->frame_dma_pool, + cmd->frame = dma_pool_zalloc(instance->frame_dma_pool, GFP_KERNEL, &cmd->frame_phys_addr); cmd->sense = dma_pool_alloc(instance->sense_dma_pool, @@ -4038,7 +4038,6 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) return -ENOMEM; } - memset(cmd->frame, 0, instance->mfi_frame_size); cmd->frame->io.context = cpu_to_le32(cmd->index); cmd->frame->io.pad_0 = 0; if ((instance->adapter_type == MFI_SERIES) && reset_devices) From 2f793a27d58f0fb302f8e162b46fe4b366bbdedd Mon Sep 17 00:00:00 2001 From: Jianchao Wang Date: Sat, 3 Mar 2018 09:54:09 +0800 Subject: [PATCH 095/168] scsi: core: use blk_mq_requeue_request in __scsi_queue_insert In scsi core, __scsi_queue_insert should just put request back on the queue and retry using the same command as before. However, for blk-mq, scsi_mq_requeue_cmd is employed here which will unprepare the request. To align with the semantics of __scsi_queue_insert, use blk_mq_requeue_request with kick_requeue_list == true and put the reference of scsi_device. Cc: Christoph Hellwig Signed-off-by: Jianchao Wang Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aea5a1ae318b..10430d500792 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -191,7 +191,19 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) */ cmd->result = 0; if (q->mq_ops) { - scsi_mq_requeue_cmd(cmd); + /* + * Before a SCSI command is dispatched, + * get_device(&sdev->sdev_gendev) is called and the host, + * target and device busy counters are increased. Since + * requeuing a request causes these actions to be repeated and + * since scsi_device_unbusy() has already been called, + * put_device(&device->sdev_gendev) must still be called. Call + * put_device() after blk_mq_requeue_request() to avoid that + * removal of the SCSI device can start before requeueing has + * happened. + */ + blk_mq_requeue_request(cmd->request, true); + put_device(&device->sdev_gendev); return; } spin_lock_irqsave(q->queue_lock, flags); From 4c06619fc4da5b7aae76f1dde25bfea3246f2591 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 10:29:03 -0800 Subject: [PATCH 096/168] scsi: lpfc: use __raw_writeX on DPP copies Commit 1351e69fc6db ("scsi: lpfc: Add push-to-adapter support to sli4") fails compilation on some 32-bit systems as writeq() is not supported on all architectures. Additionally, it was pointed out that as writeX() does byteswapping if necessary for pci vs the cpu endianness, the code was broken on BE PPC. After discussions with Arnd Bergmann, we've resolved the issue to the following: Instead of writeX(), use __raw_writeX() - which writes to io space while preserving byte order. To use this, the code was changed to use a different buffer that lpfc prepped via sli_pcimem_bcopy() that was set to the bytestream to be written. On platforms with __raw_writeq support, use the routine, otherwise use __raw_writel() [mkp: checkpatch] Fixes: 1351e69fc6db ("scsi: lpfc: Add push-to-adapter support to sli4") Signed-off-by: Dick Kennedy Signed-off-by: James Smart Reviewed-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4ce3ca6f4b79..d20cf51ca15d 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -140,9 +140,16 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); if (q->dpp_enable && q->phba->cfg_enable_dpp) { /* write to DPP aperture taking advatage of Combined Writes */ - tmp = (uint8_t *)wqe; + tmp = (uint8_t *)temp_wqe; +#ifdef __raw_writeq for (i = 0; i < q->entry_size; i += sizeof(uint64_t)) - writeq(*((uint64_t *)(tmp + i)), q->dpp_regaddr + i); + __raw_writeq(*((uint64_t *)(tmp + i)), + q->dpp_regaddr + i); +#else + for (i = 0; i < q->entry_size; i += sizeof(uint32_t)) + __raw_writel(*((uint32_t *)(tmp + i)), + q->dpp_regaddr + i); +#endif } /* ensure WQE bcopy and DPP flushed before doorbell write */ wmb(); From 8b1bb6dcba76b0fceffff77a25e990f30b10d139 Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Thu, 8 Mar 2018 18:41:57 +0530 Subject: [PATCH 097/168] scsi: ipr: Use dma_pool_zalloc() Use dma_pool_zalloc() instead of dma_pool_alloc + memset Signed-off-by: Souptick Joarder Acked-by: Brian King Signed-off-by: Martin K. Petersen --- drivers/scsi/ipr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 52735162444f..dda1a64ab89c 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -9651,14 +9651,14 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) } for (i = 0; i < IPR_NUM_CMD_BLKS; i++) { - ipr_cmd = dma_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr); + ipr_cmd = dma_pool_zalloc(ioa_cfg->ipr_cmd_pool, + GFP_KERNEL, &dma_addr); if (!ipr_cmd) { ipr_free_cmd_blks(ioa_cfg); return -ENOMEM; } - memset(ipr_cmd, 0, sizeof(*ipr_cmd)); ioa_cfg->ipr_cmnd_list[i] = ipr_cmd; ioa_cfg->ipr_cmnd_list_dma[i] = dma_addr; From 917d59ac5e26a45dce8b00d38bb0a338a7f22f23 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 10 Mar 2018 10:28:48 -0800 Subject: [PATCH 098/168] scsi: lpfc: Add missing unlock in WQ full logic Commit 6e8e1c14c61e ("scsi: lpfc: Add WQ Full Logic for NVME Target") fails the static checker. Checker correctly identified a missing unlock on a return path. Add the unlock. Fixes: 6e8e1c14c61e ("scsi: lpfc: Add WQ Full Logic for NVME Target") Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index a4a32d7ec248..a1ad18153ca9 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -904,6 +904,7 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport, lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid); wq = phba->sli4_hba.nvme_wq[ctxp->wqeq->hba_wqidx]; + spin_unlock_irqrestore(&ctxp->ctxlock, flags); lpfc_nvmet_wqfull_flush(phba, wq, ctxp); return; } From 0709263abe0de70a798dcdf481d5dd489ca4752e Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:02 -0800 Subject: [PATCH 099/168] scsi: lpfc: Fix NVME Initiator FirstBurst First Burst support was not properly indicated in NVMe PRLI. Correct the bit position and the logic to check and set first burst support. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nportdisc.c | 15 ++++++++++++++- drivers/scsi/lpfc/lpfc_nvme.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index b63179d895e2..022060636ae1 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1998,8 +1998,14 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_type |= NLP_NVME_TARGET; if (bf_get_be32(prli_disc, nvpr)) ndlp->nlp_type |= NLP_NVME_DISCOVERY; + + /* + * If prli_fba is set, the Target supports FirstBurst. + * If prli_fb_sz is 0, the FirstBurst size is unlimited, + * otherwise it defines the actual size supported by + * the NVME Target. + */ if ((bf_get_be32(prli_fba, nvpr) == 1) && - (bf_get_be32(prli_fb_sz, nvpr) > 0) && (phba->cfg_nvme_enable_fb) && (!phba->nvmet_support)) { /* Both sides support FB. The target's first @@ -2008,6 +2014,13 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_flag |= NLP_FIRSTBURST; ndlp->nvme_fb_size = bf_get_be32(prli_fb_sz, nvpr); + + /* Expressed in units of 512 bytes */ + if (ndlp->nvme_fb_size) + ndlp->nvme_fb_size <<= + LPFC_NVME_FB_SHIFT; + else + ndlp->nvme_fb_size = LPFC_NVME_MAX_FB; } } diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index e79f8f75758c..48b0229ebc99 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -27,6 +27,8 @@ #define LPFC_NVME_WAIT_TMO 10 #define LPFC_NVME_EXPEDITE_XRICNT 8 +#define LPFC_NVME_FB_SHIFT 9 +#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */ struct lpfc_nvme_qhandle { uint32_t index; /* WQ index to use */ From 205e8240a1b42d32c08b0fae5778cbaa336c9c7f Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:03 -0800 Subject: [PATCH 100/168] scsi: lpfc: Code cleanup for 128byte wqe data type The driver is very sloppy about the WQE structure passed between routines. The base struct type is a 64byte wqe. But in many routines they typecast and access 128byte wqes. There were a couple of cases in the past (corrected already) where the typecasts were incorrectly done and the 64byte buffer was accessed as a 128 byte buffer. Clean this up by properly declaring wqe's as 128byte wqe's and removing the typecasts. 64byte wqes are considered a subset of the 128byte wqes. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 11 ++++- drivers/scsi/lpfc/lpfc_nvme.c | 25 ++++++------ drivers/scsi/lpfc/lpfc_nvmet.c | 12 +++--- drivers/scsi/lpfc/lpfc_sli.c | 74 +++++++++++++++------------------- drivers/scsi/lpfc/lpfc_sli.h | 5 +-- 5 files changed, 61 insertions(+), 66 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 37c547b4bc78..a2f372d14eaa 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4601,11 +4601,18 @@ union lpfc_wqe128 { struct fcp_icmnd64_wqe fcp_icmd; struct fcp_iread64_wqe fcp_iread; struct fcp_iwrite64_wqe fcp_iwrite; + struct abort_cmd_wqe abort_cmd; + struct create_xri_wqe create_xri; + struct xmit_bcast64_wqe xmit_bcast64; + struct xmit_seq64_wqe xmit_sequence; + struct xmit_bls_rsp64_wqe xmit_bls_rsp; + struct xmit_els_rsp64_wqe xmit_els_rsp; + struct els_request64_wqe els_req; + struct gen_req64_wqe gen_req; struct fcp_trsp64_wqe fcp_trsp; struct fcp_tsend64_wqe fcp_tsend; struct fcp_treceive64_wqe fcp_treceive; - struct xmit_seq64_wqe xmit_sequence; - struct gen_req64_wqe gen_req; + struct send_frame_wqe send_frame; }; struct lpfc_grp_hdr { diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6ea6cc372647..6d215f27448f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -275,14 +275,14 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, static int lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, - struct nvmefc_ls_req *pnvme_lsreq, - void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_wcqe_complete *), - struct lpfc_nodelist *ndlp, uint32_t num_entry, - uint32_t tmo, uint8_t retry) + struct nvmefc_ls_req *pnvme_lsreq, + void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_wcqe_complete *), + struct lpfc_nodelist *ndlp, uint32_t num_entry, + uint32_t tmo, uint8_t retry) { - struct lpfc_hba *phba = vport->phba; - union lpfc_wqe *wqe; + struct lpfc_hba *phba = vport->phba; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *genwqe; struct ulp_bde64 *bpl; struct ulp_bde64 bde; @@ -628,8 +628,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, * the dma address. */ - /* 128 byte wqe support here */ - wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; + wqe = &lpfc_ncmd->cur_iocbq.wqe; /* * Adjust the FCP_CMD and FCP_RSP DMA data and sge_len to @@ -1048,7 +1047,7 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, struct lpfc_hba *phba = vport->phba; struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; struct lpfc_iocbq *pwqeq = &(lpfc_ncmd->cur_iocbq); - union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&pwqeq->wqe; + union lpfc_wqe128 *wqe = &pwqeq->wqe; uint32_t req_len; if (!pnode || !NLP_CHK_NODE_ACT(pnode)) @@ -1187,7 +1186,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; - union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; + union lpfc_wqe128 *wqe = &lpfc_ncmd->cur_iocbq.wqe; struct sli4_sge *sgl = lpfc_ncmd->nvme_sgl; struct scatterlist *data_sg; struct sli4_sge *first_data_sgl; @@ -1595,7 +1594,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, struct lpfc_iocbq *abts_buf; struct lpfc_iocbq *nvmereq_wqe; struct lpfc_nvme_fcpreq_priv *freqpriv; - union lpfc_wqe *abts_wqe; + union lpfc_wqe128 *abts_wqe; unsigned long flags; int ret_val; @@ -2139,7 +2138,7 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc) break; } pwqeq = &(lpfc_ncmd->cur_iocbq); - wqe = (union lpfc_wqe128 *)&pwqeq->wqe; + wqe = &pwqeq->wqe; /* Allocate iotag for lpfc_ncmd->cur_iocbq. */ iotag = lpfc_sli_next_iotag(phba, pwqeq); diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index a1ad18153ca9..0cd45904aaa3 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1151,7 +1151,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) } ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET; nvmewqe = ctx_buf->iocbq; - wqe = (union lpfc_wqe128 *)&nvmewqe->wqe; + wqe = &nvmewqe->wqe; /* Initialize WQE */ memset(wqe, 0, sizeof(union lpfc_wqe)); /* Word 7 */ @@ -2025,7 +2025,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, { struct lpfc_nodelist *ndlp; struct lpfc_iocbq *nvmewqe; - union lpfc_wqe *wqe; + union lpfc_wqe128 *wqe; if (!lpfc_is_link_up(phba)) { lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, @@ -2208,7 +2208,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, if (((ctxp->state == LPFC_NVMET_STE_RCV) && (ctxp->entry_cnt == 1)) || (ctxp->state == LPFC_NVMET_STE_DATA)) { - wqe = (union lpfc_wqe128 *)&nvmewqe->wqe; + wqe = &nvmewqe->wqe; } else { lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, "6111 Wrong state NVMET FCP: %d cnt %d\n", @@ -2750,7 +2750,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, { struct lpfc_nvmet_tgtport *tgtp; struct lpfc_iocbq *abts_wqeq; - union lpfc_wqe *wqe_abts; + union lpfc_wqe128 *wqe_abts; struct lpfc_nodelist *ndlp; lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, @@ -2845,7 +2845,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, { struct lpfc_nvmet_tgtport *tgtp; struct lpfc_iocbq *abts_wqeq; - union lpfc_wqe *abts_wqe; + union lpfc_wqe128 *abts_wqe; struct lpfc_nodelist *ndlp; unsigned long flags; int rc; @@ -3035,7 +3035,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba, { struct lpfc_nvmet_tgtport *tgtp; struct lpfc_iocbq *abts_wqeq; - union lpfc_wqe *wqe_abts; + union lpfc_wqe128 *wqe_abts; unsigned long flags; int rc; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d20cf51ca15d..7999a40e1370 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -109,7 +109,7 @@ lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) * The caller is expected to hold the hbalock when calling this routine. **/ static int -lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) +lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe) { union lpfc_wqe *temp_wqe; struct lpfc_register doorbell; @@ -8881,7 +8881,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, **/ static int lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, - union lpfc_wqe *wqe) + union lpfc_wqe128 *wqe) { uint32_t xmit_len = 0, total_len = 0; uint8_t ct = 0; @@ -9096,29 +9096,27 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if (phba->fcp_embed_io) { struct lpfc_scsi_buf *lpfc_cmd; struct sli4_sge *sgl; - union lpfc_wqe128 *wqe128; struct fcp_cmnd *fcp_cmnd; uint32_t *ptr; /* 128 byte wqe support here */ - wqe128 = (union lpfc_wqe128 *)wqe; lpfc_cmd = iocbq->context1; sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; fcp_cmnd = lpfc_cmd->fcp_cmnd; /* Word 0-2 - FCP_CMND */ - wqe128->generic.bde.tus.f.bdeFlags = + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; - wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe128->generic.bde.addrHigh = 0; - wqe128->generic.bde.addrLow = 88; /* Word 22 */ + wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe->generic.bde.addrHigh = 0; + wqe->generic.bde.addrLow = 88; /* Word 22 */ - bf_set(wqe_wqes, &wqe128->fcp_iwrite.wqe_com, 1); - bf_set(wqe_dbde, &wqe128->fcp_iwrite.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ - ptr = &wqe128->words[22]; + ptr = &wqe->words[22]; memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); } break; @@ -9162,29 +9160,27 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if (phba->fcp_embed_io) { struct lpfc_scsi_buf *lpfc_cmd; struct sli4_sge *sgl; - union lpfc_wqe128 *wqe128; struct fcp_cmnd *fcp_cmnd; uint32_t *ptr; /* 128 byte wqe support here */ - wqe128 = (union lpfc_wqe128 *)wqe; lpfc_cmd = iocbq->context1; sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; fcp_cmnd = lpfc_cmd->fcp_cmnd; /* Word 0-2 - FCP_CMND */ - wqe128->generic.bde.tus.f.bdeFlags = + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; - wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe128->generic.bde.addrHigh = 0; - wqe128->generic.bde.addrLow = 88; /* Word 22 */ + wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe->generic.bde.addrHigh = 0; + wqe->generic.bde.addrLow = 88; /* Word 22 */ - bf_set(wqe_wqes, &wqe128->fcp_iread.wqe_com, 1); - bf_set(wqe_dbde, &wqe128->fcp_iread.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ - ptr = &wqe128->words[22]; + ptr = &wqe->words[22]; memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); } break; @@ -9221,29 +9217,27 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if (phba->fcp_embed_io) { struct lpfc_scsi_buf *lpfc_cmd; struct sli4_sge *sgl; - union lpfc_wqe128 *wqe128; struct fcp_cmnd *fcp_cmnd; uint32_t *ptr; /* 128 byte wqe support here */ - wqe128 = (union lpfc_wqe128 *)wqe; lpfc_cmd = iocbq->context1; sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; fcp_cmnd = lpfc_cmd->fcp_cmnd; /* Word 0-2 - FCP_CMND */ - wqe128->generic.bde.tus.f.bdeFlags = + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED; - wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; - wqe128->generic.bde.addrHigh = 0; - wqe128->generic.bde.addrLow = 88; /* Word 22 */ + wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe->generic.bde.addrHigh = 0; + wqe->generic.bde.addrLow = 88; /* Word 22 */ - bf_set(wqe_wqes, &wqe128->fcp_icmd.wqe_com, 1); - bf_set(wqe_dbde, &wqe128->fcp_icmd.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); /* Word 22-29 FCP CMND Payload */ - ptr = &wqe128->words[22]; + ptr = &wqe->words[22]; memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); } break; @@ -9481,8 +9475,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - union lpfc_wqe *wqe; - union lpfc_wqe128 wqe128; + union lpfc_wqe128 wqe; struct lpfc_queue *wq; struct lpfc_sli_ring *pring; @@ -9502,9 +9495,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, /* * The WQE can be either 64 or 128 bytes, - * so allocate space on the stack assuming the largest. */ - wqe = (union lpfc_wqe *)&wqe128; lockdep_assert_held(&phba->hbalock); @@ -9554,10 +9545,10 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return IOCB_ERROR; } - if (lpfc_sli4_iocb2wqe(phba, piocb, wqe)) + if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) return IOCB_ERROR; - if (lpfc_sli4_wq_put(wq, wqe)) + if (lpfc_sli4_wq_put(wq, &wqe)) return IOCB_ERROR; lpfc_sli_ringtxcmpl_put(phba, pring, piocb); @@ -10927,7 +10918,7 @@ lpfc_sli4_abort_nvme_io(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_iocbq *abtsiocbp; - union lpfc_wqe *abts_wqe; + union lpfc_wqe128 *abts_wqe; int retval; /* @@ -19048,8 +19039,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) unsigned long iflags = 0; char *fail_msg = NULL; struct lpfc_sglq *sglq; - union lpfc_wqe128 wqe128; - union lpfc_wqe *wqe = (union lpfc_wqe *) &wqe128; + union lpfc_wqe128 wqe; uint32_t txq_cnt = 0; pring = lpfc_phba_elsring(phba); @@ -19092,9 +19082,9 @@ lpfc_drain_txq(struct lpfc_hba *phba) piocbq->sli4_xritag = sglq->sli4_xritag; if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) fail_msg = "to convert bpl to sgl"; - else if (lpfc_sli4_iocb2wqe(phba, piocbq, wqe)) + else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) fail_msg = "to convert iocb to wqe"; - else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe)) + else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) fail_msg = " - Wq is full"; else lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); @@ -19144,7 +19134,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, struct ulp_bde64 bde; struct sli4_sge *sgl = NULL; struct lpfc_dmabuf *dmabuf; - union lpfc_wqe *wqe; + union lpfc_wqe128 *wqe; int numBdes = 0; int i = 0; uint32_t offset = 0; /* accumulated offset in the sg request list */ @@ -19253,7 +19243,7 @@ int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *pwqe) { - union lpfc_wqe *wqe = &pwqe->wqe; + union lpfc_wqe128 *wqe = &pwqe->wqe; struct lpfc_nvmet_rcv_ctx *ctxp; struct lpfc_queue *wq; struct lpfc_sglq *sglq; diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index a3b1b5145d2b..ad7b2e0a2018 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -61,9 +61,8 @@ struct lpfc_iocbq { struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ uint64_t isr_timestamp; - /* Be careful here */ - union lpfc_wqe wqe; /* WQE cmd */ - IOCB_t iocb; /* For IOCB cmd or if we want 128 byte WQE */ + union lpfc_wqe128 wqe; /* SLI-4 */ + IOCB_t iocb; /* SLI-3 */ uint8_t rsvd2; uint8_t priority; /* OAS priority */ From 5fd1108517d9c75eab828e7b1d6d541eee2857f8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:04 -0800 Subject: [PATCH 101/168] scsi: lpfc: Streamline NVME Initiator WQE setup To reduce latency when initializing WQE content, create templates for the most common wqes. This reduces the number of operations taken to set the content. It's not a lot of speed up, but every bit helps. This patch updates the NVME initiator path. [mkp: fixed typo] Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_hw4.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_nvme.c | 323 +++++++++++++++++++++------------- 4 files changed, 201 insertions(+), 125 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 14a86b5b51e4..c7df22683e85 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -565,6 +565,7 @@ void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba); void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_wcqe_complete *abts_cmpl); +void lpfc_nvme_cmd_template(void); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index a2f372d14eaa..98b80559c215 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4183,6 +4183,7 @@ struct wqe_common { #define wqe_iod_SHIFT 13 #define wqe_iod_MASK 0x00000001 #define wqe_iod_WORD word10 +#define LPFC_WQE_IOD_NONE 0 #define LPFC_WQE_IOD_WRITE 0 #define LPFC_WQE_IOD_READ 1 #define wqe_dbde_SHIFT 14 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 50bc6c6efa87..68adea8e0a04 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12583,6 +12583,7 @@ lpfc_init(void) fc_release_transport(lpfc_transport_template); return -ENOMEM; } + lpfc_nvme_cmd_template(); /* Initialize in case vector mapping is needed */ lpfc_used_cpu = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6d215f27448f..52dd9479b538 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -65,6 +65,136 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_nvme_buf *); static struct nvme_fc_port_template lpfc_nvme_template; +union lpfc_wqe128 lpfc_iread_cmd_template; +union lpfc_wqe128 lpfc_iwrite_cmd_template; +union lpfc_wqe128 lpfc_icmnd_cmd_template; + +/* Setup WQE templates for NVME IOs */ +void +lpfc_nvme_cmd_template() +{ + union lpfc_wqe128 *wqe; + + /* IREAD template */ + wqe = &lpfc_iread_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iread.wqe_com, CMD_FCP_IREAD64_WQE); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iread.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iread.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_nvme, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, NVME_READ_CMD); + bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1); + + /* Word 12 - is zero */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* IWRITE template */ + wqe = &lpfc_iwrite_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - initial_xfer_len is variable */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iwrite.wqe_com, CMD_FCP_IWRITE64_WQE); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iwrite.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iwrite.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_nvme, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, NVME_WRITE_CMD); + bf_set(wqe_cqid, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1); + + /* Word 12 - is zero */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* ICMND template */ + wqe = &lpfc_icmnd_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - payload_offset_len is variable */ + + /* Word 4, 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_icmd.wqe_com, CMD_FCP_ICMND64_WQE); + bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_icmd.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_NONE); + bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); + + /* Word 11 */ + bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, FCP_COMMAND); + bf_set(wqe_cqid, &wqe->fcp_icmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_icmd.wqe_com, 0); + + /* Word 12, 13, 14, 15 - is zero */ +} + /** * lpfc_nvme_create_queue - * @lpfc_pnvme: Pointer to the driver's nvme instance data @@ -612,7 +742,7 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport, } /* Fix up the existing sgls for NVME IO. */ -static void +static inline void lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, struct lpfc_nvme_buf *lpfc_ncmd, struct nvmefc_fcp_req *nCmd) @@ -648,6 +778,37 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, wqe->generic.bde.tus.f.bdeSize = 56; wqe->generic.bde.addrHigh = 0; wqe->generic.bde.addrLow = 64; /* Word 16 */ + + /* Word 10 - dbde is 0, wqes is 1 in template */ + + /* + * Embed the payload in the last half of the WQE + * WQE words 16-30 get the NVME CMD IU payload + * + * WQE words 16-19 get payload Words 1-4 + * WQE words 20-21 get payload Words 6-7 + * WQE words 22-29 get payload Words 16-23 + */ + wptr = &wqe->words[16]; /* WQE ptr */ + dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */ + dptr++; /* Skip Word 0 in payload */ + + *wptr++ = *dptr++; /* Word 1 */ + *wptr++ = *dptr++; /* Word 2 */ + *wptr++ = *dptr++; /* Word 3 */ + *wptr++ = *dptr++; /* Word 4 */ + dptr++; /* Skip Word 5 in payload */ + *wptr++ = *dptr++; /* Word 6 */ + *wptr++ = *dptr++; /* Word 7 */ + dptr += 8; /* Skip Words 8-15 in payload */ + *wptr++ = *dptr++; /* Word 16 */ + *wptr++ = *dptr++; /* Word 17 */ + *wptr++ = *dptr++; /* Word 18 */ + *wptr++ = *dptr++; /* Word 19 */ + *wptr++ = *dptr++; /* Word 20 */ + *wptr++ = *dptr++; /* Word 21 */ + *wptr++ = *dptr++; /* Word 22 */ + *wptr = *dptr; /* Word 23 */ } else { sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->cmddma)); sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->cmddma)); @@ -657,6 +818,10 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, wqe->generic.bde.tus.f.bdeSize = nCmd->cmdlen; wqe->generic.bde.addrHigh = sgl->addr_hi; wqe->generic.bde.addrLow = sgl->addr_lo; + + /* Word 10 */ + bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); + bf_set(wqe_wqes, &wqe->generic.wqe_com, 0); } sgl++; @@ -671,50 +836,6 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, bf_set(lpfc_sli4_sge_last, sgl, 1); sgl->word2 = cpu_to_le32(sgl->word2); sgl->sge_len = cpu_to_le32(nCmd->rsplen); - - /* Word 3 */ - bf_set(payload_offset_len, &wqe->fcp_icmd, - (nCmd->rsplen + nCmd->cmdlen)); - - /* Word 10 */ - bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1); - - if (!phba->cfg_nvme_embed_cmd) { - bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); - bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 0); - return; - } - bf_set(wqe_dbde, &wqe->generic.wqe_com, 0); - bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); - - /* - * Embed the payload in the last half of the WQE - * WQE words 16-30 get the NVME CMD IU payload - * - * WQE words 16-19 get payload Words 1-4 - * WQE words 20-21 get payload Words 6-7 - * WQE words 22-29 get payload Words 16-23 - */ - wptr = &wqe->words[16]; /* WQE ptr */ - dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */ - dptr++; /* Skip Word 0 in payload */ - - *wptr++ = *dptr++; /* Word 1 */ - *wptr++ = *dptr++; /* Word 2 */ - *wptr++ = *dptr++; /* Word 3 */ - *wptr++ = *dptr++; /* Word 4 */ - dptr++; /* Skip Word 5 in payload */ - *wptr++ = *dptr++; /* Word 6 */ - *wptr++ = *dptr++; /* Word 7 */ - dptr += 8; /* Skip Words 8-15 in payload */ - *wptr++ = *dptr++; /* Word 16 */ - *wptr++ = *dptr++; /* Word 17 */ - *wptr++ = *dptr++; /* Word 18 */ - *wptr++ = *dptr++; /* Word 19 */ - *wptr++ = *dptr++; /* Word 20 */ - *wptr++ = *dptr++; /* Word 21 */ - *wptr++ = *dptr++; /* Word 22 */ - *wptr = *dptr; /* Word 23 */ } #ifdef CONFIG_SCSI_LPFC_DEBUG_FS @@ -1057,9 +1178,16 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, * There are three possibilities here - use scatter-gather segment, use * the single mapping, or neither. */ - wqe->fcp_iwrite.initial_xfer_len = 0; if (nCmd->sg_cnt) { if (nCmd->io_dir == NVMEFC_FCP_WRITE) { + /* From the iwrite template, initialize words 7 - 11 */ + memcpy(&wqe->words[7], + &lpfc_iwrite_cmd_template.words[7], + sizeof(uint32_t) * 5); + + /* Word 4 */ + wqe->fcp_iwrite.total_xfer_len = nCmd->payload_length; + /* Word 5 */ if ((phba->cfg_nvme_enable_fb) && (pnode->nlp_flag & NLP_FIRSTBURST)) { @@ -1070,69 +1198,28 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, else wqe->fcp_iwrite.initial_xfer_len = pnode->nvme_fb_size; + } else { + wqe->fcp_iwrite.initial_xfer_len = 0; } - - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->generic.wqe_com, - CMD_FCP_IWRITE64_WQE); - bf_set(wqe_pu, &wqe->generic.wqe_com, - PARM_READ_CHECK); - - /* Word 10 */ - bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0); - bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, - LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, - LPFC_WQE_LENLOC_WORD4); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1); - - /* Word 11 */ - bf_set(wqe_cmd_type, &wqe->generic.wqe_com, - NVME_WRITE_CMD); - atomic_inc(&phba->fc4NvmeOutputRequests); } else { - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->generic.wqe_com, - CMD_FCP_IREAD64_WQE); - bf_set(wqe_pu, &wqe->generic.wqe_com, - PARM_READ_CHECK); + /* From the iread template, initialize words 7 - 11 */ + memcpy(&wqe->words[7], + &lpfc_iread_cmd_template.words[7], + sizeof(uint32_t) * 5); - /* Word 10 */ - bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); - bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, - LPFC_WQE_IOD_READ); - bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, - LPFC_WQE_LENLOC_WORD4); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1); + /* Word 4 */ + wqe->fcp_iread.total_xfer_len = nCmd->payload_length; - /* Word 11 */ - bf_set(wqe_cmd_type, &wqe->generic.wqe_com, - NVME_READ_CMD); + /* Word 5 */ + wqe->fcp_iread.rsrvd5 = 0; atomic_inc(&phba->fc4NvmeInputRequests); } } else { - /* Word 4 */ - wqe->fcp_icmd.rsrvd4 = 0; - - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->generic.wqe_com, CMD_FCP_ICMND64_WQE); - bf_set(wqe_pu, &wqe->generic.wqe_com, 0); - - /* Word 10 */ - bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, - LPFC_WQE_LENLOC_NONE); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1); - - /* Word 11 */ - bf_set(wqe_cmd_type, &wqe->generic.wqe_com, NVME_READ_CMD); - + /* From the icmnd template, initialize words 4 - 11 */ + memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4], + sizeof(uint32_t) * 8); atomic_inc(&phba->fc4NvmeControlRequests); } /* @@ -1140,25 +1227,21 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, * of the nvme_cmnd request_buffer */ + /* Word 3 */ + bf_set(payload_offset_len, &wqe->fcp_icmd, + (nCmd->rsplen + nCmd->cmdlen)); + /* Word 6 */ bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, phba->sli4_hba.rpi_ids[pnode->nlp_rpi]); bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag); - /* Word 7 */ - /* Preserve Class data in the ndlp. */ - bf_set(wqe_class, &wqe->generic.wqe_com, - (pnode->nlp_fcp_info & 0x0f)); - /* Word 8 */ wqe->generic.wqe_com.abort_tag = pwqeq->iotag; /* Word 9 */ bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); - /* Word 11 */ - bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - pwqeq->vport = vport; return 0; } @@ -1269,12 +1352,14 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, le32_to_cpu(first_data_sgl->sge_len); bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; bde->tus.w = cpu_to_le32(bde->tus.w); - bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); - } else + /* wqe_pbde is 1 in template */ + } else { + memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3)); bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); - + } } else { bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); + memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3)); /* For this clause to be valid, the payload_length * and sg_cnt must zero. @@ -1287,12 +1372,6 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, return 1; } } - - /* - * Due to difference in data length between DIF/non-DIF paths, - * we need to set word 4 of WQE here - */ - wqe->fcp_iread.total_xfer_len = nCmd->payload_length; return 0; } @@ -2175,14 +2254,8 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc) lpfc_ncmd->cur_iocbq.context1 = lpfc_ncmd; - /* Word 7 */ - bf_set(wqe_erp, &wqe->generic.wqe_com, 0); - /* NVME upper layers will time things out, if needed */ - bf_set(wqe_tmo, &wqe->generic.wqe_com, 0); - - /* Word 10 */ - bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0); - bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); + /* Initialize WQE */ + memset(wqe, 0, sizeof(union lpfc_wqe)); /* add the nvme buffer to a post list */ list_add_tail(&lpfc_ncmd->list, &post_nblist); From bd3061bab3328db40d5d27491fa07a030a12e153 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:05 -0800 Subject: [PATCH 102/168] scsi: lpfc: Streamline NVME Targe6t WQE setup To reduce latency when initializing WQE content, created templates for the most common wqes. This reduces the number of operations taken to set the content. It's not a lot of speed up, but every bit helps. This patch updates the NVME target path. [mkp: fixed typo] Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_nvmet.c | 293 +++++++++++++++++++++------------ 3 files changed, 191 insertions(+), 104 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index c7df22683e85..4ae9ba425e78 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -566,6 +566,7 @@ void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_wcqe_complete *abts_cmpl); void lpfc_nvme_cmd_template(void); +void lpfc_nvmet_cmd_template(void); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 68adea8e0a04..17551540a1c5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12584,6 +12584,7 @@ lpfc_init(void) return -ENOMEM; } lpfc_nvme_cmd_template(); + lpfc_nvmet_cmd_template(); /* Initialize in case vector mapping is needed */ lpfc_used_cpu = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 0cd45904aaa3..07f89524c320 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -74,6 +74,149 @@ static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *, static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_nvmet_rcv_ctx *); +union lpfc_wqe128 lpfc_tsend_cmd_template; +union lpfc_wqe128 lpfc_treceive_cmd_template; +union lpfc_wqe128 lpfc_trsp_cmd_template; + +/* Setup WQE templates for NVME IOs */ +void +lpfc_nvmet_cmd_template() +{ + union lpfc_wqe128 *wqe; + + /* TSEND template */ + wqe = &lpfc_tsend_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - payload_offset_len is zero */ + + /* Word 4 - relative_offset is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 - wqe_ar is variable */ + bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE); + bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, PARM_REL_OFF); + bf_set(wqe_class, &wqe->fcp_tsend.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_tsend.wqe_com, SLI4_CT_RPI); + bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag, rcvoxid is variable */ + + /* Word 10 - wqes, xc is variable */ + bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com, LPFC_WQE_LENLOC_WORD12); + + /* Word 11 - sup, irsp, irsplen is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com, FCP_COMMAND_TSEND); + bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_pbde, &wqe->fcp_tsend.wqe_com, 0); + + /* Word 12 - fcp_data_len is variable */ + + /* Word 13, 14, 15 - PBDE is zero */ + + /* TRECEIVE template */ + wqe = &lpfc_treceive_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 */ + wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN; + + /* Word 4 - relative_offset is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com, CMD_FCP_TRECEIVE64_WQE); + bf_set(wqe_pu, &wqe->fcp_treceive.wqe_com, PARM_REL_OFF); + bf_set(wqe_class, &wqe->fcp_treceive.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_treceive.wqe_com, SLI4_CT_RPI); + bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag, rcvoxid is variable */ + + /* Word 10 - xc is variable */ + bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0); + bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com, LPFC_WQE_LENLOC_WORD12); + bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_treceive.wqe_com, FCP_COMMAND_TRECEIVE); + bf_set(wqe_cqid, &wqe->fcp_treceive.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_sup, &wqe->fcp_treceive.wqe_com, 0); + bf_set(wqe_irsp, &wqe->fcp_treceive.wqe_com, 0); + bf_set(wqe_irsplen, &wqe->fcp_treceive.wqe_com, 0); + bf_set(wqe_pbde, &wqe->fcp_treceive.wqe_com, 1); + + /* Word 12 - fcp_data_len is variable */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* TRSP template */ + wqe = &lpfc_trsp_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - response_len is variable */ + + /* Word 4, 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE); + bf_set(wqe_pu, &wqe->fcp_trsp.wqe_com, PARM_UNUSED); + bf_set(wqe_class, &wqe->fcp_trsp.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_trsp.wqe_com, SLI4_CT_RPI); + bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1); /* wqe_ar */ + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 wqes, xc is variable */ + bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 1); + bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0); + bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, 0); + bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_NONE); + bf_set(wqe_lenloc, &wqe->fcp_trsp.wqe_com, LPFC_WQE_LENLOC_WORD3); + + /* Word 11 irsp, irsplen is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_trsp.wqe_com, FCP_COMMAND_TRSP); + bf_set(wqe_cqid, &wqe->fcp_trsp.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_sup, &wqe->fcp_trsp.wqe_com, 0); + bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 0); + bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, 0); + bf_set(wqe_pbde, &wqe->fcp_trsp.wqe_com, 0); + + /* Word 12, 13, 14, 15 - is zero */ +} + void lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp) { @@ -1152,15 +1295,9 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET; nvmewqe = ctx_buf->iocbq; wqe = &nvmewqe->wqe; + /* Initialize WQE */ memset(wqe, 0, sizeof(union lpfc_wqe)); - /* Word 7 */ - bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI); - bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3); - /* Word 10 */ - bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); - bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0); - bf_set(wqe_qosd, &wqe->generic.wqe_com, 0); ctx_buf->iocbq->context1 = NULL; spin_lock(&phba->sli4_hba.sgl_list_lock); @@ -2220,6 +2357,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, switch (rsp->op) { case NVMET_FCOP_READDATA: case NVMET_FCOP_READDATA_RSP: + /* From the tsend template, initialize words 7 - 11 */ + memcpy(&wqe->words[7], + &lpfc_tsend_cmd_template.words[7], + sizeof(uint32_t) * 5); + /* Words 0 - 2 : The first sg segment */ sgel = &rsp->sg[0]; physaddr = sg_dma_address(sgel); @@ -2236,6 +2378,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, wqe->fcp_tsend.relative_offset = ctxp->offset; /* Word 5 */ + wqe->fcp_tsend.reserved = 0; /* Word 6 */ bf_set(wqe_ctxt_tag, &wqe->fcp_tsend.wqe_com, @@ -2243,10 +2386,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_xri_tag, &wqe->fcp_tsend.wqe_com, nvmewqe->sli4_xritag); - /* Word 7 */ - bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, 1); - bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE); - do_pbde = 0; + /* Word 7 - set ar later */ /* Word 8 */ wqe->fcp_tsend.wqe_com.abort_tag = nvmewqe->iotag; @@ -2255,23 +2395,12 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_reqtag, &wqe->fcp_tsend.wqe_com, nvmewqe->iotag); bf_set(wqe_rcvoxid, &wqe->fcp_tsend.wqe_com, ctxp->oxid); - /* Word 10 */ - bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1); - bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com, - LPFC_WQE_LENLOC_WORD12); - bf_set(wqe_ebde_cnt, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, xc); - bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_tsend.wqe_com, 1); + /* Word 10 - set wqes later, in template xc=1 */ + if (!xc) + bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 0); - /* Word 11 */ - bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com, - LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com, - FCP_COMMAND_TSEND); + /* Word 11 - set sup, irsp, irsplen later */ + do_pbde = 0; /* Word 12 */ wqe->fcp_tsend.fcp_data_len = rsp->transfer_length; @@ -2293,16 +2422,14 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, sgl++; if (rsp->op == NVMET_FCOP_READDATA_RSP) { atomic_inc(&tgtp->xmt_fcp_read_rsp); - bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1); + + /* In template ar=1 wqes=0 sup=0 irsp=0 irsplen=0 */ + if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) { if (ndlp->nlp_flag & NLP_SUPPRESS_RSP) bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 1); - bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0); } else { - bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 1); bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 1); bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, @@ -2313,15 +2440,17 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, } else { atomic_inc(&tgtp->xmt_fcp_read); - bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0); + /* In template ar=1 wqes=0 sup=0 irsp=0 irsplen=0 */ bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 0); - bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0); } break; case NVMET_FCOP_WRITEDATA: + /* From the treceive template, initialize words 3 - 11 */ + memcpy(&wqe->words[3], + &lpfc_treceive_cmd_template.words[3], + sizeof(uint32_t) * 9); + /* Words 0 - 2 : The first sg segment */ txrdy = dma_pool_alloc(phba->txrdy_payload_pool, GFP_KERNEL, &physaddr); @@ -2340,14 +2469,9 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, wqe->fcp_treceive.bde.addrHigh = cpu_to_le32(putPaddrHigh(physaddr)); - /* Word 3 */ - wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN; - /* Word 4 */ wqe->fcp_treceive.relative_offset = ctxp->offset; - /* Word 5 */ - /* Word 6 */ bf_set(wqe_ctxt_tag, &wqe->fcp_treceive.wqe_com, phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); @@ -2355,14 +2479,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, nvmewqe->sli4_xritag); /* Word 7 */ - bf_set(wqe_pu, &wqe->fcp_treceive.wqe_com, 1); - bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0); - bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com, - CMD_FCP_TRECEIVE64_WQE); - if (phba->nvme_embed_pbde) - do_pbde = 1; - else - do_pbde = 0; /* Word 8 */ wqe->fcp_treceive.wqe_com.abort_tag = nvmewqe->iotag; @@ -2371,26 +2487,17 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_reqtag, &wqe->fcp_treceive.wqe_com, nvmewqe->iotag); bf_set(wqe_rcvoxid, &wqe->fcp_treceive.wqe_com, ctxp->oxid); - /* Word 10 */ - bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1); - bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ); - bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com, - LPFC_WQE_LENLOC_WORD12); - bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, xc); - bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0); - bf_set(wqe_irsp, &wqe->fcp_treceive.wqe_com, 0); - bf_set(wqe_irsplen, &wqe->fcp_treceive.wqe_com, 0); - bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_treceive.wqe_com, 1); + /* Word 10 - in template xc=1 */ + if (!xc) + bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, 0); - /* Word 11 */ - bf_set(wqe_cqid, &wqe->fcp_treceive.wqe_com, - LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_cmd_type, &wqe->fcp_treceive.wqe_com, - FCP_COMMAND_TRECEIVE); - bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); + /* Word 11 - set pbde later */ + if (phba->nvme_embed_pbde) { + do_pbde = 1; + } else { + bf_set(wqe_pbde, &wqe->fcp_treceive.wqe_com, 0); + do_pbde = 0; + } /* Word 12 */ wqe->fcp_tsend.fcp_data_len = rsp->transfer_length; @@ -2418,6 +2525,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, break; case NVMET_FCOP_RSP: + /* From the treceive template, initialize words 4 - 11 */ + memcpy(&wqe->words[4], + &lpfc_trsp_cmd_template.words[4], + sizeof(uint32_t) * 8); + /* Words 0 - 2 */ physaddr = rsp->rspdma; wqe->fcp_trsp.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; @@ -2430,12 +2542,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, /* Word 3 */ wqe->fcp_trsp.response_len = rsp->rsplen; - /* Word 4 */ - wqe->fcp_trsp.rsvd_4_5[0] = 0; - - - /* Word 5 */ - /* Word 6 */ bf_set(wqe_ctxt_tag, &wqe->fcp_trsp.wqe_com, phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); @@ -2443,10 +2549,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, nvmewqe->sli4_xritag); /* Word 7 */ - bf_set(wqe_pu, &wqe->fcp_trsp.wqe_com, 0); - bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1); - bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE); - do_pbde = 0; /* Word 8 */ wqe->fcp_trsp.wqe_com.abort_tag = nvmewqe->iotag; @@ -2456,35 +2558,23 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, bf_set(wqe_rcvoxid, &wqe->fcp_trsp.wqe_com, ctxp->oxid); /* Word 10 */ - bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1); - bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 0); - bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_trsp.wqe_com, - LPFC_WQE_LENLOC_WORD3); - bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, xc); - bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1); - if (phba->cfg_nvme_oas) - bf_set(wqe_oas, &wqe->fcp_trsp.wqe_com, 1); + if (xc) + bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, 1); /* Word 11 */ - bf_set(wqe_cqid, &wqe->fcp_trsp.wqe_com, - LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_cmd_type, &wqe->fcp_trsp.wqe_com, - FCP_COMMAND_TRSP); - bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); - - if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) { - /* Good response - all zero's on wire */ - bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0); - bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 0); - bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, 0); - } else { + /* In template wqes=0 irsp=0 irsplen=0 - good response */ + if (rsp->rsplen != LPFC_NVMET_SUCCESS_LEN) { + /* Bad response - embed it */ bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 1); bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 1); bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, ((rsp->rsplen >> 2) - 1)); memcpy(&wqe->words[16], rsp->rspaddr, rsp->rsplen); } + do_pbde = 0; + + /* Word 12 */ + wqe->fcp_trsp.rsvd_12_15[0] = 0; /* Use rspbuf, NOT sg list */ rsp->sg_cnt = 0; @@ -2531,11 +2621,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, sgl++; ctxp->offset += cnt; } - - if (do_pbde) - bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); - else - bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); ctxp->state = LPFC_NVMET_STE_DATA; ctxp->entry_cnt++; return nvmewqe; From a3da825b499f495f959052b848e893550ddaf626 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:06 -0800 Subject: [PATCH 103/168] scsi: lpfc: Fix SCSI lun discovery when port configured for both SCSI and NVME When a port is configured for NVME and SCSI Initiator support and it probes a target supporting both SCSI and NVME, NVME devices are discovered, but SCSI devices are not. The nlp_fc4_type for all NPorts should be cleared on Link Up or just before GID_FTs get issued, as opposed to just during GID_FT cmpl. RSCN activity as well as Link Up can trigger GID_FT. One GID_FT may complete before the next one is issued. Fix by clearng nlp_fc4_type on link up and just before both GID_FTs are issued. During port swapping, copy nlp_fc4_type to the new ndlp Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 1 - drivers/scsi/lpfc/lpfc_els.c | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 5 +++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ebe8ac1b88e7..0617c8ea88c6 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -471,7 +471,6 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) "Parse GID_FTrsp: did:x%x flg:x%x x%x", Did, ndlp->nlp_flag, vport->fc_flag); - ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); /* By default, the driver expects to support FCP FC4 */ if (fc4_type == FC_TYPE_FCP) ndlp->nlp_fc4_type |= NLP_FC4_FCP; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 09e4eb9fbc69..74895e62aaea 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1661,6 +1661,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (ndlp->nrport) { ndlp->nrport = NULL; lpfc_nlp_put(ndlp); + new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type; } /* We shall actually free the ndlp with both nlp_DID and diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7855afa13568..3e7712cd6c9a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -959,6 +959,7 @@ lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport) struct lpfc_nodelist *ndlp; list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); if (!NLP_CHK_NODE_ACT(ndlp)) continue; if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) @@ -3875,6 +3876,10 @@ int lpfc_issue_gidft(struct lpfc_vport *vport) { struct lpfc_hba *phba = vport->phba; + struct lpfc_nodelist *ndlp; + + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) + ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); /* Good status, issue CT Request to NameServer */ if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || From e29d74f8eb1450b0b6c4736210d76cb56ef40e1d Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:07 -0800 Subject: [PATCH 104/168] scsi: lpfc: Fix mailbox wait for POST_SGL mbox command POST_SGL_PAGES mailbox command failed with status (timeout). wait_event_interruptible_timeout when called from mailbox wait interface, gets interrupted, and will randomly fail. Behavior seems very specific to 1 particular server type. Fix by changing from wait_event_interruptible_timeout to wait_for_completion_timeout. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 34 ++++++++++++---------------------- drivers/scsi/lpfc/lpfc_sli.h | 1 + 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7999a40e1370..1a9083adef1f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2388,18 +2388,18 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) void lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { - wait_queue_head_t *pdone_q; unsigned long drvr_flag; + struct completion *pmbox_done; /* - * If pdone_q is empty, the driver thread gave up waiting and + * If pmbox_done is empty, the driver thread gave up waiting and * continued running. */ pmboxq->mbox_flag |= LPFC_MBX_WAKE; spin_lock_irqsave(&phba->hbalock, drvr_flag); - pdone_q = (wait_queue_head_t *) pmboxq->context1; - if (pdone_q) - wake_up_interruptible(pdone_q); + pmbox_done = (struct completion *)pmboxq->context3; + if (pmbox_done) + complete(pmbox_done); spin_unlock_irqrestore(&phba->hbalock, drvr_flag); return; } @@ -11665,31 +11665,25 @@ int lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, uint32_t timeout) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); - MAILBOX_t *mb = NULL; + struct completion mbox_done; int retval; unsigned long flag; - /* The caller might set context1 for extended buffer */ - if (pmboxq->context1) - mb = (MAILBOX_t *)pmboxq->context1; - pmboxq->mbox_flag &= ~LPFC_MBX_WAKE; /* setup wake call as IOCB callback */ pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait; - /* setup context field to pass wait_queue pointer to wake function */ - pmboxq->context1 = &done_q; + /* setup context3 field to pass wait_queue pointer to wake function */ + init_completion(&mbox_done); + pmboxq->context3 = &mbox_done; /* now issue the command */ retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); if (retval == MBX_BUSY || retval == MBX_SUCCESS) { - wait_event_interruptible_timeout(done_q, - pmboxq->mbox_flag & LPFC_MBX_WAKE, - msecs_to_jiffies(timeout * 1000)); + wait_for_completion_timeout(&mbox_done, + msecs_to_jiffies(timeout * 1000)); spin_lock_irqsave(&phba->hbalock, flag); - /* restore the possible extended buffer for free resource */ - pmboxq->context1 = (uint8_t *)mb; + pmboxq->context3 = NULL; /* * if LPFC_MBX_WAKE flag is set the mailbox is completed * else do not free the resources. @@ -11701,11 +11695,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } spin_unlock_irqrestore(&phba->hbalock, flag); - } else { - /* restore the possible extended buffer for free resource */ - pmboxq->context1 = (uint8_t *)mb; } - return retval; } diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index ad7b2e0a2018..431754195505 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -147,6 +147,7 @@ typedef struct lpfcMboxq { struct lpfc_vport *vport;/* virtual port pointer */ void *context1; /* caller context information */ void *context2; /* caller context information */ + void *context3; void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *); uint8_t mbox_flag; From f44ac12f1dcccf4a6315cbe34129adb7aa8497ba Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:08 -0800 Subject: [PATCH 105/168] scsi: lpfc: Memory allocation error during driver start-up on power8 The driver fails to allocate command buffers in the routine lpfc_new_scsi_buf_s4 There is an inconsistency between lpfc_mem_alloc(), where the phba->lpfc_sg_dma_buf_pool is created, and lpfc_new_scsi_buf_s4(), when we allocate a buffer from the pool and check the alignment. The alignment should be on a page boundary, based on LPFC_SLI3_BG_ENABLED in sli3_options, for both cases. Fix by explicitly tracking sli4 vs sli3 and BG options. The result is that phba->cfg_sg_dma_buf_size is now set correctly for SLI-4. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 4 ++++ drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 7 ++++++- drivers/scsi/lpfc/lpfc_sli.c | 19 ++++++++++--------- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 46f6d97d21d6..2ac1d21c553f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -6344,6 +6344,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_poll = 0; else phba->cfg_poll = lpfc_poll; + + if (phba->cfg_enable_bg) + phba->sli3_options |= LPFC_SLI3_BG_ENABLED; + lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp); lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 17551540a1c5..7887468c71b4 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5912,7 +5912,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) * Since lpfc_sg_seg_cnt is module param, the sg_dma_buf_size * used to create the sg_dma_buf_pool must be calculated. */ - if (phba->cfg_enable_bg) { + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { /* * The scsi_buf for a T10-DIF I/O holds the FCP cmnd, * the FCP rsp, and a SGE. Sice we have no control diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fb81e8a8fb1c..050f04418f5f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -837,8 +837,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) * 4K Page alignment is CRITICAL to BlockGuard, double check * to be sure. */ - if (phba->cfg_enable_bg && (((unsigned long)(psb->data) & + if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) && + (((unsigned long)(psb->data) & (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) { + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + "3369 Memory alignment error " + "addr=%lx\n", + (unsigned long)psb->data); dma_pool_free(phba->lpfc_sg_dma_buf_pool, psb->data, psb->dma_handle); kfree(psb); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1a9083adef1f..cb17e2b2be81 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4993,13 +4993,14 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get; phba->port_gp = phba->mbox->us.s3_pgp.port; - if (phba->cfg_enable_bg) { - if (pmb->u.mb.un.varCfgPort.gbg) - phba->sli3_options |= LPFC_SLI3_BG_ENABLED; - else + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { + if (pmb->u.mb.un.varCfgPort.gbg == 0) { + phba->cfg_enable_bg = 0; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0443 Adapter did not grant " "BlockGuard\n"); + } } } else { phba->hbq_get = NULL; @@ -6991,12 +6992,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) * then turn off the global config parameters to disable the * feature in the driver. This is not a fatal error. */ - phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; - if (phba->cfg_enable_bg) { - if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)) - phba->sli3_options |= LPFC_SLI3_BG_ENABLED; - else + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { + if (!(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))) { + phba->cfg_enable_bg = 0; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; ftr_rsp++; + } } if (phba->max_vpi && phba->cfg_enable_npiv && From cb942d8e50d31ef9fa883c26b07a49916f0c190b Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:09 -0800 Subject: [PATCH 106/168] scsi: lpfc: update driver version to 12.0.0.1 Update the driver version to 12.0.0.1 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index b1ae62a44aae..e8b089abbfb3 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.0.0.0" +#define LPFC_DRIVER_VERSION "12.0.0.1" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From 217c55cd0cea8f03a5ef2faf68681bb10ae22573 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Mar 2018 12:04:10 -0800 Subject: [PATCH 107/168] scsi: lpfc: Change Copyright of 12.0.0.1 modified files to 2018 Updated Copyright in files updated as part of 12.0.0.1 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.h | 2 +- drivers/scsi/lpfc/lpfc_scsi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index 48b0229ebc99..9216653e0441 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index 5da7e15400cb..8e38e0204c47 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * From 1875ede02ed5e176a18dccbca84abc28d5b3e141 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 6 Mar 2018 22:19:49 -0500 Subject: [PATCH 108/168] scsi: core: Make SCSI Status CONDITION MET equivalent to GOOD The SCSI PRE-FETCH (10 or 16) command is present both on hard disks and some SSDs. It is useful when the address of the next block(s) to be read is known but it is not following the LBA of the current READ (so read-ahead won't help). It returns two "good" SCSI Status values. If the requested blocks have fitted (or will most likely fit (when the IMMED bit is set)) into the disk's cache, it returns CONDITION MET. If it didn't (or will not) fit then it returns GOOD status. The goal of this patch is to stop the SCSI subsystem treating the CONDITION MET SCSI status as an error. The current state makes the PRE-FETCH command effectively unusable via pass-throughs. Signed-off-by: Douglas Gilbert Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 11 +++++++++++ include/scsi/scsi.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 10430d500792..393f9db8f41b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -867,6 +867,17 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) /* for passthrough error may be set */ error = BLK_STS_OK; } + /* + * Another corner case: the SCSI status byte is non-zero but 'good'. + * Example: PRE-FETCH command returns SAM_STAT_CONDITION_MET when + * it is able to fit nominated LBs in its cache (and SAM_STAT_GOOD + * if it can't fit). Treat SAM_STAT_CONDITION_MET and the related + * intermediate statuses (both obsolete in SAM-4) as good. + */ + if (status_byte(result) && scsi_status_is_good(result)) { + result = 0; + error = BLK_STS_OK; + } /* * special case: failed zero length commands always need to diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index cb85eddb47ea..eb7853c1a23b 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -47,6 +47,8 @@ static inline int scsi_status_is_good(int status) */ status &= 0xfe; return ((status == SAM_STAT_GOOD) || + (status == SAM_STAT_CONDITION_MET) || + /* Next two "intermediate" statuses are obsolete in SAM-4 */ (status == SAM_STAT_INTERMEDIATE) || (status == SAM_STAT_INTERMEDIATE_CONDITION_MET) || /* FIXME: this is obsolete in SAM-3 */ From 4c40db995eb54c3ee8cb5a8340640f49395d5f9e Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:05 +0800 Subject: [PATCH 109/168] scsi: hisi_sas: dt-bindings: add an property of signal attenuation For some new boards with hip07 chipset we are required to set PHY config registers differently. The hw property which determines how to set these registers is in the PHY signal attenuation readings. This patch add an devicetree property, "hisilicon,signal-attenuation", which is used to describe the signal attenuation of an board. Cc: Rob Herring Cc: Mark Rutland Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Reviewed-by: Rob Herring Signed-off-by: Martin K. Petersen --- Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt index df3bef7998fa..8c6659ed2cfc 100644 --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt @@ -53,6 +53,13 @@ Main node required properties: Optional main node properties: - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the "am-max-transmissions" limitation. + - hisilicon,signal-attenuation : array of 3 32-bit values, containing de-emphasis, + preshoot, and boost attenuation readings for the board. They + are used to describe the signal attenuation of the board. These + values' range is 7600 to 12400, and used to represent -24dB to + 24dB. + The formula is "y = (x-10000)/10000". For example, 10478 + means 4.78dB. Example: sas0: sas@c1000000 { From 67c2bf23314170a17f2aefec4f0aaa4881b72181 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:06 +0800 Subject: [PATCH 110/168] scsi: hisi_sas: support the property of signal attenuation for v2 hw The register SAS_PHY_CTRL is configured according to signal quality. The signal quality is calculated by signal attenuation of hardware physical link. It may be different for different PCB layout. So, in order to give better support to new board, this patch add support to reading the devicetree property, "hisilicon,signal-attenuation". Of course, we still keep an default value in driver to adapt old board. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 39 +++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 4ccb61e2ae5c..42b3fd6a9936 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -406,6 +406,17 @@ struct hisi_sas_err_record_v2 { __le32 dma_rx_err_type; }; +struct signal_attenuation_s { + u32 de_emphasis; + u32 preshoot; + u32 boost; +}; + +struct sig_atten_lu_s { + const struct signal_attenuation_s *att; + u32 sas_phy_ctrl; +}; + static const struct hisi_sas_hw_error one_bit_ecc_errors[] = { { .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF), @@ -1130,9 +1141,16 @@ static void phys_try_accept_stp_links_v2_hw(struct hisi_hba *hisi_hba) } } +static const struct signal_attenuation_s x6000 = {9200, 0, 10476}; +static const struct sig_atten_lu_s sig_atten_lu[] = { + { &x6000, 0x3016a68 }, +}; + static void init_reg_v2_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; + u32 sas_phy_ctrl = 0x30b9908; + u32 signal[3]; int i; /* Global registers init */ @@ -1176,9 +1194,28 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + /* Get sas_phy_ctrl value to deal with TX FFE issue. */ + if (!device_property_read_u32_array(dev, "hisilicon,signal-attenuation", + signal, ARRAY_SIZE(signal))) { + for (i = 0; i < ARRAY_SIZE(sig_atten_lu); i++) { + const struct sig_atten_lu_s *lookup = &sig_atten_lu[i]; + const struct signal_attenuation_s *att = lookup->att; + + if ((signal[0] == att->de_emphasis) && + (signal[1] == att->preshoot) && + (signal[2] == att->boost)) { + sas_phy_ctrl = lookup->sas_phy_ctrl; + break; + } + } + + if (i == ARRAY_SIZE(sig_atten_lu)) + dev_warn(dev, "unknown signal attenuation values, using default PHY ctrl config\n"); + } + for (i = 0; i < hisi_hba->n_phy; i++) { hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); - hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908); + hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl); hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d); hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0); hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2); From eba8c20c7178af9673ad842b0f68251c891c8546 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:07 +0800 Subject: [PATCH 111/168] scsi: hisi_sas: fix the issue of link rate inconsistency In sysfs, there are two files about minimum linkrate, and also two files for maximum linkrate. Take maximum linkrate example, maximum_linkrate_hw is read-only and indicated by the register HARD_PHY_LINKRATE, and maximum_linkrate is read-write and corresponding to the register PROG_PHY_LINK_RATE. But in the function phy_up_v*_hw(), we get *_linkrate value from HARD_PHY_LINKRATE. It is not right. This patch is to fix this issue. Unreferenced PHY-interrupt enum is also removed for v3 hw. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 ++ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 +------- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 13 +------------ 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 2d4dbed03ee3..9d163729ff43 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -683,6 +683,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) phy->hisi_hba = hisi_hba; phy->port = NULL; + phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; + phy->maximum_linkrate = hisi_hba->hw->phy_get_max_linkrate(); sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0; sas_phy->class = SAS; sas_phy->iproto = SAS_PROTOCOL_ALL; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 679e76f58a0a..38bbda938bc1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -873,7 +873,6 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no, sas_phy->phy->maximum_linkrate = max; sas_phy->phy->minimum_linkrate = min; - min -= SAS_LINK_RATE_1_5_GBPS; max -= SAS_LINK_RATE_1_5_GBPS; for (i = 0; i <= max; i++) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 42b3fd6a9936..67be346db239 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1603,7 +1603,6 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no, sas_phy->phy->maximum_linkrate = max; sas_phy->phy->minimum_linkrate = min; - min -= SAS_LINK_RATE_1_5_GBPS; max -= SAS_LINK_RATE_1_5_GBPS; for (i = 0; i <= max; i++) @@ -2684,7 +2683,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba, static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) { int i, res = IRQ_HANDLED; - u32 port_id, link_rate, hard_phy_linkrate; + u32 port_id, link_rate; struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct device *dev = hisi_hba->dev; @@ -2723,11 +2722,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) } sas_phy->linkrate = link_rate; - hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, - HARD_PHY_LINKRATE); - phy->maximum_linkrate = hard_phy_linkrate & 0xf; - phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; - sas_phy->oob_mode = SAS_OOB_MODE; memcpy(sas_phy->attached_sas_addr, &id->sas_addr, SAS_ADDR_SIZE); dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a1f18689729a..1ee95abda1c5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -340,12 +340,6 @@ struct hisi_sas_err_record_v3 { #define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096 #define HISI_SAS_MSI_COUNT_V3_HW 32 -enum { - HISI_SAS_PHY_PHY_UPDOWN, - HISI_SAS_PHY_CHNL_INT, - HISI_SAS_PHY_INT_NR -}; - #define DIR_NO_DATA 0 #define DIR_TO_INI 1 #define DIR_TO_DEVICE 2 @@ -1121,7 +1115,7 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba, static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { int i, res = 0; - u32 context, port_id, link_rate, hard_phy_linkrate; + u32 context, port_id, link_rate; struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct device *dev = hisi_hba->dev; @@ -1139,10 +1133,6 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) goto end; } sas_phy->linkrate = link_rate; - hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, - HARD_PHY_LINKRATE); - phy->maximum_linkrate = hard_phy_linkrate & 0xf; - phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); /* Check for SATA dev */ @@ -1864,7 +1854,6 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no, sas_phy->phy->maximum_linkrate = max; sas_phy->phy->minimum_linkrate = min; - min -= SAS_LINK_RATE_1_5_GBPS; max -= SAS_LINK_RATE_1_5_GBPS; for (i = 0; i <= max; i++) From 0006ce29e87ba357f64ee73e92c8aefc270fd315 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:08 +0800 Subject: [PATCH 112/168] scsi: hisi_sas: fix the issue of setting linkrate register It is not right to set the register PROG_PHY_LINK_RATE while PHY is still enabled. So if we want to change PHY linkrate, we need to disable PHY before setting the register PROG_PHY_LINK_RATE, and then start-up PHY. This patch is to fix this issue. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 5 +++-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 +++-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 38bbda938bc1..2eb89806c512 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -881,10 +881,11 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v1_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v1_hw(hisi_hba, phy_no); + start_phy_v1_hw(hisi_hba, phy_no); } static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 67be346db239..bd1a48a590bc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1611,10 +1611,11 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v2_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v2_hw(hisi_hba, phy_no); + start_phy_v2_hw(hisi_hba, phy_no); } static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 1ee95abda1c5..8da9de7d67e5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1862,10 +1862,11 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v3_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v3_hw(hisi_hba, phy_no); + start_phy_v3_hw(hisi_hba, phy_no); } static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba) From bb9abc4af5449d2a72cda876be950988e8b2b888 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:09 +0800 Subject: [PATCH 113/168] scsi: hisi_sas: increase timer expire of internal abort task The current 110ms expiry time is not long enough for the internal abort task. The reason is that the internal abort task could be blocked in HW if the HW is retrying to set up link. The internal abort task will be executed only when the retry process finished. The maximum time is 5s for the retry of setting up link. So, the timer expire should be more than 5s. This patch increases it from 110ms to 6s. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9d163729ff43..9ff87902d67a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -871,6 +871,7 @@ static void hisi_sas_tmf_timedout(struct timer_list *t) #define TASK_TIMEOUT 20 #define TASK_RETRY 3 +#define INTERNAL_ABORT_TIMEOUT 6 static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, void *parameter, u32 para_len, struct hisi_sas_tmf_task *tmf) @@ -1574,7 +1575,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, task->task_proto = device->tproto; task->task_done = hisi_sas_task_done; task->slow_task->timer.function = hisi_sas_tmf_timedout; - task->slow_task->timer.expires = jiffies + msecs_to_jiffies(110); + task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT*HZ; add_timer(&task->slow_task->timer); res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, From 36996a1e6dff4e5835faeb00ba920ccb9a07aa52 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Wed, 7 Mar 2018 20:25:10 +0800 Subject: [PATCH 114/168] scsi: hisi_sas: remove unused variable hisi_sas_devices.running_req The structure element hisi_sas_devices.running_req to count how many commands are active is in effect only ever written in the code, so remove it. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 9 --------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 --- 3 files changed, 13 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index e7fd2877c19c..d1153e8e846b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -175,7 +175,6 @@ struct hisi_sas_device { struct hisi_sas_dq *dq; struct list_head list; u64 attached_phy; - atomic64_t running_req; enum sas_device_type dev_type; int device_id; int sata_idx; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9ff87902d67a..88ad8d42ef6f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -200,8 +200,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, if (task) { struct device *dev = hisi_hba->dev; - struct domain_device *device = task->dev; - struct hisi_sas_device *sas_dev = device->lldd_dev; if (!task->lldd_task) return; @@ -213,9 +211,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, dma_unmap_sg(dev, task->scatter, task->num_scatter, task->data_dir); - - if (sas_dev) - atomic64_dec(&sas_dev->running_req); } if (slot->buf) @@ -431,8 +426,6 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq spin_unlock_irqrestore(&task->task_state_lock, flags); dq->slot_prep = slot; - - atomic64_inc(&sas_dev->running_req); ++(*pass); return 0; @@ -1517,8 +1510,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, dq->slot_prep = slot; - atomic64_inc(&sas_dev->running_req); - /* send abort command to the chip */ hisi_hba->hw->start_delivery(dq); spin_unlock_irqrestore(&dq->lock, flags_dq); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 2eb89806c512..8dd0e6a6ff8a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1407,9 +1407,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, } out: - if (sas_dev) - atomic64_dec(&sas_dev->running_req); - hisi_sas_slot_task_free(hisi_hba, task, slot); sts = ts->stat; From 6bf6db518cd10ad57e659607d0abece1b81956c6 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:11 +0800 Subject: [PATCH 115/168] scsi: hisi_sas: fix return value of hisi_sas_task_prep() It is an implicit regulation that error code that function returned should be negative. But hisi_sas_task_prep() doesn't follow this. This may cause problems in the upper layer code. For example, in sas_expander.c of libsas, smp_execute_task_sg() may return the number of bytes of underrun. It will be conflicted with the scenaio lldd_execute_task() return an positive error code. This patch change the return value from SAS_PHY_DOWN to -ECOMM in hisi_sas_task_prep(). Signed-off-by: Xiaofei Tan Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 88ad8d42ef6f..dff972393086 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -316,7 +316,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq */ if (device->dev_type != SAS_SATA_DEV) task->task_done(task); - return SAS_PHY_DOWN; + return -ECOMM; } if (DEV_IS_GONE(sas_dev)) { @@ -327,7 +327,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq dev_info(dev, "task prep: device %016llx not ready\n", SAS_ADDR(device->sas_addr)); - return SAS_PHY_DOWN; + return -ECOMM; } port = to_hisi_sas_port(sas_port); @@ -337,7 +337,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq "SATA/STP" : "SAS", device->port->id); - return SAS_PHY_DOWN; + return -ECOMM; } if (!sas_protocol_ata(task->task_proto)) { From edafeef4f28ded4ea9ba7876cc35861d43c7b2b1 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Wed, 7 Mar 2018 20:25:12 +0800 Subject: [PATCH 116/168] scsi: hisi_sas: Code cleanup and minor bug fixes The patch does some code cleanup and fixes some small bugs: - Correct return status of phy_up_v3_hw() and phy_bcast_v3_hw() - Add static for function phy_get_max_linkrate_v3_hw() - Change exception return status when no reset method - Change magic value to ts->stat in slot_complete_vx_hw() - Remove unnecessary check for dev_is_sata() - Fix some issues of alignment and indents (Authored by Xiaofei Tan in another patch, but added here to be practical) Signed-off-by: Xiaofei Tan Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 14 ++++++------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +++- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 +++++---- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 ++++++++++++++++---------- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index dff972393086..49c1fa643803 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -33,7 +33,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_FPDMA_RECV: case ATA_CMD_FPDMA_SEND: case ATA_CMD_NCQ_NON_DATA: - return HISI_SAS_SATA_PROTOCOL_FPDMA; + return HISI_SAS_SATA_PROTOCOL_FPDMA; case ATA_CMD_DOWNLOAD_MICRO: case ATA_CMD_ID_ATA: @@ -45,7 +45,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_WRITE_LOG_EXT: case ATA_CMD_PIO_WRITE: case ATA_CMD_PIO_WRITE_EXT: - return HISI_SAS_SATA_PROTOCOL_PIO; + return HISI_SAS_SATA_PROTOCOL_PIO; case ATA_CMD_DSM: case ATA_CMD_DOWNLOAD_MICRO_DMA: @@ -64,7 +64,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_WRITE_LOG_DMA_EXT: case ATA_CMD_WRITE_STREAM_DMA_EXT: case ATA_CMD_ZAC_MGMT_IN: - return HISI_SAS_SATA_PROTOCOL_DMA; + return HISI_SAS_SATA_PROTOCOL_DMA; case ATA_CMD_CHK_POWER: case ATA_CMD_DEV_RESET: @@ -77,21 +77,21 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_STANDBY: case ATA_CMD_STANDBYNOW1: case ATA_CMD_ZAC_MGMT_OUT: - return HISI_SAS_SATA_PROTOCOL_NONDATA; + return HISI_SAS_SATA_PROTOCOL_NONDATA; default: { if (fis->command == ATA_CMD_SET_MAX) { switch (fis->features) { case ATA_SET_MAX_PASSWD: case ATA_SET_MAX_LOCK: - return HISI_SAS_SATA_PROTOCOL_PIO; + return HISI_SAS_SATA_PROTOCOL_PIO; case ATA_SET_MAX_PASSWD_DMA: case ATA_SET_MAX_UNLOCK_DMA: - return HISI_SAS_SATA_PROTOCOL_DMA; + return HISI_SAS_SATA_PROTOCOL_DMA; default: - return HISI_SAS_SATA_PROTOCOL_NONDATA; + return HISI_SAS_SATA_PROTOCOL_NONDATA; } } if (direction == DMA_NONE) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 8dd0e6a6ff8a..84a0ccc4daf5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -651,8 +651,10 @@ static int reset_hw_v1_hw(struct hisi_hba *hisi_hba) dev_err(dev, "De-reset failed\n"); return -EIO; } - } else + } else { dev_warn(dev, "no reset method\n"); + return -EINVAL; + } return 0; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index bd1a48a590bc..f89fb9a49ea9 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1095,8 +1095,10 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "SAS de-reset fail.\n"); return -EIO; } - } else - dev_warn(dev, "no reset method\n"); + } else { + dev_err(dev, "no reset method\n"); + return -EINVAL; + } return 0; } @@ -2408,7 +2410,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_task_free(hisi_hba, task, slot); spin_unlock_irqrestore(&hisi_hba->lock, flags); - return -1; + return ts->stat; } if (unlikely(!sas_dev)) { @@ -2667,7 +2669,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba, /* dw0 */ hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/ (port->id << CMD_HDR_PORT_OFF) | - ((dev_is_sata(dev) ? 1:0) << + (dev_is_sata(dev) << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | (abort_flag << CMD_HDR_ABORT_FLAG_OFF)); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8da9de7d67e5..4023fcbc3f04 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -670,8 +670,10 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba) dev_err(dev, "Reset failed\n"); return -EIO; } - } else + } else { dev_err(dev, "no reset method!\n"); + return -EINVAL; + } return 0; } @@ -731,7 +733,7 @@ static void phy_hard_reset_v3_hw(struct hisi_hba *hisi_hba, int phy_no) start_phy_v3_hw(hisi_hba, phy_no); } -enum sas_linkrate phy_get_max_linkrate_v3_hw(void) +static enum sas_linkrate phy_get_max_linkrate_v3_hw(void) { return SAS_LINK_RATE_12_0_GBPS; } @@ -1096,7 +1098,7 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba, /* dw0 */ hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/ (port->id << CMD_HDR_PORT_OFF) | - ((dev_is_sata(dev) ? 1:0) + (dev_is_sata(dev) << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | (abort_flag << CMD_HDR_ABORT_FLAG_OFF)); @@ -1112,9 +1114,9 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba, return 0; } -static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { - int i, res = 0; + int i, res; u32 context, port_id, link_rate; struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; @@ -1186,7 +1188,7 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) phy->port_id = port_id; phy->phy_attached = 1; hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); - + res = IRQ_HANDLED; end: hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_PHY_ENABLE_MSK); @@ -1195,7 +1197,7 @@ end: return res; } -static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { u32 phy_state, sl_ctrl, txid_auto; struct device *dev = hisi_hba->dev; @@ -1217,10 +1219,10 @@ static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0); - return 0; + return IRQ_HANDLED; } -static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; @@ -1231,6 +1233,8 @@ static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_RX_BCST_ACK_MSK); hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); + + return IRQ_HANDLED; } static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p) @@ -1257,7 +1261,9 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p) res = IRQ_HANDLED; if (irq_value & CHL_INT0_SL_RX_BCST_ACK_MSK) /* phy bcast */ - phy_bcast_v3_hw(phy_no, hisi_hba); + if (phy_bcast_v3_hw(phy_no, hisi_hba) + == IRQ_HANDLED) + res = IRQ_HANDLED; } else { if (irq_value & CHL_INT0_NOT_RDY_MSK) /* phy down */ @@ -1573,7 +1579,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_task_free(hisi_hba, task, slot); spin_unlock_irqrestore(&hisi_hba->lock, flags); - return -1; + return ts->stat; } if (unlikely(!sas_dev)) { From 15c38e31c47c0f2cd7e959054258714991a6a2d6 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 7 Mar 2018 20:25:13 +0800 Subject: [PATCH 117/168] scsi: hisi_sas: modify some register config for hip08 Do some modifications for register configuring for hip08. In future, to reduce kernel churn with patches to modify registers, any registers which may change between board models (mostly PHY/SERDES related) should be set in ACPI reset handler. Signed-off-by: Xiaofei Tan Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 4023fcbc3f04..5ce5ef2caabe 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -172,6 +172,7 @@ #define CHL_INT1_MSK (PORT_BASE + 0x1c4) #define CHL_INT2_MSK (PORT_BASE + 0x1c8) #define CHL_INT_COAL_EN (PORT_BASE + 0x1d0) +#define SAS_RX_TRAIN_TIMER (PORT_BASE + 0x2a4) #define PHY_CTRL_RDY_MSK (PORT_BASE + 0x2b0) #define PHYCTRL_NOT_RDY_MSK (PORT_BASE + 0x2b4) #define PHYCTRL_DWS_RESET_MSK (PORT_BASE + 0x2b8) @@ -184,6 +185,8 @@ #define DMA_RX_STATUS (PORT_BASE + 0x2e8) #define DMA_RX_STATUS_BUSY_OFF 0 #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF) + +#define COARSETUNE_TIME (PORT_BASE + 0x304) #define ERR_CNT_DWS_LOST (PORT_BASE + 0x380) #define ERR_CNT_RESET_PROB (PORT_BASE + 0x384) #define ERR_CNT_INVLD_DW (PORT_BASE + 0x390) @@ -417,10 +420,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); - hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE, 0x30000); for (i = 0; i < hisi_hba->n_phy; i++) { - hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x801); + hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); + hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80); hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff); @@ -432,17 +435,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0); - hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199b4fa); - hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, - 0xa03e8); - hisi_sas_phy_write32(hisi_hba, i, SAS_STP_CON_TIMER_CFG, - 0xa03e8); - hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, - 0x7f7a120); - hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, - 0x2a0a80); + hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1); + hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120); + + /* used for 12G negotiate */ + hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); } + for (i = 0; i < hisi_hba->queue_count; i++) { /* Delivery queue */ hisi_sas_write32(hisi_hba, From 40ec66b1bf4352315025b821f7a5aead3d8ea645 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Wed, 7 Mar 2018 20:25:14 +0800 Subject: [PATCH 118/168] scsi: hisi_sas: add v3 hw MODULE_DEVICE_TABLE() Export device table of v3 hw to userspace, or auto probe will fail for v3 hw. Also change the module alias to include "pci", instead of "platform". Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 5ce5ef2caabe..6f3e5ba6b472 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2394,6 +2394,7 @@ static const struct pci_device_id sas_v3_pci_table[] = { { PCI_VDEVICE(HUAWEI, 0xa230), hip08 }, {} }; +MODULE_DEVICE_TABLE(pci, sas_v3_pci_table); static const struct pci_error_handlers hisi_sas_err_handler = { .error_detected = hisi_sas_error_detected_v3_hw, @@ -2416,4 +2417,4 @@ module_pci_driver(sas_v3_pci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Garry "); MODULE_DESCRIPTION("HISILICON SAS controller v3 hw driver based on pci device"); -MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS("pci:" DRV_NAME); From e32ec6579f5b3134cb27cc063c17da0bb8cd29c7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 7 Mar 2018 17:56:41 +1100 Subject: [PATCH 119/168] scsi: jazz_esp, sun3x_esp: Pass struct device pointer in dma calls In jazz_esp and sun3x_esp, the esp_driver_ops methods pass esp->dev in dma api calls as if it was a pointer to a struct device. But it actually points to a struct platform_device. Fix this. Cc: Thomas Bogendoerfer Signed-off-by: Finn Thain Reviewed-by: Thomas Bogendoerfer Signed-off-by: Martin K. Petersen --- drivers/scsi/jazz_esp.c | 2 +- drivers/scsi/sun3x_esp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index 9aaa74e349cc..6eb5ff3e2e61 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -147,7 +147,7 @@ static int esp_jazz_probe(struct platform_device *dev) esp = shost_priv(host); esp->host = host; - esp->dev = dev; + esp->dev = &dev->dev; esp->ops = &jazz_esp_ops; res = platform_get_resource(dev, IORESOURCE_MEM, 0); diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index d50c5ed8f428..0b1421cdf8a0 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -210,7 +210,7 @@ static int esp_sun3x_probe(struct platform_device *dev) esp = shost_priv(host); esp->host = host; - esp->dev = dev; + esp->dev = &dev->dev; esp->ops = &sun3x_esp_ops; res = platform_get_resource(dev, IORESOURCE_MEM, 0); From 92eb506262a2a3da9aeaece7017e77490da907dd Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Fri, 9 Mar 2018 23:32:11 +0100 Subject: [PATCH 120/168] scsi: device_handler: remove VLAs In preparation to enabling -Wvla, remove VLAs and replace them with fixed-length arrays instead. scsi_dh_{alua,emc,rdac} use variable-length array declarations to store command blocks, with the appropriate size as determined by COMMAND_SIZE. This patch replaces these with fixed-sized arrays using MAX_COMMAND_SIZE, so that the array size can be determined at compile time. This was prompted by https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Stephen Kitt Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 8 ++++---- drivers/scsi/device_handler/scsi_dh_emc.c | 2 +- drivers/scsi/device_handler/scsi_dh_rdac.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 022e421c2185..c3483d811824 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -138,12 +138,12 @@ static void release_port_group(struct kref *kref) static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff, int bufflen, struct scsi_sense_hdr *sshdr, int flags) { - u8 cdb[COMMAND_SIZE(MAINTENANCE_IN)]; + u8 cdb[MAX_COMMAND_SIZE]; int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER; /* Prepare the command. */ - memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_IN)); + memset(cdb, 0x0, MAX_COMMAND_SIZE); cdb[0] = MAINTENANCE_IN; if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP)) cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; @@ -166,7 +166,7 @@ static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff, static int submit_stpg(struct scsi_device *sdev, int group_id, struct scsi_sense_hdr *sshdr) { - u8 cdb[COMMAND_SIZE(MAINTENANCE_OUT)]; + u8 cdb[MAX_COMMAND_SIZE]; unsigned char stpg_data[8]; int stpg_len = 8; int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | @@ -178,7 +178,7 @@ static int submit_stpg(struct scsi_device *sdev, int group_id, put_unaligned_be16(group_id, &stpg_data[6]); /* Prepare the command. */ - memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_OUT)); + memset(cdb, 0x0, MAX_COMMAND_SIZE); cdb[0] = MAINTENANCE_OUT; cdb[1] = MO_SET_TARGET_PGS; put_unaligned_be32(stpg_len, &cdb[6]); diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6a2792f3a37e..95c47909a58f 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -249,7 +249,7 @@ static int send_trespass_cmd(struct scsi_device *sdev, struct clariion_dh_data *csdev) { unsigned char *page22; - unsigned char cdb[COMMAND_SIZE(MODE_SELECT)]; + unsigned char cdb[MAX_COMMAND_SIZE]; int err, res = SCSI_DH_OK, len; struct scsi_sense_hdr sshdr; u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 7af31a1247ee..d27fabae8ddd 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -533,7 +533,7 @@ static void send_mode_select(struct work_struct *work) int err = SCSI_DH_OK, retry_cnt = RDAC_RETRY_COUNT; struct rdac_queue_data *tmp, *qdata; LIST_HEAD(list); - unsigned char cdb[COMMAND_SIZE(MODE_SELECT_10)]; + unsigned char cdb[MAX_COMMAND_SIZE]; struct scsi_sense_hdr sshdr; unsigned int data_size; u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | From fab2e466e9dfe47371b54a54b86f6630feced80e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 13 Mar 2018 12:08:49 +0000 Subject: [PATCH 121/168] scsi: lpfc: make several unions static, fix non-ANSI prototype There are several unions that are local to the source and do not need to be in global scope, so make them static. Also add in a missing void parameter to functions lpfc_nvme_cmd_template and lpfc_nvmet_cmd_template to clean up non-ANSI warning. Cleans up sparse warnings: drivers/scsi/lpfc/lpfc_nvme.c:68:19: warning: symbol 'lpfc_iread_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvme.c:69:19: warning: symbol 'lpfc_iwrite_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvme.c:70:19: warning: symbol 'lpfc_icmnd_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvme.c:74:24: warning: non-ANSI function 'lpfc_tsend_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvmet.c:78:19: warning: symbol 'lpfc_treceive_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvmet.c:79:19: warning: symbol 'lpfc_trsp_cmd_template' was not declared. Should it be static? drivers/scsi/lpfc/lpfc_nvmet.c:83:25: warning: non-ANSI function declaration of function 'lpfc_nvmet_cmd_template' Signed-off-by: Colin Ian King Acked-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 8 ++++---- drivers/scsi/lpfc/lpfc_nvmet.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 52dd9479b538..378dca40ca20 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -65,13 +65,13 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_nvme_buf *); static struct nvme_fc_port_template lpfc_nvme_template; -union lpfc_wqe128 lpfc_iread_cmd_template; -union lpfc_wqe128 lpfc_iwrite_cmd_template; -union lpfc_wqe128 lpfc_icmnd_cmd_template; +static union lpfc_wqe128 lpfc_iread_cmd_template; +static union lpfc_wqe128 lpfc_iwrite_cmd_template; +static union lpfc_wqe128 lpfc_icmnd_cmd_template; /* Setup WQE templates for NVME IOs */ void -lpfc_nvme_cmd_template() +lpfc_nvme_cmd_template(void) { union lpfc_wqe128 *wqe; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 07f89524c320..7271c9d885dd 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -74,13 +74,13 @@ static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *, static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_nvmet_rcv_ctx *); -union lpfc_wqe128 lpfc_tsend_cmd_template; -union lpfc_wqe128 lpfc_treceive_cmd_template; -union lpfc_wqe128 lpfc_trsp_cmd_template; +static union lpfc_wqe128 lpfc_tsend_cmd_template; +static union lpfc_wqe128 lpfc_treceive_cmd_template; +static union lpfc_wqe128 lpfc_trsp_cmd_template; /* Setup WQE templates for NVME IOs */ void -lpfc_nvmet_cmd_template() +lpfc_nvmet_cmd_template(void) { union lpfc_wqe128 *wqe; From 6b1745caa14ae0afccf1c6ee4c814fd8d5df3dcd Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 13 Mar 2018 15:06:22 -0400 Subject: [PATCH 122/168] scsi: eata: eata-pio: Deprecate legacy EATA drivers These two drivers do not appear to be in active use. Deprecate them. Suggested-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 2 - MAINTAINERS | 6 - drivers/scsi/Kconfig | 62 - drivers/scsi/Makefile | 2 - drivers/scsi/eata.c | 2571 ------------------------ drivers/scsi/eata_generic.h | 401 ---- drivers/scsi/eata_pio.c | 966 --------- drivers/scsi/eata_pio.h | 54 - 8 files changed, 4064 deletions(-) delete mode 100644 drivers/scsi/eata.c delete mode 100644 drivers/scsi/eata_generic.h delete mode 100644 drivers/scsi/eata_pio.c delete mode 100644 drivers/scsi/eata_pio.h diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 453d4b79c78d..8f7be8a05642 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -34,8 +34,6 @@ parameters may be changed at runtime by the command See drivers/scsi/BusLogic.c, comment before function BusLogic_ParseDriverOptions(). - eata= [HW,SCSI] - fdomain= [HW,SCSI] See header of drivers/scsi/fdomain.c. diff --git a/MAINTAINERS b/MAINTAINERS index 3bdc260e36b7..36eb73238cf5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5003,12 +5003,6 @@ T: git git://linuxtv.org/anttip/media_tree.git S: Maintained F: drivers/media/tuners/e4000* -EATA ISA/EISA/PCI SCSI DRIVER -M: Dario Ballabio -L: linux-scsi@vger.kernel.org -S: Maintained -F: drivers/scsi/eata.c - EC100 MEDIA DRIVER M: Antti Palosaari L: linux-media@vger.kernel.org diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8647ca9199b3..b18dfa1c14a1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -640,68 +640,6 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. -config SCSI_EATA - tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" - depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API - ---help--- - This driver supports all EATA/DMA-compliant SCSI host adapters. DPT - ISA and all EISA I/O addresses are probed looking for the "EATA" - signature. The addresses of all the PCI SCSI controllers reported - by the PCI subsystem are probed as well. - - You want to read the start of and the - SCSI-HOWTO, available from - . - - To compile this driver as a module, choose M here: the - module will be called eata. - -config SCSI_EATA_TAGGED_QUEUE - bool "enable tagged command queueing" - depends on SCSI_EATA - help - This is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. - This is equivalent to the "eata=tc:y" boot option. - -config SCSI_EATA_LINKED_COMMANDS - bool "enable elevator sorting" - depends on SCSI_EATA - help - This option enables elevator sorting for all probed SCSI disks and - CD-ROMs. It definitely reduces the average seek distance when doing - random seeks, but this does not necessarily result in a noticeable - performance improvement: your mileage may vary... - This is equivalent to the "eata=lc:y" boot option. - -config SCSI_EATA_MAX_TAGS - int "maximum number of queued commands" - depends on SCSI_EATA - default "16" - help - This specifies how many SCSI commands can be maximally queued for - each probed SCSI device. You should reduce the default value of 16 - only if you have disks with buggy or limited tagged command support. - Minimum is 2 and maximum is 62. This value is also the window size - used by the elevator sorting option above. The effective value used - by the driver for each probed SCSI device is reported at boot time. - This is equivalent to the "eata=mq:8" boot option. - -config SCSI_EATA_PIO - tristate "EATA-PIO (old DPT PM2001, PM2012A) support" - depends on (ISA || EISA || PCI) && SCSI && BROKEN - ---help--- - This driver supports all EATA-PIO protocol compliant SCSI Host - Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant - host adapters could also use this driver but are discouraged from - doing so, since this driver only supports hard disks and lacks - numerous features. You might want to have a look at the SCSI-HOWTO, - available from . - - To compile this driver as a module, choose M here: the - module will be called eata_pio. - config SCSI_FUTURE_DOMAIN tristate "Future Domain 16xx SCSI/AHA-2920A support" depends on (ISA || PCI) && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index fcfd28d2884c..46f1c1033f0e 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -93,8 +93,6 @@ obj-$(CONFIG_SCSI_HPSA) += hpsa.o obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o -obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o -obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o obj-$(CONFIG_CXLFLASH) += cxlflash/ diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c deleted file mode 100644 index 6501c330d8c8..000000000000 --- a/drivers/scsi/eata.c +++ /dev/null @@ -1,2571 +0,0 @@ -/* - * eata.c - Low-level driver for EATA/DMA SCSI host adapters. - * - * 03 Jun 2003 Rev. 8.10 for linux-2.5.70 - * + Update for new IRQ API. - * + Use "goto" when appropriate. - * + Drop eata.h. - * + Update for new module_param API. - * + Module parameters can now be specified only in the - * same format as the kernel boot options. - * - * boot option old module param - * ----------- ------------------ - * addr,... io_port=addr,... - * lc:[y|n] linked_comm=[1|0] - * mq:xx max_queue_depth=xx - * tm:[0|1|2] tag_mode=[0|1|2] - * et:[y|n] ext_tran=[1|0] - * rs:[y|n] rev_scan=[1|0] - * ip:[y|n] isa_probe=[1|0] - * ep:[y|n] eisa_probe=[1|0] - * pp:[y|n] pci_probe=[1|0] - * - * A valid example using the new parameter format is: - * modprobe eata "eata=0x7410,0x230,lc:y,tm:0,mq:4,ep:n" - * - * which is equivalent to the old format: - * modprobe eata io_port=0x7410,0x230 linked_comm=1 tag_mode=0 \ - * max_queue_depth=4 eisa_probe=0 - * - * 12 Feb 2003 Rev. 8.04 for linux 2.5.60 - * + Release irq before calling scsi_register. - * - * 12 Nov 2002 Rev. 8.02 for linux 2.5.47 - * + Release driver_lock before calling scsi_register. - * - * 11 Nov 2002 Rev. 8.01 for linux 2.5.47 - * + Fixed bios_param and scsicam_bios_param calling parameters. - * - * 28 Oct 2002 Rev. 8.00 for linux 2.5.44-ac4 - * + Use new tcq and adjust_queue_depth api. - * + New command line option (tm:[0-2]) to choose the type of tags: - * 0 -> disable tagging ; 1 -> simple tags ; 2 -> ordered tags. - * Default is tm:0 (tagged commands disabled). - * For compatibility the "tc:" option is an alias of the "tm:" - * option; tc:n is equivalent to tm:0 and tc:y is equivalent to - * tm:1. - * + The tagged_comm module parameter has been removed, use tag_mode - * instead, equivalent to the "tm:" boot option. - * - * 10 Oct 2002 Rev. 7.70 for linux 2.5.42 - * + Foreport from revision 6.70. - * - * 25 Jun 2002 Rev. 6.70 for linux 2.4.19 - * + This release is the first one tested on a Big Endian platform: - * fixed endian-ness problem due to bitfields; - * fixed endian-ness problem in read_pio. - * + Added new options for selectively probing ISA, EISA and PCI bus: - * - * Boot option Parameter name Default according to - * - * ip:[y|n] isa_probe=[1|0] CONFIG_ISA defined - * ep:[y|n] eisa_probe=[1|0] CONFIG_EISA defined - * pp:[y|n] pci_probe=[1|0] CONFIG_PCI defined - * - * The default action is to perform probing if the corresponding - * bus is configured and to skip probing otherwise. - * - * + If pci_probe is in effect and a list of I/O ports is specified - * as parameter or boot option, pci_enable_device() is performed - * on all pci devices matching PCI_CLASS_STORAGE_SCSI. - * - * 21 Feb 2002 Rev. 6.52 for linux 2.4.18 - * + Backport from rev. 7.22 (use io_request_lock). - * - * 20 Feb 2002 Rev. 7.22 for linux 2.5.5 - * + Remove any reference to virt_to_bus(). - * + Fix pio hang while detecting multiple HBAs. - * + Fixed a board detection bug: in a system with - * multiple ISA/EISA boards, all but the first one - * were erroneously detected as PCI. - * - * 01 Jan 2002 Rev. 7.20 for linux 2.5.1 - * + Use the dynamic DMA mapping API. - * - * 19 Dec 2001 Rev. 7.02 for linux 2.5.1 - * + Use SCpnt->sc_data_direction if set. - * + Use sglist.page instead of sglist.address. - * - * 11 Dec 2001 Rev. 7.00 for linux 2.5.1 - * + Use host->host_lock instead of io_request_lock. - * - * 1 May 2001 Rev. 6.05 for linux 2.4.4 - * + Clean up all pci related routines. - * + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d) - * - * 30 Jan 2001 Rev. 6.04 for linux 2.4.1 - * + Call pci_resource_start after pci_enable_device. - * - * 25 Jan 2001 Rev. 6.03 for linux 2.4.0 - * + "check_region" call replaced by "request_region". - * - * 22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11 - * + Return code checked when calling pci_enable_device. - * + Removed old scsi error handling support. - * + The obsolete boot option flag eh:n is silently ignored. - * + Removed error messages while a disk drive is powered up at - * boot time. - * + Improved boot messages: all tagged capable device are - * indicated as "tagged" or "soft-tagged" : - * - "soft-tagged" means that the driver is trying to do its - * own tagging (i.e. the tc:y option is in effect); - * - "tagged" means that the device supports tagged commands, - * but the driver lets the HBA be responsible for tagging - * support. - * - * 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18 - * + Updated to the new __setup interface for boot command line options. - * + When loaded as a module, accepts the new parameter boot_options - * which value is a string with the same format of the kernel boot - * command line options. A valid example is: - * modprobe eata 'boot_options="0x7410,0x230,lc:y,tc:n,mq:4"' - * - * 9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17 - * + 64bit cleanup for Linux/Alpha platform support - * (contribution from H.J. Lu). - * - * 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11 - * + Removed pre-2.2 source code compatibility. - * + Added call to pci_set_master. - * - * 26 Jul 1998 Rev. 4.33 for linux 2.0.35 and 2.1.111 - * + Added command line option (rs:[y|n]) to reverse the scan order - * of PCI boards. The default is rs:y, which reverses the BIOS order - * while registering PCI boards. The default value rs:y generates - * the same order of all previous revisions of this driver. - * Pls. note that "BIOS order" might have been reversed itself - * after the 2.1.9x PCI modifications in the linux kernel. - * The rs value is ignored when the explicit list of addresses - * is used by the "eata=port0,port1,..." command line option. - * + Added command line option (et:[y|n]) to force use of extended - * translation (255 heads, 63 sectors) as disk geometry. - * The default is et:n, which uses the disk geometry returned - * by scsicam_bios_param. The default value et:n is compatible with - * all previous revisions of this driver. - * - * 28 May 1998 Rev. 4.32 for linux 2.0.33 and 2.1.104 - * Increased busy timeout from 10 msec. to 200 msec. while - * processing interrupts. - * - * 16 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102 - * Improved abort handling during the eh recovery process. - * - * 13 May 1998 Rev. 4.30 for linux 2.0.33 and 2.1.101 - * The driver is now fully SMP safe, including the - * abort and reset routines. - * Added command line options (eh:[y|n]) to choose between - * new_eh_code and the old scsi code. - * If linux version >= 2.1.101 the default is eh:y, while the eh - * option is ignored for previous releases and the old scsi code - * is used. - * - * 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97 - * Reworked interrupt handler. - * - * 11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95 - * Major reliability improvement: when a batch with overlapping - * requests is detected, requests are queued one at a time - * eliminating any possible board or drive reordering. - * - * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 - * Improved SMP support (if linux version >= 2.1.95). - * - * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94 - * Added support for new PCI code and IO-APIC remapping of irqs. - * Performance improvement: when sequential i/o is detected, - * always use direct sort instead of reverse sort. - * - * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 - * io_port is now unsigned long. - * - * 17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88 - * Use new scsi error handling code (if linux version >= 2.1.88). - * Use new interrupt code. - * - * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 - * Use of udelay inside the wait loops to avoid timeout - * problems with fast cpus. - * Removed check about useless calls to the interrupt service - * routine (reported on SMP systems only). - * At initialization time "sorted/unsorted" is displayed instead - * of "linked/unlinked" to reinforce the fact that "linking" is - * nothing but "elevator sorting" in the actual implementation. - * - * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 - * Use of serial_number_at_timeout in abort and reset processing. - * Use of the __initfunc and __initdata macro in setup code. - * Minor cleanups in the list_statistics code. - * Increased controller busy timeout in order to better support - * slow SCSI devices. - * - * 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26 - * When loading as a module, parameter passing is now supported - * both in 2.0 and in 2.1 style. - * Fixed data transfer direction for some SCSI opcodes. - * Immediate acknowledge to request sense commands. - * Linked commands to each disk device are now reordered by elevator - * sorting. Rare cases in which reordering of write requests could - * cause wrong results are managed. - * Fixed spurious timeouts caused by long simple queue tag sequences. - * New command line option (tm:[0-3]) to choose the type of tags: - * 0 -> mixed (default); 1 -> simple; 2 -> head; 3 -> ordered. - * - * 18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28 - * Added command line options to enable/disable linked commands - * (lc:[y|n]), tagged commands (tc:[y|n]) and to set the max queue - * depth (mq:xx). Default is "eata=lc:n,tc:n,mq:16". - * Improved command linking. - * Documented how to setup RAID-0 with DPT SmartRAID boards. - * - * 8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27 - * Added linked command support. - * Improved detection of PCI boards using ISA base addresses. - * - * 3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27 - * Added support for tagged commands and queue depth adjustment. - * - * 22 Nov 1996 rev. 2.30 for linux 2.1.12 and 2.0.26 - * When CONFIG_PCI is defined, BIOS32 is used to include in the - * list of i/o ports to be probed all the PCI SCSI controllers. - * The list of i/o ports to be probed can be overwritten by the - * "eata=port0,port1,...." boot command line option. - * Scatter/gather lists are now allocated by a number of kmalloc - * calls, in order to avoid the previous size limit of 64Kb. - * - * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 - * Added support for EATA 2.0C, PCI, multichannel and wide SCSI. - * - * 27 Sep 1996 rev. 2.12 for linux 2.1.0 - * Portability cleanups (virtual/bus addressing, little/big endian - * support). - * - * 09 Jul 1996 rev. 2.11 for linux 2.0.4 - * Number of internal retries is now limited. - * - * 16 Apr 1996 rev. 2.10 for linux 1.3.90 - * New argument "reset_flags" to the reset routine. - * - * 6 Jul 1995 rev. 2.01 for linux 1.3.7 - * Update required by the new /proc/scsi support. - * - * 11 Mar 1995 rev. 2.00 for linux 1.2.0 - * Fixed a bug which prevented media change detection for removable - * disk drives. - * - * 23 Feb 1995 rev. 1.18 for linux 1.1.94 - * Added a check for scsi_register returning NULL. - * - * 11 Feb 1995 rev. 1.17 for linux 1.1.91 - * Now DEBUG_RESET is disabled by default. - * Register a board even if it does not assert DMA protocol support - * (DPT SK2011B does not report correctly the dmasup bit). - * - * 9 Feb 1995 rev. 1.16 for linux 1.1.90 - * Use host->wish_block instead of host->block. - * New list of Data Out SCSI commands. - * - * 8 Feb 1995 rev. 1.15 for linux 1.1.89 - * Cleared target_time_out counter while performing a reset. - * All external symbols renamed to avoid possible name conflicts. - * - * 28 Jan 1995 rev. 1.14 for linux 1.1.86 - * Added module support. - * Log and do a retry when a disk drive returns a target status - * different from zero on a recovered error. - * - * 24 Jan 1995 rev. 1.13 for linux 1.1.85 - * Use optimized board configuration, with a measured performance - * increase in the range 10%-20% on i/o throughput. - * - * 16 Jan 1995 rev. 1.12 for linux 1.1.81 - * Fix mscp structure comments (no functional change). - * Display a message if check_region detects a port address - * already in use. - * - * 17 Dec 1994 rev. 1.11 for linux 1.1.74 - * Use the scsicam_bios_param routine. This allows an easy - * migration path from disk partition tables created using - * different SCSI drivers and non optimal disk geometry. - * - * 15 Dec 1994 rev. 1.10 for linux 1.1.74 - * Added support for ISA EATA boards (DPT PM2011, DPT PM2021). - * The host->block flag is set for all the detected ISA boards. - * The detect routine no longer enforces LEVEL triggering - * for EISA boards, it just prints a warning message. - * - * 30 Nov 1994 rev. 1.09 for linux 1.1.68 - * Redo i/o on target status CHECK_CONDITION for TYPE_DISK only. - * Added optional support for using a single board at a time. - * - * 18 Nov 1994 rev. 1.08 for linux 1.1.64 - * Forces sg_tablesize = 64 and can_queue = 64 if these - * values are not correctly detected (DPT PM2012). - * - * 14 Nov 1994 rev. 1.07 for linux 1.1.63 Final BETA release. - * 04 Aug 1994 rev. 1.00 for linux 1.1.39 First BETA release. - * - * - * This driver is based on the CAM (Common Access Method Committee) - * EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol. - * - * Copyright (C) 1994-2003 Dario Ballabio (ballabio_dario@emc.com) - * - * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - */ - -/* - * - * Here is a brief description of the DPT SCSI host adapters. - * All these boards provide an EATA/DMA compatible programming interface - * and are fully supported by this driver in any configuration, including - * multiple SCSI channels: - * - * PM2011B/9X - Entry Level ISA - * PM2021A/9X - High Performance ISA - * PM2012A Old EISA - * PM2012B Old EISA - * PM2022A/9X - Entry Level EISA - * PM2122A/9X - High Performance EISA - * PM2322A/9X - Extra High Performance EISA - * PM3021 - SmartRAID Adapter for ISA - * PM3222 - SmartRAID Adapter for EISA (PM3222W is 16-bit wide SCSI) - * PM3224 - SmartRAID Adapter for PCI (PM3224W is 16-bit wide SCSI) - * PM33340UW - SmartRAID Adapter for PCI ultra wide multichannel - * - * The above list is just an indication: as a matter of fact all DPT - * boards using the EATA/DMA protocol are supported by this driver, - * since they use exactely the same programming interface. - * - * The DPT PM2001 provides only the EATA/PIO interface and hence is not - * supported by this driver. - * - * This code has been tested with up to 3 Distributed Processing Technology - * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers, - * in any combination of private and shared IRQ. - * PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS - * v003.D0, firmware v07G.0). - * - * DPT SmartRAID boards support "Hardware Array" - a group of disk drives - * which are all members of the same RAID-0, RAID-1 or RAID-5 array implemented - * in host adapter hardware. Hardware Arrays are fully compatible with this - * driver, since they look to it as a single disk drive. - * - * WARNING: to create a RAID-0 "Hardware Array" you must select "Other Unix" - * as the current OS in the DPTMGR "Initial System Installation" menu. - * Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0), - * which is not supported by the actual SCSI subsystem. - * To get the "Array Group" functionality, the Linux MD driver must be used - * instead of the DPT "Array Group" feature. - * - * Multiple ISA, EISA and PCI boards can be configured in the same system. - * It is suggested to put all the EISA boards on the same IRQ level, all - * the PCI boards on another IRQ level, while ISA boards cannot share - * interrupts. - * - * If you configure multiple boards on the same IRQ, the interrupt must - * be _level_ triggered (not _edge_ triggered). - * - * This driver detects EATA boards by probes at fixed port addresses, - * so no BIOS32 or PCI BIOS support is required. - * The suggested way to detect a generic EATA PCI board is to force on it - * any unused EISA address, even if there are other controllers on the EISA - * bus, or even if you system has no EISA bus at all. - * Do not force any ISA address on EATA PCI boards. - * - * If PCI bios support is configured into the kernel, BIOS32 is used to - * include in the list of i/o ports to be probed all the PCI SCSI controllers. - * - * Due to a DPT BIOS "feature", it might not be possible to force an EISA - * address on more than a single DPT PCI board, so in this case you have to - * let the PCI BIOS assign the addresses. - * - * The sequence of detection probes is: - * - * - ISA 0x1F0; - * - PCI SCSI controllers (only if BIOS32 is available); - * - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15); - * - ISA 0x170, 0x230, 0x330. - * - * The above list of detection probes can be totally replaced by the - * boot command line option: "eata=port0,port1,port2,...", where the - * port0, port1... arguments are ISA/EISA/PCI addresses to be probed. - * For example using "eata=0x7410,0x7450,0x230", the driver probes - * only the two PCI addresses 0x7410 and 0x7450 and the ISA address 0x230, - * in this order; "eata=0" totally disables this driver. - * - * After the optional list of detection probes, other possible command line - * options are: - * - * et:y force use of extended translation (255 heads, 63 sectors); - * et:n use disk geometry detected by scsicam_bios_param; - * rs:y reverse scan order while detecting PCI boards; - * rs:n use BIOS order while detecting PCI boards; - * lc:y enables linked commands; - * lc:n disables linked commands; - * tm:0 disables tagged commands (same as tc:n); - * tm:1 use simple queue tags (same as tc:y); - * tm:2 use ordered queue tags (same as tc:2); - * mq:xx set the max queue depth to the value xx (2 <= xx <= 32). - * - * The default value is: "eata=lc:n,mq:16,tm:0,et:n,rs:n". - * An example using the list of detection probes could be: - * "eata=0x7410,0x230,lc:y,tm:2,mq:4,et:n". - * - * When loading as a module, parameters can be specified as well. - * The above example would be (use 1 in place of y and 0 in place of n): - * - * modprobe eata io_port=0x7410,0x230 linked_comm=1 \ - * max_queue_depth=4 ext_tran=0 tag_mode=2 \ - * rev_scan=1 - * - * ---------------------------------------------------------------------------- - * In this implementation, linked commands are designed to work with any DISK - * or CD-ROM, since this linking has only the intent of clustering (time-wise) - * and reordering by elevator sorting commands directed to each device, - * without any relation with the actual SCSI protocol between the controller - * and the device. - * If Q is the queue depth reported at boot time for each device (also named - * cmds/lun) and Q > 2, whenever there is already an active command to the - * device all other commands to the same device (up to Q-1) are kept waiting - * in the elevator sorting queue. When the active command completes, the - * commands in this queue are sorted by sector address. The sort is chosen - * between increasing or decreasing by minimizing the seek distance between - * the sector of the commands just completed and the sector of the first - * command in the list to be sorted. - * Trivial math assures that the unsorted average seek distance when doing - * random seeks over S sectors is S/3. - * When (Q-1) requests are uniformly distributed over S sectors, the average - * distance between two adjacent requests is S/((Q-1) + 1), so the sorted - * average seek distance for (Q-1) random requests over S sectors is S/Q. - * The elevator sorting hence divides the seek distance by a factor Q/3. - * The above pure geometric remarks are valid in all cases and the - * driver effectively reduces the seek distance by the predicted factor - * when there are Q concurrent read i/o operations on the device, but this - * does not necessarily results in a noticeable performance improvement: - * your mileage may vary.... - * - * Note: command reordering inside a batch of queued commands could cause - * wrong results only if there is at least one write request and the - * intersection (sector-wise) of all requests is not empty. - * When the driver detects a batch including overlapping requests - * (a really rare event) strict serial (pid) order is enforced. - * ---------------------------------------------------------------------------- - * The extended translation option (et:y) is useful when using large physical - * disks/arrays. It could also be useful when switching between Adaptec boards - * and DPT boards without reformatting the disk. - * When a boot disk is partitioned with extended translation, in order to - * be able to boot it with a DPT board is could be necessary to add to - * lilo.conf additional commands as in the following example: - * - * fix-table - * disk=/dev/sda bios=0x80 sectors=63 heads=128 cylindres=546 - * - * where the above geometry should be replaced with the one reported at - * power up by the DPT controller. - * ---------------------------------------------------------------------------- - * - * The boards are named EATA0, EATA1,... according to the detection order. - * - * In order to support multiple ISA boards in a reliable way, - * the driver sets host->wish_block = 1 for all ISA boards. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static int eata2x_detect(struct scsi_host_template *); -static int eata2x_release(struct Scsi_Host *); -static int eata2x_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); -static int eata2x_eh_abort(struct scsi_cmnd *); -static int eata2x_eh_host_reset(struct scsi_cmnd *); -static int eata2x_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static int eata2x_slave_configure(struct scsi_device *); - -static struct scsi_host_template driver_template = { - .name = "EATA/DMA 2.0x rev. 8.10.00 ", - .detect = eata2x_detect, - .release = eata2x_release, - .queuecommand = eata2x_queuecommand, - .eh_abort_handler = eata2x_eh_abort, - .eh_host_reset_handler = eata2x_eh_host_reset, - .bios_param = eata2x_bios_param, - .slave_configure = eata2x_slave_configure, - .this_id = 7, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -}; - -#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) -#error "Adjust your defines" -#endif - -/* Subversion values */ -#define ISA 0 -#define ESA 1 - -#undef FORCE_CONFIG - -#undef DEBUG_LINKED_COMMANDS -#undef DEBUG_DETECT -#undef DEBUG_PCI_DETECT -#undef DEBUG_INTERRUPT -#undef DEBUG_RESET -#undef DEBUG_GENERATE_ERRORS -#undef DEBUG_GENERATE_ABORTS -#undef DEBUG_GEOMETRY - -#define MAX_ISA 4 -#define MAX_VESA 0 -#define MAX_EISA 15 -#define MAX_PCI 16 -#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) -#define MAX_CHANNEL 4 -#define MAX_LUN 32 -#define MAX_TARGET 32 -#define MAX_MAILBOXES 64 -#define MAX_SGLIST 64 -#define MAX_LARGE_SGLIST 122 -#define MAX_INTERNAL_RETRIES 64 -#define MAX_CMD_PER_LUN 2 -#define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN) - -#define SKIP ULONG_MAX -#define FREE 0 -#define IN_USE 1 -#define LOCKED 2 -#define IN_RESET 3 -#define IGNORE 4 -#define READY 5 -#define ABORTING 6 -#define NO_DMA 0xff -#define MAXLOOP 10000 -#define TAG_DISABLED 0 -#define TAG_SIMPLE 1 -#define TAG_ORDERED 2 - -#define REG_CMD 7 -#define REG_STATUS 7 -#define REG_AUX_STATUS 8 -#define REG_DATA 0 -#define REG_DATA2 1 -#define REG_SEE 6 -#define REG_LOW 2 -#define REG_LM 3 -#define REG_MID 4 -#define REG_MSB 5 -#define REGION_SIZE 9UL -#define MAX_ISA_ADDR 0x03ff -#define MIN_EISA_ADDR 0x1c88 -#define MAX_EISA_ADDR 0xfc88 -#define BSY_ASSERTED 0x80 -#define DRQ_ASSERTED 0x08 -#define ABSY_ASSERTED 0x01 -#define IRQ_ASSERTED 0x02 -#define READ_CONFIG_PIO 0xf0 -#define SET_CONFIG_PIO 0xf1 -#define SEND_CP_PIO 0xf2 -#define RECEIVE_SP_PIO 0xf3 -#define TRUNCATE_XFR_PIO 0xf4 -#define RESET_PIO 0xf9 -#define READ_CONFIG_DMA 0xfd -#define SET_CONFIG_DMA 0xfe -#define SEND_CP_DMA 0xff -#define ASOK 0x00 -#define ASST 0x01 - -#define YESNO(a) ((a) ? 'y' : 'n') -#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) - -/* "EATA", in Big Endian format */ -#define EATA_SIG_BE 0x45415441 - -/* Number of valid bytes in the board config structure for EATA 2.0x */ -#define EATA_2_0A_SIZE 28 -#define EATA_2_0B_SIZE 30 -#define EATA_2_0C_SIZE 34 - -/* Board info structure */ -struct eata_info { - u_int32_t data_len; /* Number of valid bytes after this field */ - u_int32_t sign; /* ASCII "EATA" signature */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar version : 4, - : 4; - unchar haaval : 1, - ata : 1, - drqvld : 1, - dmasup : 1, - morsup : 1, - trnxfr : 1, - tarsup : 1, - ocsena : 1; -#else - unchar : 4, /* unused low nibble */ - version : 4; /* EATA version, should be 0x1 */ - unchar ocsena : 1, /* Overlap Command Support Enabled */ - tarsup : 1, /* Target Mode Supported */ - trnxfr : 1, /* Truncate Transfer Cmd NOT Necessary */ - morsup : 1, /* More Supported */ - dmasup : 1, /* DMA Supported */ - drqvld : 1, /* DRQ Index (DRQX) is valid */ - ata : 1, /* This is an ATA device */ - haaval : 1; /* Host Adapter Address Valid */ -#endif - - ushort cp_pad_len; /* Number of pad bytes after cp_len */ - unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */ - u_int32_t cp_len; /* Number of valid bytes in cp */ - u_int32_t sp_len; /* Number of valid bytes in sp */ - ushort queue_size; /* Max number of cp that can be queued */ - ushort unused; - ushort scatt_size; /* Max number of entries in scatter/gather table */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar drqx : 2, - second : 1, - irq_tr : 1, - irq : 4; - unchar sync; - unchar : 4, - res1 : 1, - large_sg : 1, - forcaddr : 1, - isaena : 1; - unchar max_chan : 3, - max_id : 5; - unchar max_lun; - unchar eisa : 1, - pci : 1, - idquest : 1, - m1 : 1, - : 4; -#else - unchar irq : 4, /* Interrupt Request assigned to this controller */ - irq_tr : 1, /* 0 for edge triggered, 1 for level triggered */ - second : 1, /* 1 if this is a secondary (not primary) controller */ - drqx : 2; /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */ - unchar sync; /* 1 if scsi target id 7...0 is running sync scsi */ - - /* Structure extension defined in EATA 2.0B */ - unchar isaena : 1, /* ISA i/o addressing is disabled/enabled */ - forcaddr : 1, /* Port address has been forced */ - large_sg : 1, /* 1 if large SG lists are supported */ - res1 : 1, - : 4; - unchar max_id : 5, /* Max SCSI target ID number */ - max_chan : 3; /* Max SCSI channel number on this board */ - - /* Structure extension defined in EATA 2.0C */ - unchar max_lun; /* Max SCSI LUN number */ - unchar - : 4, - m1 : 1, /* This is a PCI with an M1 chip installed */ - idquest : 1, /* RAIDNUM returned is questionable */ - pci : 1, /* This board is PCI */ - eisa : 1; /* This board is EISA */ -#endif - - unchar raidnum; /* Uniquely identifies this HBA in a system */ - unchar notused; - - ushort ipad[247]; -}; - -/* Board config structure */ -struct eata_config { - ushort len; /* Number of bytes following this field */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar : 4, - tarena : 1, - mdpena : 1, - ocena : 1, - edis : 1; -#else - unchar edis : 1, /* Disable EATA interface after config command */ - ocena : 1, /* Overlapped Commands Enabled */ - mdpena : 1, /* Transfer all Modified Data Pointer Messages */ - tarena : 1, /* Target Mode Enabled for this controller */ - : 4; -#endif - unchar cpad[511]; -}; - -/* Returned status packet structure */ -struct mssp { -#if defined(__BIG_ENDIAN_BITFIELD) - unchar eoc : 1, - adapter_status : 7; -#else - unchar adapter_status : 7, /* State related to current command */ - eoc : 1; /* End Of Command (1 = command completed) */ -#endif - unchar target_status; /* SCSI status received after data transfer */ - unchar unused[2]; - u_int32_t inv_res_len; /* Number of bytes not transferred */ - u_int32_t cpp_index; /* Index of address set in cp */ - char mess[12]; -}; - -struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ -}; - -/* MailBox SCSI Command Packet */ -struct mscp { -#if defined(__BIG_ENDIAN_BITFIELD) - unchar din : 1, - dout : 1, - interp : 1, - : 1, - sg : 1, - reqsen :1, - init : 1, - sreset : 1; - unchar sense_len; - unchar unused[3]; - unchar : 7, - fwnest : 1; - unchar : 5, - hbaci : 1, - iat : 1, - phsunit : 1; - unchar channel : 3, - target : 5; - unchar one : 1, - dispri : 1, - luntar : 1, - lun : 5; -#else - unchar sreset :1, /* SCSI Bus Reset Signal should be asserted */ - init :1, /* Re-initialize controller and self test */ - reqsen :1, /* Transfer Request Sense Data to addr using DMA */ - sg :1, /* Use Scatter/Gather */ - :1, - interp :1, /* The controller interprets cp, not the target */ - dout :1, /* Direction of Transfer is Out (Host to Target) */ - din :1; /* Direction of Transfer is In (Target to Host) */ - unchar sense_len; /* Request Sense Length */ - unchar unused[3]; - unchar fwnest : 1, /* Send command to a component of an Array Group */ - : 7; - unchar phsunit : 1, /* Send to Target Physical Unit (bypass RAID) */ - iat : 1, /* Inhibit Address Translation */ - hbaci : 1, /* Inhibit HBA Caching for this command */ - : 5; - unchar target : 5, /* SCSI target ID */ - channel : 3; /* SCSI channel number */ - unchar lun : 5, /* SCSI logical unit number */ - luntar : 1, /* This cp is for Target (not LUN) */ - dispri : 1, /* Disconnect Privilege granted */ - one : 1; /* 1 */ -#endif - - unchar mess[3]; /* Massage to/from Target */ - unchar cdb[12]; /* Command Descriptor Block */ - u_int32_t data_len; /* If sg=0 Data Length, if sg=1 sglist length */ - u_int32_t cpp_index; /* Index of address to be returned in sp */ - u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */ - u_int32_t sp_dma_addr; /* Address where sp is DMA'ed when cp completes */ - u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */ - - /* Additional fields begin here. */ - struct scsi_cmnd *SCpnt; - - /* All the cp structure is zero filled by queuecommand except the - following CP_TAIL_SIZE bytes, initialized by detect */ - dma_addr_t cp_dma_addr; /* dma handle for this cp structure */ - struct sg_list *sglist; /* pointer to the allocated SG list */ -}; - -#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t)) - -struct hostdata { - struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ - unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ - unsigned int last_cp_used; /* Index of last mailbox used */ - unsigned int iocount; /* Total i/o done for this board */ - int board_number; /* Number of this board */ - char board_name[16]; /* Name of this board */ - int in_reset; /* True if board is doing a reset */ - int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ - int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If 1 redo i/o on target */ - unsigned int retries; /* Number of internal retries */ - unsigned long last_retried_pid; /* Pid of last retried command */ - unsigned char subversion; /* Bus type, either ISA or EISA/PCI */ - unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */ - unsigned char is_pci; /* 1 is bus type is PCI */ - struct pci_dev *pdev; /* pdev for PCI bus, NULL otherwise */ - struct mssp *sp_cpu_addr; /* cpu addr for DMA buffer sp */ - dma_addr_t sp_dma_addr; /* dma handle for DMA buffer sp */ - struct mssp sp; /* Local copy of sp buffer */ -}; - -static struct Scsi_Host *sh[MAX_BOARDS]; -static const char *driver_name = "EATA"; -static char sha[MAX_BOARDS]; - -/* Initialize num_boards so that ihdlr can work while detect is in progress */ -static unsigned int num_boards = MAX_BOARDS; - -static unsigned long io_port[] = { - - /* Space for MAX_INT_PARAM ports usable while loading as a module */ - SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, - SKIP, SKIP, - - /* First ISA */ - 0x1f0, - - /* Space for MAX_PCI ports possibly reported by PCI_BIOS */ - SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, - SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, - - /* MAX_EISA ports */ - 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, - 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, - - /* Other (MAX_ISA - 1) ports */ - 0x170, 0x230, 0x330, - - /* End of list */ - 0x0 -}; - -/* Device is Big Endian */ -#define H2DEV(x) cpu_to_be32(x) -#define DEV2H(x) be32_to_cpu(x) -#define H2DEV16(x) cpu_to_be16(x) -#define DEV2H16(x) be16_to_cpu(x) - -/* But transfer orientation from the 16 bit data register is Little Endian */ -#define REG2H(x) le16_to_cpu(x) - -static irqreturn_t do_interrupt_handler(int, void *); -static void flush_dev(struct scsi_device *, unsigned long, struct hostdata *, - unsigned int); -static int do_trace = 0; -static int setup_done = 0; -static int link_statistics; -static int ext_tran = 0; -static int rev_scan = 1; - -#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) -static int tag_mode = TAG_SIMPLE; -#else -static int tag_mode = TAG_DISABLED; -#endif - -#if defined(CONFIG_SCSI_EATA_LINKED_COMMANDS) -static int linked_comm = 1; -#else -static int linked_comm = 0; -#endif - -#if defined(CONFIG_SCSI_EATA_MAX_TAGS) -static int max_queue_depth = CONFIG_SCSI_EATA_MAX_TAGS; -#else -static int max_queue_depth = MAX_CMD_PER_LUN; -#endif - -#if defined(CONFIG_ISA) -static int isa_probe = 1; -#else -static int isa_probe = 0; -#endif - -#if defined(CONFIG_EISA) -static int eisa_probe = 1; -#else -static int eisa_probe = 0; -#endif - -#if defined(CONFIG_PCI) -static int pci_probe = 1; -#else -static int pci_probe = 0; -#endif - -#define MAX_INT_PARAM 10 -#define MAX_BOOT_OPTIONS_SIZE 256 -static char boot_options[MAX_BOOT_OPTIONS_SIZE]; - -#if defined(MODULE) -#include -#include - -module_param_string(eata, boot_options, MAX_BOOT_OPTIONS_SIZE, 0); -MODULE_PARM_DESC(eata, " equivalent to the \"eata=...\" kernel boot option." - " Example: modprobe eata \"eata=0x7410,0x230,lc:y,tm:0,mq:4,ep:n\""); -MODULE_AUTHOR("Dario Ballabio"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("EATA/DMA SCSI Driver"); - -#endif - -static int eata2x_slave_configure(struct scsi_device *dev) -{ - int tqd, utqd; - char *tag_suffix, *link_suffix; - - utqd = MAX_CMD_PER_LUN; - tqd = max_queue_depth; - - if (TLDEV(dev->type) && dev->tagged_supported) { - if (tag_mode == TAG_SIMPLE) { - tag_suffix = ", simple tags"; - } else if (tag_mode == TAG_ORDERED) { - tag_suffix = ", ordered tags"; - } else { - tag_suffix = ", no tags"; - } - scsi_change_queue_depth(dev, tqd); - } else if (TLDEV(dev->type) && linked_comm) { - scsi_change_queue_depth(dev, tqd); - tag_suffix = ", untagged"; - } else { - scsi_change_queue_depth(dev, utqd); - tag_suffix = ""; - } - - if (TLDEV(dev->type) && linked_comm && dev->queue_depth > 2) - link_suffix = ", sorted"; - else if (TLDEV(dev->type)) - link_suffix = ", unsorted"; - else - link_suffix = ""; - - sdev_printk(KERN_INFO, dev, - "cmds/lun %d%s%s.\n", - dev->queue_depth, link_suffix, tag_suffix); - - return 0; -} - -static int wait_on_busy(unsigned long iobase, unsigned int loop) -{ - while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { - udelay(1L); - if (--loop == 0) - return 1; - } - return 0; -} - -static int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) -{ - unsigned char *byaddr; - unsigned long devaddr; - - if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) - return 1; - - if (addr) { - devaddr = H2DEV(addr); - byaddr = (unsigned char *)&devaddr; - outb(byaddr[3], iobase + REG_LOW); - outb(byaddr[2], iobase + REG_LM); - outb(byaddr[1], iobase + REG_MID); - outb(byaddr[0], iobase + REG_MSB); - } - - outb(cmd, iobase + REG_CMD); - return 0; -} - -static int read_pio(unsigned long iobase, ushort * start, ushort * end) -{ - unsigned int loop = MAXLOOP; - ushort *p; - - for (p = start; p <= end; p++) { - while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { - udelay(1L); - if (--loop == 0) - return 1; - } - loop = MAXLOOP; - *p = REG2H(inw(iobase)); - } - - return 0; -} - -static struct pci_dev *get_pci_dev(unsigned long port_base) -{ -#if defined(CONFIG_PCI) - unsigned int addr; - struct pci_dev *dev = NULL; - - while ((dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { - addr = pci_resource_start(dev, 0); - -#if defined(DEBUG_PCI_DETECT) - printk("%s: get_pci_dev, bus %d, devfn 0x%x, addr 0x%x.\n", - driver_name, dev->bus->number, dev->devfn, addr); -#endif - - /* we are in so much trouble for a pci hotplug system with this driver - * anyway, so doing this at least lets people unload the driver and not - * cause memory problems, but in general this is a bad thing to do (this - * driver needs to be converted to the proper PCI api someday... */ - pci_dev_put(dev); - if (addr + PCI_BASE_ADDRESS_0 == port_base) - return dev; - } -#endif /* end CONFIG_PCI */ - return NULL; -} - -static void enable_pci_ports(void) -{ -#if defined(CONFIG_PCI) - struct pci_dev *dev = NULL; - - while ((dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { -#if defined(DEBUG_PCI_DETECT) - printk("%s: enable_pci_ports, bus %d, devfn 0x%x.\n", - driver_name, dev->bus->number, dev->devfn); -#endif - - if (pci_enable_device(dev)) - printk - ("%s: warning, pci_enable_device failed, bus %d devfn 0x%x.\n", - driver_name, dev->bus->number, dev->devfn); - } - -#endif /* end CONFIG_PCI */ -} - -static int port_detect(unsigned long port_base, unsigned int j, - struct scsi_host_template *tpnt) -{ - unsigned char irq, dma_channel, subversion, i, is_pci = 0; - unsigned char protocol_rev; - struct eata_info info; - char *bus_type, dma_name[16]; - struct pci_dev *pdev; - /* Allowed DMA channels for ISA (0 indicates reserved) */ - unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; - struct Scsi_Host *shost; - struct hostdata *ha; - char name[16]; - - sprintf(name, "%s%d", driver_name, j); - - if (!request_region(port_base, REGION_SIZE, driver_name)) { -#if defined(DEBUG_DETECT) - printk("%s: address 0x%03lx in use, skipping probe.\n", name, - port_base); -#endif - goto fail; - } - - if (do_dma(port_base, 0, READ_CONFIG_PIO)) { -#if defined(DEBUG_DETECT) - printk("%s: detect, do_dma failed at 0x%03lx.\n", name, - port_base); -#endif - goto freelock; - } - - /* Read the info structure */ - if (read_pio(port_base, (ushort *) & info, (ushort *) & info.ipad[0])) { -#if defined(DEBUG_DETECT) - printk("%s: detect, read_pio failed at 0x%03lx.\n", name, - port_base); -#endif - goto freelock; - } - - info.data_len = DEV2H(info.data_len); - info.sign = DEV2H(info.sign); - info.cp_pad_len = DEV2H16(info.cp_pad_len); - info.cp_len = DEV2H(info.cp_len); - info.sp_len = DEV2H(info.sp_len); - info.scatt_size = DEV2H16(info.scatt_size); - info.queue_size = DEV2H16(info.queue_size); - - /* Check the controller "EATA" signature */ - if (info.sign != EATA_SIG_BE) { -#if defined(DEBUG_DETECT) - printk("%s: signature 0x%04x discarded.\n", name, info.sign); -#endif - goto freelock; - } - - if (info.data_len < EATA_2_0A_SIZE) { - printk - ("%s: config structure size (%d bytes) too short, detaching.\n", - name, info.data_len); - goto freelock; - } else if (info.data_len == EATA_2_0A_SIZE) - protocol_rev = 'A'; - else if (info.data_len == EATA_2_0B_SIZE) - protocol_rev = 'B'; - else - protocol_rev = 'C'; - - if (protocol_rev != 'A' && info.forcaddr) { - printk("%s: warning, port address has been forced.\n", name); - bus_type = "PCI"; - is_pci = 1; - subversion = ESA; - } else if (port_base > MAX_EISA_ADDR - || (protocol_rev == 'C' && info.pci)) { - bus_type = "PCI"; - is_pci = 1; - subversion = ESA; - } else if (port_base >= MIN_EISA_ADDR - || (protocol_rev == 'C' && info.eisa)) { - bus_type = "EISA"; - subversion = ESA; - } else if (protocol_rev == 'C' && !info.eisa && !info.pci) { - bus_type = "ISA"; - subversion = ISA; - } else if (port_base > MAX_ISA_ADDR) { - bus_type = "PCI"; - is_pci = 1; - subversion = ESA; - } else { - bus_type = "ISA"; - subversion = ISA; - } - - if (!info.haaval || info.ata) { - printk - ("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n", - name, port_base, bus_type, info.haaval, info.ata); - goto freelock; - } - - if (info.drqvld) { - if (subversion == ESA) - printk("%s: warning, weird %s board using DMA.\n", name, - bus_type); - - subversion = ISA; - dma_channel = dma_channel_table[3 - info.drqx]; - } else { - if (subversion == ISA) - printk("%s: warning, weird %s board not using DMA.\n", - name, bus_type); - - subversion = ESA; - dma_channel = NO_DMA; - } - - if (!info.dmasup) - printk("%s: warning, DMA protocol support not asserted.\n", - name); - - irq = info.irq; - - if (subversion == ESA && !info.irq_tr) - printk - ("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", - name, irq); - - if (is_pci) { - pdev = get_pci_dev(port_base); - if (!pdev) - printk - ("%s: warning, failed to get pci_dev structure.\n", - name); - } else - pdev = NULL; - - if (pdev && (irq != pdev->irq)) { - printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, - pdev->irq); - irq = pdev->irq; - } - - /* Board detected, allocate its IRQ */ - if (request_irq(irq, do_interrupt_handler, - (subversion == ESA) ? IRQF_SHARED : 0, - driver_name, (void *)&sha[j])) { - printk("%s: unable to allocate IRQ %u, detaching.\n", name, - irq); - goto freelock; - } - - if (subversion == ISA && request_dma(dma_channel, driver_name)) { - printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - goto freeirq; - } -#if defined(FORCE_CONFIG) - { - struct eata_config *cf; - dma_addr_t cf_dma_addr; - - cf = pci_zalloc_consistent(pdev, sizeof(struct eata_config), - &cf_dma_addr); - - if (!cf) { - printk - ("%s: config, pci_alloc_consistent failed, detaching.\n", - name); - goto freedma; - } - - /* Set board configuration */ - cf->len = (ushort) H2DEV16((ushort) 510); - cf->ocena = 1; - - if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { - printk - ("%s: busy timeout sending configuration, detaching.\n", - name); - pci_free_consistent(pdev, sizeof(struct eata_config), - cf, cf_dma_addr); - goto freedma; - } - - } -#endif - - sh[j] = shost = scsi_register(tpnt, sizeof(struct hostdata)); - if (shost == NULL) { - printk("%s: unable to register host, detaching.\n", name); - goto freedma; - } - - shost->io_port = port_base; - shost->unique_id = port_base; - shost->n_io_port = REGION_SIZE; - shost->dma_channel = dma_channel; - shost->irq = irq; - shost->sg_tablesize = (ushort) info.scatt_size; - shost->this_id = (ushort) info.host_addr[3]; - shost->can_queue = (ushort) info.queue_size; - shost->cmd_per_lun = MAX_CMD_PER_LUN; - - ha = (struct hostdata *)shost->hostdata; - - memset(ha, 0, sizeof(struct hostdata)); - ha->subversion = subversion; - ha->protocol_rev = protocol_rev; - ha->is_pci = is_pci; - ha->pdev = pdev; - ha->board_number = j; - - if (ha->subversion == ESA) - shost->unchecked_isa_dma = 0; - else { - unsigned long flags; - shost->unchecked_isa_dma = 1; - - flags = claim_dma_lock(); - disable_dma(dma_channel); - clear_dma_ff(dma_channel); - set_dma_mode(dma_channel, DMA_MODE_CASCADE); - enable_dma(dma_channel); - release_dma_lock(flags); - - } - - strcpy(ha->board_name, name); - - /* DPT PM2012 does not allow to detect sg_tablesize correctly */ - if (shost->sg_tablesize > MAX_SGLIST || shost->sg_tablesize < 2) { - printk("%s: detect, wrong n. of SG lists %d, fixed.\n", - ha->board_name, shost->sg_tablesize); - shost->sg_tablesize = MAX_SGLIST; - } - - /* DPT PM2012 does not allow to detect can_queue correctly */ - if (shost->can_queue > MAX_MAILBOXES || shost->can_queue < 2) { - printk("%s: detect, wrong n. of mbox %d, fixed.\n", - ha->board_name, shost->can_queue); - shost->can_queue = MAX_MAILBOXES; - } - - if (protocol_rev != 'A') { - if (info.max_chan > 0 && info.max_chan < MAX_CHANNEL) - shost->max_channel = info.max_chan; - - if (info.max_id > 7 && info.max_id < MAX_TARGET) - shost->max_id = info.max_id + 1; - - if (info.large_sg && shost->sg_tablesize == MAX_SGLIST) - shost->sg_tablesize = MAX_LARGE_SGLIST; - } - - if (protocol_rev == 'C') { - if (info.max_lun > 7 && info.max_lun < MAX_LUN) - shost->max_lun = info.max_lun + 1; - } - - if (dma_channel == NO_DMA) - sprintf(dma_name, "%s", "BMST"); - else - sprintf(dma_name, "DMA %u", dma_channel); - - for (i = 0; i < shost->can_queue; i++) - ha->cp[i].cp_dma_addr = pci_map_single(ha->pdev, - &ha->cp[i], - sizeof(struct mscp), - PCI_DMA_BIDIRECTIONAL); - - for (i = 0; i < shost->can_queue; i++) { - size_t sz = shost->sg_tablesize *sizeof(struct sg_list); - gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC; - ha->cp[i].sglist = kmalloc(sz, gfp_mask); - if (!ha->cp[i].sglist) { - printk - ("%s: kmalloc SGlist failed, mbox %d, detaching.\n", - ha->board_name, i); - goto release; - } - } - - if (!(ha->sp_cpu_addr = pci_alloc_consistent(ha->pdev, - sizeof(struct mssp), - &ha->sp_dma_addr))) { - printk("%s: pci_alloc_consistent failed, detaching.\n", ha->board_name); - goto release; - } - - if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) - max_queue_depth = MAX_TAGGED_CMD_PER_LUN; - - if (max_queue_depth < MAX_CMD_PER_LUN) - max_queue_depth = MAX_CMD_PER_LUN; - - if (tag_mode != TAG_DISABLED && tag_mode != TAG_SIMPLE) - tag_mode = TAG_ORDERED; - - if (j == 0) { - printk - ("EATA/DMA 2.0x: Copyright (C) 1994-2003 Dario Ballabio.\n"); - printk - ("%s config options -> tm:%d, lc:%c, mq:%d, rs:%c, et:%c, " - "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_mode, - YESNO(linked_comm), max_queue_depth, YESNO(rev_scan), - YESNO(ext_tran), YESNO(isa_probe), YESNO(eisa_probe), - YESNO(pci_probe)); - } - - printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n", - ha->board_name, ha->protocol_rev, bus_type, - (unsigned long)shost->io_port, shost->irq, dma_name, - shost->sg_tablesize, shost->can_queue); - - if (shost->max_id > 8 || shost->max_lun > 8) - printk - ("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", - ha->board_name, shost->max_id, shost->max_lun); - - for (i = 0; i <= shost->max_channel; i++) - printk("%s: SCSI channel %u enabled, host target ID %d.\n", - ha->board_name, i, info.host_addr[3 - i]); - -#if defined(DEBUG_DETECT) - printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, " - "sec. %u, infol %d, cpl %d spl %d.\n", name, info.version, - info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, - info.second, info.data_len, info.cp_len, info.sp_len); - - if (protocol_rev == 'B' || protocol_rev == 'C') - printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, " - "large_sg %u, res1 %u.\n", name, info.isaena, - info.forcaddr, info.max_id, info.max_chan, info.large_sg, - info.res1); - - if (protocol_rev == 'C') - printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, " - "raidnum %u.\n", name, info.max_lun, info.m1, - info.idquest, info.pci, info.eisa, info.raidnum); -#endif - - if (ha->pdev) { - pci_set_master(ha->pdev); - if (pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(32))) - printk("%s: warning, pci_set_dma_mask failed.\n", - ha->board_name); - } - - return 1; - - freedma: - if (subversion == ISA) - free_dma(dma_channel); - freeirq: - free_irq(irq, &sha[j]); - freelock: - release_region(port_base, REGION_SIZE); - fail: - return 0; - - release: - eata2x_release(shost); - return 0; -} - -static void internal_setup(char *str, int *ints) -{ - int i, argc = ints[0]; - char *cur = str, *pc; - - if (argc > 0) { - if (argc > MAX_INT_PARAM) - argc = MAX_INT_PARAM; - - for (i = 0; i < argc; i++) - io_port[i] = ints[i + 1]; - - io_port[i] = 0; - setup_done = 1; - } - - while (cur && (pc = strchr(cur, ':'))) { - int val = 0, c = *++pc; - - if (c == 'n' || c == 'N') - val = 0; - else if (c == 'y' || c == 'Y') - val = 1; - else - val = (int)simple_strtoul(pc, NULL, 0); - - if (!strncmp(cur, "lc:", 3)) - linked_comm = val; - else if (!strncmp(cur, "tm:", 3)) - tag_mode = val; - else if (!strncmp(cur, "tc:", 3)) - tag_mode = val; - else if (!strncmp(cur, "mq:", 3)) - max_queue_depth = val; - else if (!strncmp(cur, "ls:", 3)) - link_statistics = val; - else if (!strncmp(cur, "et:", 3)) - ext_tran = val; - else if (!strncmp(cur, "rs:", 3)) - rev_scan = val; - else if (!strncmp(cur, "ip:", 3)) - isa_probe = val; - else if (!strncmp(cur, "ep:", 3)) - eisa_probe = val; - else if (!strncmp(cur, "pp:", 3)) - pci_probe = val; - - if ((cur = strchr(cur, ','))) - ++cur; - } - - return; -} - -static int option_setup(char *str) -{ - int ints[MAX_INT_PARAM]; - char *cur = str; - int i = 1; - - while (cur && isdigit(*cur) && i < MAX_INT_PARAM) { - ints[i++] = simple_strtoul(cur, NULL, 0); - - if ((cur = strchr(cur, ',')) != NULL) - cur++; - } - - ints[0] = i - 1; - internal_setup(cur, ints); - return 1; -} - -static void add_pci_ports(void) -{ -#if defined(CONFIG_PCI) - unsigned int addr, k; - struct pci_dev *dev = NULL; - - for (k = 0; k < MAX_PCI; k++) { - - if (!(dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) - break; - - if (pci_enable_device(dev)) { -#if defined(DEBUG_PCI_DETECT) - printk - ("%s: detect, bus %d, devfn 0x%x, pci_enable_device failed.\n", - driver_name, dev->bus->number, dev->devfn); -#endif - - continue; - } - - addr = pci_resource_start(dev, 0); - -#if defined(DEBUG_PCI_DETECT) - printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", - driver_name, k, dev->bus->number, dev->devfn, addr); -#endif - - /* Order addresses according to rev_scan value */ - io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] = - addr + PCI_BASE_ADDRESS_0; - } - - pci_dev_put(dev); -#endif /* end CONFIG_PCI */ -} - -static int eata2x_detect(struct scsi_host_template *tpnt) -{ - unsigned int j = 0, k; - - tpnt->proc_name = "eata2x"; - - if (strlen(boot_options)) - option_setup(boot_options); - -#if defined(MODULE) - /* io_port could have been modified when loading as a module */ - if (io_port[0] != SKIP) { - setup_done = 1; - io_port[MAX_INT_PARAM] = 0; - } -#endif - - for (k = MAX_INT_PARAM; io_port[k]; k++) - if (io_port[k] == SKIP) - continue; - else if (io_port[k] <= MAX_ISA_ADDR) { - if (!isa_probe) - io_port[k] = SKIP; - } else if (io_port[k] >= MIN_EISA_ADDR - && io_port[k] <= MAX_EISA_ADDR) { - if (!eisa_probe) - io_port[k] = SKIP; - } - - if (pci_probe) { - if (!setup_done) - add_pci_ports(); - else - enable_pci_ports(); - } - - for (k = 0; io_port[k]; k++) { - - if (io_port[k] == SKIP) - continue; - - if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) - j++; - } - - num_boards = j; - return j; -} - -static void map_dma(unsigned int i, struct hostdata *ha) -{ - unsigned int k, pci_dir; - int count; - struct scatterlist *sg; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &ha->cp[i]; - SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (SCpnt->sense_buffer) - cpp->sense_addr = - H2DEV(pci_map_single(ha->pdev, SCpnt->sense_buffer, - SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE)); - - cpp->sense_len = SCSI_SENSE_BUFFERSIZE; - - if (!scsi_sg_count(SCpnt)) { - cpp->data_len = 0; - return; - } - - count = pci_map_sg(ha->pdev, scsi_sglist(SCpnt), scsi_sg_count(SCpnt), - pci_dir); - BUG_ON(!count); - - scsi_for_each_sg(SCpnt, sg, count, k) { - cpp->sglist[k].address = H2DEV(sg_dma_address(sg)); - cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg)); - } - - cpp->sg = 1; - cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist, - scsi_sg_count(SCpnt) * - sizeof(struct sg_list), - pci_dir)); - cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list))); -} - -static void unmap_dma(unsigned int i, struct hostdata *ha) -{ - unsigned int pci_dir; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &ha->cp[i]; - SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (DEV2H(cpp->sense_addr)) - pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr), - DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - - if (scsi_sg_count(SCpnt)) - pci_unmap_sg(ha->pdev, scsi_sglist(SCpnt), scsi_sg_count(SCpnt), - pci_dir); - - if (!DEV2H(cpp->data_len)) - pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (DEV2H(cpp->data_address)) - pci_unmap_single(ha->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); -} - -static void sync_dma(unsigned int i, struct hostdata *ha) -{ - unsigned int pci_dir; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &ha->cp[i]; - SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (DEV2H(cpp->sense_addr)) - pci_dma_sync_single_for_cpu(ha->pdev, DEV2H(cpp->sense_addr), - DEV2H(cpp->sense_len), - PCI_DMA_FROMDEVICE); - - if (scsi_sg_count(SCpnt)) - pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt), - scsi_sg_count(SCpnt), pci_dir); - - if (!DEV2H(cpp->data_len)) - pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (DEV2H(cpp->data_address)) - pci_dma_sync_single_for_cpu(ha->pdev, - DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); -} - -static void scsi_to_dev_dir(unsigned int i, struct hostdata *ha) -{ - unsigned int k; - - static const unsigned char data_out_cmds[] = { - 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e, - 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, - 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b, 0x5d - }; - - static const unsigned char data_none_cmds[] = { - 0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e, - 0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47, - 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00 - }; - - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &ha->cp[i]; - SCpnt = cpp->SCpnt; - - if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { - cpp->din = 1; - cpp->dout = 0; - return; - } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { - cpp->din = 0; - cpp->dout = 1; - return; - } else if (SCpnt->sc_data_direction == DMA_NONE) { - cpp->din = 0; - cpp->dout = 0; - return; - } - - if (SCpnt->sc_data_direction != DMA_BIDIRECTIONAL) - panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", - ha->board_name); - - for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) - if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->dout = 1; - break; - } - - if ((cpp->din = !cpp->dout)) - for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) - if (SCpnt->cmnd[0] == data_none_cmds[k]) { - cpp->din = 0; - break; - } - -} - -static int eata2x_queuecommand_lck(struct scsi_cmnd *SCpnt, - void (*done) (struct scsi_cmnd *)) -{ - struct Scsi_Host *shost = SCpnt->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; - unsigned int i, k; - struct mscp *cpp; - - if (SCpnt->host_scribble) - panic("%s: qcomm, SCpnt %p already active.\n", - ha->board_name, SCpnt); - - /* i is the mailbox number, look for the first free mailbox - starting from last_cp_used */ - i = ha->last_cp_used + 1; - - for (k = 0; k < shost->can_queue; k++, i++) { - if (i >= shost->can_queue) - i = 0; - if (ha->cp_stat[i] == FREE) { - ha->last_cp_used = i; - break; - } - } - - if (k == shost->can_queue) { - printk("%s: qcomm, no free mailbox.\n", ha->board_name); - return 1; - } - - /* Set pointer to control packet structure */ - cpp = &ha->cp[i]; - - memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); - - /* Set pointer to status packet structure, Big Endian format */ - cpp->sp_dma_addr = H2DEV(ha->sp_dma_addr); - - SCpnt->scsi_done = done; - cpp->cpp_index = i; - SCpnt->host_scribble = (unsigned char *)&cpp->cpp_index; - - if (do_trace) - scmd_printk(KERN_INFO, SCpnt, - "qcomm, mbox %d.\n", i); - - cpp->reqsen = 1; - cpp->dispri = 1; -#if 0 - if (SCpnt->device->type == TYPE_TAPE) - cpp->hbaci = 1; -#endif - cpp->one = 1; - cpp->channel = SCpnt->device->channel; - cpp->target = SCpnt->device->id; - cpp->lun = SCpnt->device->lun; - cpp->SCpnt = SCpnt; - memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - /* Use data transfer direction SCpnt->sc_data_direction */ - scsi_to_dev_dir(i, ha); - - /* Map DMA buffers and SG list */ - map_dma(i, ha); - - if (linked_comm && SCpnt->device->queue_depth > 2 - && TLDEV(SCpnt->device->type)) { - ha->cp_stat[i] = READY; - flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 0); - return 0; - } - - /* Send control packet to the board */ - if (do_dma(shost->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) { - unmap_dma(i, ha); - SCpnt->host_scribble = NULL; - scmd_printk(KERN_INFO, SCpnt, "qcomm, adapter busy.\n"); - return 1; - } - - ha->cp_stat[i] = IN_USE; - return 0; -} - -static DEF_SCSI_QCMD(eata2x_queuecommand) - -static int eata2x_eh_abort(struct scsi_cmnd *SCarg) -{ - struct Scsi_Host *shost = SCarg->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; - unsigned int i; - - if (SCarg->host_scribble == NULL) { - scmd_printk(KERN_INFO, SCarg, "abort, cmd inactive.\n"); - return SUCCESS; - } - - i = *(unsigned int *)SCarg->host_scribble; - scmd_printk(KERN_WARNING, SCarg, "abort, mbox %d.\n", i); - - if (i >= shost->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name); - - if (wait_on_busy(shost->io_port, MAXLOOP)) { - printk("%s: abort, timeout error.\n", ha->board_name); - return FAILED; - } - - if (ha->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", ha->board_name, i); - return SUCCESS; - } - - if (ha->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", ha->board_name, i); - - if (SCarg != ha->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - ha->board_name, i, SCarg, ha->cp[i].SCpnt); - - if (inb(shost->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) - printk("%s: abort, mbox %d, interrupt pending.\n", - ha->board_name, i); - - return FAILED; - } - - if (ha->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", ha->board_name, i); - return FAILED; - } - - if (ha->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", ha->board_name, i); - return SUCCESS; - } - - if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) { - unmap_dma(i, ha); - SCarg->result = DID_ABORT << 16; - SCarg->host_scribble = NULL; - ha->cp_stat[i] = FREE; - printk("%s, abort, mbox %d ready, DID_ABORT, done.\n", - ha->board_name, i); - SCarg->scsi_done(SCarg); - return SUCCESS; - } - - panic("%s: abort, mbox %d, invalid cp_stat.\n", ha->board_name, i); -} - -static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) -{ - unsigned int i, time, k, c, limit = 0; - struct scsi_cmnd *SCpnt; - struct Scsi_Host *shost = SCarg->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; - - scmd_printk(KERN_INFO, SCarg, "reset, enter.\n"); - - spin_lock_irq(shost->host_lock); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, inactive.\n", ha->board_name); - - if (ha->in_reset) { - printk("%s: reset, exit, already in reset.\n", ha->board_name); - spin_unlock_irq(shost->host_lock); - return FAILED; - } - - if (wait_on_busy(shost->io_port, MAXLOOP)) { - printk("%s: reset, exit, timeout error.\n", ha->board_name); - spin_unlock_irq(shost->host_lock); - return FAILED; - } - - ha->retries = 0; - - for (c = 0; c <= shost->max_channel; c++) - for (k = 0; k < shost->max_id; k++) { - ha->target_redo[k][c] = 1; - ha->target_to[k][c] = 0; - } - - for (i = 0; i < shost->can_queue; i++) { - - if (ha->cp_stat[i] == FREE) - continue; - - if (ha->cp_stat[i] == LOCKED) { - ha->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", - ha->board_name, i); - continue; - } - - if (!(SCpnt = ha->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", ha->board_name, i); - - if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) { - ha->cp_stat[i] = ABORTING; - printk("%s: reset, mbox %d aborting.\n", - ha->board_name, i); - } - - else { - ha->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset.\n", - ha->board_name, i); - } - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", ha->board_name, i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", ha->board_name, i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", - ha->board_name, i); - } - - if (do_dma(shost->io_port, 0, RESET_PIO)) { - printk("%s: reset, cannot reset, timeout error.\n", ha->board_name); - spin_unlock_irq(shost->host_lock); - return FAILED; - } - - printk("%s: reset, board reset done, enabling interrupts.\n", ha->board_name); - -#if defined(DEBUG_RESET) - do_trace = 1; -#endif - - ha->in_reset = 1; - - spin_unlock_irq(shost->host_lock); - - /* FIXME: use a sleep instead */ - time = jiffies; - while ((jiffies - time) < (10 * HZ) && limit++ < 200000) - udelay(100L); - - spin_lock_irq(shost->host_lock); - - printk("%s: reset, interrupts disabled, loops %d.\n", ha->board_name, limit); - - for (i = 0; i < shost->can_queue; i++) { - - if (ha->cp_stat[i] == IN_RESET) { - SCpnt = ha->cp[i].SCpnt; - unmap_dma(i, ha); - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - ha->cp_stat[i] = LOCKED; - - printk - ("%s, reset, mbox %d locked, DID_RESET, done.\n", - ha->board_name, i); - } - - else if (ha->cp_stat[i] == ABORTING) { - SCpnt = ha->cp[i].SCpnt; - unmap_dma(i, ha); - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox was never queued to the adapter */ - ha->cp_stat[i] = FREE; - - printk - ("%s, reset, mbox %d aborting, DID_RESET, done.\n", - ha->board_name, i); - } - - else - /* Any other mailbox has already been set free by interrupt */ - continue; - - SCpnt->scsi_done(SCpnt); - } - - ha->in_reset = 0; - do_trace = 0; - - printk("%s: reset, exit.\n", ha->board_name); - - spin_unlock_irq(shost->host_lock); - return SUCCESS; -} - -int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *dkinfo) -{ - unsigned int size = capacity; - - if (ext_tran || (scsicam_bios_param(bdev, capacity, dkinfo) < 0)) { - dkinfo[0] = 255; - dkinfo[1] = 63; - dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); - } -#if defined (DEBUG_GEOMETRY) - printk("%s: bios_param, head=%d, sec=%d, cyl=%d.\n", driver_name, - dkinfo[0], dkinfo[1], dkinfo[2]); -#endif - - return 0; -} - -static void sort(unsigned long sk[], unsigned int da[], unsigned int n, - unsigned int rev) -{ - unsigned int i, j, k, y; - unsigned long x; - - for (i = 0; i < n - 1; i++) { - k = i; - - for (j = k + 1; j < n; j++) - if (rev) { - if (sk[j] > sk[k]) - k = j; - } else { - if (sk[j] < sk[k]) - k = j; - } - - if (k != i) { - x = sk[k]; - sk[k] = sk[i]; - sk[i] = x; - y = da[k]; - da[k] = da[i]; - da[i] = y; - } - } - - return; -} - -static int reorder(struct hostdata *ha, unsigned long cursec, - unsigned int ihdlr, unsigned int il[], unsigned int n_ready) -{ - struct scsi_cmnd *SCpnt; - struct mscp *cpp; - unsigned int k, n; - unsigned int rev = 0, s = 1, r = 1; - unsigned int input_only = 1, overlap = 0; - unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; - unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; - unsigned long ioseek = 0; - - static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; - static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; - static unsigned int readysorted = 0, revcount = 0; - static unsigned long seeksorted = 0, seeknosort = 0; - - if (link_statistics && !(++flushcount % link_statistics)) - printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d" - " av %ldK as %ldK.\n", flushcount, batchcount, - inputcount, ovlcount, readycount, readysorted, sortcount, - revcount, seeknosort / (readycount + 1), - seeksorted / (readycount + 1)); - - if (n_ready <= 1) - return 0; - - for (n = 0; n < n_ready; n++) { - k = il[n]; - cpp = &ha->cp[k]; - SCpnt = cpp->SCpnt; - - if (!cpp->din) - input_only = 0; - - if (blk_rq_pos(SCpnt->request) < minsec) - minsec = blk_rq_pos(SCpnt->request); - if (blk_rq_pos(SCpnt->request) > maxsec) - maxsec = blk_rq_pos(SCpnt->request); - - sl[n] = blk_rq_pos(SCpnt->request); - ioseek += blk_rq_sectors(SCpnt->request); - - if (!n) - continue; - - if (sl[n] < sl[n - 1]) - s = 0; - if (sl[n] > sl[n - 1]) - r = 0; - - if (link_statistics) { - if (sl[n] > sl[n - 1]) - seek += sl[n] - sl[n - 1]; - else - seek += sl[n - 1] - sl[n]; - } - - } - - if (link_statistics) { - if (cursec > sl[0]) - seek += cursec - sl[0]; - else - seek += sl[0] - cursec; - } - - if (cursec > ((maxsec + minsec) / 2)) - rev = 1; - - if (ioseek > ((maxsec - minsec) / 2)) - rev = 0; - - if (!((rev && r) || (!rev && s))) - sort(sl, il, n_ready, rev); - - if (!input_only) - for (n = 0; n < n_ready; n++) { - k = il[n]; - cpp = &ha->cp[k]; - SCpnt = cpp->SCpnt; - ll[n] = blk_rq_sectors(SCpnt->request); - pl[n] = SCpnt->serial_number; - - if (!n) - continue; - - if ((sl[n] == sl[n - 1]) - || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) - || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) - overlap = 1; - } - - if (overlap) - sort(pl, il, n_ready, 0); - - if (link_statistics) { - if (cursec > sl[0]) - iseek = cursec - sl[0]; - else - iseek = sl[0] - cursec; - batchcount++; - readycount += n_ready; - seeknosort += seek / 1024; - if (input_only) - inputcount++; - if (overlap) { - ovlcount++; - seeksorted += iseek / 1024; - } else - seeksorted += (iseek + maxsec - minsec) / 1024; - if (rev && !r) { - revcount++; - readysorted += n_ready; - } - if (!rev && !s) { - sortcount++; - readysorted += n_ready; - } - } -#if defined(DEBUG_LINKED_COMMANDS) - if (link_statistics && (overlap || !(flushcount % link_statistics))) - for (n = 0; n < n_ready; n++) { - k = il[n]; - cpp = &ha->cp[k]; - SCpnt = cpp->SCpnt; - scmd_printk(KERN_INFO, SCpnt, - "%s mb %d fc %d nr %d sec %ld ns %u" - " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", - (ihdlr ? "ihdlr" : "qcomm"), - k, flushcount, - n_ready, blk_rq_pos(SCpnt->request), - blk_rq_sectors(SCpnt->request), cursec, YESNO(s), - YESNO(r), YESNO(rev), YESNO(input_only), - YESNO(overlap), cpp->din); - } -#endif - return overlap; -} - -static void flush_dev(struct scsi_device *dev, unsigned long cursec, - struct hostdata *ha, unsigned int ihdlr) -{ - struct scsi_cmnd *SCpnt; - struct mscp *cpp; - unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES]; - - for (k = 0; k < dev->host->can_queue; k++) { - - if (ha->cp_stat[k] != READY && ha->cp_stat[k] != IN_USE) - continue; - - cpp = &ha->cp[k]; - SCpnt = cpp->SCpnt; - - if (SCpnt->device != dev) - continue; - - if (ha->cp_stat[k] == IN_USE) - return; - - il[n_ready++] = k; - } - - if (reorder(ha, cursec, ihdlr, il, n_ready)) - n_ready = 1; - - for (n = 0; n < n_ready; n++) { - k = il[n]; - cpp = &ha->cp[k]; - SCpnt = cpp->SCpnt; - - if (do_dma(dev->host->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) { - scmd_printk(KERN_INFO, SCpnt, - "%s, mbox %d, adapter" - " busy, will abort.\n", - (ihdlr ? "ihdlr" : "qcomm"), - k); - ha->cp_stat[k] = ABORTING; - continue; - } - - ha->cp_stat[k] = IN_USE; - } -} - -static irqreturn_t ihdlr(struct Scsi_Host *shost) -{ - struct scsi_cmnd *SCpnt; - unsigned int i, k, c, status, tstatus, reg; - struct mssp *spp; - struct mscp *cpp; - struct hostdata *ha = (struct hostdata *)shost->hostdata; - int irq = shost->irq; - - /* Check if this board need to be serviced */ - if (!(inb(shost->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) - goto none; - - ha->iocount++; - - if (do_trace) - printk("%s: ihdlr, enter, irq %d, count %d.\n", ha->board_name, irq, - ha->iocount); - - /* Check if this board is still busy */ - if (wait_on_busy(shost->io_port, 20 * MAXLOOP)) { - reg = inb(shost->io_port + REG_STATUS); - printk - ("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", - ha->board_name, irq, reg, ha->iocount); - goto none; - } - - spp = &ha->sp; - - /* Make a local copy just before clearing the interrupt indication */ - memcpy(spp, ha->sp_cpu_addr, sizeof(struct mssp)); - - /* Clear the completion flag and cp pointer on the dynamic copy of sp */ - memset(ha->sp_cpu_addr, 0, sizeof(struct mssp)); - - /* Read the status register to clear the interrupt indication */ - reg = inb(shost->io_port + REG_STATUS); - -#if defined (DEBUG_INTERRUPT) - { - unsigned char *bytesp; - int cnt; - bytesp = (unsigned char *)spp; - if (ha->iocount < 200) { - printk("sp[] ="); - for (cnt = 0; cnt < 15; cnt++) - printk(" 0x%x", bytesp[cnt]); - printk("\n"); - } - } -#endif - - /* Reject any sp with supspect data */ - if (spp->eoc == 0 && ha->iocount > 1) - printk - ("%s: ihdlr, spp->eoc == 0, irq %d, reg 0x%x, count %d.\n", - ha->board_name, irq, reg, ha->iocount); - if (spp->cpp_index < 0 || spp->cpp_index >= shost->can_queue) - printk - ("%s: ihdlr, bad spp->cpp_index %d, irq %d, reg 0x%x, count %d.\n", - ha->board_name, spp->cpp_index, irq, reg, ha->iocount); - if (spp->eoc == 0 || spp->cpp_index < 0 - || spp->cpp_index >= shost->can_queue) - goto handled; - - /* Find the mailbox to be serviced on this board */ - i = spp->cpp_index; - - cpp = &(ha->cp[i]); - -#if defined(DEBUG_GENERATE_ABORTS) - if ((ha->iocount > 500) && ((ha->iocount % 500) < 3)) - goto handled; -#endif - - if (ha->cp_stat[i] == IGNORE) { - ha->cp_stat[i] = FREE; - goto handled; - } else if (ha->cp_stat[i] == LOCKED) { - ha->cp_stat[i] = FREE; - printk("%s: ihdlr, mbox %d unlocked, count %d.\n", ha->board_name, i, - ha->iocount); - goto handled; - } else if (ha->cp_stat[i] == FREE) { - printk("%s: ihdlr, mbox %d is free, count %d.\n", ha->board_name, i, - ha->iocount); - goto handled; - } else if (ha->cp_stat[i] == IN_RESET) - printk("%s: ihdlr, mbox %d is in reset.\n", ha->board_name, i); - else if (ha->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", - ha->board_name, i, ha->cp_stat[i]); - - ha->cp_stat[i] = FREE; - SCpnt = cpp->SCpnt; - - if (SCpnt == NULL) - panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", ha->board_name, i); - - if (SCpnt->host_scribble == NULL) - panic("%s: ihdlr, mbox %d, SCpnt %p garbled.\n", ha->board_name, - i, SCpnt); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: ihdlr, mbox %d, index mismatch %d.\n", - ha->board_name, i, - *(unsigned int *)SCpnt->host_scribble); - - sync_dma(i, ha); - - if (linked_comm && SCpnt->device->queue_depth > 2 - && TLDEV(SCpnt->device->type)) - flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 1); - - tstatus = status_byte(spp->target_status); - -#if defined(DEBUG_GENERATE_ERRORS) - if ((ha->iocount > 500) && ((ha->iocount % 200) < 2)) - spp->adapter_status = 0x01; -#endif - - switch (spp->adapter_status) { - case ASOK: /* status OK */ - - /* Forces a reset if a disk drive keeps returning BUSY */ - if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) - status = DID_ERROR << 16; - - /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK - && ha->target_redo[SCpnt->device->id][SCpnt-> - device-> - channel]) - status = DID_BUS_BUSY << 16; - - /* Works around a flaw in scsi.c */ - else if (tstatus == CHECK_CONDITION - && SCpnt->device->type == TYPE_DISK - && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) - status = DID_BUS_BUSY << 16; - - else - status = DID_OK << 16; - - if (tstatus == GOOD) - ha->target_redo[SCpnt->device->id][SCpnt->device-> - channel] = 0; - - if (spp->target_status && SCpnt->device->type == TYPE_DISK && - (!(tstatus == CHECK_CONDITION && ha->iocount <= 1000 && - (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) - printk("%s: ihdlr, target %d.%d:%d, " - "target_status 0x%x, sense key 0x%x.\n", - ha->board_name, - SCpnt->device->channel, SCpnt->device->id, - (u8)SCpnt->device->lun, - spp->target_status, SCpnt->sense_buffer[2]); - - ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; - - if (ha->last_retried_pid == SCpnt->serial_number) - ha->retries = 0; - - break; - case ASST: /* Selection Time Out */ - case 0x02: /* Command Time Out */ - - if (ha->target_to[SCpnt->device->id][SCpnt->device->channel] > 1) - status = DID_ERROR << 16; - else { - status = DID_TIME_OUT << 16; - ha->target_to[SCpnt->device->id][SCpnt->device-> - channel]++; - } - - break; - - /* Perform a limited number of internal retries */ - case 0x03: /* SCSI Bus Reset Received */ - case 0x04: /* Initial Controller Power-up */ - - for (c = 0; c <= shost->max_channel; c++) - for (k = 0; k < shost->max_id; k++) - ha->target_redo[k][c] = 1; - - if (SCpnt->device->type != TYPE_TAPE - && ha->retries < MAX_INTERNAL_RETRIES) { - -#if defined(DID_SOFT_ERROR) - status = DID_SOFT_ERROR << 16; -#else - status = DID_BUS_BUSY << 16; -#endif - - ha->retries++; - ha->last_retried_pid = SCpnt->serial_number; - } else - status = DID_ERROR << 16; - - break; - case 0x05: /* Unexpected Bus Phase */ - case 0x06: /* Unexpected Bus Free */ - case 0x07: /* Bus Parity Error */ - case 0x08: /* SCSI Hung */ - case 0x09: /* Unexpected Message Reject */ - case 0x0a: /* SCSI Bus Reset Stuck */ - case 0x0b: /* Auto Request-Sense Failed */ - case 0x0c: /* Controller Ram Parity Error */ - default: - status = DID_ERROR << 16; - break; - } - - SCpnt->result = status | spp->target_status; - -#if defined(DEBUG_INTERRUPT) - if (SCpnt->result || do_trace) -#else - if ((spp->adapter_status != ASOK && ha->iocount > 1000) || - (spp->adapter_status != ASOK && - spp->adapter_status != ASST && ha->iocount <= 1000) || - do_trace || msg_byte(spp->target_status)) -#endif - scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x," - " reg 0x%x, count %d.\n", - i, spp->adapter_status, spp->target_status, - reg, ha->iocount); - - unmap_dma(i, ha); - - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; - - SCpnt->scsi_done(SCpnt); - - if (do_trace) - printk("%s: ihdlr, exit, irq %d, count %d.\n", ha->board_name, - irq, ha->iocount); - - handled: - return IRQ_HANDLED; - none: - return IRQ_NONE; -} - -static irqreturn_t do_interrupt_handler(int dummy, void *shap) -{ - struct Scsi_Host *shost; - unsigned int j; - unsigned long spin_flags; - irqreturn_t ret; - - /* Check if the interrupt must be processed by this handler */ - if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) - return IRQ_NONE; - shost = sh[j]; - - spin_lock_irqsave(shost->host_lock, spin_flags); - ret = ihdlr(shost); - spin_unlock_irqrestore(shost->host_lock, spin_flags); - return ret; -} - -static int eata2x_release(struct Scsi_Host *shost) -{ - struct hostdata *ha = (struct hostdata *)shost->hostdata; - unsigned int i; - - for (i = 0; i < shost->can_queue; i++) - kfree((&ha->cp[i])->sglist); - - for (i = 0; i < shost->can_queue; i++) - pci_unmap_single(ha->pdev, ha->cp[i].cp_dma_addr, - sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); - - if (ha->sp_cpu_addr) - pci_free_consistent(ha->pdev, sizeof(struct mssp), - ha->sp_cpu_addr, ha->sp_dma_addr); - - free_irq(shost->irq, &sha[ha->board_number]); - - if (shost->dma_channel != NO_DMA) - free_dma(shost->dma_channel); - - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -#include "scsi_module.c" - -#ifndef MODULE -__setup("eata=", option_setup); -#endif /* end MODULE */ diff --git a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h deleted file mode 100644 index 1a396c5e7f73..000000000000 --- a/drivers/scsi/eata_generic.h +++ /dev/null @@ -1,401 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/******************************************************** -* Header file for eata_dma.c and eata_pio.c * -* Linux EATA SCSI drivers * -* (c) 1993-96 Michael Neuffer * -* mike@i-Connect.Net * -* neuffer@mail.uni-mainz.de * -********************************************************* -* last change: 96/08/14 * -********************************************************/ - - -#ifndef _EATA_GENERIC_H -#define _EATA_GENERIC_H - - - -/********************************************* - * Misc. definitions * - *********************************************/ - -#define R_LIMIT 0x20000 - -#define MAXISA 4 -#define MAXEISA 16 -#define MAXPCI 16 -#define MAXIRQ 16 -#define MAXTARGET 16 -#define MAXCHANNEL 3 - -#define IS_ISA 'I' -#define IS_EISA 'E' -#define IS_PCI 'P' - -#define BROKEN_INQUIRY 1 - -#define BUSMASTER 0xff -#define PIO 0xfe - -#define EATA_SIGNATURE 0x45415441 /* BIG ENDIAN coded "EATA" sig. */ - -#define DPT_ID1 0x12 -#define DPT_ID2 0x14 - -#define ATT_ID1 0x06 -#define ATT_ID2 0x94 -#define ATT_ID3 0x0 - -#define NEC_ID1 0x38 -#define NEC_ID2 0xa3 -#define NEC_ID3 0x82 - - -#define EATA_CP_SIZE 44 - -#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */ -#define MAX_METHOD_2 16 /* Max Devices For Method 2 */ -#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */ - -#define SG_SIZE 64 -#define SG_SIZE_BIG 252 /* max. 8096 elements, 64k */ - -#define UPPER_DEVICE_QUEUE_LIMIT 64 /* The limit we have to set for the - * device queue to keep the broken - * midlevel SCSI code from producing - * bogus timeouts - */ - -#define TYPE_DISK_QUEUE 16 -#define TYPE_TAPE_QUEUE 4 -#define TYPE_ROM_QUEUE 4 -#define TYPE_OTHER_QUEUE 2 - -#define FREE 0 -#define OK 0 -#define NO_TIMEOUT 0 -#define USED 1 -#define TIMEOUT 2 -#define RESET 4 -#define LOCKED 8 -#define ABORTED 16 - -#define READ 0 -#define WRITE 1 -#define OTHER 2 - -#define HD(cmd) ((hostdata *)&(cmd->device->host->hostdata)) -#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble)) -#define SD(host) ((hostdata *)&(host->hostdata)) - -/*********************************************** - * EATA Command & Register definitions * - ***********************************************/ -#define PCI_REG_DPTconfig 0x40 -#define PCI_REG_PumpModeAddress 0x44 -#define PCI_REG_PumpModeData 0x48 -#define PCI_REG_ConfigParam1 0x50 -#define PCI_REG_ConfigParam2 0x54 - - -#define EATA_CMD_PIO_SETUPTEST 0xc6 -#define EATA_CMD_PIO_READ_CONFIG 0xf0 -#define EATA_CMD_PIO_SET_CONFIG 0xf1 -#define EATA_CMD_PIO_SEND_CP 0xf2 -#define EATA_CMD_PIO_RECEIVE_SP 0xf3 -#define EATA_CMD_PIO_TRUNC 0xf4 - -#define EATA_CMD_RESET 0xf9 -#define EATA_CMD_IMMEDIATE 0xfa - -#define EATA_CMD_DMA_READ_CONFIG 0xfd -#define EATA_CMD_DMA_SET_CONFIG 0xfe -#define EATA_CMD_DMA_SEND_CP 0xff - -#define ECS_EMULATE_SENSE 0xd4 - -#define EATA_GENERIC_ABORT 0x00 -#define EATA_SPECIFIC_RESET 0x01 -#define EATA_BUS_RESET 0x02 -#define EATA_SPECIFIC_ABORT 0x03 -#define EATA_QUIET_INTR 0x04 -#define EATA_COLD_BOOT_HBA 0x06 /* Only as a last resort */ -#define EATA_FORCE_IO 0x07 - -#define HA_CTRLREG 0x206 /* control register for HBA */ -#define HA_CTRL_DISINT 0x02 /* CTRLREG: disable interrupts */ -#define HA_CTRL_RESCPU 0x04 /* CTRLREG: reset processor */ -#define HA_CTRL_8HEADS 0x08 /* CTRLREG: set for drives with* - * >=8 heads (WD1003 rudimentary :-) */ - -#define HA_WCOMMAND 0x07 /* command register offset */ -#define HA_WIFC 0x06 /* immediate command offset */ -#define HA_WCODE 0x05 -#define HA_WCODE2 0x04 -#define HA_WDMAADDR 0x02 /* DMA address LSB offset */ -#define HA_RAUXSTAT 0x08 /* aux status register offset*/ -#define HA_RSTATUS 0x07 /* status register offset */ -#define HA_RDATA 0x00 /* data register (16bit) */ -#define HA_WDATA 0x00 /* data register (16bit) */ - -#define HA_ABUSY 0x01 /* aux busy bit */ -#define HA_AIRQ 0x02 /* aux IRQ pending bit */ -#define HA_SERROR 0x01 /* pr. command ended in error*/ -#define HA_SMORE 0x02 /* more data soon to come */ -#define HA_SCORR 0x04 /* data corrected */ -#define HA_SDRQ 0x08 /* data request active */ -#define HA_SSC 0x10 /* seek complete */ -#define HA_SFAULT 0x20 /* write fault */ -#define HA_SREADY 0x40 /* drive ready */ -#define HA_SBUSY 0x80 /* drive busy */ -#define HA_SDRDY HA_SSC+HA_SREADY+HA_SDRQ - -/********************************************** - * Message definitions * - **********************************************/ - -#define HA_NO_ERROR 0x00 /* No Error */ -#define HA_ERR_SEL_TO 0x01 /* Selection Timeout */ -#define HA_ERR_CMD_TO 0x02 /* Command Timeout */ -#define HA_BUS_RESET 0x03 /* SCSI Bus Reset Received */ -#define HA_INIT_POWERUP 0x04 /* Initial Controller Power-up */ -#define HA_UNX_BUSPHASE 0x05 /* Unexpected Bus Phase */ -#define HA_UNX_BUS_FREE 0x06 /* Unexpected Bus Free */ -#define HA_BUS_PARITY 0x07 /* Bus Parity Error */ -#define HA_SCSI_HUNG 0x08 /* SCSI Hung */ -#define HA_UNX_MSGRJCT 0x09 /* Unexpected Message Rejected */ -#define HA_RESET_STUCK 0x0a /* SCSI Bus Reset Stuck */ -#define HA_RSENSE_FAIL 0x0b /* Auto Request-Sense Failed */ -#define HA_PARITY_ERR 0x0c /* Controller Ram Parity Error */ -#define HA_CP_ABORT_NA 0x0d /* Abort Message sent to non-active cmd */ -#define HA_CP_ABORTED 0x0e /* Abort Message sent to active cmd */ -#define HA_CP_RESET_NA 0x0f /* Reset Message sent to non-active cmd */ -#define HA_CP_RESET 0x10 /* Reset Message sent to active cmd */ -#define HA_ECC_ERR 0x11 /* Controller Ram ECC Error */ -#define HA_PCI_PARITY 0x12 /* PCI Parity Error */ -#define HA_PCI_MABORT 0x13 /* PCI Master Abort */ -#define HA_PCI_TABORT 0x14 /* PCI Target Abort */ -#define HA_PCI_STABORT 0x15 /* PCI Signaled Target Abort */ - -/********************************************** - * Other definitions * - **********************************************/ - -struct reg_bit { /* reading this one will clear the interrupt */ - __u8 error:1; /* previous command ended in an error */ - __u8 more:1; /* more DATA coming soon, poll BSY & DRQ (PIO) */ - __u8 corr:1; /* data read was successfully corrected with ECC*/ - __u8 drq:1; /* data request active */ - __u8 sc:1; /* seek complete */ - __u8 fault:1; /* write fault */ - __u8 ready:1; /* drive ready */ - __u8 busy:1; /* controller busy */ -}; - -struct reg_abit { /* reading this won't clear the interrupt */ - __u8 abusy:1; /* auxiliary busy */ - __u8 irq:1; /* set when drive interrupt is asserted */ - __u8 dummy:6; -}; - -struct eata_register { /* EATA register set */ - __u8 data_reg[2]; /* R, couldn't figure this one out */ - __u8 cp_addr[4]; /* W, CP address register */ - union { - __u8 command; /* W, command code: [read|set] conf, send CP*/ - struct reg_bit status; /* R, see register_bit1 */ - __u8 statusbyte; - } ovr; - struct reg_abit aux_stat; /* R, see register_bit2 */ -}; - -struct get_conf { /* Read Configuration Array */ - __u32 len; /* Should return 0x22, 0x24, etc */ - __u32 signature; /* Signature MUST be "EATA" */ - __u8 version2:4, - version:4; /* EATA Version level */ - __u8 OCS_enabled:1, /* Overlap Command Support enabled */ - TAR_support:1, /* SCSI Target Mode supported */ - TRNXFR:1, /* Truncate Transfer Cmd not necessary * - * Only used in PIO Mode */ - MORE_support:1, /* MORE supported (only PIO Mode) */ - DMA_support:1, /* DMA supported Driver uses only * - * this mode */ - DMA_valid:1, /* DRQ value in Byte 30 is valid */ - ATA:1, /* ATA device connected (not supported) */ - HAA_valid:1; /* Hostadapter Address is valid */ - - __u16 cppadlen; /* Number of pad bytes send after CD data * - * set to zero for DMA commands */ - __u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. * - * if not, zero is returned */ - __u32 cplen; /* CP length: number of valid cp bytes */ - __u32 splen; /* Number of bytes returned after * - * Receive SP command */ - __u16 queuesiz; /* max number of queueable CPs */ - __u16 dummy; - __u16 SGsiz; /* max number of SG table entries */ - __u8 IRQ:4, /* IRQ used this HA */ - IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */ - SECOND:1, /* This is a secondary controller */ - DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */ - __u8 sync; /* device at ID 7 tru 0 is running in * - * synchronous mode, this will disappear */ - __u8 DSBLE:1, /* ISA i/o addressing is disabled */ - FORCADR:1, /* i/o address has been forced */ - SG_64K:1, - SG_UAE:1, - :4; - __u8 MAX_ID:5, /* Max number of SCSI target IDs */ - MAX_CHAN:3; /* Number of SCSI busses on HBA */ - __u8 MAX_LUN; /* Max number of LUNs */ - __u8 :3, - AUTOTRM:1, - M1_inst:1, - ID_qest:1, /* Raidnum ID is questionable */ - is_PCI:1, /* HBA is PCI */ - is_EISA:1; /* HBA is EISA */ - __u8 RAIDNUM; /* unique HBA identifier */ - __u8 unused[474]; -}; - -struct eata_sg_list -{ - __u32 data; - __u32 len; -}; - -struct eata_ccb { /* Send Command Packet structure */ - - __u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */ - HBA_Init:1, /* Cause Controller to reinitialize */ - Auto_Req_Sen:1, /* Do Auto Request Sense on errors */ - scatter:1, /* Data Ptr points to a SG Packet */ - Resrvd:1, /* RFU */ - Interpret:1, /* Interpret the SCSI cdb of own use */ - DataOut:1, /* Data Out phase with command */ - DataIn:1; /* Data In phase with command */ - __u8 reqlen; /* Request Sense Length * - * Valid if Auto_Req_Sen=1 */ - __u8 unused[3]; - __u8 FWNEST:1, /* send cmd to phys RAID component */ - unused2:7; - __u8 Phsunit:1, /* physical unit on mirrored pair */ - I_AT:1, /* inhibit address translation */ - I_HBA_C:1, /* HBA inhibit caching */ - unused3:5; - - __u8 cp_id:5, /* SCSI Device ID of target */ - cp_channel:3; /* SCSI Channel # of HBA */ - __u8 cp_lun:3, - :2, - cp_luntar:1, /* CP is for target ROUTINE */ - cp_dispri:1, /* Grant disconnect privilege */ - cp_identify:1; /* Always TRUE */ - __u8 cp_msg1; /* Message bytes 0-3 */ - __u8 cp_msg2; - __u8 cp_msg3; - __u8 cp_cdb[12]; /* Command Descriptor Block */ - __u32 cp_datalen; /* Data Transfer Length * - * If scatter=1 len of sg package */ - void *cp_viraddr; /* address of this ccb */ - __u32 cp_dataDMA; /* Data Address, if scatter=1 * - * address of scatter packet */ - __u32 cp_statDMA; /* address for Status Packet */ - __u32 cp_reqDMA; /* Request Sense Address, used if * - * CP command ends with error */ - /* Additional CP info begins here */ - __u32 timestamp; /* Needed to measure command latency */ - __u32 timeout; - __u8 sizeindex; - __u8 rw_latency; - __u8 retries; - __u8 status; /* status of this queueslot */ - struct scsi_cmnd *cmd; /* address of cmd */ - struct eata_sg_list *sg_list; -}; - - -struct eata_sp { - __u8 hba_stat:7, /* HBA status */ - EOC:1; /* True if command finished */ - __u8 scsi_stat; /* Target SCSI status */ - __u8 reserved[2]; - __u32 residue_len; /* Number of bytes not transferred */ - struct eata_ccb *ccb; /* Address set in COMMAND PACKET */ - __u8 msg[12]; -}; - -typedef struct hstd { - __u8 vendor[9]; - __u8 name[18]; - __u8 revision[6]; - __u8 EATA_revision; - __u32 firmware_revision; - __u8 HBA_number; - __u8 bustype; /* bustype of HBA */ - __u8 channel; /* # of avail. scsi channels */ - __u8 state; /* state of HBA */ - __u8 primary; /* true if primary */ - __u8 more_support:1, /* HBA supports MORE flag */ - immediate_support:1, /* HBA supports IMMEDIATE CMDs*/ - broken_INQUIRY:1; /* This is an EISA HBA with * - * broken INQUIRY */ - __u8 do_latency; /* Latency measurement flag */ - __u32 reads[13]; - __u32 writes[13]; - __u32 reads_lat[12][4]; - __u32 writes_lat[12][4]; - __u32 all_lat[4]; - __u8 resetlevel[MAXCHANNEL]; - __u32 last_ccb; /* Last used ccb */ - __u32 cplen; /* size of CP in words */ - __u16 cppadlen; /* pad length of cp in words */ - __u16 queuesize; - __u16 sgsize; /* # of entries in the SG list*/ - __u16 devflags; /* bits set for detected devices */ - __u8 hostid; /* SCSI ID of HBA */ - __u8 moresupport; /* HBA supports MORE flag */ - struct Scsi_Host *next; - struct Scsi_Host *prev; - struct pci_dev *pdev; /* PCI device or NULL for non PCI */ - struct eata_sp sp; /* status packet */ - struct eata_ccb ccb[0]; /* ccb array begins here */ -}hostdata; - -/* structure for max. 2 emulated drives */ -struct drive_geom_emul { - __u8 trans; /* translation flag 1=transl */ - __u8 channel; /* SCSI channel number */ - __u8 HBA; /* HBA number (prim/sec) */ - __u8 id; /* drive id */ - __u8 lun; /* drive lun */ - __u32 heads; /* number of heads */ - __u32 sectors; /* number of sectors */ - __u32 cylinder; /* number of cylinders */ -}; - -struct geom_emul { - __u8 bios_drives; /* number of emulated drives */ - struct drive_geom_emul drv[2]; /* drive structures */ -}; - -#endif /* _EATA_GENERIC_H */ - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c deleted file mode 100644 index 4299fa485622..000000000000 --- a/drivers/scsi/eata_pio.c +++ /dev/null @@ -1,966 +0,0 @@ -/************************************************************ - * * - * Linux EATA SCSI PIO driver * - * * - * based on the CAM document CAM/89-004 rev. 2.0c, * - * DPT's driver kit, some internal documents and source, * - * and several other Linux scsi drivers and kernel docs. * - * * - * The driver currently: * - * -supports all EATA-PIO boards * - * -only supports DASD devices * - * * - * (c)1993-96 Michael Neuffer, Alfred Arnold * - * neuffer@goofy.zdv.uni-mainz.de * - * a.arnold@kfa-juelich.de * - * * - * Updated 2002 by Alan Cox for * - * Linux 2.5.x and the newer locking and error handling * - * * - * This program is free software; you can redistribute it * - * and/or modify it under the terms of the GNU General * - * Public License as published by the Free Software * - * Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the * - * implied warranty of MERCHANTABILITY or FITNESS FOR A * - * PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General * - * Public License along with this kernel; if not, write to * - * the Free Software Foundation, Inc., 675 Mass Ave, * - * Cambridge, MA 02139, USA. * - * * - * For the avoidance of doubt the "preferred form" of this * - * code is one which is in an open non patent encumbered * - * format. Where cryptographic key signing forms part of * - * the process of creating an executable the information * - * including keys needed to generate an equivalently * - * functional executable are deemed to be part of the * - * source code are deemed to be part of the source code. * - * * - ************************************************************ - * last change: 2002/11/02 OS: Linux 2.5.45 * - ************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "eata_generic.h" -#include "eata_pio.h" - - -static unsigned int ISAbases[MAXISA] = { - 0x1F0, 0x170, 0x330, 0x230 -}; - -static unsigned int ISAirqs[MAXISA] = { - 14, 12, 15, 11 -}; - -static unsigned char EISAbases[] = { - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 -}; - -static unsigned int registered_HBAs; -static struct Scsi_Host *last_HBA; -static struct Scsi_Host *first_HBA; -static unsigned char reg_IRQ[16]; -static unsigned char reg_IRQL[16]; -static unsigned long int_counter; -static unsigned long queue_counter; - -static struct scsi_host_template driver_template; - -static int eata_pio_show_info(struct seq_file *m, struct Scsi_Host *shost) -{ - seq_printf(m, "EATA (Extended Attachment) PIO driver version: " - "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB); - seq_printf(m, "queued commands: %10ld\n" - "processed interrupts:%10ld\n", queue_counter, int_counter); - seq_printf(m, "\nscsi%-2d: HBA %.10s\n", - shost->host_no, SD(shost)->name); - seq_printf(m, "Firmware revision: v%s\n", - SD(shost)->revision); - seq_puts(m, "IO: PIO\n"); - seq_printf(m, "Base IO : %#.4x\n", (u32) shost->base); - seq_printf(m, "Host Bus: %s\n", - (SD(shost)->bustype == 'P')?"PCI ": - (SD(shost)->bustype == 'E')?"EISA":"ISA "); - return 0; -} - -static int eata_pio_release(struct Scsi_Host *sh) -{ - hostdata *hd = SD(sh); - if (sh->irq && reg_IRQ[sh->irq] == 1) - free_irq(sh->irq, NULL); - else - reg_IRQ[sh->irq]--; - if (SD(sh)->channel == 0) { - if (sh->io_port && sh->n_io_port) - release_region(sh->io_port, sh->n_io_port); - } - /* At this point the PCI reference can go */ - if (hd->pdev) - pci_dev_put(hd->pdev); - return 1; -} - -static void IncStat(struct scsi_pointer *SCp, unsigned int Increment) -{ - SCp->ptr += Increment; - if ((SCp->this_residual -= Increment) == 0) { - if ((--SCp->buffers_residual) == 0) - SCp->Status = 0; - else { - SCp->buffer++; - SCp->ptr = sg_virt(SCp->buffer); - SCp->this_residual = SCp->buffer->length; - } - } -} - -static irqreturn_t eata_pio_int_handler(int irq, void *dev_id); - -static irqreturn_t do_eata_pio_int_handler(int irq, void *dev_id) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - irqreturn_t ret; - - spin_lock_irqsave(dev->host_lock, flags); - ret = eata_pio_int_handler(irq, dev_id); - spin_unlock_irqrestore(dev->host_lock, flags); - return ret; -} - -static irqreturn_t eata_pio_int_handler(int irq, void *dev_id) -{ - unsigned int eata_stat = 0xfffff; - struct scsi_cmnd *cmd; - hostdata *hd; - struct eata_ccb *cp; - unsigned long base; - unsigned int x, z; - struct Scsi_Host *sh; - unsigned short zwickel = 0; - unsigned char stat, odd; - irqreturn_t ret = IRQ_NONE; - - for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) - { - if (sh->irq != irq) - continue; - if (inb(sh->base + HA_RSTATUS) & HA_SBUSY) - continue; - - int_counter++; - ret = IRQ_HANDLED; - - hd = SD(sh); - - cp = &hd->ccb[0]; - cmd = cp->cmd; - base = cmd->device->host->base; - - do { - stat = inb(base + HA_RSTATUS); - if (stat & HA_SDRQ) { - if (cp->DataIn) { - z = 256; - odd = 0; - while ((cmd->SCp.Status) && ((z > 0) || (odd))) { - if (odd) { - *(cmd->SCp.ptr) = zwickel >> 8; - IncStat(&cmd->SCp, 1); - odd = 0; - } - x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); - insw(base + HA_RDATA, cmd->SCp.ptr, x); - z -= x; - IncStat(&cmd->SCp, 2 * x); - if ((z > 0) && (cmd->SCp.this_residual == 1)) { - zwickel = inw(base + HA_RDATA); - *(cmd->SCp.ptr) = zwickel & 0xff; - IncStat(&cmd->SCp, 1); - z--; - odd = 1; - } - } - while (z > 0) { - zwickel = inw(base + HA_RDATA); - z--; - } - } else { /* cp->DataOut */ - - odd = 0; - z = 256; - while ((cmd->SCp.Status) && ((z > 0) || (odd))) { - if (odd) { - zwickel += *(cmd->SCp.ptr) << 8; - IncStat(&cmd->SCp, 1); - outw(zwickel, base + HA_RDATA); - z--; - odd = 0; - } - x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); - outsw(base + HA_RDATA, cmd->SCp.ptr, x); - z -= x; - IncStat(&cmd->SCp, 2 * x); - if ((z > 0) && (cmd->SCp.this_residual == 1)) { - zwickel = *(cmd->SCp.ptr); - zwickel &= 0xff; - IncStat(&cmd->SCp, 1); - odd = 1; - } - } - while (z > 0 || odd) { - outw(zwickel, base + HA_RDATA); - z--; - odd = 0; - } - } - } - } - while ((stat & HA_SDRQ) || ((stat & HA_SMORE) && hd->moresupport)); - - /* terminate handler if HBA goes busy again, i.e. transfers - * more data */ - - if (stat & HA_SBUSY) - break; - - /* OK, this is quite stupid, but I haven't found any correct - * way to get HBA&SCSI status so far */ - - if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { - cmd->result = (DID_OK << 16); - hd->devflags |= (1 << cp->cp_id); - } else if (hd->devflags & (1 << cp->cp_id)) - cmd->result = (DID_OK << 16) + 0x02; - else - cmd->result = (DID_NO_CONNECT << 16); - - if (cp->status == LOCKED) { - cp->status = FREE; - eata_stat = inb(base + HA_RSTATUS); - printk(KERN_CRIT "eata_pio: int_handler, freeing locked " "queueslot\n"); - return ret; - } -#if DBG_INTR2 - if (stat != 0x50) - printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, cmd->result); -#endif - - cp->status = FREE; /* now we can release the slot */ - - cmd->scsi_done(cmd); - } - - return ret; -} - -static inline unsigned int eata_pio_send_command(unsigned long base, unsigned char command) -{ - unsigned int loop = 50; - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return 1; - - /* Enable interrupts for HBA. It is not the best way to do it at this - * place, but I hope that it doesn't interfere with the IDE driver - * initialization this way */ - - outb(HA_CTRL_8HEADS, base + HA_CTRLREG); - - outb(command, base + HA_WCOMMAND); - return 0; -} - -static int eata_pio_queue_lck(struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) -{ - unsigned int x, y; - unsigned long base; - - hostdata *hd; - struct Scsi_Host *sh; - struct eata_ccb *cp; - - queue_counter++; - - hd = HD(cmd); - sh = cmd->device->host; - base = sh->base; - - /* use only slot 0, as 2001 can handle only one cmd at a time */ - - y = x = 0; - - if (hd->ccb[y].status != FREE) { - - DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", sh->can_queue, x, y)); -#if DEBUG_EATA - panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " "intrno: %ld\n", queue_counter, int_counter); -#else - panic(KERN_EMERG "eata_pio: run out of queue slots....\n"); -#endif - } - - cp = &hd->ccb[y]; - - memset(cp, 0, sizeof(struct eata_ccb)); - - cp->status = USED; /* claim free slot */ - - DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, - "eata_pio_queue 0x%p, y %d\n", cmd, y)); - - cmd->scsi_done = (void *) done; - - if (cmd->sc_data_direction == DMA_TO_DEVICE) - cp->DataOut = 1; /* Output mode */ - else - cp->DataIn = 0; /* Input mode */ - - cp->Interpret = (cmd->device->id == hd->hostid); - cp->cp_datalen = cpu_to_be32(scsi_bufflen(cmd)); - cp->Auto_Req_Sen = 0; - cp->cp_reqDMA = 0; - cp->reqlen = 0; - - cp->cp_id = cmd->device->id; - cp->cp_lun = cmd->device->lun; - cp->cp_dispri = 0; - cp->cp_identify = 1; - memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); - - cp->cp_statDMA = 0; - - cp->cp_viraddr = cp; - cp->cmd = cmd; - cmd->host_scribble = (char *) &hd->ccb[y]; - - if (!scsi_bufflen(cmd)) { - cmd->SCp.buffers_residual = 1; - cmd->SCp.ptr = NULL; - cmd->SCp.this_residual = 0; - cmd->SCp.buffer = NULL; - } else { - cmd->SCp.buffer = scsi_sglist(cmd); - cmd->SCp.buffers_residual = scsi_sg_count(cmd); - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - cmd->SCp.this_residual = cmd->SCp.buffer->length; - } - cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes - * are to transfer */ - - if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) { - cmd->result = DID_BUS_BUSY << 16; - scmd_printk(KERN_NOTICE, cmd, - "eata_pio_queue pid 0x%p, HBA busy, " - "returning DID_BUS_BUSY, done.\n", cmd); - done(cmd); - cp->status = FREE; - return 0; - } - /* FIXME: timeout */ - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - cpu_relax(); - outsw(base + HA_RDATA, cp, hd->cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (x = 0; x < hd->cppadlen; x++) - outw(0, base + HA_RDATA); - - DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, - "Queued base %#.4lx cmd: 0x%p " - "slot %d irq %d\n", sh->base, cmd, y, sh->irq)); - - return 0; -} - -static DEF_SCSI_QCMD(eata_pio_queue) - -static int eata_pio_abort(struct scsi_cmnd *cmd) -{ - unsigned int loop = 100; - - DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, - "eata_pio_abort called pid: 0x%p\n", cmd)); - - while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY) - if (--loop == 0) { - printk(KERN_WARNING "eata_pio: abort, timeout error.\n"); - return FAILED; - } - if (CD(cmd)->status == FREE) { - DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n")); - return FAILED; - } - if (CD(cmd)->status == USED) { - DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n")); - /* We want to sleep a bit more here */ - return FAILED; /* SNOOZE */ - } - if (CD(cmd)->status == RESET) { - printk(KERN_WARNING "eata_pio: abort, command reset error.\n"); - return FAILED; - } - if (CD(cmd)->status == LOCKED) { - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot " "locked.\n")); - return FAILED; - } - panic("eata_pio: abort: invalid slot status\n"); -} - -static int eata_pio_host_reset(struct scsi_cmnd *cmd) -{ - unsigned int x, limit = 0; - unsigned char success = 0; - struct scsi_cmnd *sp; - struct Scsi_Host *host = cmd->device->host; - - DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, - "eata_pio_reset called\n")); - - spin_lock_irq(host->host_lock); - - if (HD(cmd)->state == RESET) { - printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n"); - spin_unlock_irq(host->host_lock); - return FAILED; - } - - /* force all slots to be free */ - - for (x = 0; x < cmd->device->host->can_queue; x++) { - - if (HD(cmd)->ccb[x].status == FREE) - continue; - - sp = HD(cmd)->ccb[x].cmd; - HD(cmd)->ccb[x].status = RESET; - printk(KERN_WARNING "eata_pio_reset: slot %d in reset.\n", x); - - if (sp == NULL) - panic("eata_pio_reset: slot %d, sp==NULL.\n", x); - } - - /* hard reset the HBA */ - outb(EATA_CMD_RESET, cmd->device->host->base + HA_WCOMMAND); - - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n")); - HD(cmd)->state = RESET; - - spin_unlock_irq(host->host_lock); - msleep(3000); - spin_lock_irq(host->host_lock); - - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit)); - - for (x = 0; x < cmd->device->host->can_queue; x++) { - - /* Skip slots already set free by interrupt */ - if (HD(cmd)->ccb[x].status != RESET) - continue; - - sp = HD(cmd)->ccb[x].cmd; - sp->result = DID_RESET << 16; - - /* This mailbox is terminated */ - printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n", x); - HD(cmd)->ccb[x].status = FREE; - - sp->scsi_done(sp); - } - - HD(cmd)->state = 0; - - spin_unlock_irq(host->host_lock); - - if (success) { /* hmmm... */ - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n")); - return SUCCESS; - } else { - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n")); - return FAILED; - } -} - -static char *get_pio_board_data(unsigned long base, unsigned int irq, unsigned int id, unsigned long cplen, unsigned short cppadlen) -{ - struct eata_ccb cp; - static char buff[256]; - int z; - - memset(&cp, 0, sizeof(struct eata_ccb)); - memset(buff, 0, sizeof(buff)); - - cp.DataIn = 1; - cp.Interpret = 1; /* Interpret command */ - - cp.cp_datalen = cpu_to_be32(254); - cp.cp_dataDMA = cpu_to_be32(0); - - cp.cp_id = id; - cp.cp_lun = 0; - - cp.cp_cdb[0] = INQUIRY; - cp.cp_cdb[1] = 0; - cp.cp_cdb[2] = 0; - cp.cp_cdb[3] = 0; - cp.cp_cdb[4] = 254; - cp.cp_cdb[5] = 0; - - if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) - return NULL; - - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - cpu_relax(); - - outsw(base + HA_RDATA, &cp, cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (z = 0; z < cppadlen; z++) - outw(0, base + HA_RDATA); - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - cpu_relax(); - - if (inb(base + HA_RSTATUS) & HA_SERROR) - return NULL; - else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - return NULL; - else { - insw(base + HA_RDATA, &buff, 127); - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - return buff; - } -} - -static int get_pio_conf_PIO(unsigned long base, struct get_conf *buf) -{ - unsigned long loop = HZ / 2; - int z; - unsigned short *p; - - if (!request_region(base, 9, "eata_pio")) - return 0; - - memset(buf, 0, sizeof(struct get_conf)); - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - goto fail; - - DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#lx\n", base)); - eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); - - loop = 50; - for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) { - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - if (--loop == 0) - goto fail; - - loop = 50; - *p = inw(base + HA_RDATA); - } - if (inb(base + HA_RSTATUS) & HA_SERROR) { - DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during " - "transfer for HBA at %lx\n", base)); - goto fail; - } - - if (cpu_to_be32(EATA_SIGNATURE) != buf->signature) - goto fail; - - DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " - "at %#4lx EATA Level: %x\n", - base, (unsigned int) (buf->version))); - - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - - if (!ALLOW_DMA_BOARDS) { - for (z = 0; z < MAXISA; z++) - if (base == ISAbases[z]) { - buf->IRQ = ISAirqs[z]; - break; - } - } - - return 1; - - fail: - release_region(base, 9); - return 0; -} - -static void print_pio_config(struct get_conf *gc) -{ - printk("Please check values: (read config data)\n"); - printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", be32_to_cpu(gc->len), gc->version, gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support); - printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], gc->scsi_id[1], be16_to_cpu(gc->queuesiz), be16_to_cpu(gc->SGsiz), gc->SECOND); - printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", gc->IRQ, gc->IRQ_TR, gc->FORCADR, gc->MAX_CHAN, gc->ID_qest); -} - -static unsigned int print_selftest(unsigned int base) -{ - unsigned char buffer[512]; -#ifdef VERBOSE_SETUP - int z; -#endif - - printk("eata_pio: executing controller self test & setup...\n"); - while (inb(base + HA_RSTATUS) & HA_SBUSY); - outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND); - do { - while (inb(base + HA_RSTATUS) & HA_SBUSY) - /* nothing */ ; - if (inb(base + HA_RSTATUS) & HA_SDRQ) { - insw(base + HA_RDATA, &buffer, 256); -#ifdef VERBOSE_SETUP - /* no beeps please... */ - for (z = 0; z < 511 && buffer[z]; z++) - if (buffer[z] != 7) - printk("%c", buffer[z]); -#endif - } - } while (inb(base + HA_RSTATUS) & (HA_SBUSY | HA_SDRQ)); - - return (!(inb(base + HA_RSTATUS) & HA_SERROR)); -} - -static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev) -{ - unsigned long size = 0; - char *buff; - unsigned long cplen; - unsigned short cppadlen; - struct Scsi_Host *sh; - hostdata *hd; - - DBG(DBG_REGISTER, print_pio_config(gc)); - - if (gc->DMA_support) { - printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base); - if (!ALLOW_DMA_BOARDS) - return 0; - } - - if ((buff = get_pio_board_data(base, gc->IRQ, gc->scsi_id[3], cplen = (cpu_to_be32(gc->cplen) + 1) / 2, cppadlen = (cpu_to_be16(gc->cppadlen) + 1) / 2)) == NULL) { - printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", base); - return 0; - } - - if (!print_selftest(base) && !ALLOW_DMA_BOARDS) { - printk("HBA at %#lx failed while performing self test & setup.\n", base); - return 0; - } - - size = sizeof(hostdata) + (sizeof(struct eata_ccb) * be16_to_cpu(gc->queuesiz)); - - sh = scsi_register(&driver_template, size); - if (sh == NULL) - return 0; - - if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ - if (!request_irq(gc->IRQ, do_eata_pio_int_handler, 0, "EATA-PIO", sh)) { - reg_IRQ[gc->IRQ]++; - if (!gc->IRQ_TR) - reg_IRQL[gc->IRQ] = 1; /* IRQ is edge triggered */ - } else { - printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); - return 0; - } - } else { /* More than one HBA on this IRQ */ - if (reg_IRQL[gc->IRQ]) { - printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n"); - return 0; - } else - reg_IRQ[gc->IRQ]++; - } - - hd = SD(sh); - - memset(hd->ccb, 0, (sizeof(struct eata_ccb) * be16_to_cpu(gc->queuesiz))); - memset(hd->reads, 0, sizeof(hd->reads)); - - strlcpy(SD(sh)->vendor, &buff[8], sizeof(SD(sh)->vendor)); - strlcpy(SD(sh)->name, &buff[16], sizeof(SD(sh)->name)); - SD(sh)->revision[0] = buff[32]; - SD(sh)->revision[1] = buff[33]; - SD(sh)->revision[2] = buff[34]; - SD(sh)->revision[3] = '.'; - SD(sh)->revision[4] = buff[35]; - SD(sh)->revision[5] = 0; - - switch (be32_to_cpu(gc->len)) { - case 0x1c: - SD(sh)->EATA_revision = 'a'; - break; - case 0x1e: - SD(sh)->EATA_revision = 'b'; - break; - case 0x22: - SD(sh)->EATA_revision = 'c'; - break; - case 0x24: - SD(sh)->EATA_revision = 'z'; - break; - default: - SD(sh)->EATA_revision = '?'; - } - - if (be32_to_cpu(gc->len) >= 0x22) { - if (gc->is_PCI) - hd->bustype = IS_PCI; - else if (gc->is_EISA) - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } else { - if (buff[21] == '4') - hd->bustype = IS_PCI; - else if (buff[21] == '2') - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } - - SD(sh)->cplen = cplen; - SD(sh)->cppadlen = cppadlen; - SD(sh)->hostid = gc->scsi_id[3]; - SD(sh)->devflags = 1 << gc->scsi_id[3]; - SD(sh)->moresupport = gc->MORE_support; - sh->unique_id = base; - sh->base = base; - sh->io_port = base; - sh->n_io_port = 9; - sh->irq = gc->IRQ; - sh->dma_channel = PIO; - sh->this_id = gc->scsi_id[3]; - sh->can_queue = 1; - sh->cmd_per_lun = 1; - sh->sg_tablesize = SG_ALL; - - hd->channel = 0; - - hd->pdev = pci_dev_get(pdev); /* Keep a PCI reference */ - - sh->max_id = 8; - sh->max_lun = 8; - - if (gc->SECOND) - hd->primary = 0; - else - hd->primary = 1; - - hd->next = NULL; /* build a linked list of all HBAs */ - hd->prev = last_HBA; - if (hd->prev != NULL) - SD(hd->prev)->next = sh; - last_HBA = sh; - if (first_HBA == NULL) - first_HBA = sh; - registered_HBAs++; - return (1); -} - -static void find_pio_ISA(struct get_conf *buf) -{ - int i; - - for (i = 0; i < MAXISA; i++) { - if (!ISAbases[i]) - continue; - if (!get_pio_conf_PIO(ISAbases[i], buf)) - continue; - if (!register_pio_HBA(ISAbases[i], buf, NULL)) - release_region(ISAbases[i], 9); - else - ISAbases[i] = 0; - } - return; -} - -static void find_pio_EISA(struct get_conf *buf) -{ - u32 base; - int i; - -#ifdef CHECKPAL - u8 pal1, pal2, pal3; -#endif - - for (i = 0; i < MAXEISA; i++) { - if (EISAbases[i]) { /* Still a possibility ? */ - - base = 0x1c88 + (i * 0x1000); -#ifdef CHECKPAL - pal1 = inb((u16) base - 8); - pal2 = inb((u16) base - 7); - pal3 = inb((u16) base - 6); - - if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { - DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3)); -#endif - if (get_pio_conf_PIO(base, buf)) { - DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); - if (buf->IRQ) { - if (!register_pio_HBA(base, buf, NULL)) - release_region(base, 9); - } else { - printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n"); - release_region(base, 9); - } - } - /* Nothing found here so we take it from the list */ - EISAbases[i] = 0; -#ifdef CHECKPAL - } -#endif - } - } - return; -} - -static void find_pio_PCI(struct get_conf *buf) -{ -#ifndef CONFIG_PCI - printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); -#else - struct pci_dev *dev = NULL; - unsigned long base, x; - - while ((dev = pci_get_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { - DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", pci_name(dev))); - if (pci_enable_device(dev)) - continue; - pci_set_master(dev); - base = pci_resource_flags(dev, 0); - if (base & IORESOURCE_MEM) { - printk("eata_pio: invalid base address of device %s\n", pci_name(dev)); - continue; - } - base = pci_resource_start(dev, 0); - /* EISA tag there ? */ - if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) - continue; /* Jep, it's forced, so move on */ - base += 0x10; /* Now, THIS is the real address */ - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_pio_conf_PIO(base, buf)) { - if (buf->FORCADR) { /* If the address is forced */ - release_region(base, 9); - continue; /* we'll find it later */ - } - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - - if (!register_pio_HBA(base, buf, dev)) { - release_region(base, 9); - continue; - } - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } - } - } else if ((base & 0x0fff) == 0x0c88) { - x = (base >> 12) & 0x0f; - EISAbases[x] = 0; - } - } -#ifdef CHECK_BLINK - else if (check_blink_state(base)) { - printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n"); - } -#endif - } - } -#endif /* #ifndef CONFIG_PCI */ -} - -static int eata_pio_detect(struct scsi_host_template *tpnt) -{ - struct Scsi_Host *HBA_ptr; - struct get_conf gc; - int i; - - find_pio_PCI(&gc); - find_pio_EISA(&gc); - find_pio_ISA(&gc); - - for (i = 0; i < MAXIRQ; i++) - if (reg_IRQ[i]) - request_irq(i, do_eata_pio_int_handler, 0, "EATA-PIO", NULL); - - HBA_ptr = first_HBA; - - if (registered_HBAs != 0) { - printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n" - "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" " Alfred Arnold, a.arnold@kfa-juelich.de\n" "This release only supports DASD devices (harddisks)\n", VER_MAJOR, VER_MINOR, VER_SUB); - - printk("Registered HBAs:\n"); - printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " QS: SG: CPL:\n"); - for (i = 1; i <= registered_HBAs; i++) { - printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4lx %2d %d %d %c" - " %2d %2d %2d\n", - HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, - SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ? - "PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ", - HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, - SD(HBA_ptr)->primary ? 'Y' : 'N', HBA_ptr->can_queue, - HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun); - HBA_ptr = SD(HBA_ptr)->next; - } - } - return (registered_HBAs); -} - -static struct scsi_host_template driver_template = { - .proc_name = "eata_pio", - .name = "EATA (Extended Attachment) PIO driver", - .show_info = eata_pio_show_info, - .detect = eata_pio_detect, - .release = eata_pio_release, - .queuecommand = eata_pio_queue, - .eh_abort_handler = eata_pio_abort, - .eh_host_reset_handler = eata_pio_host_reset, - .use_clustering = ENABLE_CLUSTERING, -}; - -MODULE_AUTHOR("Michael Neuffer, Alfred Arnold"); -MODULE_DESCRIPTION("EATA SCSI PIO driver"); -MODULE_LICENSE("GPL"); - -#include "scsi_module.c" diff --git a/drivers/scsi/eata_pio.h b/drivers/scsi/eata_pio.h deleted file mode 100644 index 5b5e3d13670b..000000000000 --- a/drivers/scsi/eata_pio.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/******************************************************** -* Header file for eata_pio.c Linux EATA-PIO SCSI driver * -* (c) 1993-96 Michael Neuffer * -********************************************************* -* last change: 2002/11/02 * -********************************************************/ - - -#ifndef _EATA_PIO_H -#define _EATA_PIO_H - -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_SUB "1b" - -/************************************************************************ - * Here you can switch parts of the code on and of * - ************************************************************************/ - -#define VERBOSE_SETUP /* show startup screen of 2001 */ -#define ALLOW_DMA_BOARDS 1 - -/************************************************************************ - * Debug options. * - * Enable DEBUG and whichever options you require. * - ************************************************************************/ -#define DEBUG_EATA 1 /* Enable debug code. */ -#define DPT_DEBUG 0 /* Bobs special */ -#define DBG_DELAY 0 /* Build in delays so debug messages can be - * be read before they vanish of the top of - * the screen! - */ -#define DBG_PROBE 0 /* Debug probe routines. */ -#define DBG_ISA 0 /* Trace ISA routines */ -#define DBG_EISA 0 /* Trace EISA routines */ -#define DBG_PCI 0 /* Trace PCI routines */ -#define DBG_PIO 0 /* Trace get_config_PIO */ -#define DBG_COM 0 /* Trace command call */ -#define DBG_QUEUE 0 /* Trace command queueing. */ -#define DBG_INTR 0 /* Trace interrupt service routine. */ -#define DBG_INTR2 0 /* Trace interrupt service routine. */ -#define DBG_PROC 0 /* Debug proc-fs related statistics */ -#define DBG_PROC_WRITE 0 -#define DBG_REGISTER 0 /* */ -#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */ - -#if DEBUG_EATA -#define DBG(x, y) if ((x)) {y;} -#else -#define DBG(x, y) -#endif - -#endif /* _EATA_PIO_H */ From 38e09e3bb056b90d70308fe1e3db387ef976ce6e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 14 Mar 2018 12:48:23 +0100 Subject: [PATCH 123/168] scsi: dpt_i2o: stop using scsi_unregister dpt_i2o doesn't use scsi_register, so it should not use scsi_unregister either. Also refactor the module exit path to make a little more sense. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 16 ++++------------ drivers/scsi/dpti.h | 1 - 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index fd172b0890d3..3c667b23a801 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -302,16 +302,12 @@ rebuild_sys_tab: } -/* - * scsi_unregister will be called AFTER we return. - */ -static int adpt_release(struct Scsi_Host *host) +static void adpt_release(adpt_hba *pHba) { - adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; + scsi_remove_host(pHba->host); // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); - scsi_unregister(host); - return 0; + scsi_host_put(pHba->host); } @@ -1087,8 +1083,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) mutex_lock(&adpt_configuration_lock); - // scsi_unregister calls our adpt_release which - // does a quiese if(pHba->host){ free_irq(pHba->host->irq, pHba); } @@ -3595,11 +3589,9 @@ static void __exit adpt_exit(void) { adpt_hba *pHba, *next; - for (pHba = hba_chain; pHba; pHba = pHba->next) - scsi_remove_host(pHba->host); for (pHba = hba_chain; pHba; pHba = next) { next = pHba->next; - adpt_release(pHba->host); + adpt_release(pHba); } } diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 1fa345ab8ecb..dfc8d2eaa09e 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -32,7 +32,6 @@ static int adpt_detect(struct scsi_host_template * sht); static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd); static int adpt_abort(struct scsi_cmnd * cmd); static int adpt_reset(struct scsi_cmnd* cmd); -static int adpt_release(struct Scsi_Host *host); static int adpt_slave_configure(struct scsi_device *); static const char *adpt_info(struct Scsi_Host *pSHost); From 59ee56697b0f89a1778ffa24ee3bf9a826a97e1d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 14 Mar 2018 12:48:24 +0100 Subject: [PATCH 124/168] scsi: ips: don't set .detect and .release in the host template Since moving away from using scsi_module.c these were never called. The implementations are called directly, though so they remain. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/ips.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 67621308eb9c..e3c8857741a1 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -224,8 +224,6 @@ module_param(ips, charp, 0); /* * Function prototypes */ -static int ips_detect(struct scsi_host_template *); -static int ips_release(struct Scsi_Host *); static int ips_eh_abort(struct scsi_cmnd *); static int ips_eh_reset(struct scsi_cmnd *); static int ips_queue(struct Scsi_Host *, struct scsi_cmnd *); @@ -355,8 +353,6 @@ static dma_addr_t ips_flashbusaddr; static long ips_FlashDataInUse; /* CD Boot - Flash Data In Use Flag */ static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Lite Adapter */ static struct scsi_host_template ips_driver_template = { - .detect = ips_detect, - .release = ips_release, .info = ips_info, .queuecommand = ips_queue, .eh_abort_handler = ips_eh_abort, From 1dc09e120c83143bdccf2e445f604666e7eebc11 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 14 Mar 2018 12:48:25 +0100 Subject: [PATCH 125/168] scsi: aha1740: stop using scsi_unregister aha1740 doesn't use scsi_register, so it should not use scsi_unregister either. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/aha1740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index bad35ffc015d..b48d5436f094 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -592,7 +592,7 @@ static int aha1740_probe (struct device *dev) DMA_BIDIRECTIONAL); if (!host->ecb_dma_addr) { printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n"); - scsi_unregister (shpnt); + scsi_host_put (shpnt); goto err_host_put; } From 50041071b5716eb1585c68a482989ab9fc885968 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 14 Mar 2018 12:48:34 +0100 Subject: [PATCH 126/168] scsi: documentation: remove ChangeLog.1992-1997 This 20+ year old changelog has no useful information for kernel development or users, so remove it. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/scsi/ChangeLog.1992-1997 | 2023 ------------------------ 1 file changed, 2023 deletions(-) delete mode 100644 Documentation/scsi/ChangeLog.1992-1997 diff --git a/Documentation/scsi/ChangeLog.1992-1997 b/Documentation/scsi/ChangeLog.1992-1997 deleted file mode 100644 index 6faad7e6417c..000000000000 --- a/Documentation/scsi/ChangeLog.1992-1997 +++ /dev/null @@ -1,2023 +0,0 @@ -Sat Jan 18 15:51:45 1997 Richard Henderson - - * Don't play with usage_count directly, instead hand around - the module header and use the module macros. - -Fri May 17 00:00:00 1996 Leonard N. Zubkoff - - * BusLogic Driver Version 2.0.3 Released. - -Tue Apr 16 21:00:00 1996 Leonard N. Zubkoff - - * BusLogic Driver Version 1.3.2 Released. - -Sun Dec 31 23:26:00 1995 Leonard N. Zubkoff - - * BusLogic Driver Version 1.3.1 Released. - -Fri Nov 10 15:29:49 1995 Leonard N. Zubkoff - - * Released new BusLogic driver. - -Wed Aug 9 22:37:04 1995 Andries Brouwer - - As a preparation for new device code, separated the various - functions the request->dev field had into the device proper, - request->rq_dev and a status field request->rq_status. - - The 2nd argument of bios_param is now a kdev_t. - -Wed Jul 19 10:43:15 1995 Michael Neuffer - - * scsi.c (scsi_proc_info): /proc/scsi/scsi now also lists all - attached devices. - - * scsi_proc.c (proc_print_scsidevice): Added. Used by scsi.c and - eata_dma_proc.c to produce some device info for /proc/scsi. - - * eata_dma.c (eata_queue)(eata_int_handler)(eata_scsi_done): - Changed handling of internal SCSI commands send to the HBA. - - -Wed Jul 19 10:09:17 1995 Michael Neuffer - - * Linux 1.3.11 released. - - * eata_dma.c (eata_queue)(eata_int_handler): Added code to do - command latency measurements if requested by root through - /proc/scsi interface. - Throughout Use HZ constant for time references. - - * eata_pio.c: Use HZ constant for time references. - - * aic7xxx.c, aic7xxx.h, aic7xxx_asm.c: Changed copyright from BSD - to GNU style. - - * scsi.h: Added READ_12 command opcode constant - -Wed Jul 19 09:25:30 1995 Michael Neuffer - - * Linux 1.3.10 released. - - * scsi_proc.c (dispatch_scsi_info): Removed unused variable. - -Wed Jul 19 09:25:30 1995 Michael Neuffer - - * Linux 1.3.9 released. - - * scsi.c Blacklist concept expanded to 'support' more device - deficiencies. blacklist[] renamed to device_list[] - (scan_scsis): Code cleanup. - - * scsi_debug.c (scsi_debug_proc_info): Added support to control - device lockup simulation via /proc/scsi interface. - - -Wed Jul 19 09:22:34 1995 Michael Neuffer - - * Linux 1.3.7 released. - - * scsi_proc.c: Fixed a number of bugs in directory handling - -Wed Jul 19 09:18:28 1995 Michael Neuffer - - * Linux 1.3.5 released. - - * Native wide, multichannel and /proc/scsi support now in official - kernel distribution. - - * scsi.c/h, hosts.c/h et al reindented to increase readability - (especially on 80 column wide terminals). - - * scsi.c, scsi_proc.c, ../../fs/proc/inode.c: Added - /proc/scsi/scsi which allows root to scan for hotplugged devices. - - * scsi.c (scsi_proc_info): Added, to support /proc/scsi/scsi. - (scan_scsis): Added some 'spaghetti' code to allow scanning for - single devices. - - -Thu Jun 20 15:20:27 1995 Michael Neuffer - - * proc.c: Renamed to scsi_proc.c - -Mon Jun 12 20:32:45 1995 Michael Neuffer - - * Linux 1.3.0 released. - -Mon May 15 19:33:14 1995 Michael Neuffer - - * scsi.c: Added native multichannel and wide scsi support. - - * proc.c (dispatch_scsi_info) (build_proc_dir_hba_entries): - Updated /proc/scsi interface. - -Thu May 4 17:58:48 1995 Michael Neuffer - - * sd.c (requeue_sd_request): Zero out the scatterlist only if - scsi_malloc returned memory for it. - - * eata_dma.c (register_HBA) (eata_queue): Add support for - large scatter/gather tables and set use_clustering accordingly - - * hosts.c: Make use_clustering changeable in the Scsi_Host structure. - -Wed Apr 12 15:25:52 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.5 released. - - * buslogic.c: Update to version 1.15 (From Leonard N. Zubkoff). - Fixed interrupt routine to avoid races when handling multiple - complete commands per interrupt. Seems to come up with faster - cards. - - * eata_dma.c: Update to 2.3.5r. Modularize. Improved error handling - throughout and fixed bug interrupt routine which resulted in shifted - status bytes. Added blink LED state checks for ISA and EISA HBAs. - Memory management bug seems to have disappeared ==> increasing - C_P_L_CURRENT_MAX to 16 for now. Decreasing C_P_L_DIV to 3 for - performance reasons. - - * scsi.c: If we get a FMK, EOM, or ILI when attempting to scan - the bus, assume that it was just noise on the bus, and ignore - the device. - - * scsi.h: Update and add a bunch of missing commands which we - were never using. - - * sd.c: Use restore_flags in do_sd_request - this may result in - latency conditions, but it gets rid of races and crashes. - Do not save flags again when searching for a second command to - queue. - - * st.c: Use bytes, not STP->buffer->buffer_size when reading - from tape. - - -Tue Apr 4 09:42:08 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.4 released. - - * st.c: Fix typo - restoring wrong flags. - -Wed Mar 29 06:55:12 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.3 released. - - * st.c: Perform some waiting operations with interrupts off. - Is this correct??? - -Wed Mar 22 10:34:26 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.2 released. - - * aha152x.c: Modularize. Add support for PCMCIA. - - * eata.c: Update to version 2.0. Fixed bug preventing media - detection. If scsi_register_host returns NULL, fail gracefully. - - * scsi.c: Detect as NEC (for photo-cd purposes) for the 84 - and 25 models as "NEC_OLDCDR". - - * scsi.h: Add define for NEC_OLDCDR - - * sr.c: Add handling for NEC_OLDCDR. Treat as unknown. - - * u14-34f.c: Update to version 2.0. Fixed same bug as in - eata.c. - - -Mon Mar 6 11:11:20 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.0 released. Yeah!!! - - * Minor spelling/punctuation changes throughout. Nothing - substantive. - -Mon Feb 20 21:33:03 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.95 released. - - * qlogic.c: Update to version 0.41. - - * seagate.c: Change some message to be more descriptive about what - we detected. - - * sr.c: spelling/whitespace changes. - -Mon Feb 20 21:33:03 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.94 released. - -Mon Feb 20 08:57:17 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.93 released. - - * hosts.h: Change io_port to long int from short. - - * 53c7,8xx.c: crash on AEN fixed, SCSI reset is no longer a NOP, - NULL pointer panic on odd UDCs fixed, two bugs in diagnostic output - fixed, should initialize correctly if left running, now loadable, - new memory allocation, extraneous diagnostic output suppressed, - splx() replaced with save/restore flags. [ Drew ] - - * hosts.c, hosts.h, scsi_ioctl.c, sd.c, sd_ioctl.c, sg.c, sr.c, - sr_ioctl.c: Add special junk at end that Emacs will use for - formatting the file. - - * qlogic.c: Update to v0.40a. Improve parity handling. - - * scsi.c: Add Hitachi DK312C to blacklist. Change "};" to "}" in - many places. Use scsi_init_malloc to get command block - may - need this to be dma compatible for some host adapters. - Restore interrupts after unregistering a host. - - * sd.c: Use sti instead of restore flags - causes latency problems. - - * seagate.c: Use controller_type to determine string used when - registering irq. - - * sr.c: More photo-cd hacks to make sure we get the xa stuff right. - * sr.h, sr.c: Change is_xa to xa_flags field. - - * st.c: Disable retries for write operations. - -Wed Feb 15 10:52:56 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.92 released. - - * eata.c: Update to 1.17. - - * eata_dma.c: Update to 2.31a. Add more support for /proc/scsi. - Continuing modularization. Less crashes because of the bug in the - memory management ==> increase C_P_L_CURRENT_MAX to 10 - and decrease C_P_L_DIV to 4. - - * hosts.c: If we remove last host registered, reuse host number. - When freeing memory from host being deregistered, free extra_bytes - too. - - * scsi.c (scan_scsis): memset(SDpnt, 0) and set SCmd.device to SDpnt. - Change memory allocation to work around bugs in __get_dma_pages. - Do not free host if usage count is not zero (for modules). - - * sr_ioctl.c: Increase IOCTL_TIMEOUT to 3000. - - * st.c: Allow for ST_EXTRA_DEVS in st data structures. - - * u14-34f.c: Update to 1.17. - -Thu Feb 9 10:11:16 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.91 released. - - * eata.c: Update to 1.16. Use wish_block instead of host->block. - - * hosts.c: Initialize wish_block to 0. - - * hosts.h: Add wish_block. - - * scsi.c: Use wish_block as indicator that the host should be added - to block list. - - * sg.c: Add SG_EXTRA_DEVS to number of slots. - - * u14-34f.c: Use wish_block. - -Tue Feb 7 11:46:04 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.90 released. - - * eata.c: Change naming from eata_* to eata2x_*. Now at vers 1.15. - Update interrupt handler to take pt_regs as arg. Allow blocking - even if loaded as module. Initialize target_time_out array. - Do not put sti(); in timing loop. - - * hosts.c: Do not reuse host numbers. - Use scsi_make_blocked_list to generate blocking list. - - * script_asm.pl: Beats me. Don't know perl. Something to do with - phase index. - - * scsi.c (scsi_make_blocked_list): New function - code copied from - hosts.c. - - * scsi.c: Update code to disable photo CD for Toshiba cdroms. - Use just manufacturer name, not model number. - - * sr.c: Fix setting density for Toshiba drives. - - * u14-34f.c: Clear target_time_out array during reset. - -Wed Feb 1 09:20:45 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.89 released. - - * Makefile, u14-34f.c: Modularize. - - * Makefile, eata.c: Modularize. Now version 1.14 - - * NCR5380.c: Update interrupt handler with new arglist. Minor - cleanups. - - * eata_dma.c: Begin to modularize. Add hooks for /proc/scsi. - New version 2.3.0a. Add code in interrupt handler to allow - certain CDROM drivers to be detected which return a - CHECK_CONDITION during SCSI bus scan. Add opcode check to get - all DATA IN and DATA OUT phases right. Utilize HBA_interpret flag. - Improvements in HBA identification. Various other minor stuff. - - * hosts.c: Initialize ->dma_channel and ->io_port when registering - a new host. - - * qlogic.c: Modularize and add PCMCIA support. - - * scsi.c: Add Hitachi to blacklist. - - * scsi.c: Change default to no lun scan (too many problem devices). - - * scsi.h: Define QUEUE_FULL condition. - - * sd.c: Do not check for non-existent partition until after - new media check. - - * sg.c: Undo previous change which was wrong. - - * sr_ioctl.c: Increase IOCTL_TIMEOUT to 2000. - - * st.c: Patches from Kai - improve filemark handling. - -Tue Jan 31 17:32:12 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.88 released. - - * Throughout - spelling/grammar fixups. - - * scsi.c: Make sure that all buffers are 16 byte aligned - some - drivers (buslogic) need this. - - * scsi.c (scan_scsis): Remove message printed. - - * scsi.c (scsi_init): Move message here. - -Mon Jan 30 06:40:25 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.87 released. - - * sr.c: Photo-cd related changes. (Gerd Knorr??). - - * st.c: Changes from Kai related to EOM detection. - -Mon Jan 23 23:53:10 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.86 released. - - * 53c7,8xx.h: Change SG size to 127. - - * eata_dma: Update to version 2.10i. Remove bug in the registration - of multiple HBAs and channels. Minor other improvements and stylistic - changes. - - * scsi.c: Test for Toshiba XM-3401TA and exclude from detection - as toshiba drive - photo cd does not work with this drive. - - * sr.c: Update photocd code. - -Mon Jan 23 23:53:10 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.85 released. - - * st.c, st_ioctl.c, sg.c, sd_ioctl.c, scsi_ioctl.c, hosts.c: - include linux/mm.h - - * qlogic.c, buslogic.c, aha1542.c: Include linux/module.h. - -Sun Jan 22 22:08:46 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.84 released. - - * Makefile: Support for loadable QLOGIC boards. - - * aha152x.c: Update to version 1.8 from Juergen. - - * eata_dma.c: Update from Michael Neuffer. - Remove hard limit of 2 commands per lun and make it better - configurable. Improvements in HBA identification. - - * in2000.c: Fix biosparam to support large disks. - - * qlogic.c: Minor changes (change sti -> restore_flags). - -Wed Jan 18 23:33:09 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.83 released. - - * aha1542.c(aha1542_intr_handle): Use arguments handed down to find - which irq. - - * buslogic.c: Likewise. - - * eata_dma.c: Use min of 2 cmd_per_lun for OCS_enabled boards. - - * scsi.c: Make RECOVERED_ERROR a SUGGEST_IS_OK. - - * sd.c: Fail if we are opening a non-existent partition. - - * sr.c: Bump SR_TIMEOUT to 15000. - Do not probe for media size at boot time(hard on changers). - Flag device as needing sector size instead. - - * sr_ioctl.c: Remove CDROMMULTISESSION_SYS ioctl. - - * ultrastor.c: Fix bug in call to ultrastor_interrupt (wrong #args). - -Mon Jan 16 07:18:23 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.82 released. - - Throughout. - - Change all interrupt handlers to accept new calling convention. - In particular, we now receive the irq number as one of the arguments. - - * More minor spelling corrections in some of the new files. - - * aha1542.c, buslogic.c: Clean up interrupt handler a little now - that we receive the irq as an arg. - - * aha274x.c: s/snarf_region/request_region/ - - * eata.c: Update to version 1.12. Fix some comments and display a - message if we cannot reserve the port addresses. - - * u14-34f.c: Update to version 1.13. Fix some comments and display a - message if we cannot reserve the port addresses. - - * eata_dma.c: Define get_board_data function (send INQUIRY command). - Use to improve detection of variants of different DPT boards. Change - version subnumber to "0g". - - * fdomain.c: Update to version 5.26. Improve detection of some boards - repackaged by IBM. - - * scsi.c (scsi_register_host): Change "name" to const char *. - - * sr.c: Fix problem in set mode command for Toshiba drives. - - * sr.c: Fix typo from patch 81. - -Fri Jan 13 12:54:46 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.81 released. Codefreeze for 1.2 release announced. - - Big changes here. - - * eata_dma.*: New files from Michael Neuffer. - (neuffer@goofy.zdv.uni-mainz.de). Should support - all eata/dpt cards. - - * hosts.c, Makefile: Add eata_dma. - - * README.st: Document MTEOM. - - Patches from me (ERY) to finish support for low-level loadable scsi. - It now works, and is actually useful. - - * Throughout - add new argument to scsi_init_malloc that takes an - additional parameter. This is used as a priority to kmalloc, - and you can specify the GFP_DMA flag if you need DMA-able memory. - - * Makefile: For source files that are loadable, always add name - to SCSI_SRCS. Fill in modules: target. - - * hosts.c: Change next_host to next_scsi_host, and make global. - Print hosts after we have identified all of them. Use info() - function if present, otherwise use name field. - - * hosts.h: Change attach function to return int, not void. - Define number of device slots to allow for loadable devices. - Define tags to tell scsi module code what type of module we - are loading. - - * scsi.c: Fix scan_scsis so that it can be run by a user process. - Do not use waiting loops - use up and down mechanism as long - as current != task[0]. - - * scsi.c(scan_scsis): Do not use stack variables for I/O - this - could be > 16Mb if we are loading a module at runtime (i.e. use - scsi_init_malloc to get some memory we know will be safe). - - * scsi.c: Change dma freelist to be a set of pages. This allows - us to dynamically adjust the size of the list by adding more pages - to the pagelist. Fix scsi_malloc and scsi_free accordingly. - - * scsi_module.c: Fix include. - - * sd.c: Declare detach function. Increment/decrement module usage - count as required. Fix init functions to allow loaded devices. - Revalidate all new disks so we get the partition tables. Define - detach function. - - * sr.c: Likewise. - - * sg.c: Declare detach function. Allow attachment of devices on - loaded drivers. - - * st.c: Declare detach function. Increment/decrement module usage - count as required. - -Tue Jan 10 10:09:58 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.79 released. - - Patch from some undetermined individual who needs to get a life :-). - - * sr.c: Attacked by spelling bee... - - Patches from Gerd Knorr: - - * sr.c: make printk messages for photoCD a little more informative. - - * sr_ioctl.c: Fix CDROMMULTISESSION_SYS ioctl. - -Mon Jan 9 10:01:37 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.78 released. - - * Makefile: Add empty modules: target. - - * Wheee. Now change register_iomem to request_region. - - * in2000.c: Bugfix - apparently this is the fix that we have - all been waiting for. It fixes a problem whereby the driver - is not stable under heavy load. Race condition and all that. - Patch from Peter Lu. - -Wed Jan 4 21:17:40 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.77 released. - - * 53c7,8xx.c: Fix from Linus - emulate splx. - - Throughout: - - Change "snarf_region" with "register_iomem". - - * scsi_module.c: New file. Contains support for low-level loadable - scsi drivers. [ERY]. - - * sd.c: More s/int/long/ changes. - - * seagate.c: Explicitly include linux/config.h - - * sg.c: Increment/decrement module usage count on open/close. - - * sg.c: Be a bit more careful about the user not supplying enough - information for a valid command. Pass correct size down to - scsi_do_cmd. - - * sr.c: More changes for Photo-CD. This apparently breaks NEC drives. - - * sr_ioctl.c: Support CDROMMULTISESSION ioctl. - - -Sun Jan 1 19:55:21 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.76 released. - - * constants.c: Add type cast in switch statement. - - * scsi.c (scsi_free): Change datatype of "offset" to long. - (scsi_malloc): Change a few more variables to long. Who - did this and why was it important? 64 bit machines? - - - Lots of changes to use save_state/restore_state instead of cli/sti. - Files changed include: - - * aha1542.c: - * aha1740.c: - * buslogic.c: - * in2000.c: - * scsi.c: - * scsi_debug.c: - * sd.c: - * sr.c: - * st.c: - -Wed Dec 28 16:38:29 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.75 released. - - * buslogic.c: Spelling fix. - - * scsi.c: Add HP C1790A and C2500A scanjet to blacklist. - - * scsi.c: Spelling fixup. - - * sd.c: Add support for sd_hardsizes (hard sector sizes). - - * ultrastor.c: Use save_flags/restore_flags instead of cli/sti. - -Fri Dec 23 13:36:25 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.74 released. - - * README.st: Update from Kai Makisara. - - * eata.c: New version from Dario - version 1.11. - use scsicam bios_param routine. Add support for 2011 - and 2021 boards. - - * hosts.c: Add support for blocking. Linked list automatically - generated when shpnt->block is set. - - * scsi.c: Add sankyo & HP scanjet to blacklist. Add support for - kicking things loose when we deadlock. - - * scsi.c: Recognize scanners and processors in scan_scsis. - - * scsi_ioctl.h: Increase timeout to 9 seconds. - - * st.c: New version from Kai - add better support for backspace. - - * u14-34f.c: New version from Dario. Supports blocking. - -Wed Dec 14 14:46:30 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.73 released. - - * buslogic.c: Update from Dave Gentzel. Version 1.14. - Add module related stuff. More fault tolerant if out of - DMA memory. - - * fdomain.c: New version from Rik Faith - version 5.22. Add support - for ISA-200S SCSI adapter. - - * hosts.c: Spelling. - - * qlogic.c: Update to version 0.38a. Add more support for PCMCIA. - - * scsi.c: Mask device type with 0x1f during scan_scsis. - Add support for deadlocking, err, make that getting out of - deadlock situations that are created when we allow the user - to limit requests to one host adapter at a time. - - * scsi.c: Bugfix - pass pid, not SCpnt as second arg to - scsi_times_out. - - * scsi.c: Restore interrupt state to previous value instead of using - cli/sti pairs. - - * scsi.c: Add a bunch of module stuff (all commented out for now). - - * scsi.c: Clean up scsi_dump_status. - -Tue Dec 6 12:34:20 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.72 released. - - * sg.c: Bugfix - always use sg_free, since we might have big buff. - -Fri Dec 2 11:24:53 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.71 released. - - * sg.c: Clear buff field when not in use. Only call scsi_free if - non-null. - - * scsi.h: Call wake_up(&wait_for_request) when done with a - command. - - * scsi.c (scsi_times_out): Pass pid down so that we can protect - against race conditions. - - * scsi.c (scsi_abort): Zero timeout field if we get the - NOT_RUNNING message back from low-level driver. - - - * scsi.c (scsi_done): Restore cmd_len, use_sg here. - - * scsi.c (request_sense): Not here. - - * hosts.h: Add new forbidden_addr, forbidden_size fields. Who - added these and why???? - - * hosts.c (scsi_mem_init): Mark pages as reserved if they fall in - the forbidden regions. I am not sure - I think this is so that - we can deal with boards that do incomplete decoding of their - address lines for the bios chips, but I am not entirely sure. - - * buslogic.c: Set forbidden_addr stuff if using a buggy board. - - * aha1740.c: Test for NULL pointer in SCtmp. This should not - occur, but a nice message is better than a kernel segfault. - - * 53c7,8xx.c: Add new PCI chip ID for 815. - -Fri Dec 2 11:24:53 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.70 released. - - * ChangeLog, st.c: Spelling. - -Tue Nov 29 18:48:42 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.69 released. - - * u14-34f.h: Non-functional change. [Dario]. - - * u14-34f.c: Use block field in Scsi_Host to prevent commands from - being queued to more than one host at the same time (used when - motherboard does not deal with multiple bus-masters very well). - Only when SINGLE_HOST_OPERATIONS is defined. - Use new cmd_per_lun field. [Dario] - - * eata.c: Likewise. - - * st.c: More changes from Kai. Add ready flag to indicate drive - status. - - * README.st: Document this. - - * sr.c: Bugfix (do not subtract CD_BLOCK_OFFSET) for photo-cd - code. - - * sg.c: Bugfix - fix problem where opcode is not correctly set up. - - * seagate.[c,h]: Use #defines to set driver name. - - * scsi_ioctl.c: Zero buffer before executing command. - - * scsi.c: Use new cmd_per_lun field in Scsi_Hosts as appropriate. - Add Sony CDU55S to blacklist. - - * hosts.h: Add new cmd_per_lun field to Scsi_Hosts. - - * hosts.c: Initialize cmd_per_lun in Scsi_Hosts from template. - - * buslogic.c: Use cmd_per_lun field - initialize to different - values depending upon bus type (i.e. use 1 if ISA, so we do not - hog memory). Use other patches which got lost from 1.1.68. - - * aha1542.c: Spelling. - -Tue Nov 29 15:43:50 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.68 released. - - Add support for 12 byte vendor specific commands in scsi-generics, - more (i.e. the last mandatory) low-level changes to support - loadable modules, plus a few other changes people have requested - lately. Changes by me (ERY) unless otherwise noted. Spelling - changes appear from some unknown corner of the universe. - - * Throughout: Change COMMAND_SIZE() to use SCpnt->cmd_len. - - * Throughout: Change info() low level function to take a Scsi_Host - pointer. This way the info function can return specific - information about the host in question, if desired. - - * All low-level drivers: Add NULL in initializer for the - usage_count field added to Scsi_Host_Template. - - * aha152x.[c,h]: Remove redundant info() function. - - * aha1542.[c,h]: Likewise. - - * aha1740.[c,h]: Likewise. - - * aha274x.[c,h]: Likewise. - - * eata.[c,h]: Likewise. - - * pas16.[c,h]: Likewise. - - * scsi_debug.[c,h]: Likewise. - - * t128.[c,h]: Likewise. - - * u14-34f.[c,h]: Likewise. - - * ultrastor.[c,h]: Likewise. - - * wd7000.[c,h]: Likewise. - - * aha1542.c: Add support for command line options with lilo to set - DMA parameters, I/O port. From Matt Aarnio. - - * buslogic.[c,h]: New version (1.13) from Dave Gentzel. - - * hosts.h: Add new field to Scsi_Hosts "block" to allow blocking - all I/O to certain other cards. Helps prevent problems with some - ISA motherboards. - - * hosts.h: Add usage_count to Scsi_Host_Template. - - * hosts.h: Add n_io_port to Scsi_Host (used when releasing module). - - * hosts.c: Initialize block field. - - * in2000.c: Remove "static" declarations from exported functions. - - * in2000.h: Likewise. - - * scsi.c: Correctly set cmd_len field as required. Save and - change setting when doing a request_sense, restore when done. - Move abort timeout message. Fix panic in request_queueable to - print correct function name. - - * scsi.c: When incrementing usage count, walk block linked list - for host, and or in SCSI_HOST_BLOCK bit. When decrementing usage - count to 0, clear this bit to allow usage to continue, wake up - processes waiting. - - - * scsi_ioctl.c: If we have an info() function, call it, otherwise - if we have a "name" field, use it, else do nothing. - - * sd.c, sr.c: Clear cmd_len field prior to each command we - generate. - - * sd.h: Add "has_part_table" bit to rscsi_disks. - - * sg.[c,h]: Add support for vendor specific 12 byte commands (i.e. - override command length in COMMAND_SIZE). - - * sr.c: Bugfix from Gerd in photocd code. - - * sr.c: Bugfix in get_sectorsize - always use scsi_malloc buffer - - we cannot guarantee that the stack is < 16Mb. - -Tue Nov 22 15:40:46 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.67 released. - - * sr.c: Change spelling of manufactor to manufacturer. - - * scsi.h: Likewise. - - * scsi.c: Likewise. - - * qlogic.c: Spelling corrections. - - * in2000.h: Spelling corrections. - - * in2000.c: Update from Bill Earnest, change from - jshiffle@netcom.com. Support new bios versions. - - * README.qlogic: Spelling correction. - -Tue Nov 22 15:40:46 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.66 released. - - * u14-34f.c: Spelling corrections. - - * sr.[h,c]: Add support for multi-session CDs from Gerd Knorr. - - * scsi.h: Add manufactor field for keeping track of device - manufacturer. - - * scsi.c: More spelling corrections. - - * qlogic.h, qlogic.c, README.qlogic: New driver from Tom Zerucha. - - * in2000.c, in2000.h: New driver from Brad McLean/Bill Earnest. - - * fdomain.c: Spelling correction. - - * eata.c: Spelling correction. - -Fri Nov 18 15:22:44 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.65 released. - - * eata.h: Update version string to 1.08.00. - - * eata.c: Set sg_tablesize correctly for DPT PM2012 boards. - - * aha274x.seq: Spell checking. - - * README.st: Likewise. - - * README.aha274x: Likewise. - - * ChangeLog: Likewise. - -Tue Nov 15 15:35:08 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.64 released. - - * u14-34f.h: Update version number to 1.10.01. - - * u14-34f.c: Use Scsi_Host can_queue variable instead of one from template. - - * eata.[c,h]: New driver for DPT boards from Dario Ballabio. - - * buslogic.c: Use can_queue field. - -Wed Nov 30 12:09:09 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.63 released. - - * sd.c: Give I/O error if we attempt 512 byte I/O to a disk with - 1024 byte sectors. - - * scsicam.c: Make sure we do read from whole disk (mask off - partition). - - * scsi.c: Use can_queue in Scsi_Host structure. - Fix panic message about invalid host. - - * hosts.c: Initialize can_queue from template. - - * hosts.h: Add can_queue to Scsi_Host structure. - - * aha1740.c: Print out warning about NULL ecbptr. - -Fri Nov 4 12:40:30 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.62 released. - - * fdomain.c: Update to version 5.20. (From Rik Faith). Support - BIOS version 3.5. - - * st.h: Add ST_EOD symbol. - - * st.c: Patches from Kai Makisara - support additional densities, - add support for MTFSS, MTBSS, MTWSM commands. - - * README.st: Update to document new commands. - - * scsi.c: Add Mediavision CDR-H93MV to blacklist. - -Sat Oct 29 20:57:36 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.60 released. - - * u14-34f.[c,h]: New driver from Dario Ballabio. - - * aic7770.c, aha274x_seq.h, aha274x.seq, aha274x.h, aha274x.c, - README.aha274x: New files, new driver from John Aycock. - - -Tue Oct 11 08:47:39 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.54 released. - - * Add third PCI chip id. [Drew] - - * buslogic.c: Set BUSLOGIC_CMDLUN back to 1 [Eric]. - - * ultrastor.c: Fix asm directives for new GCC. - - * sr.c, sd.c: Use new end_scsi_request function. - - * scsi.h(end_scsi_request): Return pointer to block if still - active, else return NULL if inactive. Fixes race condition. - -Sun Oct 9 20:23:14 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.53 released. - - * scsi.c: Do not allocate dma bounce buffers if we have exactly - 16Mb. - -Fri Sep 9 05:35:30 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.51 released. - - * aha152x.c: Add support for disabling the parity check. Update - to version 1.4. [Juergen]. - - * seagate.c: Tweak debugging message. - -Wed Aug 31 10:15:55 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.50 released. - - * aha152x.c: Add eb800 for Vtech Platinum SMP boards. [Juergen]. - - * scsi.c: Add Quantum PD1225S to blacklist. - -Fri Aug 26 09:38:45 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.49 released. - - * sd.c: Fix bug when we were deleting the wrong entry if we - get an unsupported sector size device. - - * sr.c: Another spelling patch. - -Thu Aug 25 09:15:27 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.48 released. - - * Throughout: Use new semantics for request_dma, as appropriate. - - * sr.c: Print correct device number. - -Sun Aug 21 17:49:23 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.47 released. - - * NCR5380.c: Add support for LIMIT_TRANSFERSIZE. - - * constants.h: Add prototype for print_Scsi_Cmnd. - - * pas16.c: Some more minor tweaks. Test for Mediavision board. - Allow for disks > 1Gb. [Drew??] - - * sr.c: Set SCpnt->transfersize. - -Tue Aug 16 17:29:35 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.46 released. - - * Throughout: More spelling fixups. - - * buslogic.c: Add a few more fixups from Dave. Disk translation - mainly. - - * pas16.c: Add a few patches (Drew?). - - -Thu Aug 11 20:45:15 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.44 released. - - * hosts.c: Add type casts for scsi_init_malloc. - - * scsicam.c: Add type cast. - -Wed Aug 10 19:23:01 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.43 released. - - * Throughout: Spelling cleanups. [??] - - * aha152x.c, NCR53*.c, fdomain.c, g_NCR5380.c, pas16.c, seagate.c, - t128.c: Use request_irq, not irqaction. [??] - - * aha1542.c: Move test for shost before we start to use shost. - - * aha1542.c, aha1740.c, ultrastor.c, wd7000.c: Use new - calling sequence for request_irq. - - * buslogic.c: Update from Dave Gentzel. - -Tue Aug 9 09:32:59 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.42 released. - - * NCR5380.c: Change NCR5380_print_status to static. - - * seagate.c: A few more bugfixes. Only Drew knows what they are - for. - - * ultrastor.c: Tweak some __asm__ directives so that it works - with newer compilers. [??] - -Sat Aug 6 21:29:36 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.40 released. - - * NCR5380.c: Return SCSI_RESET_WAKEUP from reset function. - - * aha1542.c: Reset mailbox status after a bus device reset. - - * constants.c: Fix typo (;;). - - * g_NCR5380.c: - * pas16.c: Correct usage of NCR5380_init. - - * scsi.c: Remove redundant (and unused variables). - - * sd.c: Use memset to clear all of rscsi_disks before we use it. - - * sg.c: Ditto, except for scsi_generics. - - * sr.c: Ditto, except for scsi_CDs. - - * st.c: Initialize STp->device. - - * seagate.c: Fix bug. [Drew] - -Thu Aug 4 08:47:27 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.39 released. - - * Makefile: Fix typo in NCR53C7xx. - - * st.c: Print correct number for device. - -Tue Aug 2 11:29:14 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.38 released. - - Lots of changes in 1.1.38. All from Drew unless otherwise noted. - - * 53c7,8xx.c: New file from Drew. PCI driver. - - * 53c7,8xx.h: Likewise. - - * 53c7,8xx.scr: Likewise. - - * 53c8xx_d.h, 53c8xx_u.h, script_asm.pl: Likewise. - - * scsicam.c: New file from Drew. Read block 0 on the disk and - read the partition table. Attempt to deduce the geometry from - the partition table if possible. Only used by 53c[7,8]xx right - now, but could be used by any device for which we have no way - of identifying the geometry. - - * sd.c: Use device letters instead of sd%d in a lot of messages. - - * seagate.c: Fix bug that resulted in lockups with some devices. - - * sr.c (sr_open): Return -EROFS, not -EACCES if we attempt to open - device for write. - - * hosts.c, Makefile: Update for new driver. - - * NCR5380.c, NCR5380.h, g_NCR5380.h: Update from Drew to support - 53C400 chip. - - * constants.c: Define CONST_CMND and CONST_MSG. Other minor - cleanups along the way. Improve handling of CONST_MSG. - - * fdomain.c, fdomain.h: New version from Rik Faith. Update to - 5.18. Should now support TMC-3260 PCI card with 18C30 chip. - - * pas16.c: Update with new irq initialization. - - * t128.c: Update with minor cleanups. - - * scsi.c (scsi_pid): New variable - gives each command a unique - id. Add Quantum LPS5235S to blacklist. Change in_scan to - in_scan_scsis and make global. - - * scsi.h: Add some defines for extended message handling, - INITIATE/RELEASE_RECOVERY. Add a few new fields to support sync - transfers. - - * scsi_ioctl.h: Add ioctl to request synchronous transfers. - - -Tue Jul 26 21:36:58 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.37 released. - - * aha1542.c: Always call aha1542_mbenable, use new udelay - mechanism so we do not wait a long time if the board does not - implement this command. - - * g_NCR5380.c: Remove #include and #if - defined(CONFIG_SCSI_*). - - * seagate.c: Likewise. - - Next round of changes to support loadable modules. Getting closer - now, still not possible to do anything remotely usable. - - hosts.c: Create a linked list of detected high level devices. - (scsi_register_device): New function to insert into this list. - (scsi_init): Call scsi_register_device for each of the known high - level drivers. - - hosts.h: Add prototype for linked list header. Add structure - definition for device template structure which defines the linked - list. - - scsi.c: (scan_scsis): Use linked list instead of knowledge about - existing high level device drivers. - (scsi_dev_init): Use init functions for drivers on linked list - instead of explicit list to initialize and attach devices to high - level drivers. - - scsi.h: Add new field "attached" to scsi_device - count of number - of high level devices attached. - - sd.c, sr.c, sg.c, st.c: Adjust init/attach functions to use new - scheme. - -Sat Jul 23 13:03:17 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.35 released. - - * ultrastor.c: Change constraint on asm() operand so that it works - with gcc 2.6.0. - -Thu Jul 21 10:37:39 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.33 released. - - * sr.c(sr_open): Do not allow opens with write access. - -Mon Jul 18 09:51:22 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.31 released. - - * sd.c: Increase SD_TIMEOUT from 300 to 600. - - * sr.c: Remove stray task_struct* variable that was no longer - used. - - * sr_ioctl.c: Fix typo in up() call. - -Sun Jul 17 16:25:29 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.30 released. - - * scsi.c (scan_scsis): Fix detection of some Toshiba CDROM drives - that report themselves as disk drives. - - * (Throughout): Use request.sem instead of request.waiting. - Should fix swap problem with fdomain. - -Thu Jul 14 10:51:42 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.29 released. - - * scsi.c (scan_scsis): Add new devices to end of linked list, not - to the beginning. - - * scsi.h (SCSI_SLEEP): Remove brain dead hack to try to save - the task state before sleeping. - -Sat Jul 9 15:01:03 1994 Eric Youngdale (eric@esp22) - - More changes to eventually support loadable modules. Mainly - we want to use linked lists instead of arrays because it is easier - to dynamically add and remove things this way. - - Quite a bit more work is needed before loadable modules are - possible (and usable) with scsi, but this is most of the grunge - work. - - * Linux 1.1.28 released. - - * scsi.c, scsi.h (allocate_device, request_queueable): Change - argument from index into scsi_devices to a pointer to the - Scsi_Device struct. - - * Throughout: Change all calls to allocate_device, - request_queueable to use new calling sequence. - - * Throughout: Use SCpnt->device instead of - scsi_devices[SCpnt->index]. Ugh - the pointer was there all along - - much cleaner this way. - - * scsi.c (scsi_init_malloc, scsi_free_malloc): New functions - - allow us to pretend that we have a working malloc when we - initialize. Use this instead of passing memory_start, memory_end - around all over the place. - - * scsi.h, st.c, sr.c, sd.c, sg.c: Change *_init1 functions to use - scsi_init_malloc, remove all arguments, no return value. - - * scsi.h: Remove index field from Scsi_Device and Scsi_Cmnd - structs. - - * scsi.c (scsi_dev_init): Set up for scsi_init_malloc. - (scan_scsis): Get SDpnt from scsi_init_malloc, and refresh - when we discover a device. Free pointer before returning. - Change scsi_devices into a linked list. - - * scsi.c (scan_scsis): Change to only scan one host. - (scsi_dev_init): Loop over all detected hosts, and scan them. - - * hosts.c (scsi_init_free): Change so that number of extra bytes - is stored in struct, and we do not have to pass it each time. - - * hosts.h: Change Scsi_Host_Template struct to include "next" and - "release" functions. Initialize to NULL in all low level - adapters. - - * hosts.c: Rename scsi_hosts to builtin_scsi_hosts, create linked - list scsi_hosts, linked together with the new "next" field. - -Wed Jul 6 05:45:02 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.25 released. - - * aha152x.c: Changes from Juergen - cleanups and updates. - - * sd.c, sr.c: Use new check_media_change and revalidate - file_operations fields. - - * st.c, st.h: Add changes from Kai Makisara, dated Jun 22. - - * hosts.h: Change SG_ALL back to 0xff. Apparently soft error - in /dev/brain resulted in having this bumped up. - Change first parameter in bios_param function to be Disk * instead - of index into rscsi_disks. - - * sd_ioctl.c: Pass pointer to rscsi_disks element instead of index - to array. - - * sd.h: Add struct name "scsi_disk" to typedef for Scsi_Disk. - - * scsi.c: Remove redundant Maxtor XT8760S from blacklist. - In scsi_reset, add printk when DEBUG defined. - - * All low level drivers: Modify definitions of bios_param in - appropriate way. - -Thu Jun 16 10:31:59 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.20 released. - - * scsi_ioctl.c: Only pass down the actual number of characters - required to scsi_do_cmd, not the one rounded up to a even number - of sectors. - - * ultrastor.c: Changes from Caleb Epstein for 24f cards. Support - larger SG lists. - - * ultrastor.c: Changes from me - use scsi_register to register - host. Add some consistency checking, - -Wed Jun 1 21:12:13 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.19 released. - - * scsi.h: Add new return code for reset() function: - SCSI_RESET_PUNT. - - * scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for - now. - - * aha1542.c: If the command responsible for the reset is not - pending, return SCSI_RESET_PUNT. - - * aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return - SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE. - -Tue May 31 19:36:01 1994 Eric Youngdale (eric@esp22) - - * buslogic.c: Do not print out message about "must be Adaptec" - if we have detected a buslogic card. Print out a warning message - if we are configuring for >16Mb, since the 445S at board level - D or earlier does not work right. The "D" level board can be made - to work by flipping an undocumented switch, but this is too subtle. - - Changes based upon patches in Yggdrasil distribution. - - * sg.c, sg.h: Return sense data to user. - - * aha1542.c, aha1740.c, buslogic.c: Do not panic if - sense buffer is wrong size. - - * hosts.c: Test for ultrastor card before any of the others. - - * scsi.c: Allow boot-time option for max_scsi_luns=? so that - buggy firmware has an easy work-around. - -Sun May 15 20:24:34 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.15 released. - - Post-codefreeze thaw... - - * buslogic.[c,h]: New driver from David Gentzel. - - * hosts.h: Add use_clustering field to explicitly say whether - clustering should be used for devices attached to this host - adapter. The buslogic board apparently supports large SG lists, - but it is apparently faster if sd.c condenses this into a smaller - list. - - * sd.c: Use this field instead of heuristic. - - * All host adapter include files: Add appropriate initializer for - use_clustering field. - - * scsi.h: Add #defines for return codes for the abort and reset - functions. There are now a specific set of return codes to fully - specify all of the possible things that the low-level adapter - could do. - - * scsi.c: Act based upon return codes from abort/reset functions. - - * All host adapter abort/reset functions: Return new return code. - - * Add code in scsi.c to help debug timeouts. Use #define - DEBUG_TIMEOUT to enable this. - - * scsi.c: If the host->irq field is set, use - disable_irq/enable_irq before calling queuecommand if we - are not already in an interrupt. Reduce races, and we - can be sloppier about cli/sti in the interrupt routines now - (reduce interrupt latency). - - * constants.c: Fix some things to eliminate warnings. Add some - sense descriptions that were omitted before. - - * aha1542.c: Watch for SCRD from host adapter - if we see it, set - a flag. Currently we only print out the number of pending - commands that might need to be restarted. - - * aha1542.c (aha1542_abort): Look for lost interrupts, OGMB still - full, and attempt to recover. Otherwise give up. - - * aha1542.c (aha1542_reset): Try BUS DEVICE RESET, and then pass - DID_RESET back up to the upper level code for all commands running - on this target (even on different LUNs). - -Sat May 7 14:54:01 1994 - - * Linux 1.1.12 released. - - * st.c, st.h: New version from Kai. Supports boot time - specification of number of buffers. - - * wd7000.[c,h]: Updated driver from John Boyd. Now supports - more than one wd7000 board in machine at one time, among other things. - -Wed Apr 20 22:20:35 1994 - - * Linux 1.1.8 released. - - * sd.c: Add a few type casts where scsi_malloc is called. - -Wed Apr 13 12:53:29 1994 - - * Linux 1.1.4 released. - - * scsi.c: Clean up a few printks (use %p to print pointers). - -Wed Apr 13 11:33:02 1994 - - * Linux 1.1.3 released. - - * fdomain.c: Update to version 5.16 (Handle different FIFO sizes - better). - -Fri Apr 8 08:57:19 1994 - - * Linux 1.1.2 released. - - * Throughout: SCSI portion of cluster diffs added. - -Tue Apr 5 07:41:50 1994 - - * Linux 1.1 development tree initiated. - - * The linux 1.0 development tree is now effectively frozen except - for obvious bugfixes. - -****************************************************************** -****************************************************************** -****************************************************************** -****************************************************************** - -Sun Apr 17 00:17:39 1994 - - * Linux 1.0, patchlevel 9 released. - - * fdomain.c: Update to version 5.16 (Handle different FIFO sizes - better). - -Thu Apr 7 08:36:20 1994 - - * Linux 1.0, patchlevel8 released. - - * fdomain.c: Update to version 5.15 from 5.9. Handles 3.4 bios. - -Sun Apr 3 14:43:03 1994 - - * Linux 1.0, patchlevel6 released. - - * wd7000.c: Make stab at fixing race condition. - -Sat Mar 26 14:14:50 1994 - - * Linux 1.0, patchlevel5 released. - - * aha152x.c, Makefile: Fix a few bugs (too much data message). - Add a few more bios signatures. (Patches from Juergen). - - * aha1542.c: Fix race condition in aha1542_out. - -Mon Mar 21 16:36:20 1994 - - * Linux 1.0, patchlevel3 released. - - * sd.c, st.c, sr.c, sg.c: Return -ENXIO, not -ENODEV if we attempt - to open a non-existent device. - - * scsi.c: Add Chinon cdrom to blacklist. - - * sr_ioctl.c: Check return status of verify_area. - -Sat Mar 6 16:06:19 1994 - - * Linux 1.0 released (technically a pre-release). - - * scsi.c: Add IMS CDD521, Maxtor XT-8760S to blacklist. - -Tue Feb 15 10:58:20 1994 - - * pl15e released. - - * aha1542.c: For 1542C, allow dynamic device scan with >1Gb turned - off. - - * constants.c: Fix typo in definition of CONSTANTS. - - * pl15d released. - -Fri Feb 11 10:10:16 1994 - - * pl15c released. - - * scsi.c: Add Maxtor XT-3280 and Rodime RO3000S to blacklist. - - * scsi.c: Allow tagged queueing for scsi 3 devices as well. - Some really old devices report a version number of 0. Disallow - LUN != 0 for these. - -Thu Feb 10 09:48:57 1994 - - * pl15b released. - -Sun Feb 6 12:19:46 1994 - - * pl15a released. - -Fri Feb 4 09:02:17 1994 - - * scsi.c: Add Teac cdrom to blacklist. - -Thu Feb 3 14:16:43 1994 - - * pl15 released. - -Tue Feb 1 15:47:43 1994 - - * pl14w released. - - * wd7000.c (wd_bases): Fix typo in last change. - -Mon Jan 24 17:37:23 1994 - - * pl14u released. - - * aha1542.c: Support 1542CF/extended bios. Different from 1542C - - * wd7000.c: Allow bios at 0xd8000 as well. - - * ultrastor.c: Do not truncate cylinders to 1024. - - * fdomain.c: Update to version 5.9 (add new bios signature). - - * NCR5380.c: Update from Drew - should work a lot better now. - -Sat Jan 8 15:13:10 1994 - - * pl14o released. - - * sr_ioctl.c: Zero reserved field before trying to set audio volume. - -Wed Jan 5 13:21:10 1994 - - * pl14m released. - - * fdomain.c: Update to version 5.8. No functional difference??? - -Tue Jan 4 14:26:13 1994 - - * pl14l released. - - * ultrastor.c: Remove outl, inl functions (now provided elsewhere). - -Mon Jan 3 12:27:25 1994 - - * pl14k released. - - * aha152x.c: Remove insw and outsw functions. - - * fdomain.c: Ditto. - -Wed Dec 29 09:47:20 1993 - - * pl14i released. - - * scsi.c: Support RECOVERED_ERROR for tape drives. - - * st.c: Update of tape driver from Kai. - -Tue Dec 21 09:18:30 1993 - - * pl14g released. - - * aha1542.[c,h]: Support extended BIOS stuff. - - * scsi.c: Clean up messages about disks, so they are displayed as - sda, sdb, etc instead of sd0, sd1, etc. - - * sr.c: Force reread of capacity if disk was changed. - Clear buffer before asking for capacity/sectorsize (some drives - do not report this properly). Set needs_sector_size flag if - drive did not return sensible sector size. - -Mon Dec 13 12:13:47 1993 - - * aha152x.c: Update to version .101 from Juergen. - -Mon Nov 29 03:03:00 1993 - - * linux 0.99.14 released. - - * All scsi stuff moved from kernel/blk_drv/scsi to drivers/scsi. - - * Throughout: Grammatical corrections to various comments. - - * Makefile: fix so that we do not need to compile things we are - not going to use. - - * NCR5380.c, NCR5380.h, g_NCR5380.c, g_NCR5380.h, pas16.c, - pas16.h, t128.c, t128.h: New files from Drew. - - * aha152x.c, aha152x.h: New files from Juergen Fischer. - - * aha1542.c: Support for more than one 1542 in the machine - at the same time. Make functions static that do not need - visibility. - - * aha1740.c: Set NEEDS_JUMPSTART flag in reset function, so we - know to restart the command. Change prototype of aha1740_reset - to take a command pointer. - - * constants.c: Clean up a few things. - - * fdomain.c: Update to version 5.6. Move snarf_region. Allow - board to be set at different SCSI ids. Remove support for - reselection (did not work well). Set JUMPSTART flag in reset - code. - - * hosts.c: Support new low-level adapters. Allow for more than - one adapter of a given type. - - * hosts.h: Allow for more than one adapter of a given type. - - * scsi.c: Add scsi_device_types array, if NEEDS_JUMPSTART is set - after a low-level reset, start the command again. Sort blacklist, - and add Maxtor MXT-1240S, XT-4170S, NEC CDROM 84, Seagate ST157N. - - * scsi.h: Add constants for tagged queueing. - - * Throughout: Use constants from major.h instead of hardcoded - numbers for major numbers. - - * scsi_ioctl.c: Fix bug in buffer length in ioctl_command. Use - verify_area in GET_IDLUN ioctl. Add new ioctls for - TAGGED_QUEUE_ENABLE, DISABLE. Only allow IOCTL_SEND_COMMAND by - superuser. - - * sd.c: Only pay attention to UNIT_ATTENTION for removable disks. - Fix bug where sometimes portions of blocks would get lost - resulting in processes hanging. Add messages when we spin up a - disk, and fix a bug in the timing. Increase read-ahead for disks - that are on a scatter-gather capable host adapter. - - * seagate.c: Fix so that some parameters can be set from the lilo - prompt. Supply jumpstart flag if we are resetting and need the - command restarted. Fix so that we return 1 if we detect a card - so that multiple card detection works correctly. Add yet another - signature for FD cards (950). Add another signature for ST0x. - - * sg.c, sg.h: New files from Lawrence Foard for generic scsi - access. - - * sr.c: Add type casts for (void*) so that we can do pointer - arithmetic. Works with GCC without this, but it is not strictly - correct. Same bugfix as was in sd.c. Increase read-ahead a la - disk driver. - - * sr_ioctl.c: Use scsi_malloc buffer instead of buffer from stack - since we cannot guarantee that the stack is < 16Mb. - - ultrastor.c: Update to support 24f properly (JFC's driver). - - wd7000.c: Supply jumpstart flag for reset. Do not round up - number of cylinders in biosparam function. - -Sat Sep 4 20:49:56 1993 - - * 0.99pl13 released. - - * Throughout: Use check_region/snarf_region for all low-level - drivers. - - * aha1542.c: Do hard reset instead of soft (some ethercard probes - screw us up). - - * scsi.c: Add new flag ASKED_FOR_SENSE so that we can tell if we are - in a loop whereby the device returns null sense data. - - * sd.c: Add code to spin up a drive if it is not already spinning. - Do this one at a time to make it easier on power supplies. - - * sd_ioctl.c: Use sync_dev instead of fsync_dev in BLKFLSBUF ioctl. - - * seagate.c: Switch around DATA/CONTROL lines. - - * st.c: Change sense to unsigned. - -Thu Aug 5 11:59:18 1993 - - * 0.99pl12 released. - - * constants.c, constants.h: New files with ascii descriptions of - various conditions. - - * Makefile: Do not try to count the number of low-level drivers, - just generate the list of .o files. - - * aha1542.c: Replace 16 with sizeof(SCpnt->sense_buffer). Add tests - for addresses > 16Mb, panic if we find one. - - * aha1740.c: Ditto with sizeof(). - - * fdomain.c: Update to version 3.18. Add new signature, register IRQ - with irqaction. Use ID 7 for new board. Be more intelligent about - obtaining the h/s/c numbers for biosparam. - - * hosts.c: Do not depend upon Makefile generated count of the number - of low-level host adapters. - - * scsi.c: Use array for scsi_command_size instead of a function. Add - Texel cdrom and Maxtor XT-4380S to blacklist. Allow compile time - option for no-multi lun scan. Add semaphore for possible problems - with handshaking, assume device is faulty until we know it not to be - the case. Add DEBUG_INIT symbol to dump info as we scan for devices. - Zero sense buffer so we can tell if we need to request it. When - examining sense information, request sense if buffer is all zero. - If RESET, request sense information to see what to do next. - - * scsi_debug.c: Change some constants to use symbols like INT_MAX. - - * scsi_ioctl.c (kernel_scsi_ioctl): New function -for making ioctl - calls from kernel space. - - * sd.c: Increase timeout to 300. Use functions in constants.h to - display info. Use scsi_malloc buffer for READ_CAPACITY, since - we cannot guarantee that a stack based buffer is < 16Mb. - - * sd_ioctl.c: Add BLKFLSBUF ioctl. - - * seagate.c: Add new compile time options for ARBITRATE, - SLOW_HANDSHAKE, and SLOW_RATE. Update assembly loops for transferring - data. Use kernel_scsi_ioctl to request mode page with geometry. - - * sr.c: Use functions in constants.c to display messages. - - * st.c: Support for variable block size. - - * ultrastor.c: Do not use cache for tape drives. Set - unchecked_isa_dma flag, even though this may not be needed (gets set - later). - -Sat Jul 17 18:32:44 1993 - - * 0.99pl11 released. C++ compilable. - - * Throughout: Add type casts all over the place, and use "ip" instead - of "info" in the various biosparam functions. - - * Makefile: Compile seagate.c with C++ compiler. - - * aha1542.c: Always set ccb pointer as this gets trashed somehow on - some systems. Add a few type casts. Update biosparam function a little. - - * aha1740.c: Add a few type casts. - - * fdomain.c: Update to version 3.17 from 3.6. Now works with - TMC-18C50. - - * scsi.c: Minor changes here and there with datatypes. Save use_sg - when requesting sense information so that this can properly be - restored if we retry the command. Set aside dma buffers assuming each - block is 1 page, not 1Kb minix block. - - * scsi_ioctl.c: Add a few type casts. Other minor changes. - - * sd.c: Correctly free all scsi_malloc'd memory if we run out of - dma_pool. Store blocksize information for each partition. - - * seagate.c: Minor cleanups here and there. - - * sr.c: Set up blocksize array for all discs. Fix bug in freeing - buffers if we run out of dma pool. - -Thu Jun 2 17:58:11 1993 - - * 0.99pl10 released. - - * aha1542.c: Support for BT 445S (VL-bus board with no dma channel). - - * fdomain.c: Upgrade to version 3.6. Preliminary support for TNC-18C50. - - * scsi.c: First attempt to fix problem with old_use_sg. Change - NOT_READY to a SUGGEST_ABORT. Fix timeout race where time might - get decremented past zero. - - * sd.c: Add block_fsync function to dispatch table. - - * sr.c: Increase timeout to 500 from 250. Add entry for sync in - dispatch table (supply NULL). If we do not have a sectorsize, - try to get it in the sd_open function. Add new function just to - obtain sectorsize. - - * sr.h: Add needs_sector_size semaphore. - - * st.c: Add NULL for fsync in dispatch table. - - * wd7000.c: Allow another condition for power on that are normal - and do not require a panic. - -Thu Apr 22 23:10:11 1993 - - * 0.99pl9 released. - - * aha1542.c: Use (void) instead of () in setup_mailboxes. - - * scsi.c: Initialize transfersize and underflow fields in SCmd to 0. - Do not panic for unsupported message bytes. - - * scsi.h: Allocate 12 bytes instead of 10 for commands. Add - transfersize and underflow fields. - - * scsi_ioctl.c: Further bugfix to ioctl_probe. - - * sd.c: Use long instead of int for last parameter in sd_ioctl. - Initialize transfersize and underflow fields. - - * sd_ioctl.c: Ditto for sd_ioctl(,,,,); - - * seagate.c: New version from Drew. Includes new signatures for FD - cards. Support for 0ws jumper. Correctly initialize - scsi_hosts[hostnum].this_id. Improved handing of - disconnect/reconnect, and support command linking. Use - transfersize and underflow fields. Support scatter-gather. - - * sr.c, sr_ioctl.c: Use long instead of int for last parameter in sr_ioctl. - Use buffer and buflength in do_ioctl. Patches from Chris Newbold for - scsi-2 audio commands. - - * ultrastor.c: Comment out in_byte (compiler warning). - - * wd7000.c: Change () to (void) in wd7000_enable_dma. - -Wed Mar 31 16:36:25 1993 - - * 0.99pl8 released. - - * aha1542.c: Handle mailboxes better for 1542C. - Do not truncate number of cylinders at 1024 for biosparam call. - - * aha1740.c: Fix a few minor bugs for multiple devices. - Same as above for biosparam. - - * scsi.c: Add lockable semaphore for removable devices that can have - media removal prevented. Add another signature for flopticals. - (allocate_device): Fix race condition. Allow more space in dma pool - for blocksizes of up to 4Kb. - - * scsi.h: Define COMMAND_SIZE. Define a SCSI specific version of - INIT_REQUEST that can run with interrupts off. - - * scsi_ioctl.c: Make ioctl_probe function more idiot-proof. If - a removable device says ILLEGAL REQUEST to a door-locking command, - clear lockable flag. Add SCSI_IOCTL_GET_IDLUN ioctl. Do not attempt - to lock door for devices that do not have lockable semaphore set. - - * sd.c: Fix race condition for multiple disks. Use INIT_SCSI_REQUEST - instead of INIT_REQUEST. Allow sector sizes of 1024 and 256. For - removable disks that are not ready, mark them as having a media change - (some drives do not report this later). - - * seagate.c: Use volatile keyword for memory-mapped register pointers. - - * sr.c: Fix race condition, a la sd.c. Increase the number of retries - to 1. Use INIT_SCSI_REQUEST. Allow 512 byte sector sizes. Do a - read_capacity when we init the device so we know the size and - sectorsize. - - * st.c: If ioctl not found in st.c, try scsi_ioctl for others. - - * ultrastor.c: Do not truncate number of cylinders at 1024 for - biosparam call. - - * wd7000.c: Ditto. - Throughout: Use COMMAND_SIZE macro to determine length of scsi - command. - - - -Sat Mar 13 17:31:29 1993 - - * 0.99pl7 released. - - Throughout: Improve punctuation in some messages, and use new - verify_area syntax. - - * aha1542.c: Handle unexpected interrupts better. - - * scsi.c: Ditto. Handle reset conditions a bit better, asking for - sense information and retrying if required. - - * scsi_ioctl.c: Allow for 12 byte scsi commands. - - * ultrastor.c: Update to use scatter-gather. - -Sat Feb 20 17:57:15 1993 - - * 0.99pl6 released. - - * fdomain.c: Update to version 3.5. Handle spurious interrupts - better. - - * sd.c: Use register_blkdev function. - - * sr.c: Ditto. - - * st.c: Use register_chrdev function. - - * wd7000.c: Undo previous change. - -Sat Feb 6 11:20:43 1993 - - * 0.99pl5 released. - - * scsi.c: Fix bug in testing for UNIT_ATTENTION. - - * wd7000.c: Check at more addresses for bios. Fix bug in biosparam - (heads & sectors turned around). - -Wed Jan 20 18:13:59 1993 - - * 0.99pl4 released. - - * scsi.c: Ignore leading spaces when looking for blacklisted devices. - - * seagate.c: Add a few new signatures for FD cards. Another patch - with SCint to fix race condition. Use recursion_depth to keep track - of how many times we have been recursively called, and do not start - another command unless we are on the outer level. Fixes bug - with Syquest cartridge drives (used to crash kernel), because - they do not disconnect with large data transfers. - -Tue Jan 12 14:33:36 1993 - - * 0.99pl3 released. - - * fdomain.c: Update to version 3.3 (a few new signatures). - - * scsi.c: Add CDU-541, Denon DRD-25X to blacklist. - (allocate_request, request_queueable): Init request.waiting to NULL if - non-buffer type of request. - - * seagate.c: Allow controller to be overridden with CONTROLLER symbol. - Set SCint=NULL when we are done, to remove race condition. - - * st.c: Changes from Kai. - -Wed Dec 30 20:03:47 1992 - - * 0.99pl2 released. - - * scsi.c: Blacklist back in. Remove Newbury drive as other bugfix - eliminates need for it here. - - * sd.c: Return ENODEV instead of EACCES if no such device available. - (sd_init) Init blkdev_fops earlier so that sd_open is available sooner. - - * sr.c: Same as above for sd.c. - - * st.c: Return ENODEV instead of ENXIO if no device. Init chrdev_fops - sooner, so that it is always there even if no tapes. - - * seagate.c (controller_type): New variable to keep track of ST0x or - FD. Modify signatures list to indicate controller type, and init - controller_type once we find a match. - - * wd7000.c (wd7000_set_sync): Remove redundant function. - -Sun Dec 20 16:26:24 1992 - - * 0.99pl1 released. - - * scsi_ioctl.c: Bugfix - check dev->index, not dev->id against - NR_SCSI_DEVICES. - - * sr_ioctl.c: Verify that device exists before allowing an ioctl. - - * st.c: Patches from Kai - change timeout values, improve end of tape - handling. - -Sun Dec 13 18:15:23 1992 - - * 0.99 kernel released. Baseline for this ChangeLog. From 2e8c3002e350f4aa6b1c4c9d5a0409926e6eb556 Mon Sep 17 00:00:00 2001 From: John Pittman Date: Wed, 14 Mar 2018 09:52:36 -0400 Subject: [PATCH 127/168] scsi: scsi_dh_alua: Correct comment for alua_alloc_pg() In the comment for function alua_alloc_pg() the argument '@h' is mistakenly referred to. Fix this by replacing it with the correct argument reference, '@tpgs', and provide a short description. Signed-off-by: John Pittman Reviewed-by Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index c3483d811824..acd7fb356f01 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -214,8 +214,8 @@ static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, /* * alua_alloc_pg - Allocate a new port_group structure * @sdev: scsi device - * @h: alua device_handler data * @group_id: port group id + * @tpgs: target port group settings * * Allocate a new port_group structure for a given * device. From 88b13609afca8ed2992c107c15326b4a8142e5da Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Thu, 8 Mar 2018 21:51:58 +0100 Subject: [PATCH 128/168] scsi: aic7xxx: aic79xx: remove VLAs In preparation to enabling -Wvla, remove VLAs and replace them with fixed-length arrays instead. The arrays fixed here, using the number of constant sections, aren't really VLAs, but they appear so to the compiler. Replace the array sizes with a pre-processor-level constant instead using ARRAY_SIZE. This was prompted by https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Stephen Kitt Reviewed-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/scsi/aic7xxx/aic79xx_core.c | 8 ++++---- drivers/scsi/aic7xxx/aic79xx_seq.h_shipped | 3 +-- drivers/scsi/aic7xxx/aic7xxx_core.c | 8 ++++---- drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped | 3 +-- drivers/scsi/aic7xxx/aicasm/aicasm.c | 3 +-- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index b560f396ee99..034f4eebb160 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -9338,9 +9338,9 @@ ahd_dumpseq(struct ahd_softc* ahd) static void ahd_loadseq(struct ahd_softc *ahd) { - struct cs cs_table[num_critical_sections]; - u_int begin_set[num_critical_sections]; - u_int end_set[num_critical_sections]; + struct cs cs_table[NUM_CRITICAL_SECTIONS]; + u_int begin_set[NUM_CRITICAL_SECTIONS]; + u_int end_set[NUM_CRITICAL_SECTIONS]; const struct patch *cur_patch; u_int cs_count; u_int cur_cs; @@ -9456,7 +9456,7 @@ ahd_loadseq(struct ahd_softc *ahd) * Move through the CS table until we find a CS * that might apply to this instruction. */ - for (; cur_cs < num_critical_sections; cur_cs++) { + for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) { if (critical_sections[cur_cs].end <= i) { if (begin_set[cs_count] == TRUE && end_set[cs_count] == FALSE) { diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped index 4b51e232392f..fd64a950ee44 100644 --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped @@ -1186,5 +1186,4 @@ static const struct cs { { 759, 763 } }; -static const int num_critical_sections = sizeof(critical_sections) - / sizeof(*critical_sections); +#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections) diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 6612ff3b2e83..e97eceacf522 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -6848,9 +6848,9 @@ ahc_dumpseq(struct ahc_softc* ahc) static int ahc_loadseq(struct ahc_softc *ahc) { - struct cs cs_table[num_critical_sections]; - u_int begin_set[num_critical_sections]; - u_int end_set[num_critical_sections]; + struct cs cs_table[NUM_CRITICAL_SECTIONS]; + u_int begin_set[NUM_CRITICAL_SECTIONS]; + u_int end_set[NUM_CRITICAL_SECTIONS]; const struct patch *cur_patch; u_int cs_count; u_int cur_cs; @@ -6915,7 +6915,7 @@ ahc_loadseq(struct ahc_softc *ahc) * Move through the CS table until we find a CS * that might apply to this instruction. */ - for (; cur_cs < num_critical_sections; cur_cs++) { + for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) { if (critical_sections[cur_cs].end <= i) { if (begin_set[cs_count] == TRUE && end_set[cs_count] == FALSE) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped index 07e93fbae706..f37362bc8ece 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped @@ -1304,5 +1304,4 @@ static const struct cs { { 875, 877 } }; -static const int num_critical_sections = sizeof(critical_sections) - / sizeof(*critical_sections); +#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections) diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c index 21ac265280bf..5f474e490f3e 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c @@ -451,8 +451,7 @@ output_code() fprintf(ofile, "\n};\n\n"); fprintf(ofile, -"static const int num_critical_sections = sizeof(critical_sections)\n" -" / sizeof(*critical_sections);\n"); + "#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections)\n"); fprintf(stderr, "%s: %d instructions used\n", appname, instrcount); } From 1929e82e37d9c43ce7063025877a779ac649d1e0 Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Thu, 8 Mar 2018 22:38:41 +0100 Subject: [PATCH 129/168] scsi: bfa: remove VLA In preparation to enabling -Wvla, remove VLAs and replace them with fixed-length arrays instead. bfad_bsg.c uses a variable-length array declaration to measure the size of a putative array; this can be replaced by the product of the size of an element and the number of elements, avoiding the VLA altogether. This was prompted by https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Stephen Kitt Reviewed-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/scsi/bfa/bfad_bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 3976e787ba64..7c884f881180 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -891,7 +891,7 @@ bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd, if (bfad_chk_iocmd_sz(payload_len, sizeof(struct bfa_bsg_fabric_get_lports_s), - sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) { + sizeof(wwn_t) * iocmd->nports) != BFA_STATUS_OK) { iocmd->status = BFA_STATUS_VERSION_FAIL; goto out; } From e1735d9a98ab5593484bbba1933e362a261e0de0 Mon Sep 17 00:00:00 2001 From: Varun Prakash Date: Sun, 11 Mar 2018 18:02:13 +0530 Subject: [PATCH 130/168] scsi: csiostor: add support for 32 bit port capabilities 32 bit port capabilities are required to support new speeds which can not be supported using 16 bit port capabilities. Signed-off-by: Varun Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/csiostor/csio_attr.c | 16 +- drivers/scsi/csiostor/csio_hw.c | 275 ++++++++++++++++++++++++++++- drivers/scsi/csiostor/csio_hw.h | 59 +++++++ drivers/scsi/csiostor/csio_lnode.c | 8 + drivers/scsi/csiostor/csio_mb.c | 70 +++++--- drivers/scsi/csiostor/csio_mb.h | 9 +- 6 files changed, 395 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c index 2d1c4ebd40f9..8a004036e3d7 100644 --- a/drivers/scsi/csiostor/csio_attr.c +++ b/drivers/scsi/csiostor/csio_attr.c @@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *shost) spin_lock_irq(&hw->lock); switch (hw->pport[ln->portid].link_speed) { - case FW_PORT_CAP_SPEED_1G: + case FW_PORT_CAP32_SPEED_1G: fc_host_speed(shost) = FC_PORTSPEED_1GBIT; break; - case FW_PORT_CAP_SPEED_10G: + case FW_PORT_CAP32_SPEED_10G: fc_host_speed(shost) = FC_PORTSPEED_10GBIT; break; + case FW_PORT_CAP32_SPEED_25G: + fc_host_speed(shost) = FC_PORTSPEED_25GBIT; + break; + case FW_PORT_CAP32_SPEED_40G: + fc_host_speed(shost) = FC_PORTSPEED_40GBIT; + break; + case FW_PORT_CAP32_SPEED_50G: + fc_host_speed(shost) = FC_PORTSPEED_50GBIT; + break; + case FW_PORT_CAP32_SPEED_100G: + fc_host_speed(shost) = FC_PORTSPEED_100GBIT; + break; default: fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index 0bd1131b6cc9..96bbb82c826d 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -1409,6 +1409,235 @@ out: return rv; } +static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec) +{ + enum cc_fec cc_fec = 0; + + if (fw_fec & FW_PORT_CAP32_FEC_RS) + cc_fec |= FEC_RS; + if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS) + cc_fec |= FEC_BASER_RS; + + return cc_fec; +} + +static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause) +{ + fw_port_cap32_t fw_pause = 0; + + if (cc_pause & PAUSE_RX) + fw_pause |= FW_PORT_CAP32_FC_RX; + if (cc_pause & PAUSE_TX) + fw_pause |= FW_PORT_CAP32_FC_TX; + + return fw_pause; +} + +static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec) +{ + fw_port_cap32_t fw_fec = 0; + + if (cc_fec & FEC_RS) + fw_fec |= FW_PORT_CAP32_FEC_RS; + if (cc_fec & FEC_BASER_RS) + fw_fec |= FW_PORT_CAP32_FEC_BASER_RS; + + return fw_fec; +} + +/** + * fwcap_to_fwspeed - return highest speed in Port Capabilities + * @acaps: advertised Port Capabilities + * + * Get the highest speed for the port from the advertised Port + * Capabilities. + */ +fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps) +{ + #define TEST_SPEED_RETURN(__caps_speed) \ + do { \ + if (acaps & FW_PORT_CAP32_SPEED_##__caps_speed) \ + return FW_PORT_CAP32_SPEED_##__caps_speed; \ + } while (0) + + TEST_SPEED_RETURN(400G); + TEST_SPEED_RETURN(200G); + TEST_SPEED_RETURN(100G); + TEST_SPEED_RETURN(50G); + TEST_SPEED_RETURN(40G); + TEST_SPEED_RETURN(25G); + TEST_SPEED_RETURN(10G); + TEST_SPEED_RETURN(1G); + TEST_SPEED_RETURN(100M); + + #undef TEST_SPEED_RETURN + + return 0; +} + +/** + * fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits + * @caps16: a 16-bit Port Capabilities value + * + * Returns the equivalent 32-bit Port Capabilities value. + */ +fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16) +{ + fw_port_cap32_t caps32 = 0; + + #define CAP16_TO_CAP32(__cap) \ + do { \ + if (caps16 & FW_PORT_CAP_##__cap) \ + caps32 |= FW_PORT_CAP32_##__cap; \ + } while (0) + + CAP16_TO_CAP32(SPEED_100M); + CAP16_TO_CAP32(SPEED_1G); + CAP16_TO_CAP32(SPEED_25G); + CAP16_TO_CAP32(SPEED_10G); + CAP16_TO_CAP32(SPEED_40G); + CAP16_TO_CAP32(SPEED_100G); + CAP16_TO_CAP32(FC_RX); + CAP16_TO_CAP32(FC_TX); + CAP16_TO_CAP32(ANEG); + CAP16_TO_CAP32(MDIX); + CAP16_TO_CAP32(MDIAUTO); + CAP16_TO_CAP32(FEC_RS); + CAP16_TO_CAP32(FEC_BASER_RS); + CAP16_TO_CAP32(802_3_PAUSE); + CAP16_TO_CAP32(802_3_ASM_DIR); + + #undef CAP16_TO_CAP32 + + return caps32; +} + +/** + * lstatus_to_fwcap - translate old lstatus to 32-bit Port Capabilities + * @lstatus: old FW_PORT_ACTION_GET_PORT_INFO lstatus value + * + * Translates old FW_PORT_ACTION_GET_PORT_INFO lstatus field into new + * 32-bit Port Capabilities value. + */ +fw_port_cap32_t lstatus_to_fwcap(u32 lstatus) +{ + fw_port_cap32_t linkattr = 0; + + /* The format of the Link Status in the old + * 16-bit Port Information message isn't the same as the + * 16-bit Port Capabilities bitfield used everywhere else. + */ + if (lstatus & FW_PORT_CMD_RXPAUSE_F) + linkattr |= FW_PORT_CAP32_FC_RX; + if (lstatus & FW_PORT_CMD_TXPAUSE_F) + linkattr |= FW_PORT_CAP32_FC_TX; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) + linkattr |= FW_PORT_CAP32_SPEED_100M; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) + linkattr |= FW_PORT_CAP32_SPEED_1G; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) + linkattr |= FW_PORT_CAP32_SPEED_10G; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_25G)) + linkattr |= FW_PORT_CAP32_SPEED_25G; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) + linkattr |= FW_PORT_CAP32_SPEED_40G; + if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100G)) + linkattr |= FW_PORT_CAP32_SPEED_100G; + + return linkattr; +} + +/** + * csio_init_link_config - initialize a link's SW state + * @lc: pointer to structure holding the link state + * @pcaps: link Port Capabilities + * @acaps: link current Advertised Port Capabilities + * + * Initializes the SW state maintained for each link, including the link's + * capabilities and default speed/flow-control/autonegotiation settings. + */ +static void csio_init_link_config(struct link_config *lc, fw_port_cap32_t pcaps, + fw_port_cap32_t acaps) +{ + lc->pcaps = pcaps; + lc->def_acaps = acaps; + lc->lpacaps = 0; + lc->speed_caps = 0; + lc->speed = 0; + lc->requested_fc = PAUSE_RX | PAUSE_TX; + lc->fc = lc->requested_fc; + + /* + * For Forward Error Control, we default to whatever the Firmware + * tells us the Link is currently advertising. + */ + lc->requested_fec = FEC_AUTO; + lc->fec = fwcap_to_cc_fec(lc->def_acaps); + + /* If the Port is capable of Auto-Negtotiation, initialize it as + * "enabled" and copy over all of the Physical Port Capabilities + * to the Advertised Port Capabilities. Otherwise mark it as + * Auto-Negotiate disabled and select the highest supported speed + * for the link. Note parallel structure in t4_link_l1cfg_core() + * and t4_handle_get_port_info(). + */ + if (lc->pcaps & FW_PORT_CAP32_ANEG) { + lc->acaps = lc->pcaps & ADVERT_MASK; + lc->autoneg = AUTONEG_ENABLE; + lc->requested_fc |= PAUSE_AUTONEG; + } else { + lc->acaps = 0; + lc->autoneg = AUTONEG_DISABLE; + } +} + +static void csio_link_l1cfg(struct link_config *lc, uint16_t fw_caps, + uint32_t *rcaps) +{ + unsigned int fw_mdi = FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO); + fw_port_cap32_t fw_fc, cc_fec, fw_fec, lrcap; + + lc->link_ok = 0; + + /* + * Convert driver coding of Pause Frame Flow Control settings into the + * Firmware's API. + */ + fw_fc = cc_to_fwcap_pause(lc->requested_fc); + + /* + * Convert Common Code Forward Error Control settings into the + * Firmware's API. If the current Requested FEC has "Automatic" + * (IEEE 802.3) specified, then we use whatever the Firmware + * sent us as part of it's IEEE 802.3-based interpratation of + * the Transceiver Module EPROM FEC parameters. Otherwise we + * use whatever is in the current Requested FEC settings. + */ + if (lc->requested_fec & FEC_AUTO) + cc_fec = fwcap_to_cc_fec(lc->def_acaps); + else + cc_fec = lc->requested_fec; + fw_fec = cc_to_fwcap_fec(cc_fec); + + /* Figure out what our Requested Port Capabilities are going to be. + * Note parallel structure in t4_handle_get_port_info() and + * init_link_config(). + */ + if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { + lrcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec; + lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; + lc->fec = cc_fec; + } else if (lc->autoneg == AUTONEG_DISABLE) { + lrcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi; + lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; + lc->fec = cc_fec; + } else { + lrcap = lc->acaps | fw_fc | fw_fec | fw_mdi; + } + + *rcaps = lrcap; +} + /* * csio_enable_ports - Bring up all available ports. * @hw: HW module. @@ -1418,8 +1647,10 @@ static int csio_enable_ports(struct csio_hw *hw) { struct csio_mb *mbp; + u16 fw_caps = FW_CAPS_UNKNOWN; enum fw_retval retval; uint8_t portid; + fw_port_cap32_t pcaps, acaps, rcaps; int i; mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); @@ -1431,9 +1662,39 @@ csio_enable_ports(struct csio_hw *hw) for (i = 0; i < hw->num_pports; i++) { portid = hw->pport[i].portid; + if (fw_caps == FW_CAPS_UNKNOWN) { + u32 param, val; + + param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_PORT_CAPS32)); + val = 1; + + csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO, + hw->pfn, 0, 1, ¶m, &val, false, + NULL); + + if (csio_mb_issue(hw, mbp)) { + csio_err(hw, "failed to issue FW_PARAMS_CMD(r) port:%d\n", + portid); + mempool_free(mbp, hw->mb_mempool); + return -EINVAL; + } + + csio_mb_process_read_params_rsp(hw, mbp, &retval, 1, + &val); + if (retval != FW_SUCCESS) { + csio_err(hw, "FW_PARAMS_CMD(r) port:%d failed: 0x%x\n", + portid, retval); + mempool_free(mbp, hw->mb_mempool); + return -EINVAL; + } + + fw_caps = val; + } + /* Read PORT information */ csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, - false, 0, 0, NULL); + false, 0, fw_caps, NULL); if (csio_mb_issue(hw, mbp)) { csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n", @@ -1442,8 +1703,8 @@ csio_enable_ports(struct csio_hw *hw) return -EINVAL; } - csio_mb_process_read_port_rsp(hw, mbp, &retval, - &hw->pport[i].pcap); + csio_mb_process_read_port_rsp(hw, mbp, &retval, fw_caps, + &pcaps, &acaps); if (retval != FW_SUCCESS) { csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n", portid, retval); @@ -1451,9 +1712,13 @@ csio_enable_ports(struct csio_hw *hw) return -EINVAL; } + csio_init_link_config(&hw->pport[i].link_cfg, pcaps, acaps); + + csio_link_l1cfg(&hw->pport[i].link_cfg, fw_caps, &rcaps); + /* Write back PORT information */ - csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true, - (PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL); + csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, + true, rcaps, fw_caps, NULL); if (csio_mb_issue(hw, mbp)) { csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n", diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h index 30f5f523c8cc..9e73ef771eb7 100644 --- a/drivers/scsi/csiostor/csio_hw.h +++ b/drivers/scsi/csiostor/csio_hw.h @@ -268,8 +268,62 @@ struct csio_vpd { uint8_t id[ID_LEN + 1]; }; +/* Firmware Port Capabilities types. */ + +typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */ +typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */ + +enum fw_caps { + FW_CAPS_UNKNOWN = 0, /* 0'ed out initial state */ + FW_CAPS16 = 1, /* old Firmware: 16-bit Port Capabilities */ + FW_CAPS32 = 2, /* new Firmware: 32-bit Port Capabilities */ +}; + +enum cc_pause { + PAUSE_RX = 1 << 0, + PAUSE_TX = 1 << 1, + PAUSE_AUTONEG = 1 << 2 +}; + +enum cc_fec { + FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */ + FEC_RS = 1 << 1, /* Reed-Solomon */ + FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */ +}; + +struct link_config { + fw_port_cap32_t pcaps; /* link capabilities */ + fw_port_cap32_t def_acaps; /* default advertised capabilities */ + fw_port_cap32_t acaps; /* advertised capabilities */ + fw_port_cap32_t lpacaps; /* peer advertised capabilities */ + + fw_port_cap32_t speed_caps; /* speed(s) user has requested */ + unsigned int speed; /* actual link speed (Mb/s) */ + + enum cc_pause requested_fc; /* flow control user has requested */ + enum cc_pause fc; /* actual link flow control */ + + enum cc_fec requested_fec; /* Forward Error Correction: */ + enum cc_fec fec; /* requested and actual in use */ + + unsigned char autoneg; /* autonegotiating? */ + + unsigned char link_ok; /* link up? */ + unsigned char link_down_rc; /* link down reason */ +}; + +#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16) + +#define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \ + FW_PORT_CAP32_ANEG) + +/* Enable or disable autonegotiation. */ +#define AUTONEG_DISABLE 0x00 +#define AUTONEG_ENABLE 0x01 + struct csio_pport { uint16_t pcap; + uint16_t acap; uint8_t portid; uint8_t link_status; uint16_t link_speed; @@ -278,6 +332,7 @@ struct csio_pport { uint8_t rsvd1; uint8_t rsvd2; uint8_t rsvd3; + struct link_config link_cfg; }; /* fcoe resource information */ @@ -582,6 +637,10 @@ int csio_hw_slow_intr_handler(struct csio_hw *); int csio_handle_intr_status(struct csio_hw *, unsigned int, const struct intr_info *); +fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps); +fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16); +fw_port_cap32_t lstatus_to_fwcap(u32 lstatus); + int csio_hw_start(struct csio_hw *); int csio_hw_stop(struct csio_hw *); int csio_hw_reset(struct csio_hw *); diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c index be5ee2d37815..1c53179523b8 100644 --- a/drivers/scsi/csiostor/csio_lnode.c +++ b/drivers/scsi/csiostor/csio_lnode.c @@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) val = htonl(FC_PORTSPEED_1GBIT); else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G) val = htonl(FC_PORTSPEED_10GBIT); + else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_25G) + val = htonl(FC_PORTSPEED_25GBIT); + else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_40G) + val = htonl(FC_PORTSPEED_40GBIT); + else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_50G) + val = htonl(FC_PORTSPEED_50GBIT); + else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_100G) + val = htonl(FC_PORTSPEED_100GBIT); else val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN); csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c index 5f4e0a787bd1..c026417269c3 100644 --- a/drivers/scsi/csiostor/csio_mb.c +++ b/drivers/scsi/csiostor/csio_mb.c @@ -326,10 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET); } -#define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ - FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G |\ - FW_PORT_CAP_ANEG) - /* * csio_mb_port- FW PORT command helper * @hw: The HW structure @@ -344,11 +340,10 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, */ void csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, - uint8_t portid, bool wr, uint32_t fc, uint16_t caps, + u8 portid, bool wr, uint32_t fc, uint16_t fw_caps, void (*cbfn) (struct csio_hw *, struct csio_mb *)) { struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb); - unsigned int lfc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO); CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); @@ -358,26 +353,24 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, FW_PORT_CMD_PORTID_V(portid)); if (!wr) { cmdp->action_to_len16 = htonl( - FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | + FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16 + ? FW_PORT_ACTION_GET_PORT_INFO + : FW_PORT_ACTION_GET_PORT_INFO32) | FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); return; } /* Set port */ cmdp->action_to_len16 = htonl( - FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) | + FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16 + ? FW_PORT_ACTION_L1_CFG + : FW_PORT_ACTION_L1_CFG32) | FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); - if (fc & PAUSE_RX) - lfc |= FW_PORT_CAP_FC_RX; - if (fc & PAUSE_TX) - lfc |= FW_PORT_CAP_FC_TX; - - if (!(caps & FW_PORT_CAP_ANEG)) - cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc); + if (fw_caps == FW_CAPS16) + cmdp->u.l1cfg.rcap = cpu_to_be32(fc); else - cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | - lfc | mdi); + cmdp->u.l1cfg32.rcap32 = cpu_to_be32(fc); } /* @@ -390,14 +383,22 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, */ void csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp, - enum fw_retval *retval, uint16_t *caps) + enum fw_retval *retval, uint16_t fw_caps, + u32 *pcaps, u32 *acaps) { struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb); *retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16)); - if (*retval == FW_SUCCESS) - *caps = ntohs(rsp->u.info.pcap); + if (*retval == FW_SUCCESS) { + if (fw_caps == FW_CAPS16) { + *pcaps = fwcaps16_to_caps32(ntohs(rsp->u.info.pcap)); + *acaps = fwcaps16_to_caps32(ntohs(rsp->u.info.acap)); + } else { + *pcaps = ntohs(rsp->u.info32.pcaps32); + *acaps = ntohs(rsp->u.info32.acaps32); + } + } } /* @@ -1409,6 +1410,7 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd) uint32_t link_status; uint16_t action; uint8_t mod_type; + fw_port_cap32_t linkattr; if (opcode == FW_PORT_CMD) { pcmd = (struct fw_port_cmd *)cmd; @@ -1416,22 +1418,34 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd) ntohl(pcmd->op_to_portid)); action = FW_PORT_CMD_ACTION_G( ntohl(pcmd->action_to_len16)); - if (action != FW_PORT_ACTION_GET_PORT_INFO) { + if (action != FW_PORT_ACTION_GET_PORT_INFO && + action != FW_PORT_ACTION_GET_PORT_INFO32) { csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n", action); return -EINVAL; } - link_status = ntohl(pcmd->u.info.lstatus_to_modtype); - mod_type = FW_PORT_CMD_MODTYPE_G(link_status); + if (action == FW_PORT_ACTION_GET_PORT_INFO) { + link_status = ntohl(pcmd->u.info.lstatus_to_modtype); + mod_type = FW_PORT_CMD_MODTYPE_G(link_status); + linkattr = lstatus_to_fwcap(link_status); - hw->pport[port_id].link_status = - FW_PORT_CMD_LSTATUS_G(link_status); - hw->pport[port_id].link_speed = - FW_PORT_CMD_LSPEED_G(link_status); + hw->pport[port_id].link_status = + FW_PORT_CMD_LSTATUS_G(link_status); + } else { + link_status = + ntohl(pcmd->u.info32.lstatus32_to_cbllen32); + mod_type = FW_PORT_CMD_MODTYPE32_G(link_status); + linkattr = ntohl(pcmd->u.info32.linkattr32); + + hw->pport[port_id].link_status = + FW_PORT_CMD_LSTATUS32_G(link_status); + } + + hw->pport[port_id].link_speed = fwcap_to_fwspeed(linkattr); csio_info(hw, "Port:%x - LINK %s\n", port_id, - FW_PORT_CMD_LSTATUS_G(link_status) ? "UP" : "DOWN"); + hw->pport[port_id].link_status ? "UP" : "DOWN"); if (mod_type != hw->pport[port_id].mod_type) { hw->pport[port_id].mod_type = mod_type; diff --git a/drivers/scsi/csiostor/csio_mb.h b/drivers/scsi/csiostor/csio_mb.h index a6823df73015..b07e891c5936 100644 --- a/drivers/scsi/csiostor/csio_mb.h +++ b/drivers/scsi/csiostor/csio_mb.h @@ -88,12 +88,6 @@ enum csio_dev_state { FW_PARAMS_PARAM_Y_V(0) | \ FW_PARAMS_PARAM_Z_V(0)) -enum { - PAUSE_RX = 1 << 0, - PAUSE_TX = 1 << 1, - PAUSE_AUTONEG = 1 << 2 -}; - #define CSIO_INIT_MBP(__mbp, __cp, __tmo, __priv, __fn, __clear) \ do { \ if (__clear) \ @@ -189,7 +183,8 @@ void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t, void (*) (struct csio_hw *, struct csio_mb *)); void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *, - enum fw_retval *, uint16_t *); + enum fw_retval *, uint16_t, + uint32_t *, uint32_t *); void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t, void (*)(struct csio_hw *, struct csio_mb *)); From fa1467fb0076143ea678ae1837b5b3bb27153329 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:34:58 +0100 Subject: [PATCH 131/168] scsi: core: unexport scsi_host_set_state This function is only used inside the SCSI midlayer, so remove the export for it. Signed-off-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index a0a7e4ff255c..0a5362822ed6 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -154,7 +154,6 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) scsi_host_state_name(state))); return -EINVAL; } -EXPORT_SYMBOL(scsi_host_set_state); /** * scsi_remove_host - remove a scsi host From 5785bfadcdb596df7e103636c81e5ae6dd0caa5e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:48 +0100 Subject: [PATCH 132/168] scsi: esas2r: remove initialization / cleanup dead wood esas2r has been converted to hotplug style initialization long ago, but kept various remant of the old-style scsi_module.c initialization around. Remove those. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r.h | 2 - drivers/scsi/esas2r/esas2r_init.c | 21 --------- drivers/scsi/esas2r/esas2r_main.c | 72 ++----------------------------- 3 files changed, 4 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index 1da6407ee142..858c3b33db78 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h @@ -962,7 +962,6 @@ struct esas2r_adapter { * Function Declarations * SCSI functions */ -int esas2r_release(struct Scsi_Host *); const char *esas2r_info(struct Scsi_Host *); int esas2r_write_params(struct esas2r_adapter *a, struct esas2r_request *rq, struct esas2r_sas_nvram *data); @@ -984,7 +983,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd); /* Internal functions */ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, int index); -int esas2r_cleanup(struct Scsi_Host *host); int esas2r_read_fw(struct esas2r_adapter *a, char *buf, long off, int count); int esas2r_write_fw(struct esas2r_adapter *a, const char *buf, long off, int count); diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 5b14dd29b764..9dffcb28c9b7 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -661,27 +661,6 @@ void esas2r_kill_adapter(int i) } } -int esas2r_cleanup(struct Scsi_Host *host) -{ - struct esas2r_adapter *a; - int index; - - if (host == NULL) { - int i; - - esas2r_debug("esas2r_cleanup everything"); - for (i = 0; i < MAX_ADAPTERS; i++) - esas2r_kill_adapter(i); - return -1; - } - - esas2r_debug("esas2r_cleanup called for host %p", host); - a = (struct esas2r_adapter *)host->hostdata; - index = a->index; - esas2r_kill_adapter(index); - return index; -} - int esas2r_suspend(struct pci_dev *pdev, pm_message_t state) { struct Scsi_Host *host = pci_get_drvdata(pdev); diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 4eb14301a497..e07eac5be087 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -235,7 +235,6 @@ static struct scsi_host_template driver_template = { .module = THIS_MODULE, .show_info = esas2r_show_info, .name = ESAS2R_LONGNAME, - .release = esas2r_release, .info = esas2r_info, .ioctl = esas2r_ioctl, .queuecommand = esas2r_queuecommand, @@ -520,44 +519,16 @@ static int esas2r_probe(struct pci_dev *pcid, static void esas2r_remove(struct pci_dev *pdev) { - struct Scsi_Host *host; - int index; - - if (pdev == NULL) { - esas2r_log(ESAS2R_LOG_WARN, "esas2r_remove pdev==NULL"); - return; - } - - host = pci_get_drvdata(pdev); - - if (host == NULL) { - /* - * this can happen if pci_set_drvdata was already called - * to clear the host pointer. if this is the case, we - * are okay; this channel has already been cleaned up. - */ - - return; - } + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct esas2r_adapter *a = (struct esas2r_adapter *)host->hostdata; esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), "esas2r_remove(%p) called; " "host:%p", pdev, host); - index = esas2r_cleanup(host); - - if (index < 0) - esas2r_log_dev(ESAS2R_LOG_WARN, &(pdev->dev), - "unknown host in %s", - __func__); - + esas2r_kill_adapter(a->index); found_adapters--; - - /* if this was the last adapter, clean up the rest of the driver */ - - if (found_adapters == 0) - esas2r_cleanup(NULL); } static int __init esas2r_init(void) @@ -638,30 +609,7 @@ static int __init esas2r_init(void) for (i = 0; i < MAX_ADAPTERS; i++) esas2r_adapters[i] = NULL; - /* initialize */ - - driver_template.module = THIS_MODULE; - - if (pci_register_driver(&esas2r_pci_driver) != 0) - esas2r_log(ESAS2R_LOG_CRIT, "pci_register_driver FAILED"); - else - esas2r_log(ESAS2R_LOG_INFO, "pci_register_driver() OK"); - - if (!found_adapters) { - pci_unregister_driver(&esas2r_pci_driver); - esas2r_cleanup(NULL); - - esas2r_log(ESAS2R_LOG_CRIT, - "driver will not be loaded because no ATTO " - "%s devices were found", - ESAS2R_DRVR_NAME); - return -1; - } else { - esas2r_log(ESAS2R_LOG_INFO, "found %d adapters", - found_adapters); - } - - return 0; + return pci_register_driver(&esas2r_pci_driver); } /* Handle ioctl calls to "/proc/scsi/esas2r/ATTOnode" */ @@ -753,18 +701,6 @@ int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh) } -int esas2r_release(struct Scsi_Host *sh) -{ - esas2r_log_dev(ESAS2R_LOG_INFO, &(sh->shost_gendev), - "esas2r_release() called"); - - esas2r_cleanup(sh); - if (sh->irq) - free_irq(sh->irq, NULL); - scsi_unregister(sh); - return 0; -} - const char *esas2r_info(struct Scsi_Host *sh) { struct esas2r_adapter *a = (struct esas2r_adapter *)sh->hostdata; From 6937d7322ac4c56b56cc6bd5c83fd1d36ce52f5d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:49 +0100 Subject: [PATCH 133/168] scsi: mvme147: stop using scsi_module.c Convert the driver to modern style probing. Given that there only is a single instance for a given board that can be done using a global struct Scsi_Host instance easily. Also fix the removal path by passing the correct cookie to free_irq, and enable it unconditionally. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/mvme147.c | 107 ++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index e6b2b681fda3..7d1ab414b78f 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include #include @@ -14,9 +17,6 @@ #include "wd33c93.h" #include "mvme147.h" -#include - - static irqreturn_t mvme147_intr(int irq, void *data) { struct Scsi_Host *instance = data; @@ -65,40 +65,57 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, m147_pcc->dma_cntrl = 0; } -int mvme147_detect(struct scsi_host_template *tpnt) +static struct scsi_host_template mvme147_host_template = { + .module = THIS_MODULE, + .proc_name = "MVME147", + .name = "MVME147 built-in SCSI", + .queuecommand = wd33c93_queuecommand, + .eh_abort_handler = wd33c93_abort, + .eh_host_reset_handler = wd33c93_host_reset, + .show_info = wd33c93_show_info, + .write_info = wd33c93_write_info, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING +}; + +static struct Scsi_Host *mvme147_shost; + +static int __init mvme147_init(void) { - static unsigned char called = 0; - struct Scsi_Host *instance; wd33c93_regs regs; struct WD33C93_hostdata *hdata; + int error = -ENOMEM; - if (!MACH_IS_MVME147 || called) + if (!MACH_IS_MVME147) return 0; - called++; - tpnt->proc_name = "MVME147"; - tpnt->show_info = wd33c93_show_info, - tpnt->write_info = wd33c93_write_info, - - instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (!instance) + mvme147_shost = scsi_host_alloc(&mvme147_host_template, + sizeof(struct WD33C93_hostdata)); + if (!mvme147_shost) goto err_out; + mvme147_shost->base = 0xfffe4000; + mvme147_shost->irq = MVME147_IRQ_SCSI_PORT; - instance->base = 0xfffe4000; - instance->irq = MVME147_IRQ_SCSI_PORT; regs.SASR = (volatile unsigned char *)0xfffe4000; regs.SCMD = (volatile unsigned char *)0xfffe4001; - hdata = shost_priv(instance); + + hdata = shost_priv(mvme147_shost); hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; - wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10); - if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, - "MVME147 SCSI PORT", instance)) + wd33c93_init(mvme147_shost, regs, dma_setup, dma_stop, WD33C93_FS_8_10); + + error = request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, + "MVME147 SCSI PORT", mvme147_shost); + if (error) goto err_unregister; - if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, - "MVME147 SCSI DMA", instance)) + error = request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, + "MVME147 SCSI DMA", mvme147_shost); + if (error) goto err_free_irq; #if 0 /* Disabled; causes problems booting */ m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ @@ -112,40 +129,30 @@ int mvme147_detect(struct scsi_host_template *tpnt) m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */ m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ - return 1; + error = scsi_add_host(mvme147_shost, NULL); + if (error) + goto err_free_irq; + scsi_scan_host(mvme147_shost); + return 0; err_free_irq: - free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); + free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost); err_unregister: - scsi_unregister(instance); + scsi_host_put(mvme147_shost); err_out: - return 0; + return error; } -static struct scsi_host_template driver_template = { - .proc_name = "MVME147", - .name = "MVME147 built-in SCSI", - .detect = mvme147_detect, - .release = mvme147_release, - .queuecommand = wd33c93_queuecommand, - .eh_abort_handler = wd33c93_abort, - .eh_host_reset_handler = wd33c93_host_reset, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = ENABLE_CLUSTERING -}; - - -#include "scsi_module.c" - -int mvme147_release(struct Scsi_Host *instance) +static void __exit mvme147_exit(void) { -#ifdef MODULE + scsi_remove_host(mvme147_shost); + /* XXX Make sure DMA is stopped! */ - free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); - free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr); -#endif - return 1; + free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost); + free_irq(MVME147_IRQ_SCSI_DMA, mvme147_shost); + + scsi_host_put(mvme147_shost); } + +module_init(mvme147_init); +module_exit(mvme147_exit); From e184f2bf4d9f1a3c612a8c1d67e73e9cf8ab5ab9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:50 +0100 Subject: [PATCH 134/168] scsi: remove the fdomain and fdomain_cs drivers These drivers haven't seen any recent bug fixing and are two of the last drivers using the scsi_module.c infrastruture that has been deprecated 15 years ago. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- MAINTAINERS | 6 - arch/powerpc/configs/c2k_defconfig | 1 - drivers/scsi/Kconfig | 20 - drivers/scsi/Makefile | 1 - drivers/scsi/fdomain.c | 1783 ---------------------------- drivers/scsi/fdomain.h | 24 - drivers/scsi/pcmcia/Kconfig | 9 - drivers/scsi/pcmcia/Makefile | 2 - drivers/scsi/pcmcia/fdomain_core.c | 2 - drivers/scsi/pcmcia/fdomain_stub.c | 209 ---- 10 files changed, 2057 deletions(-) delete mode 100644 drivers/scsi/fdomain.c delete mode 100644 drivers/scsi/fdomain.h delete mode 100644 drivers/scsi/pcmcia/fdomain_core.c delete mode 100644 drivers/scsi/pcmcia/fdomain_stub.c diff --git a/MAINTAINERS b/MAINTAINERS index 36eb73238cf5..ccde214bb82d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5842,12 +5842,6 @@ F: tools/testing/selftests/futex/ F: tools/perf/bench/futex* F: Documentation/*futex* -FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) -M: Rik Faith -L: linux-scsi@vger.kernel.org -S: Odd Fixes (e.g., new signatures) -F: drivers/scsi/fdomain.* - GCC PLUGINS M: Kees Cook R: Emese Revfy diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig index 4bb832a41d55..6c1196b0f81e 100644 --- a/arch/powerpc/configs/c2k_defconfig +++ b/arch/powerpc/configs/c2k_defconfig @@ -184,7 +184,6 @@ CONFIG_MEGARAID_NEWGEN=y CONFIG_MEGARAID_MM=m CONFIG_MEGARAID_MAILBOX=m CONFIG_MEGARAID_SAS=m -CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_GDTH=m CONFIG_SCSI_IPS=m CONFIG_SCSI_INITIO=m diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index b18dfa1c14a1..117c2fb41b77 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -640,26 +640,6 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. -config SCSI_FUTURE_DOMAIN - tristate "Future Domain 16xx SCSI/AHA-2920A support" - depends on (ISA || PCI) && SCSI - select CHECK_SIGNATURE - ---help--- - This is support for Future Domain's 16-bit SCSI host adapters - (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and - other adapters based on the Future Domain chipsets (Quantum - ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board). - It is explained in section 3.7 of the SCSI-HOWTO, available from - . - - NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip - and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI - controller support"). This Future Domain driver works with the older - Adaptec AHA-2920A boards with a Future Domain chip on them. - - To compile this driver as a module, choose M here: the - module will be called fdomain. - config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 46f1c1033f0e..77bb0017bb02 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -74,7 +74,6 @@ obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o -obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c deleted file mode 100644 index ebbe5a3e665d..000000000000 --- a/drivers/scsi/fdomain.c +++ /dev/null @@ -1,1783 +0,0 @@ -/* fdomain.c -- Future Domain TMC-16x0 SCSI driver - * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu - * Revised: Mon Dec 28 21:59:02 1998 by faith@acm.org - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org) - * Shared IRQ supported added 7/7/2001 Alan Cox - - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - - ************************************************************************** - - SUMMARY: - - Future Domain BIOS versions supported for autodetect: - 2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 - Chips are supported: - TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 - Boards supported: - Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX - Future Domain TMC-3260 (PCI) - Quantum ISA-200S, ISA-250MG - Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] - IBM ? - LILO/INSMOD command-line options: - fdomain=,[,] - - - - NOTE: - - The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. - Use the aic7xxx driver for this board. - - The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right - driver for that card. Unfortunately, the boxes will probably just say - "2920", so you'll have to look on the card for a Future Domain logo, or a - letter after the 2920. - - - - THANKS: - - Thanks to Adaptec for providing PCI boards for testing. This finally - enabled me to test the PCI detection and correct it for PCI boards that do - not have a BIOS at a standard ISA location. For PCI boards, LILO/INSMOD - command-line options should no longer be needed. --RF 18Nov98 - - - - DESCRIPTION: - - This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 - TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a - 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin - high-density external connector. The 1670 and 1680 have floppy disk - controllers built in. The TMC-3260 is a PCI bus card. - - Future Domain's older boards are based on the TMC-1800 chip, and this - driver was originally written for a TMC-1680 board with the TMC-1800 chip. - More recently, boards are being produced with the TMC-18C50 and TMC-18C30 - chips. The latest and greatest board may not work with this driver. If - you have to patch this driver so that it will recognize your board's BIOS - signature, then the driver may fail to function after the board is - detected. - - Please note that the drive ordering that Future Domain implemented in BIOS - versions 3.4 and 3.5 is the opposite of the order (currently) used by the - rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have - more than one drive, then the drive ordering will be the reverse of that - which you see under DOS. For example, under DOS SCSI ID 0 will be D: and - SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be - /dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent - with that provided by all the other SCSI drivers for Linux. If you want - this changed, you will probably have to patch the higher level SCSI code. - If you do so, please send me patches that are protected by #ifdefs. - - If you have a TMC-8xx or TMC-9xx board, then this is not the driver for - your board. Please refer to the Seagate driver for more information and - possible support. - - - - HISTORY: - - Linux Driver Driver - Version Version Date Support/Notes - - 0.0 3 May 1992 V2.0 BIOS; 1800 chip - 0.97 1.9 28 Jul 1992 - 0.98.6 3.1 27 Nov 1992 - 0.99 3.2 9 Dec 1992 - - 0.99.3 3.3 10 Jan 1993 V3.0 BIOS - 0.99.5 3.5 18 Feb 1993 - 0.99.10 3.6 15 May 1993 V3.2 BIOS; 18C50 chip - 0.99.11 3.17 3 Jul 1993 (now under RCS) - 0.99.12 3.18 13 Aug 1993 - 0.99.14 5.6 31 Oct 1993 (reselection code removed) - - 0.99.15 5.9 23 Jan 1994 V3.4 BIOS (preliminary) - 1.0.8/1.1.1 5.15 1 Apr 1994 V3.4 BIOS; 18C30 chip (preliminary) - 1.0.9/1.1.3 5.16 7 Apr 1994 V3.4 BIOS; 18C30 chip - 1.1.38 5.18 30 Jul 1994 36C70 chip (PCI version of 18C30) - 1.1.62 5.20 2 Nov 1994 V3.5 BIOS - 1.1.73 5.22 7 Dec 1994 Quantum ISA-200S board; V2.0 BIOS - - 1.1.82 5.26 14 Jan 1995 V3.5 BIOS; TMC-1610M/MER/MEX board - 1.2.10 5.28 5 Jun 1995 Quantum ISA-250MG board; V2.0, V2.01 BIOS - 1.3.4 5.31 23 Jun 1995 PCI BIOS-32 detection (preliminary) - 1.3.7 5.33 4 Jul 1995 PCI BIOS-32 detection - 1.3.28 5.36 17 Sep 1995 V3.61 BIOS; LILO command-line support - 1.3.34 5.39 12 Oct 1995 V3.60 BIOS; /proc - 1.3.72 5.39 8 Feb 1996 Adaptec AHA-2920 board - 1.3.85 5.41 4 Apr 1996 - 2.0.12 5.44 8 Aug 1996 Use ID 7 for all PCI cards - 2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x - 2.1.97 5.46 23 Apr 1998 Rewritten PCI detection routines [mj] - 2.1.11x 5.47 9 Aug 1998 Touched for 8 SCSI disk majors support - 5.48 18 Nov 1998 BIOS no longer needed for PCI detection - 2.2.0 5.50 28 Dec 1998 Support insmod parameters - - - REFERENCES USED: - - "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, - 1990. - - "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain - Corporation, January 1992. - - "LXT SCSI Products: Specifications and OEM Technical Manual (Revision - B/September 1991)", Maxtor Corporation, 1991. - - "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. - - "Draft Proposed American National Standard: Small Computer System - Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, - revision 10h, October 17, 1991) - - Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric - Youngdale (ericy@cais.com), 1992. - - Private communication, Tuong Le (Future Domain Engineering department), - 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and - TMC-18C30 detection.) - - Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page - 60 (2.39: Disk Partition Table Layout). - - "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page - 6-1. - - - - NOTES ON REFERENCES: - - The Maxtor manuals were free. Maxtor telephone technical support is - great! - - The Future Domain manuals were $25 and $35. They document the chip, not - the TMC-16x0 boards, so some information I had to guess at. In 1992, - Future Domain sold DOS BIOS source for $250 and the UN*X driver source was - $750, but these required a non-disclosure agreement, so even if I could - have afforded them, they would *not* have been useful for writing this - publicly distributable driver. Future Domain technical support has - provided some information on the phone and have sent a few useful FAXs. - They have been much more helpful since they started to recognize that the - word "Linux" refers to an operating system :-). - - - - ALPHA TESTERS: - - There are many other alpha testers that come and go as the driver - develops. The people listed here were most helpful in times of greatest - need (mostly early on -- I've probably left out a few worthy people in - more recent times): - - Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken - Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari - Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad - Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). - - Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me - his 18C50-based card for debugging. He is the sole reason that this - driver works with the 18C50 chip. - - Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for - the version 3.4 BIOS. - - Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for providing - patches that support the TMC-3260, a PCI bus card with the 36C70 chip. - The 36C70 chip appears to be "completely compatible" with the 18C30 chip. - - Thanks to Eric Kasten (tigger@petroglyph.cl.msu.edu) for providing the - patch for the version 3.5 BIOS. - - Thanks for Stephen Henson (shenson@nyx10.cs.du.edu) for providing the - patch for the Quantum ISA-200S SCSI adapter. - - Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards, to - Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to some - random TMC-1680 repackaged by IBM; and to Mintak Ng (mintak@panix.com) for - the version 3.61 BIOS signature. - - Thanks for Mark Singer (elf@netcom.com) and Richard Simpson - (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective - work on the Quantum RAM layout. - - Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for - providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 - card (a PCI bus card with the 36C70 chip). Please send James PCI-related - bug reports. - - Thanks to Tom Cavin (tec@usa1.com) for preliminary command-line option - patches. - - New PCI detection code written by Martin Mares - - Insmod parameter code based on patches from Daniel Graham - . - - All of the alpha testers deserve much thanks. - - - - NOTES ON USER DEFINABLE OPTIONS: - - DEBUG: This turns on the printing of various debug information. - - ENABLE_PARITY: This turns on SCSI parity checking. With the current - driver, all attached devices must support SCSI parity. If none of your - devices support parity, then you can probably get the driver to work by - turning this option off. I have no way of testing this, however, and it - would appear that no one ever uses this option. - - FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the - 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by - the SCSI device, an interrupt will be raised. Therefore, this could be as - low as 0, or as high as 16. Note, however, that values which are too high - or too low seem to prevent any interrupts from occurring, and thereby lock - up the machine. I have found that 2 is a good number, but throughput may - be increased by changing this value to values which are close to 2. - Please let me know if you try any different values. - - RESELECTION: This is no longer an option, since I gave up trying to - implement it in version 4.x of this driver. It did not improve - performance at all and made the driver unstable (because I never found one - of the two race conditions which were introduced by the multiple - outstanding command code). The instability seems a very high price to pay - just so that you don't have to wait for the tape to rewind. If you want - this feature implemented, send me patches. I'll be happy to send a copy - of my (broken) driver to anyone who would like to see a copy. - - **************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include -#include -#include -#include "fdomain.h" - -#ifndef PCMCIA -MODULE_AUTHOR("Rickard E. Faith"); -MODULE_DESCRIPTION("Future domain SCSI driver"); -MODULE_LICENSE("GPL"); -#endif - - -#define VERSION "$Revision: 5.51 $" - -/* START OF USER DEFINABLE OPTIONS */ - -#define DEBUG 0 /* Enable debugging output */ -#define ENABLE_PARITY 1 /* Enable SCSI Parity */ -#define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ - -/* END OF USER DEFINABLE OPTIONS */ - -#if DEBUG -#define EVERY_ACCESS 0 /* Write a line on every scsi access */ -#define ERRORS_ONLY 1 /* Only write a line if there is an error */ -#define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ -#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ -#define DEBUG_ABORT 1 /* Debug abort() routine */ -#define DEBUG_RESET 1 /* Debug reset() routine */ -#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ -#else -#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ -#define ERRORS_ONLY 0 -#define DEBUG_DETECT 0 -#define DEBUG_MESSAGES 0 -#define DEBUG_ABORT 0 -#define DEBUG_RESET 0 -#define DEBUG_RACE 0 -#endif - -/* Errors are reported on the line, so we don't need to report them again */ -#if EVERY_ACCESS -#undef ERRORS_ONLY -#define ERRORS_ONLY 0 -#endif - -#if ENABLE_PARITY -#define PARITY_MASK 0x08 -#else -#define PARITY_MASK 0x00 -#endif - -enum chip_type { - unknown = 0x00, - tmc1800 = 0x01, - tmc18c50 = 0x02, - tmc18c30 = 0x03, -}; - -enum { - in_arbitration = 0x02, - in_selection = 0x04, - in_other = 0x08, - disconnect = 0x10, - aborted = 0x20, - sent_ident = 0x40, -}; - -enum in_port_type { - Read_SCSI_Data = 0, - SCSI_Status = 1, - TMC_Status = 2, - FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ - Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ - LSB_ID_Code = 5, - MSB_ID_Code = 6, - Read_Loopback = 7, - SCSI_Data_NoACK = 8, - Interrupt_Status = 9, - Configuration1 = 10, - Configuration2 = 11, /* tmc18c50/tmc18c30 only */ - Read_FIFO = 12, - FIFO_Data_Count = 14 -}; - -enum out_port_type { - Write_SCSI_Data = 0, - SCSI_Cntl = 1, - Interrupt_Cntl = 2, - SCSI_Mode_Cntl = 3, - TMC_Cntl = 4, - Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ - Write_Loopback = 7, - IO_Control = 11, /* tmc18c30 only */ - Write_FIFO = 12 -}; - -/* .bss will zero all the static variables below */ -static int port_base; -static unsigned long bios_base; -static void __iomem * bios_mem; -static int bios_major; -static int bios_minor; -static int PCI_bus; -#ifdef CONFIG_PCI -static struct pci_dev *PCI_dev; -#endif -static int Quantum; /* Quantum board variant */ -static int interrupt_level; -static volatile int in_command; -static struct scsi_cmnd *current_SC; -static enum chip_type chip = unknown; -static int adapter_mask; -static int this_id; -static int setup_called; - -#if DEBUG_RACE -static volatile int in_interrupt_flag; -#endif - -static int FIFO_Size = 0x2000; /* 8k FIFO for - pre-tmc18c30 chips */ - -static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id ); -/* Allow insmod parameters to be like LILO parameters. For example: - insmod fdomain fdomain=0x140,11 */ -static char * fdomain = NULL; -module_param(fdomain, charp, 0); - -#ifndef PCMCIA - -static unsigned long addresses[] = { - 0xc8000, - 0xca000, - 0xce000, - 0xde000, - 0xcc000, /* Extra addresses for PCI boards */ - 0xd0000, - 0xe0000, -}; -#define ADDRESS_COUNT ARRAY_SIZE(addresses) - -static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; -#define PORT_COUNT ARRAY_SIZE(ports) - -static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; - -#endif /* !PCMCIA */ - -/* - - READ THIS BEFORE YOU ADD A SIGNATURE! - - READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! - - READ EVERY WORD, ESPECIALLY THE WORD *NOT* - - This driver works *ONLY* for Future Domain cards using the TMC-1800, - TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, - and 1680. These are all 16-bit cards. - - The following BIOS signature signatures are for boards which do *NOT* - work with this driver (these TMC-8xx and TMC-9xx boards may work with the - Seagate driver): - - FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 - FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 - FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 - FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 - FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 - FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 - FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 - - (The cards which do *NOT* work are all 8-bit cards -- although some of - them have a 16-bit form-factor, the upper 8-bits are used only for IRQs - and are *NOT* used for data. You can tell the difference by following - the tracings on the circuit board -- if only the IRQ lines are involved, - you have a "8-bit" card, and should *NOT* use this driver.) - -*/ - -#ifndef PCMCIA - -static struct signature { - const char *signature; - int sig_offset; - int sig_length; - int major_bios_version; - int minor_bios_version; - int flag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ -} signatures[] = { - /* 1 2 3 4 5 6 */ - /* 123456789012345678901234567890123456789012345678901234567890 */ - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, - { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, - { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, - { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 }, - { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 }, - { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, - { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, - { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, -1, 1 }, - { "IBM F1 P264/32", 5, 14, 3, -1, 1 }, - /* This next signature may not be a 3.5 bios */ - { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, - { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, - { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 }, - { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 }, - { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 }, - { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, - - /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE - Also, fix the disk geometry code for your signature and send your - changes for faith@cs.unc.edu. Above all, do *NOT* change any old - signatures! - - Note that the last line will match a "generic" 18XX bios. Because - Future Domain has changed the host SCSI ID and/or the location of the - geometry information in the on-board RAM area for each of the first - three BIOS's, it is still important to enter a fully qualified - signature in the table for any new BIOS's (after the host SCSI ID and - geometry location are verified). */ -}; - -#define SIGNATURE_COUNT ARRAY_SIZE(signatures) - -#endif /* !PCMCIA */ - -static void print_banner( struct Scsi_Host *shpnt ) -{ - if (!shpnt) return; /* This won't ever happen */ - - if (bios_major < 0 && bios_minor < 0) { - printk(KERN_INFO "scsi%d: No BIOS; using scsi id %d\n", - shpnt->host_no, shpnt->this_id); - } else { - printk(KERN_INFO "scsi%d: BIOS version ", shpnt->host_no); - - if (bios_major >= 0) printk("%d.", bios_major); - else printk("?."); - - if (bios_minor >= 0) printk("%d", bios_minor); - else printk("?."); - - printk( " at 0x%lx using scsi id %d\n", - bios_base, shpnt->this_id ); - } - - /* If this driver works for later FD PCI - boards, we will have to modify banner - for additional PCI cards, but for now if - it's PCI it's a TMC-3260 - JTM */ - printk(KERN_INFO "scsi%d: %s chip at 0x%x irq ", - shpnt->host_no, - chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")), - port_base); - - if (interrupt_level) - printk("%d", interrupt_level); - else - printk(""); - - printk( "\n" ); -} - -int fdomain_setup(char *str) -{ - int ints[4]; - - (void)get_options(str, ARRAY_SIZE(ints), ints); - - if (setup_called++ || ints[0] < 2 || ints[0] > 3) { - printk(KERN_INFO "scsi: Usage: fdomain=,[,]\n"); - printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); - return 0; - } - - port_base = ints[0] >= 1 ? ints[1] : 0; - interrupt_level = ints[0] >= 2 ? ints[2] : 0; - this_id = ints[0] >= 3 ? ints[3] : 0; - - bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ - ++setup_called; - return 1; -} - -__setup("fdomain=", fdomain_setup); - - -static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ -{ - mdelay(10*amount); -} - -static inline void fdomain_make_bus_idle( void ) -{ - outb(0, port_base + SCSI_Cntl); - outb(0, port_base + SCSI_Mode_Cntl); - if (chip == tmc18c50 || chip == tmc18c30) - outb(0x21 | PARITY_MASK, port_base + TMC_Cntl); /* Clear forced intr. */ - else - outb(0x01 | PARITY_MASK, port_base + TMC_Cntl); -} - -static int fdomain_is_valid_port( int port ) -{ -#if DEBUG_DETECT - printk( " (%x%x),", - inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) ); -#endif - - /* The MCA ID is a unique id for each MCA compatible board. We - are using ISA boards, but Future Domain provides the MCA ID - anyway. We can use this ID to ensure that this is a Future - Domain TMC-1660/TMC-1680. - */ - - if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */ - if (inb( port + LSB_ID_Code ) != 0x27) return 0; - if (inb( port + MSB_ID_Code ) != 0x61) return 0; - chip = tmc1800; - } else { /* test for 0xe960 id */ - if (inb( port + MSB_ID_Code ) != 0x60) return 0; - chip = tmc18c50; - - /* Try to toggle 32-bit mode. This only - works on an 18c30 chip. (User reports - say this works, so we should switch to - it in the near future.) */ - - outb( 0x80, port + IO_Control ); - if ((inb( port + Configuration2 ) & 0x80) == 0x80) { - outb( 0x00, port + IO_Control ); - if ((inb( port + Configuration2 ) & 0x80) == 0x00) { - chip = tmc18c30; - FIFO_Size = 0x800; /* 2k FIFO */ - } - } - /* If that failed, we are an 18c50. */ - } - - return 1; -} - -static int fdomain_test_loopback( void ) -{ - int i; - int result; - - for (i = 0; i < 255; i++) { - outb( i, port_base + Write_Loopback ); - result = inb( port_base + Read_Loopback ); - if (i != result) - return 1; - } - return 0; -} - -#ifndef PCMCIA - -/* fdomain_get_irq assumes that we have a valid MCA ID for a - TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the - bios_base matches these ports. If someone was unlucky enough to have - purchased more than one Future Domain board, then they will have to - modify this code, as we only detect one board here. [The one with the - lowest bios_base.] - - Note that this routine is only used for systems without a PCI BIOS32 - (e.g., ISA bus). For PCI bus systems, this routine will likely fail - unless one of the IRQs listed in the ints array is used by the board. - Sometimes it is possible to use the computer's BIOS setup screen to - configure a PCI system so that one of these IRQs will be used by the - Future Domain card. */ - -static int fdomain_get_irq( int base ) -{ - int options = inb(base + Configuration1); - -#if DEBUG_DETECT - printk("scsi: Options = %x\n", options); -#endif - - /* Check for board with lowest bios_base -- - this isn't valid for the 18c30 or for - boards on the PCI bus, so just assume we - have the right board. */ - - if (chip != tmc18c30 && !PCI_bus && addresses[(options & 0xc0) >> 6 ] != bios_base) - return 0; - return ints[(options & 0x0e) >> 1]; -} - -static int fdomain_isa_detect( int *irq, int *iobase ) -{ - int i, j; - int base = 0xdeadbeef; - int flag = 0; - -#if DEBUG_DETECT - printk( "scsi: fdomain_isa_detect:" ); -#endif - - for (i = 0; i < ADDRESS_COUNT; i++) { - void __iomem *p = ioremap(addresses[i], 0x2000); - if (!p) - continue; -#if DEBUG_DETECT - printk( " %lx(%lx),", addresses[i], bios_base ); -#endif - for (j = 0; j < SIGNATURE_COUNT; j++) { - if (check_signature(p + signatures[j].sig_offset, - signatures[j].signature, - signatures[j].sig_length )) { - bios_major = signatures[j].major_bios_version; - bios_minor = signatures[j].minor_bios_version; - PCI_bus = (signatures[j].flag == 1); - Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; - bios_base = addresses[i]; - bios_mem = p; - goto found; - } - } - iounmap(p); - } - -found: - if (bios_major == 2) { - /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. - Assuming the ROM is enabled (otherwise we wouldn't have been - able to read the ROM signature :-), then the ROM sets up the - RAM area with some magic numbers, such as a list of port - base addresses and a list of the disk "geometry" reported to - DOS (this geometry has nothing to do with physical geometry). - */ - - switch (Quantum) { - case 2: /* ISA_200S */ - case 3: /* ISA_250MG */ - base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8); - break; - case 4: /* ISA_200S (another one) */ - base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8); - break; - default: - base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8); - break; - } - -#if DEBUG_DETECT - printk( " %x,", base ); -#endif - - for (i = 0; i < PORT_COUNT; i++) { - if (base == ports[i]) { - if (!request_region(base, 0x10, "fdomain")) - break; - if (!fdomain_is_valid_port(base)) { - release_region(base, 0x10); - break; - } - *irq = fdomain_get_irq( base ); - *iobase = base; - return 1; - } - } - - /* This is a bad sign. It usually means that someone patched the - BIOS signature list (the signatures variable) to contain a BIOS - signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ - -#if DEBUG_DETECT - printk( " RAM FAILED, " ); -#endif - } - - /* Anyway, the alternative to finding the address in the RAM is to just - search through every possible port address for one that is attached - to the Future Domain card. Don't panic, though, about reading all - these random port addresses -- there are rumors that the Future - Domain BIOS does something very similar. - - Do not, however, check ports which the kernel knows are being used by - another driver. */ - - for (i = 0; i < PORT_COUNT; i++) { - base = ports[i]; - if (!request_region(base, 0x10, "fdomain")) { -#if DEBUG_DETECT - printk( " (%x inuse),", base ); -#endif - continue; - } -#if DEBUG_DETECT - printk( " %x,", base ); -#endif - flag = fdomain_is_valid_port(base); - if (flag) - break; - release_region(base, 0x10); - } - -#if DEBUG_DETECT - if (flag) printk( " SUCCESS\n" ); - else printk( " FAILURE\n" ); -#endif - - if (!flag) return 0; /* iobase not found */ - - *irq = fdomain_get_irq( base ); - *iobase = base; - - return 1; /* success */ -} - -#else /* PCMCIA */ - -static int fdomain_isa_detect( int *irq, int *iobase ) -{ - if (irq) - *irq = 0; - if (iobase) - *iobase = 0; - return 0; -} - -#endif /* !PCMCIA */ - - -/* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* - iobase) This function gets the Interrupt Level and I/O base address from - the PCI configuration registers. */ - -#ifdef CONFIG_PCI -static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev ) -{ - unsigned int pci_irq; /* PCI interrupt line */ - unsigned long pci_base; /* PCI I/O base address */ - struct pci_dev *pdev = NULL; - -#if DEBUG_DETECT - /* Tell how to print a list of the known PCI devices from bios32 and - list vendor and device IDs being used if in debug mode. */ - - printk( "scsi: INFO: use lspci -v to see list of PCI devices\n" ); - printk( "scsi: TMC-3260 detect:" - " Using Vendor ID: 0x%x and Device ID: 0x%x\n", - PCI_VENDOR_ID_FD, - PCI_DEVICE_ID_FD_36C70 ); -#endif - - if ((pdev = pci_get_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) - return 0; - if (pci_enable_device(pdev)) - goto fail; - -#if DEBUG_DETECT - printk( "scsi: TMC-3260 detect:" - " PCI bus %u, device %u, function %u\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); -#endif - - /* We now have the appropriate device function for the FD board so we - just read the PCI config info from the registers. */ - - pci_base = pci_resource_start(pdev, 0); - pci_irq = pdev->irq; - - if (!request_region( pci_base, 0x10, "fdomain" )) - goto fail; - - /* Now we have the I/O base address and interrupt from the PCI - configuration registers. */ - - *irq = pci_irq; - *iobase = pci_base; - *ret_pdev = pdev; - -#if DEBUG_DETECT - printk( "scsi: TMC-3260 detect:" - " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base ); -#endif - - if (!fdomain_is_valid_port(pci_base)) { - printk(KERN_ERR "scsi: PCI card detected, but driver not loaded (invalid port)\n" ); - release_region(pci_base, 0x10); - goto fail; - } - - /* Fill in a few global variables. Ugh. */ - bios_major = bios_minor = -1; - PCI_bus = 1; - PCI_dev = pdev; - Quantum = 0; - bios_base = 0; - - return 1; -fail: - pci_dev_put(pdev); - return 0; -} - -#endif - -struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) -{ - int retcode; - struct Scsi_Host *shpnt; - struct pci_dev *pdev = NULL; - - if (setup_called) { -#if DEBUG_DETECT - printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", - port_base, interrupt_level ); -#endif - if (!request_region(port_base, 0x10, "fdomain")) { - printk( "scsi: port 0x%x is busy\n", port_base ); - printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - return NULL; - } - if (!fdomain_is_valid_port( port_base )) { - printk( "scsi: Cannot locate chip at port base 0x%x\n", - port_base ); - printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - release_region(port_base, 0x10); - return NULL; - } - } else { - int flag = 0; - -#ifdef CONFIG_PCI - /* Try PCI detection first */ - flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev ); -#endif - if (!flag) { - /* Then try ISA bus detection */ - flag = fdomain_isa_detect( &interrupt_level, &port_base ); - - if (!flag) { - printk( "scsi: Detection failed (no card)\n" ); - return NULL; - } - } - } - - fdomain_16x0_host_reset(NULL); - - if (fdomain_test_loopback()) { - printk(KERN_ERR "scsi: Detection failed (loopback test failed at port base 0x%x)\n", port_base); - if (setup_called) { - printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); - } - goto fail; - } - - if (this_id) { - tpnt->this_id = (this_id & 0x07); - adapter_mask = (1 << tpnt->this_id); - } else { - if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) { - tpnt->this_id = 7; - adapter_mask = 0x80; - } else { - tpnt->this_id = 6; - adapter_mask = 0x40; - } - } - -/* Print out a banner here in case we can't - get resources. */ - - shpnt = scsi_register( tpnt, 0 ); - if(shpnt == NULL) { - release_region(port_base, 0x10); - return NULL; - } - shpnt->irq = interrupt_level; - shpnt->io_port = port_base; - shpnt->n_io_port = 0x10; - print_banner( shpnt ); - - /* Log IRQ with kernel */ - if (!interrupt_level) { - printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); - goto fail; - } else { - /* Register the IRQ with the kernel */ - - retcode = request_irq( interrupt_level, - do_fdomain_16x0_intr, pdev?IRQF_SHARED:0, "fdomain", shpnt); - - if (retcode < 0) { - if (retcode == -EINVAL) { - printk(KERN_ERR "scsi: IRQ %d is bad!\n", interrupt_level ); - printk(KERN_ERR " This shouldn't happen!\n" ); - printk(KERN_ERR " Send mail to faith@acm.org\n" ); - } else if (retcode == -EBUSY) { - printk(KERN_ERR "scsi: IRQ %d is already in use!\n", interrupt_level ); - printk(KERN_ERR " Please use another IRQ!\n" ); - } else { - printk(KERN_ERR "scsi: Error getting IRQ %d\n", interrupt_level ); - printk(KERN_ERR " This shouldn't happen!\n" ); - printk(KERN_ERR " Send mail to faith@acm.org\n" ); - } - printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); - goto fail; - } - } - return shpnt; -fail: - pci_dev_put(pdev); - release_region(port_base, 0x10); - return NULL; -} - -static int fdomain_16x0_detect(struct scsi_host_template *tpnt) -{ - if (fdomain) - fdomain_setup(fdomain); - return (__fdomain_16x0_detect(tpnt) != NULL); -} - -static const char *fdomain_16x0_info( struct Scsi_Host *ignore ) -{ - static char buffer[128]; - char *pt; - - strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" ); - if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ - strcat( buffer, strchr( VERSION, ':' ) + 1 ); - pt = strrchr( buffer, '$') - 1; - if (!pt) /* Stripped RCS Revision string? */ - pt = buffer + strlen( buffer ) - 1; - if (*pt != ' ') - ++pt; - *pt = '\0'; - } else { /* Assume VERSION is a number */ - strcat( buffer, " " VERSION ); - } - - return buffer; -} - -#if 0 -static int fdomain_arbitrate( void ) -{ - int status = 0; - unsigned long timeout; - -#if EVERY_ACCESS - printk( "fdomain_arbitrate()\n" ); -#endif - - outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */ - outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */ - outb(0x04 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */ - - timeout = 500; - do { - status = inb(port_base + TMC_Status); /* Read adapter status */ - if (status & 0x02) /* Arbitration complete */ - return 0; - mdelay(1); /* Wait one millisecond */ - } while (--timeout); - - /* Make bus idle */ - fdomain_make_bus_idle(); - -#if EVERY_ACCESS - printk( "Arbitration failed, status = %x\n", status ); -#endif -#if ERRORS_ONLY - printk( "scsi: Arbitration failed, status = %x\n", status ); -#endif - return 1; -} -#endif - -static int fdomain_select( int target ) -{ - int status; - unsigned long timeout; -#if ERRORS_ONLY - static int flag = 0; -#endif - - outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */ - outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK); - - /* Stop arbitration and enable parity */ - outb(PARITY_MASK, port_base + TMC_Cntl); - - timeout = 350; /* 350 msec */ - - do { - status = inb(port_base + SCSI_Status); /* Read adapter status */ - if (status & 1) { /* Busy asserted */ - /* Enable SCSI Bus (on error, should make bus idle with 0) */ - outb(0x80, port_base + SCSI_Cntl); - return 0; - } - mdelay(1); /* wait one msec */ - } while (--timeout); - /* Make bus idle */ - fdomain_make_bus_idle(); -#if EVERY_ACCESS - if (!target) printk( "Selection failed\n" ); -#endif -#if ERRORS_ONLY - if (!target) { - if (!flag) /* Skip first failure for all chips. */ - ++flag; - else - printk( "scsi: Selection failed\n" ); - } -#endif - return 1; -} - -static void my_done(int error) -{ - if (in_command) { - in_command = 0; - outb(0x00, port_base + Interrupt_Cntl); - fdomain_make_bus_idle(); - current_SC->result = error; - if (current_SC->scsi_done) - current_SC->scsi_done( current_SC ); - else panic( "scsi: current_SC->scsi_done() == NULL" ); - } else { - panic( "scsi: my_done() called outside of command\n" ); - } -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif -} - -static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id) -{ - unsigned long flags; - int status; - int done = 0; - unsigned data_count; - - /* The fdomain_16x0_intr is only called via - the interrupt handler. The goal of the - sti() here is to allow other - interruptions while this routine is - running. */ - - /* Check for other IRQ sources */ - if ((inb(port_base + TMC_Status) & 0x01) == 0) - return IRQ_NONE; - - /* It is our IRQ */ - outb(0x00, port_base + Interrupt_Cntl); - - /* We usually have one spurious interrupt after each command. Ignore it. */ - if (!in_command || !current_SC) { /* Spurious interrupt */ -#if EVERY_ACCESS - printk( "Spurious interrupt, in_command = %d, current_SC = %x\n", - in_command, current_SC ); -#endif - return IRQ_NONE; - } - - /* Abort calls my_done, so we do nothing here. */ - if (current_SC->SCp.phase & aborted) { -#if DEBUG_ABORT - printk( "scsi: Interrupt after abort, ignoring\n" ); -#endif - /* - return IRQ_HANDLED; */ - } - -#if DEBUG_RACE - ++in_interrupt_flag; -#endif - - if (current_SC->SCp.phase & in_arbitration) { - status = inb(port_base + TMC_Status); /* Read adapter status */ - if (!(status & 0x02)) { -#if EVERY_ACCESS - printk( " AFAIL " ); -#endif - spin_lock_irqsave(current_SC->device->host->host_lock, flags); - my_done( DID_BUS_BUSY << 16 ); - spin_unlock_irqrestore(current_SC->device->host->host_lock, flags); - return IRQ_HANDLED; - } - current_SC->SCp.phase = in_selection; - - outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl); - - outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */ - outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK); - - /* Stop arbitration and enable parity */ - outb(0x10 | PARITY_MASK, port_base + TMC_Cntl); -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return IRQ_HANDLED; - } else if (current_SC->SCp.phase & in_selection) { - status = inb(port_base + SCSI_Status); - if (!(status & 0x01)) { - /* Try again, for slow devices */ - if (fdomain_select( scmd_id(current_SC) )) { -#if EVERY_ACCESS - printk( " SFAIL " ); -#endif - spin_lock_irqsave(current_SC->device->host->host_lock, flags); - my_done( DID_NO_CONNECT << 16 ); - spin_unlock_irqrestore(current_SC->device->host->host_lock, flags); - return IRQ_HANDLED; - } else { -#if EVERY_ACCESS - printk( " AltSel " ); -#endif - /* Stop arbitration and enable parity */ - outb(0x10 | PARITY_MASK, port_base + TMC_Cntl); - } - } - current_SC->SCp.phase = in_other; - outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl); - outb(0x80, port_base + SCSI_Cntl); -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return IRQ_HANDLED; - } - - /* current_SC->SCp.phase == in_other: this is the body of the routine */ - - status = inb(port_base + SCSI_Status); - - if (status & 0x10) { /* REQ */ - - switch (status & 0x0e) { - - case 0x08: /* COMMAND OUT */ - outb(current_SC->cmnd[current_SC->SCp.sent_command++], - port_base + Write_SCSI_Data); -#if EVERY_ACCESS - printk( "CMD = %x,", - current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); -#endif - break; - case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ - if (chip != tmc1800 && !current_SC->SCp.have_data_in) { - current_SC->SCp.have_data_in = -1; - outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl); - } - break; - case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ - if (chip != tmc1800 && !current_SC->SCp.have_data_in) { - current_SC->SCp.have_data_in = 1; - outb(0x90 | PARITY_MASK, port_base + TMC_Cntl); - } - break; - case 0x0c: /* STATUS IN */ - current_SC->SCp.Status = inb(port_base + Read_SCSI_Data); -#if EVERY_ACCESS - printk( "Status = %x, ", current_SC->SCp.Status ); -#endif -#if ERRORS_ONLY - if (current_SC->SCp.Status - && current_SC->SCp.Status != 2 - && current_SC->SCp.Status != 8) { - printk( "scsi: target = %d, command = %x, status = %x\n", - current_SC->device->id, - current_SC->cmnd[0], - current_SC->SCp.Status ); - } -#endif - break; - case 0x0a: /* MESSAGE OUT */ - outb(MESSAGE_REJECT, port_base + Write_SCSI_Data); /* Reject */ - break; - case 0x0e: /* MESSAGE IN */ - current_SC->SCp.Message = inb(port_base + Read_SCSI_Data); -#if EVERY_ACCESS - printk( "Message = %x, ", current_SC->SCp.Message ); -#endif - if (!current_SC->SCp.Message) ++done; -#if DEBUG_MESSAGES || EVERY_ACCESS - if (current_SC->SCp.Message) { - printk( "scsi: message = %x\n", - current_SC->SCp.Message ); - } -#endif - break; - } - } - - if (chip == tmc1800 && !current_SC->SCp.have_data_in - && (current_SC->SCp.sent_command >= current_SC->cmd_len)) { - - if(current_SC->sc_data_direction == DMA_TO_DEVICE) - { - current_SC->SCp.have_data_in = -1; - outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl); - } - else - { - current_SC->SCp.have_data_in = 1; - outb(0x90 | PARITY_MASK, port_base + TMC_Cntl); - } - } - - if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ - while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) { -#if EVERY_ACCESS - printk( "DC=%d, ", data_count ) ; -#endif - if (data_count > current_SC->SCp.this_residual) - data_count = current_SC->SCp.this_residual; - if (data_count > 0) { -#if EVERY_ACCESS - printk( "%d OUT, ", data_count ); -#endif - if (data_count == 1) { - outb(*current_SC->SCp.ptr++, port_base + Write_FIFO); - --current_SC->SCp.this_residual; - } else { - data_count >>= 1; - outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count); - current_SC->SCp.ptr += 2 * data_count; - current_SC->SCp.this_residual -= 2 * data_count; - } - } - if (!current_SC->SCp.this_residual) { - if (current_SC->SCp.buffers_residual) { - --current_SC->SCp.buffers_residual; - ++current_SC->SCp.buffer; - current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - } else - break; - } - } - } - - if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ - while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) { -#if EVERY_ACCESS - printk( "DC=%d, ", data_count ); -#endif - if (data_count > current_SC->SCp.this_residual) - data_count = current_SC->SCp.this_residual; - if (data_count) { -#if EVERY_ACCESS - printk( "%d IN, ", data_count ); -#endif - if (data_count == 1) { - *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO); - --current_SC->SCp.this_residual; - } else { - data_count >>= 1; /* Number of words */ - insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count); - current_SC->SCp.ptr += 2 * data_count; - current_SC->SCp.this_residual -= 2 * data_count; - } - } - if (!current_SC->SCp.this_residual - && current_SC->SCp.buffers_residual) { - --current_SC->SCp.buffers_residual; - ++current_SC->SCp.buffer; - current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - } - } - } - - if (done) { -#if EVERY_ACCESS - printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in ); -#endif - -#if ERRORS_ONLY - if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { - char *buf = scsi_sglist(current_SC); - if ((unsigned char)(*(buf + 2)) & 0x0f) { - unsigned char key; - unsigned char code; - unsigned char qualifier; - - key = (unsigned char)(*(buf + 2)) & 0x0f; - code = (unsigned char)(*(buf + 12)); - qualifier = (unsigned char)(*(buf + 13)); - - if (key != UNIT_ATTENTION - && !(key == NOT_READY - && code == 0x04 - && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) - && !(key == ILLEGAL_REQUEST && (code == 0x25 - || code == 0x24 - || !code))) - - printk( "scsi: REQUEST SENSE" - " Key = %x, Code = %x, Qualifier = %x\n", - key, code, qualifier ); - } - } -#endif -#if EVERY_ACCESS - printk( "BEFORE MY_DONE. . ." ); -#endif - spin_lock_irqsave(current_SC->device->host->host_lock, flags); - my_done( (current_SC->SCp.Status & 0xff) - | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) ); - spin_unlock_irqrestore(current_SC->device->host->host_lock, flags); -#if EVERY_ACCESS - printk( "RETURNING.\n" ); -#endif - - } else { - if (current_SC->SCp.phase & disconnect) { - outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl); - outb(0x00, port_base + SCSI_Cntl); - } else { - outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl); - } - } -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return IRQ_HANDLED; -} - -static int fdomain_16x0_queue_lck(struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) -{ - if (in_command) { - panic( "scsi: fdomain_16x0_queue() NOT REENTRANT!\n" ); - } -#if EVERY_ACCESS - printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", - SCpnt->target, - *(unsigned char *)SCpnt->cmnd, - scsi_sg_count(SCpnt), - scsi_bufflen(SCpnt)); -#endif - - fdomain_make_bus_idle(); - - current_SC = SCpnt; /* Save this for the done function */ - current_SC->scsi_done = done; - - /* Initialize static data */ - - if (scsi_sg_count(current_SC)) { - current_SC->SCp.buffer = scsi_sglist(current_SC); - current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1; - } else { - current_SC->SCp.ptr = NULL; - current_SC->SCp.this_residual = 0; - current_SC->SCp.buffer = NULL; - current_SC->SCp.buffers_residual = 0; - } - - current_SC->SCp.Status = 0; - current_SC->SCp.Message = 0; - current_SC->SCp.have_data_in = 0; - current_SC->SCp.sent_command = 0; - current_SC->SCp.phase = in_arbitration; - - /* Start arbitration */ - outb(0x00, port_base + Interrupt_Cntl); - outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */ - outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */ - ++in_command; - outb(0x20, port_base + Interrupt_Cntl); - outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */ - - return 0; -} - -static DEF_SCSI_QCMD(fdomain_16x0_queue) - -#if DEBUG_ABORT -static void print_info(struct scsi_cmnd *SCpnt) -{ - unsigned int imr; - unsigned int irr; - unsigned int isr; - - if (!SCpnt || !SCpnt->device || !SCpnt->device->host) { - printk(KERN_WARNING "scsi: Cannot provide detailed information\n"); - return; - } - - printk(KERN_INFO "%s\n", fdomain_16x0_info( SCpnt->device->host ) ); - print_banner(SCpnt->device->host); - switch (SCpnt->SCp.phase) { - case in_arbitration: printk("arbitration"); break; - case in_selection: printk("selection"); break; - case in_other: printk("other"); break; - default: printk("unknown"); break; - } - - printk( " (%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", - SCpnt->SCp.phase, - SCpnt->device->id, - *(unsigned char *)SCpnt->cmnd, - scsi_sg_count(SCpnt), - scsi_bufflen(SCpnt)); - printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", - SCpnt->SCp.sent_command, - SCpnt->SCp.have_data_in, - SCpnt->timeout ); -#if DEBUG_RACE - printk( "in_interrupt_flag = %d\n", in_interrupt_flag ); -#endif - - imr = (inb( 0x0a1 ) << 8) + inb( 0x21 ); - outb( 0x0a, 0xa0 ); - irr = inb( 0xa0 ) << 8; - outb( 0x0a, 0x20 ); - irr += inb( 0x20 ); - outb( 0x0b, 0xa0 ); - isr = inb( 0xa0 ) << 8; - outb( 0x0b, 0x20 ); - isr += inb( 0x20 ); - - /* Print out interesting information */ - printk( "IMR = 0x%04x", imr ); - if (imr & (1 << interrupt_level)) - printk( " (masked)" ); - printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); - - printk( "SCSI Status = 0x%02x\n", inb(port_base + SCSI_Status)); - printk( "TMC Status = 0x%02x", inb(port_base + TMC_Status)); - if (inb((port_base + TMC_Status) & 1)) - printk( " (interrupt)" ); - printk( "\n" ); - printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status)); - if (inb(port_base + Interrupt_Status) & 0x08) - printk( " (enabled)" ); - printk( "\n" ); - if (chip == tmc18c50 || chip == tmc18c30) { - printk("FIFO Status = 0x%02x\n", inb(port_base + FIFO_Status)); - printk( "Int. Condition = 0x%02x\n", - inb( port_base + Interrupt_Cond ) ); - } - printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) ); - if (chip == tmc18c50 || chip == tmc18c30) - printk( "Configuration 2 = 0x%02x\n", - inb( port_base + Configuration2 ) ); -} -#endif - -static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt) -{ -#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT - printk( "scsi: abort " ); -#endif - - if (!in_command) { -#if EVERY_ACCESS || ERRORS_ONLY - printk( " (not in command)\n" ); -#endif - return FAILED; - } else printk( "\n" ); - -#if DEBUG_ABORT - print_info( SCpnt ); -#endif - - fdomain_make_bus_idle(); - current_SC->SCp.phase |= aborted; - current_SC->result = DID_ABORT << 16; - - /* Aborts are not done well. . . */ - my_done(DID_ABORT << 16); - return SUCCESS; -} - -int fdomain_16x0_host_reset(struct scsi_cmnd *SCpnt) -{ - unsigned long flags; - - local_irq_save(flags); - - outb(1, port_base + SCSI_Cntl); - do_pause( 2 ); - outb(0, port_base + SCSI_Cntl); - do_pause( 115 ); - outb(0, port_base + SCSI_Mode_Cntl); - outb(PARITY_MASK, port_base + TMC_Cntl); - - local_irq_restore(flags); - return SUCCESS; -} - -static int fdomain_16x0_biosparam(struct scsi_device *sdev, - struct block_device *bdev, - sector_t capacity, int *info_array) -{ - int drive; - int size = capacity; - unsigned long offset; - struct drive_info { - unsigned short cylinders; - unsigned char heads; - unsigned char sectors; - } i; - - /* NOTES: - The RAM area starts at 0x1f00 from the bios_base address. - - For BIOS Version 2.0: - - The drive parameter table seems to start at 0x1f30. - The first byte's purpose is not known. - Next is the cylinder, head, and sector information. - The last 4 bytes appear to be the drive's size in sectors. - The other bytes in the drive parameter table are unknown. - If anyone figures them out, please send me mail, and I will - update these notes. - - Tape drives do not get placed in this table. - - There is another table at 0x1fea: - If the byte is 0x01, then the SCSI ID is not in use. - If the byte is 0x18 or 0x48, then the SCSI ID is in use, - although tapes don't seem to be in this table. I haven't - seen any other numbers (in a limited sample). - - 0x1f2d is a drive count (i.e., not including tapes) - - The table at 0x1fcc are I/O ports addresses for the various - operations. I calculate these by hand in this driver code. - - - - For the ISA-200S version of BIOS Version 2.0: - - The drive parameter table starts at 0x1f33. - - WARNING: Assume that the table entry is 25 bytes long. Someone needs - to check this for the Quantum ISA-200S card. - - - - For BIOS Version 3.2: - - The drive parameter table starts at 0x1f70. Each entry is - 0x0a bytes long. Heads are one less than we need to report. - */ - - if (MAJOR(bdev->bd_dev) != SCSI_DISK0_MAJOR) { - printk("scsi: fdomain_16x0_biosparam: too many disks"); - return 0; - } - drive = MINOR(bdev->bd_dev) >> 4; - - if (bios_major == 2) { - switch (Quantum) { - case 2: /* ISA_200S */ - /* The value of 25 has never been verified. - It should probably be 15. */ - offset = 0x1f33 + drive * 25; - break; - case 3: /* ISA_250MG */ - offset = 0x1f36 + drive * 15; - break; - case 4: /* ISA_200S (another one) */ - offset = 0x1f34 + drive * 15; - break; - default: - offset = 0x1f31 + drive * 25; - break; - } - memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) ); - info_array[0] = i.heads; - info_array[1] = i.sectors; - info_array[2] = i.cylinders; - } else if (bios_major == 3 - && bios_minor >= 0 - && bios_minor < 4) { /* 3.0 and 3.2 BIOS */ - memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10, - sizeof( struct drive_info ) ); - info_array[0] = i.heads + 1; - info_array[1] = i.sectors; - info_array[2] = i.cylinders; - } else { /* 3.4 BIOS (and up?) */ - /* This algorithm was provided by Future Domain (much thanks!). */ - unsigned char *p = scsi_bios_ptable(bdev); - - if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */ - && p[4]) { /* Partition type */ - - /* The partition table layout is as follows: - - Start: 0x1b3h - Offset: 0 = partition status - 1 = starting head - 2 = starting sector and cylinder (word, encoded) - 4 = partition type - 5 = ending head - 6 = ending sector and cylinder (word, encoded) - 8 = starting absolute sector (double word) - c = number of sectors (double word) - Signature: 0x1fe = 0x55aa - - So, this algorithm assumes: - 1) the first partition table is in use, - 2) the data in the first entry is correct, and - 3) partitions never divide cylinders - - Note that (1) may be FALSE for NetBSD (and other BSD flavors), - as well as for Linux. Note also, that Linux doesn't pay any - attention to the fields that are used by this algorithm -- it - only uses the absolute sector data. Recent versions of Linux's - fdisk(1) will fill this data in correctly, and forthcoming - versions will check for consistency. - - Checking for a non-zero partition type is not part of the - Future Domain algorithm, but it seemed to be a reasonable thing - to do, especially in the Linux and BSD worlds. */ - - info_array[0] = p[5] + 1; /* heads */ - info_array[1] = p[6] & 0x3f; /* sectors */ - } else { - - /* Note that this new method guarantees that there will always be - less than 1024 cylinders on a platter. This is good for drives - up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ - - if ((unsigned int)size >= 0x7e0000U) { - info_array[0] = 0xff; /* heads = 255 */ - info_array[1] = 0x3f; /* sectors = 63 */ - } else if ((unsigned int)size >= 0x200000U) { - info_array[0] = 0x80; /* heads = 128 */ - info_array[1] = 0x3f; /* sectors = 63 */ - } else { - info_array[0] = 0x40; /* heads = 64 */ - info_array[1] = 0x20; /* sectors = 32 */ - } - } - /* For both methods, compute the cylinders */ - info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); - kfree(p); - } - - return 0; -} - -static int fdomain_16x0_release(struct Scsi_Host *shpnt) -{ - if (shpnt->irq) - free_irq(shpnt->irq, shpnt); - if (shpnt->io_port && shpnt->n_io_port) - release_region(shpnt->io_port, shpnt->n_io_port); - if (PCI_bus) - pci_dev_put(PCI_dev); - return 0; -} - -struct scsi_host_template fdomain_driver_template = { - .module = THIS_MODULE, - .name = "fdomain", - .proc_name = "fdomain", - .detect = fdomain_16x0_detect, - .info = fdomain_16x0_info, - .queuecommand = fdomain_16x0_queue, - .eh_abort_handler = fdomain_16x0_abort, - .eh_host_reset_handler = fdomain_16x0_host_reset, - .bios_param = fdomain_16x0_biosparam, - .release = fdomain_16x0_release, - .can_queue = 1, - .this_id = 6, - .sg_tablesize = 64, - .use_clustering = DISABLE_CLUSTERING, -}; - -#ifndef PCMCIA -#if defined(CONFIG_PCI) && defined(MODULE) - -static struct pci_device_id fdomain_pci_tbl[] = { - { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { } -}; -MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl); -#endif -#define driver_template fdomain_driver_template -#include "scsi_module.c" - -#endif diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h deleted file mode 100644 index 5cbe86b573ae..000000000000 --- a/drivers/scsi/fdomain.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * fdomain.c -- Future Domain TMC-16x0 SCSI driver - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -extern struct scsi_host_template fdomain_driver_template; -extern int fdomain_setup(char *str); -extern struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ); -extern int fdomain_16x0_host_reset(struct scsi_cmnd *SCpnt); diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index ecc855c550aa..2d435f105b16 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -19,15 +19,6 @@ config PCMCIA_AHA152X To compile this driver as a module, choose M here: the module will be called aha152x_cs. -config PCMCIA_FDOMAIN - tristate "Future Domain PCMCIA support" - help - Say Y here if you intend to attach this type of PCMCIA SCSI host - adapter to your computer. - - To compile this driver as a module, choose M here: the - module will be called fdomain_cs. - config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" depends on !64BIT diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile index 44eea2d43143..faa87a4b2d2b 100644 --- a/drivers/scsi/pcmcia/Makefile +++ b/drivers/scsi/pcmcia/Makefile @@ -4,11 +4,9 @@ ccflags-y := -Idrivers/scsi # 16-bit client drivers obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs.o -obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o obj-$(CONFIG_PCMCIA_NINJA_SCSI) += nsp_cs.o obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o aha152x_cs-objs := aha152x_stub.o aha152x_core.o -fdomain_cs-objs := fdomain_stub.o fdomain_core.o qlogic_cs-objs := qlogic_stub.o diff --git a/drivers/scsi/pcmcia/fdomain_core.c b/drivers/scsi/pcmcia/fdomain_core.c deleted file mode 100644 index a48913791868..000000000000 --- a/drivers/scsi/pcmcia/fdomain_core.c +++ /dev/null @@ -1,2 +0,0 @@ -#define PCMCIA 1 -#include "fdomain.c" diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c deleted file mode 100644 index 953a792150ae..000000000000 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ /dev/null @@ -1,209 +0,0 @@ -/*====================================================================== - - A driver for Future Domain-compatible PCMCIA SCSI cards - - fdomain_cs.c 1.47 2001/10/13 00:08:52 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in - which case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scsi.h" -#include -#include "fdomain.h" - -#include -#include - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds "); -MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver"); -MODULE_LICENSE("Dual MPL/GPL"); - -/*====================================================================*/ - -typedef struct scsi_info_t { - struct pcmcia_device *p_dev; - struct Scsi_Host *host; -} scsi_info_t; - - -static void fdomain_release(struct pcmcia_device *link); -static void fdomain_detach(struct pcmcia_device *p_dev); -static int fdomain_config(struct pcmcia_device *link); - -static int fdomain_probe(struct pcmcia_device *link) -{ - scsi_info_t *info; - - dev_dbg(&link->dev, "fdomain_attach()\n"); - - /* Create new SCSI device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - link->config_regs = PRESENT_OPTION; - - return fdomain_config(link); -} /* fdomain_attach */ - -/*====================================================================*/ - -static void fdomain_detach(struct pcmcia_device *link) -{ - dev_dbg(&link->dev, "fdomain_detach\n"); - - fdomain_release(link); - - kfree(link->priv); -} /* fdomain_detach */ - -/*====================================================================*/ - -static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data) -{ - p_dev->io_lines = 10; - p_dev->resource[0]->end = 0x10; - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - return pcmcia_request_io(p_dev); -} - - -static int fdomain_config(struct pcmcia_device *link) -{ - scsi_info_t *info = link->priv; - int ret; - char str[22]; - struct Scsi_Host *host; - - dev_dbg(&link->dev, "fdomain_config\n"); - - ret = pcmcia_loop_config(link, fdomain_config_check, NULL); - if (ret) - goto failed; - - if (!link->irq) - goto failed; - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - /* A bad hack... */ - release_region(link->resource[0]->start, resource_size(link->resource[0])); - - /* Set configuration options for the fdomain driver */ - sprintf(str, "%d,%d", (unsigned int) link->resource[0]->start, link->irq); - fdomain_setup(str); - - host = __fdomain_16x0_detect(&fdomain_driver_template); - if (!host) { - printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); - goto failed; - } - - if (scsi_add_host(host, NULL)) - goto failed; - scsi_scan_host(host); - - info->host = host; - - return 0; - -failed: - fdomain_release(link); - return -ENODEV; -} /* fdomain_config */ - -/*====================================================================*/ - -static void fdomain_release(struct pcmcia_device *link) -{ - scsi_info_t *info = link->priv; - - dev_dbg(&link->dev, "fdomain_release\n"); - - scsi_remove_host(info->host); - pcmcia_disable_device(link); - scsi_unregister(info->host); -} - -/*====================================================================*/ - -static int fdomain_resume(struct pcmcia_device *link) -{ - fdomain_16x0_host_reset(NULL); - - return 0; -} - -static const struct pcmcia_device_id fdomain_ids[] = { - PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20), - PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e), - PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", "SCSI PCMCIA Credit Card Controller", 0x182bdafe, 0xc80d106f), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); - -static struct pcmcia_driver fdomain_cs_driver = { - .owner = THIS_MODULE, - .name = "fdomain_cs", - .probe = fdomain_probe, - .remove = fdomain_detach, - .id_table = fdomain_ids, - .resume = fdomain_resume, -}; - -static int __init init_fdomain_cs(void) -{ - return pcmcia_register_driver(&fdomain_cs_driver); -} - -static void __exit exit_fdomain_cs(void) -{ - pcmcia_unregister_driver(&fdomain_cs_driver); -} - -module_init(init_fdomain_cs); -module_exit(exit_fdomain_cs); From 94d4731cc5848e582e6cd510d57c41bc3be82045 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:51 +0100 Subject: [PATCH 135/168] scsi: remove the NCR53c406a driver This driver hasn't seen any recent bug fixing and is one of the last drivers using the scsi_module.c infrastruture that has been deprecated 15 years ago. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 12 - drivers/scsi/Makefile | 1 - drivers/scsi/NCR53c406a.c | 1090 ------------------------------------- 3 files changed, 1103 deletions(-) delete mode 100644 drivers/scsi/NCR53c406a.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 117c2fb41b77..9fa0cfd5a068 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -841,18 +841,6 @@ config SCSI_IZIP_SLOW_CTR Generally, saying N is fine. -config SCSI_NCR53C406A - tristate "NCR53c406a SCSI support" - depends on ISA && SCSI - help - This is support for the NCR53c406a SCSI host adapter. For user - configurable parameters, check out - in the kernel source. Also read the SCSI-HOWTO, available from - . - - To compile this driver as a module, choose M here: the - module will be called NCR53c406. - config SCSI_NCR_D700 tristate "NCR Dual 700 MCA SCSI support" depends on MCA && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 77bb0017bb02..192a58d7d9d9 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -75,7 +75,6 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o -obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c deleted file mode 100644 index 44b09870bf51..000000000000 --- a/drivers/scsi/NCR53c406a.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * NCR53c406.c - * Low-level SCSI driver for NCR53c406a chip. - * Copyright (C) 1994, 1995, 1996 Normunds Saumanis (normunds@fi.ibm.com) - * - * LILO command line usage: ncr53c406a=[,[,]] - * Specify IRQ = 0 for non-interrupt driven mode. - * FASTPIO = 1 for fast pio mode, 0 for slow mode. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#define NCR53C406A_DEBUG 0 -#define VERBOSE_NCR53C406A_DEBUG 0 - -/* Set this to 1 for PIO mode (recommended) or to 0 for DMA mode */ -#define USE_PIO 1 - -#define USE_BIOS 0 - /* #define BIOS_ADDR 0xD8000 *//* define this if autoprobe fails */ - /* #define PORT_BASE 0x330 *//* define this if autoprobe fails */ - /* #define IRQ_LEV 0 *//* define this if autoprobe fails */ -#define DMA_CHAN 5 /* this is ignored if DMA is disabled */ - -/* Set this to 0 if you encounter kernel lockups while transferring - * data in PIO mode */ -#define USE_FAST_PIO 1 - -/* ============= End of user configurable parameters ============= */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "scsi.h" -#include - -/* ============================================================= */ - -#define WATCHDOG 5000000 - -#define SYNC_MODE 0 /* Synchronous transfer mode */ - -#ifdef DEBUG -#undef NCR53C406A_DEBUG -#define NCR53C406A_DEBUG 1 -#endif - -#if USE_PIO -#define USE_DMA 0 -#else -#define USE_DMA 1 -#endif - -/* Default configuration */ -#define C1_IMG 0x07 /* ID=7 */ -#define C2_IMG 0x48 /* FE SCSI2 */ -#if USE_DMA -#define C3_IMG 0x21 /* CDB TE */ -#else -#define C3_IMG 0x20 /* CDB */ -#endif -#define C4_IMG 0x04 /* ANE */ -#define C5_IMG 0xb6 /* AA PI SIE POL */ - -#define REG0 (outb(C4_IMG, CONFIG4)) -#define REG1 (outb(C5_IMG, CONFIG5)) - -#if NCR53C406A_DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -#if VERBOSE_NCR53C406A_DEBUG -#define VDEB(x) x -#else -#define VDEB(x) -#endif - -#define LOAD_DMA_COUNT(count) \ - outb(count & 0xff, TC_LSB); \ - outb((count >> 8) & 0xff, TC_MSB); \ - outb((count >> 16) & 0xff, TC_HIGH); - -/* Chip commands */ -#define DMA_OP 0x80 - -#define SCSI_NOP 0x00 -#define FLUSH_FIFO 0x01 -#define CHIP_RESET 0x02 -#define SCSI_RESET 0x03 -#define RESELECT 0x40 -#define SELECT_NO_ATN 0x41 -#define SELECT_ATN 0x42 -#define SELECT_ATN_STOP 0x43 -#define ENABLE_SEL 0x44 -#define DISABLE_SEL 0x45 -#define SELECT_ATN3 0x46 -#define RESELECT3 0x47 -#define TRANSFER_INFO 0x10 -#define INIT_CMD_COMPLETE 0x11 -#define MSG_ACCEPT 0x12 -#define TRANSFER_PAD 0x18 -#define SET_ATN 0x1a -#define RESET_ATN 0x1b -#define SEND_MSG 0x20 -#define SEND_STATUS 0x21 -#define SEND_DATA 0x22 -#define DISCONN_SEQ 0x23 -#define TERMINATE_SEQ 0x24 -#define TARG_CMD_COMPLETE 0x25 -#define DISCONN 0x27 -#define RECV_MSG 0x28 -#define RECV_CMD 0x29 -#define RECV_DATA 0x2a -#define RECV_CMD_SEQ 0x2b -#define TARGET_ABORT_DMA 0x04 - -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at */ -/* 1 = blue - 2 = green - 3 = cyan - 4 = red - 5 = magenta - 6 = yellow - 7 = white -*/ - -#if NCR53C406A_DEBUG -#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} -#else -#define rtrc(i) {} -#endif -/*----------------------------------------------------------------*/ - -enum Phase { - idle, - data_out, - data_in, - command_ph, - status_ph, - message_out, - message_in -}; - -/* Static function prototypes */ -static void NCR53c406a_intr(void *); -static irqreturn_t do_NCR53c406a_intr(int, void *); -static void chip_init(void); -static void calc_port_addr(void); -#ifndef IRQ_LEV -static int irq_probe(void); -#endif - -/* ================================================================= */ - -#if USE_BIOS -static void *bios_base; -#endif - -#ifdef PORT_BASE -static int port_base = PORT_BASE; -#else -static int port_base; -#endif - -#ifdef IRQ_LEV -static int irq_level = IRQ_LEV; -#else -static int irq_level = -1; /* 0 is 'no irq', so use -1 for 'uninitialized' */ -#endif - -#if USE_DMA -static int dma_chan; -#endif - -#if USE_PIO -static int fast_pio = USE_FAST_PIO; -#endif - -static Scsi_Cmnd *current_SC; -static char info_msg[256]; - -/* ================================================================= */ - -/* possible BIOS locations */ -#if USE_BIOS -static void *addresses[] = { - (void *) 0xd8000, - (void *) 0xc8000 -}; -#define ADDRESS_COUNT ARRAY_SIZE(addresses) -#endif /* USE_BIOS */ - -/* possible i/o port addresses */ -static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; -#define PORT_COUNT ARRAY_SIZE(ports) - -#ifndef MODULE -/* possible interrupt channels */ -static unsigned short intrs[] = { 10, 11, 12, 15 }; -#define INTR_COUNT ARRAY_SIZE(intrs) -#endif /* !MODULE */ - -/* signatures for NCR 53c406a based controllers */ -#if USE_BIOS -struct signature { - char *signature; - int sig_offset; - int sig_length; -} signatures[] __initdata = { - /* 1 2 3 4 5 6 */ - /* 123456789012345678901234567890123456789012345678901234567890 */ - { -"Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82},}; - -#define SIGNATURE_COUNT ARRAY_SIZE(signatures) -#endif /* USE_BIOS */ - -/* ============================================================ */ - -/* Control Register Set 0 */ -static int TC_LSB; /* transfer counter lsb */ -static int TC_MSB; /* transfer counter msb */ -static int SCSI_FIFO; /* scsi fifo register */ -static int CMD_REG; /* command register */ -static int STAT_REG; /* status register */ -static int DEST_ID; /* selection/reselection bus id */ -static int INT_REG; /* interrupt status register */ -static int SRTIMOUT; /* select/reselect timeout reg */ -static int SEQ_REG; /* sequence step register */ -static int SYNCPRD; /* synchronous transfer period */ -static int FIFO_FLAGS; /* indicates # of bytes in fifo */ -static int SYNCOFF; /* synchronous offset register */ -static int CONFIG1; /* configuration register */ -static int CLKCONV; /* clock conversion reg */ - /*static int TESTREG;*//* test mode register */ -static int CONFIG2; /* Configuration 2 Register */ -static int CONFIG3; /* Configuration 3 Register */ -static int CONFIG4; /* Configuration 4 Register */ -static int TC_HIGH; /* Transfer Counter High */ - /*static int FIFO_BOTTOM;*//* Reserve FIFO byte register */ - -/* Control Register Set 1 */ - /*static int JUMPER_SENSE;*//* Jumper sense port reg (r/w) */ - /*static int SRAM_PTR;*//* SRAM address pointer reg (r/w) */ - /*static int SRAM_DATA;*//* SRAM data register (r/w) */ -static int PIO_FIFO; /* PIO FIFO registers (r/w) */ - /*static int PIO_FIFO1;*//* */ - /*static int PIO_FIFO2;*//* */ - /*static int PIO_FIFO3;*//* */ -static int PIO_STATUS; /* PIO status (r/w) */ - /*static int ATA_CMD;*//* ATA command/status reg (r/w) */ - /*static int ATA_ERR;*//* ATA features/error register (r/w) */ -static int PIO_FLAG; /* PIO flag interrupt enable (r/w) */ -static int CONFIG5; /* Configuration 5 register (r/w) */ - /*static int SIGNATURE;*//* Signature Register (r) */ - /*static int CONFIG6;*//* Configuration 6 register (r) */ - -/* ============================================================== */ - -#if USE_DMA -static __inline__ int NCR53c406a_dma_setup(unsigned char *ptr, unsigned int count, unsigned char mode) -{ - unsigned limit; - unsigned long flags = 0; - - VDEB(printk("dma: before count=%d ", count)); - if (dma_chan <= 3) { - if (count > 65536) - count = 65536; - limit = 65536 - (((unsigned) ptr) & 0xFFFF); - } else { - if (count > (65536 << 1)) - count = (65536 << 1); - limit = (65536 << 1) - (((unsigned) ptr) & 0x1FFFF); - } - - if (count > limit) - count = limit; - - VDEB(printk("after count=%d\n", count)); - if ((count & 1) || (((unsigned) ptr) & 1)) - panic("NCR53c406a: attempted unaligned DMA transfer\n"); - - flags = claim_dma_lock(); - disable_dma(dma_chan); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, (long) ptr); - set_dma_count(dma_chan, count); - set_dma_mode(dma_chan, mode); - enable_dma(dma_chan); - release_dma_lock(flags); - - return count; -} - -static __inline__ int NCR53c406a_dma_write(unsigned char *src, unsigned int count) -{ - return NCR53c406a_dma_setup(src, count, DMA_MODE_WRITE); -} - -static __inline__ int NCR53c406a_dma_read(unsigned char *src, unsigned int count) -{ - return NCR53c406a_dma_setup(src, count, DMA_MODE_READ); -} - -static __inline__ int NCR53c406a_dma_residual(void) -{ - register int tmp; - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - tmp = get_dma_residue(dma_chan); - release_dma_lock(flags); - - return tmp; -} -#endif /* USE_DMA */ - -#if USE_PIO -static __inline__ int NCR53c406a_pio_read(unsigned char *request, unsigned int reqlen) -{ - int i; - int len; /* current scsi fifo size */ - - REG1; - while (reqlen) { - i = inb(PIO_STATUS); - /* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) - return 0; - - switch (i & 0x1e) { - default: - case 0x10: - len = 0; - break; - case 0x0: - len = 1; - break; - case 0x8: - len = 42; - break; - case 0xc: - len = 84; - break; - case 0xe: - len = 128; - break; - } - - if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occurred */ - return 0; - } - - if (len) { - if (len > reqlen) - len = reqlen; - - if (fast_pio && len > 3) { - insl(PIO_FIFO, request, len >> 2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } else { - while (len--) { - *request++ = inb(PIO_FIFO); - reqlen--; - } - } - } - } - return 0; -} - -static __inline__ int NCR53c406a_pio_write(unsigned char *request, unsigned int reqlen) -{ - int i = 0; - int len; /* current scsi fifo size */ - - REG1; - while (reqlen && !(i & 0x40)) { - i = inb(PIO_STATUS); - /* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) /* error */ - return 0; - - switch (i & 0x1e) { - case 0x10: - len = 128; - break; - case 0x0: - len = 84; - break; - case 0x8: - len = 42; - break; - case 0xc: - len = 1; - break; - default: - case 0xe: - len = 0; - break; - } - - if (len) { - if (len > reqlen) - len = reqlen; - - if (fast_pio && len > 3) { - outsl(PIO_FIFO, request, len >> 2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } else { - while (len--) { - outb(*request++, PIO_FIFO); - reqlen--; - } - } - } - } - return 0; -} -#endif /* USE_PIO */ - -static int NCR53c406a_detect(struct scsi_host_template * tpnt) -{ - int present = 0; - struct Scsi_Host *shpnt = NULL; -#ifndef PORT_BASE - int i; -#endif - -#if USE_BIOS - int ii, jj; - bios_base = 0; - /* look for a valid signature */ - for (ii = 0; ii < ADDRESS_COUNT && !bios_base; ii++) - for (jj = 0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) - if (!memcmp((void *) addresses[ii] + signatures[jj].sig_offset, (void *) signatures[jj].signature, (int) signatures[jj].sig_length)) - bios_base = addresses[ii]; - - if (!bios_base) { - printk("NCR53c406a: BIOS signature not found\n"); - return 0; - } - - DEB(printk("NCR53c406a BIOS found at 0x%x\n", (unsigned int) bios_base); - ); -#endif /* USE_BIOS */ - -#ifdef PORT_BASE - if (!request_region(port_base, 0x10, "NCR53c406a")) /* ports already snatched */ - port_base = 0; - -#else /* autodetect */ - if (port_base) { /* LILO override */ - if (!request_region(port_base, 0x10, "NCR53c406a")) - port_base = 0; - } else { - for (i = 0; i < PORT_COUNT && !port_base; i++) { - if (!request_region(ports[i], 0x10, "NCR53c406a")) { - DEB(printk("NCR53c406a: port 0x%x in use\n", ports[i])); - } else { - VDEB(printk("NCR53c406a: port 0x%x available\n", ports[i])); - outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */ - if ((inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 && (inb(ports[i] + 0x0e) & 0xf8) == 0x58) { - port_base = ports[i]; - VDEB(printk("NCR53c406a: Sig register valid\n")); - VDEB(printk("port_base=0x%x\n", port_base)); - break; - } - release_region(ports[i], 0x10); - } - } - } -#endif /* PORT_BASE */ - - if (!port_base) { /* no ports found */ - printk("NCR53c406a: no available ports found\n"); - return 0; - } - - DEB(printk("NCR53c406a detected\n")); - - calc_port_addr(); - chip_init(); - -#ifndef IRQ_LEV - if (irq_level < 0) { /* LILO override if >= 0 */ - irq_level = irq_probe(); - if (irq_level < 0) { /* Trouble */ - printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); - goto err_release; - } - } -#endif - - DEB(printk("NCR53c406a: using port_base 0x%x\n", port_base)); - - present = 1; - tpnt->proc_name = "NCR53c406a"; - - shpnt = scsi_register(tpnt, 0); - if (!shpnt) { - printk("NCR53c406a: Unable to register host, giving up.\n"); - goto err_release; - } - - if (irq_level > 0) { - if (request_irq(irq_level, do_NCR53c406a_intr, 0, "NCR53c406a", shpnt)) { - printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); - goto err_free_scsi; - } - tpnt->can_queue = 1; - DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); - } else if (irq_level == 0) { - tpnt->can_queue = 0; - DEB(printk("NCR53c406a: No interrupts detected\n")); - printk("NCR53c406a driver no longer supports polling interface\n"); - printk("Please email linux-scsi@vger.kernel.org\n"); - -#if USE_DMA - printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); -#endif /* USE_DMA */ - goto err_free_scsi; - } else { - DEB(printk("NCR53c406a: Shouldn't get here!\n")); - goto err_free_scsi; - } - -#if USE_DMA - dma_chan = DMA_CHAN; - if (request_dma(dma_chan, "NCR53c406a") != 0) { - printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); - goto err_free_irq; - } - - DEB(printk("Allocated DMA channel %d\n", dma_chan)); -#endif /* USE_DMA */ - - shpnt->irq = irq_level; - shpnt->io_port = port_base; - shpnt->n_io_port = 0x10; -#if USE_DMA - shpnt->dma = dma_chan; -#endif - -#if USE_DMA - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", port_base, irq_level, dma_chan); -#else - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", port_base, irq_level, fast_pio ? "fast" : "slow"); -#endif - - return (present); - -#if USE_DMA - err_free_irq: - if (irq_level) - free_irq(irq_level, shpnt); -#endif - err_free_scsi: - scsi_unregister(shpnt); - err_release: - release_region(port_base, 0x10); - return 0; -} - -static int NCR53c406a_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); -#if USE_DMA - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); -#endif - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - - scsi_unregister(shost); - return 0; -} - -#ifndef MODULE -/* called from init/main.c */ -static int __init NCR53c406a_setup(char *str) -{ - static size_t setup_idx = 0; - size_t i; - int ints[4]; - - DEB(printk("NCR53c406a: Setup called\n"); - ); - - if (setup_idx >= PORT_COUNT - 1) { - printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); - return 0; - } - get_options(str, 4, ints); - if (ints[0] < 1 || ints[0] > 3) { - printk("NCR53c406a: Malformed command line\n"); - printk("NCR53c406a: Usage: ncr53c406a=[,[,]]\n"); - return 0; - } - for (i = 0; i < PORT_COUNT && !port_base; i++) - if (ports[i] == ints[1]) { - port_base = ints[1]; - DEB(printk("NCR53c406a: Specified port_base 0x%x\n", port_base); - ) - } - if (!port_base) { - printk("NCR53c406a: Invalid PORTBASE 0x%x specified\n", ints[1]); - return 0; - } - - if (ints[0] > 1) { - if (ints[2] == 0) { - irq_level = 0; - DEB(printk("NCR53c406a: Specified irq %d\n", irq_level); - ) - } else - for (i = 0; i < INTR_COUNT && irq_level < 0; i++) - if (intrs[i] == ints[2]) { - irq_level = ints[2]; - DEB(printk("NCR53c406a: Specified irq %d\n", port_base); - ) - } - if (irq_level < 0) - printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); - } - - if (ints[0] > 2) - fast_pio = ints[3]; - - DEB(printk("NCR53c406a: port_base=0x%x, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);) - return 1; -} - -__setup("ncr53c406a=", NCR53c406a_setup); - -#endif /* !MODULE */ - -static const char *NCR53c406a_info(struct Scsi_Host *SChost) -{ - DEB(printk("NCR53c406a_info called\n")); - return (info_msg); -} - -#if 0 -static void wait_intr(void) -{ - unsigned long i = jiffies + WATCHDOG; - - while (time_after(i, jiffies) && !(inb(STAT_REG) & 0xe0)) { /* wait for a pseudo-interrupt */ - cpu_relax(); - barrier(); - } - - if (time_before_eq(i, jiffies)) { /* Timed out */ - rtrc(0); - current_SC->result = DID_TIME_OUT << 16; - current_SC->SCp.phase = idle; - current_SC->scsi_done(current_SC); - return; - } - - NCR53c406a_intr(NULL); -} -#endif - -static int NCR53c406a_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) -{ - int i; - - VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->target, (u8)SCpnt->device->lun, scsi_bufflen(SCpnt))); - -#if 0 - VDEB(for (i = 0; i < SCpnt->cmd_len; i++) - printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); - VDEB(printk("\n")); -#endif - - current_SC = SCpnt; - current_SC->scsi_done = done; - current_SC->SCp.phase = command_ph; - current_SC->SCp.Status = 0; - current_SC->SCp.Message = 0; - - /* We are locked here already by the mid layer */ - REG0; - outb(scmd_id(SCpnt), DEST_ID); /* set destination */ - outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ - - for (i = 0; i < SCpnt->cmd_len; i++) { - outb(SCpnt->cmnd[i], SCSI_FIFO); - } - outb(SELECT_NO_ATN, CMD_REG); - - rtrc(1); - return 0; -} - -static DEF_SCSI_QCMD(NCR53c406a_queue) - -static int NCR53c406a_host_reset(Scsi_Cmnd * SCpnt) -{ - DEB(printk("NCR53c406a_reset called\n")); - - spin_lock_irq(SCpnt->device->host->host_lock); - - outb(C4_IMG, CONFIG4); /* Select reg set 0 */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); /* required after reset */ - outb(SCSI_RESET, CMD_REG); - chip_init(); - - rtrc(2); - - spin_unlock_irq(SCpnt->device->host->host_lock); - - return SUCCESS; -} - -static int NCR53c406a_biosparm(struct scsi_device *disk, - struct block_device *dev, - sector_t capacity, int *info_array) -{ - int size; - - DEB(printk("NCR53c406a_biosparm called\n")); - - size = capacity; - info_array[0] = 64; /* heads */ - info_array[1] = 32; /* sectors */ - info_array[2] = size >> 11; /* cylinders */ - if (info_array[2] > 1024) { /* big disk */ - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = size / (255 * 63); - } - return 0; -} - -static irqreturn_t do_NCR53c406a_intr(int unused, void *dev_id) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - spin_lock_irqsave(dev->host_lock, flags); - NCR53c406a_intr(dev_id); - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static void NCR53c406a_intr(void *dev_id) -{ - DEB(unsigned char fifo_size; - ) - DEB(unsigned char seq_reg; - ) - unsigned char status, int_reg; -#if USE_PIO - unsigned char pio_status; - struct scatterlist *sg; - int i; -#endif - - VDEB(printk("NCR53c406a_intr called\n")); - -#if USE_PIO - REG1; - pio_status = inb(PIO_STATUS); -#endif - REG0; - status = inb(STAT_REG); - DEB(seq_reg = inb(SEQ_REG)); - int_reg = inb(INT_REG); - DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); - -#if NCR53C406A_DEBUG - printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", status, seq_reg, int_reg, fifo_size); -#if (USE_DMA) - printk("\n"); -#else - printk(", pio=%02x\n", pio_status); -#endif /* USE_DMA */ -#endif /* NCR53C406A_DEBUG */ - - if (int_reg & 0x80) { /* SCSI reset intr */ - rtrc(3); - DEB(printk("NCR53c406a: reset intr received\n")); - current_SC->SCp.phase = idle; - current_SC->result = DID_RESET << 16; - current_SC->scsi_done(current_SC); - return; - } -#if USE_PIO - if (pio_status & 0x80) { - printk("NCR53C406A: Warning: PIO error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } -#endif /* USE_PIO */ - - if (status & 0x20) { /* Parity error */ - printk("NCR53c406a: Warning: parity error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_PARITY << 16; - current_SC->scsi_done(current_SC); - return; - } - - if (status & 0x40) { /* Gross error */ - printk("NCR53c406a: Warning: gross error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } - - if (int_reg & 0x20) { /* Disconnect */ - DEB(printk("NCR53c406a: disconnect intr received\n")); - if (current_SC->SCp.phase != message_in) { /* Unexpected disconnect */ - current_SC->result = DID_NO_CONNECT << 16; - } else { /* Command complete, return status and message */ - current_SC->result = (current_SC->SCp.Status & 0xff) - | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); - } - - rtrc(0); - current_SC->SCp.phase = idle; - current_SC->scsi_done(current_SC); - return; - } - - switch (status & 0x07) { /* scsi phase */ - case 0x00: /* DATA-OUT */ - if (int_reg & 0x10) { /* Target requesting info transfer */ - rtrc(5); - current_SC->SCp.phase = data_out; - VDEB(printk("NCR53c406a: Data-Out phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(scsi_bufflen(current_SC)); /* Max transfer size */ -#if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_write(scsi_sglist(current_SC), - scsdi_bufflen(current_SC)); - -#endif /* USE_DMA */ - outb(TRANSFER_INFO | DMA_OP, CMD_REG); -#if USE_PIO - scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { - NCR53c406a_pio_write(sg_virt(sg), sg->length); - } - REG0; -#endif /* USE_PIO */ - } - break; - - case 0x01: /* DATA-IN */ - if (int_reg & 0x10) { /* Target requesting info transfer */ - rtrc(6); - current_SC->SCp.phase = data_in; - VDEB(printk("NCR53c406a: Data-In phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(scsi_bufflen(current_SC)); /* Max transfer size */ -#if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_read(scsi_sglist(current_SC), - scsdi_bufflen(current_SC)); -#endif /* USE_DMA */ - outb(TRANSFER_INFO | DMA_OP, CMD_REG); -#if USE_PIO - scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { - NCR53c406a_pio_read(sg_virt(sg), sg->length); - } - REG0; -#endif /* USE_PIO */ - } - break; - - case 0x02: /* COMMAND */ - current_SC->SCp.phase = command_ph; - printk("NCR53c406a: Warning: Unknown interrupt occurred in command phase!\n"); - break; - - case 0x03: /* STATUS */ - rtrc(7); - current_SC->SCp.phase = status_ph; - VDEB(printk("NCR53c406a: Status phase\n")); - outb(FLUSH_FIFO, CMD_REG); - outb(INIT_CMD_COMPLETE, CMD_REG); - break; - - case 0x04: /* Reserved */ - case 0x05: /* Reserved */ - printk("NCR53c406a: WARNING: Reserved phase!!!\n"); - break; - - case 0x06: /* MESSAGE-OUT */ - DEB(printk("NCR53c406a: Message-Out phase\n")); - current_SC->SCp.phase = message_out; - outb(SET_ATN, CMD_REG); /* Reject the message */ - outb(MSG_ACCEPT, CMD_REG); - break; - - case 0x07: /* MESSAGE-IN */ - rtrc(4); - VDEB(printk("NCR53c406a: Message-In phase\n")); - current_SC->SCp.phase = message_in; - - current_SC->SCp.Status = inb(SCSI_FIFO); - current_SC->SCp.Message = inb(SCSI_FIFO); - - VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); - DEB(printk("Status = %02x Message = %02x\n", current_SC->SCp.Status, current_SC->SCp.Message)); - - if (current_SC->SCp.Message == SAVE_POINTERS || current_SC->SCp.Message == DISCONNECT) { - outb(SET_ATN, CMD_REG); /* Reject message */ - DEB(printk("Discarding SAVE_POINTERS message\n")); - } - outb(MSG_ACCEPT, CMD_REG); - break; - } -} - -#ifndef IRQ_LEV -static int irq_probe(void) -{ - int irqs, irq; - unsigned long i; - - inb(INT_REG); /* clear the interrupt register */ - irqs = probe_irq_on(); - - /* Invalid command will cause an interrupt */ - REG0; - outb(0xff, CMD_REG); - - /* Wait for the interrupt to occur */ - i = jiffies + WATCHDOG; - while (time_after(i, jiffies) && !(inb(STAT_REG) & 0x80)) - barrier(); - if (time_before_eq(i, jiffies)) { /* Timed out, must be hardware trouble */ - probe_irq_off(irqs); - return -1; - } - - irq = probe_irq_off(irqs); - - /* Kick the chip */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); - chip_init(); - - return irq; -} -#endif /* IRQ_LEV */ - -static void chip_init(void) -{ - REG1; -#if USE_DMA - outb(0x00, PIO_STATUS); -#else /* USE_PIO */ - outb(0x01, PIO_STATUS); -#endif - outb(0x00, PIO_FLAG); - - outb(C4_IMG, CONFIG4); /* REG0; */ - outb(C3_IMG, CONFIG3); - outb(C2_IMG, CONFIG2); - outb(C1_IMG, CONFIG1); - - outb(0x05, CLKCONV); /* clock conversion factor */ - outb(0x9C, SRTIMOUT); /* Selection timeout */ - outb(0x05, SYNCPRD); /* Synchronous transfer period */ - outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ -} - -static void __init calc_port_addr(void) -{ - /* Control Register Set 0 */ - TC_LSB = (port_base + 0x00); - TC_MSB = (port_base + 0x01); - SCSI_FIFO = (port_base + 0x02); - CMD_REG = (port_base + 0x03); - STAT_REG = (port_base + 0x04); - DEST_ID = (port_base + 0x04); - INT_REG = (port_base + 0x05); - SRTIMOUT = (port_base + 0x05); - SEQ_REG = (port_base + 0x06); - SYNCPRD = (port_base + 0x06); - FIFO_FLAGS = (port_base + 0x07); - SYNCOFF = (port_base + 0x07); - CONFIG1 = (port_base + 0x08); - CLKCONV = (port_base + 0x09); - /* TESTREG = (port_base+0x0A); */ - CONFIG2 = (port_base + 0x0B); - CONFIG3 = (port_base + 0x0C); - CONFIG4 = (port_base + 0x0D); - TC_HIGH = (port_base + 0x0E); - /* FIFO_BOTTOM = (port_base+0x0F); */ - - /* Control Register Set 1 */ - /* JUMPER_SENSE = (port_base+0x00); */ - /* SRAM_PTR = (port_base+0x01); */ - /* SRAM_DATA = (port_base+0x02); */ - PIO_FIFO = (port_base + 0x04); - /* PIO_FIFO1 = (port_base+0x05); */ - /* PIO_FIFO2 = (port_base+0x06); */ - /* PIO_FIFO3 = (port_base+0x07); */ - PIO_STATUS = (port_base + 0x08); - /* ATA_CMD = (port_base+0x09); */ - /* ATA_ERR = (port_base+0x0A); */ - PIO_FLAG = (port_base + 0x0B); - CONFIG5 = (port_base + 0x0D); - /* SIGNATURE = (port_base+0x0E); */ - /* CONFIG6 = (port_base+0x0F); */ -} - -MODULE_LICENSE("GPL"); - -/* NOTE: scatter-gather support only works in PIO mode. - * Use SG_NONE if DMA mode is enabled! - */ - -static struct scsi_host_template driver_template = -{ - .proc_name = "NCR53c406a" /* proc_name */, - .name = "NCR53c406a" /* name */, - .detect = NCR53c406a_detect /* detect */, - .release = NCR53c406a_release, - .info = NCR53c406a_info /* info */, - .queuecommand = NCR53c406a_queue /* queuecommand */, - .eh_host_reset_handler = NCR53c406a_host_reset /* reset */, - .bios_param = NCR53c406a_biosparm /* biosparm */, - .can_queue = 1 /* can_queue */, - .this_id = 7 /* SCSI ID of the chip */, - .sg_tablesize = 32 /*SG_ALL*/ /*SG_NONE*/, - .unchecked_isa_dma = 1 /* unchecked_isa_dma */, - .use_clustering = ENABLE_CLUSTERING, -}; - -#include "scsi_module.c" - -/* - * Overrides for Emacs so that we get a uniform tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ From 616434e2aa7091f0fc5f7838af0f8bc809c8cf85 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:52 +0100 Subject: [PATCH 136/168] scsi: remove the sym53c416 driver This driver hasn't seen any recent bug fixing and is one of the last drivers using the scsi_module.c infrastruture that has been deprecated 15 years ago. Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 3 - drivers/scsi/Kconfig | 18 - drivers/scsi/Makefile | 1 - drivers/scsi/sym53c416.c | 844 ------------------------- drivers/scsi/sym53c416.h | 33 - 5 files changed, 899 deletions(-) delete mode 100644 drivers/scsi/sym53c416.c delete mode 100644 drivers/scsi/sym53c416.h diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 8f7be8a05642..2dc7f11179d1 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -108,9 +108,6 @@ parameters may be changed at runtime by the command st= [HW,SCSI] SCSI tape parameters (buffers, etc.) See Documentation/scsi/st.txt. - sym53c416= [HW,SCSI] - See header of drivers/scsi/sym53c416.c. - tmscsim= [HW,SCSI] See comment before function dc390_setup() in drivers/scsi/tmscsim.c. diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 9fa0cfd5a068..11e89e56b865 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1172,24 +1172,6 @@ config SCSI_SIM710 It currently supports Compaq EISA cards and NCR MCA cards -config SCSI_SYM53C416 - tristate "Symbios 53c416 SCSI support" - depends on ISA && SCSI - ---help--- - This is support for the sym53c416 SCSI host adapter, the SCSI - adapter that comes with some HP scanners. This driver requires that - the sym53c416 is configured first using some sort of PnP - configuration program (e.g. isapnp) or by a PnP aware BIOS. If you - are using isapnp then you need to compile this driver as a module - and then load it using insmod after isapnp has run. The parameters - of the configured card(s) should be passed to the driver. The format - is: - - insmod sym53c416 sym53c416=, [sym53c416_1=,] - - To compile this driver as a module, choose M here: the - module will be called sym53c416. - config SCSI_DC395x tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 192a58d7d9d9..d5135efbf9cd 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -77,7 +77,6 @@ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o -obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c deleted file mode 100644 index e68bcdc75bc3..000000000000 --- a/drivers/scsi/sym53c416.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * sym53c416.c - * Low-level SCSI driver for sym53c416 chip. - * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) - * - * Changes : - * - * Marcelo Tosatti : Added io_request_lock locking - * Alan Cox : Cleaned up code formatting - * Fixed an irq locking bug - * Added ISAPnP support - * Bjoern A. Zeeb : Initial irq locking updates - * Added another card with ISAPnP support - * - * LILO command line usage: sym53c416=[,] - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsi.h" -#include -#include "sym53c416.h" - -#define VERSION_STRING "Version 1.0.0-ac" - -#define TC_LOW 0x00 /* Transfer counter low */ -#define TC_MID 0x01 /* Transfer counter mid */ -#define SCSI_FIFO 0x02 /* SCSI FIFO register */ -#define COMMAND_REG 0x03 /* Command Register */ -#define STATUS_REG 0x04 /* Status Register (READ) */ -#define DEST_BUS_ID 0x04 /* Destination Bus ID (WRITE) */ -#define INT_REG 0x05 /* Interrupt Register (READ) */ -#define TOM 0x05 /* Time out multiplier (WRITE) */ -#define STP 0x06 /* Synchronous Transfer period */ -#define SYNC_OFFSET 0x07 /* Synchronous Offset */ -#define CONF_REG_1 0x08 /* Configuration register 1 */ -#define CONF_REG_2 0x0B /* Configuration register 2 */ -#define CONF_REG_3 0x0C /* Configuration register 3 */ -#define CONF_REG_4 0x0D /* Configuration register 4 */ -#define TC_HIGH 0x0E /* Transfer counter high */ -#define PIO_FIFO_1 0x10 /* PIO FIFO register 1 */ -#define PIO_FIFO_2 0x11 /* PIO FIFO register 2 */ -#define PIO_FIFO_3 0x12 /* PIO FIFO register 3 */ -#define PIO_FIFO_4 0x13 /* PIO FIFO register 4 */ -#define PIO_FIFO_CNT 0x14 /* PIO FIFO count */ -#define PIO_INT_REG 0x15 /* PIO interrupt register */ -#define CONF_REG_5 0x16 /* Configuration register 5 */ -#define FEATURE_EN 0x1D /* Feature Enable register */ - -/* Configuration register 1 entries: */ -/* Bits 2-0: SCSI ID of host adapter */ -#define SCM 0x80 /* Slow Cable Mode */ -#define SRID 0x40 /* SCSI Reset Interrupt Disable */ -#define PTM 0x20 /* Parity Test Mode */ -#define EPC 0x10 /* Enable Parity Checking */ -#define CTME 0x08 /* Special Test Mode */ - -/* Configuration register 2 entries: */ -#define FE 0x40 /* Features Enable */ -#define SCSI2 0x08 /* SCSI 2 Enable */ -#define TBPA 0x04 /* Target Bad Parity Abort */ - -/* Configuration register 3 entries: */ -#define IDMRC 0x80 /* ID Message Reserved Check */ -#define QTE 0x40 /* Queue Tag Enable */ -#define CDB10 0x20 /* Command Descriptor Block 10 */ -#define FSCSI 0x10 /* FastSCSI */ -#define FCLK 0x08 /* FastClock */ - -/* Configuration register 4 entries: */ -#define RBS 0x08 /* Register bank select */ -#define EAN 0x04 /* Enable Active Negotiation */ - -/* Configuration register 5 entries: */ -#define LPSR 0x80 /* Lower Power SCSI Reset */ -#define IE 0x20 /* Interrupt Enable */ -#define LPM 0x02 /* Low Power Mode */ -#define WSE0 0x01 /* 0WS Enable */ - -/* Interrupt register entries: */ -#define SRST 0x80 /* SCSI Reset */ -#define ILCMD 0x40 /* Illegal Command */ -#define DIS 0x20 /* Disconnect */ -#define BS 0x10 /* Bus Service */ -#define FC 0x08 /* Function Complete */ -#define RESEL 0x04 /* Reselected */ -#define SI 0x03 /* Selection Interrupt */ - -/* Status Register Entries: */ -#define SCI 0x80 /* SCSI Core Int */ -#define GE 0x40 /* Gross Error */ -#define PE 0x20 /* Parity Error */ -#define TC 0x10 /* Terminal Count */ -#define VGC 0x08 /* Valid Group Code */ -#define PHBITS 0x07 /* Phase bits */ - -/* PIO Interrupt Register Entries: */ -#define SCI 0x80 /* SCSI Core Int */ -#define PFI 0x40 /* PIO FIFO Interrupt */ -#define FULL 0x20 /* PIO FIFO Full */ -#define EMPTY 0x10 /* PIO FIFO Empty */ -#define CE 0x08 /* Collision Error */ -#define OUE 0x04 /* Overflow / Underflow error */ -#define FIE 0x02 /* Full Interrupt Enable */ -#define EIE 0x01 /* Empty Interrupt Enable */ - -/* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */ -#define PHASE_DATA_OUT 0x00 -#define PHASE_DATA_IN 0x01 -#define PHASE_COMMAND 0x02 -#define PHASE_STATUS 0x03 -#define PHASE_RESERVED_1 0x04 -#define PHASE_RESERVED_2 0x05 -#define PHASE_MESSAGE_OUT 0x06 -#define PHASE_MESSAGE_IN 0x07 - -/* SYM53C416 core commands */ -#define NOOP 0x00 -#define FLUSH_FIFO 0x01 -#define RESET_CHIP 0x02 -#define RESET_SCSI_BUS 0x03 -#define DISABLE_SEL_RESEL 0x45 -#define RESEL_SEQ 0x40 -#define SEL_WITHOUT_ATN_SEQ 0x41 -#define SEL_WITH_ATN_SEQ 0x42 -#define SEL_WITH_ATN_AND_STOP_SEQ 0x43 -#define ENABLE_SEL_RESEL 0x44 -#define SEL_WITH_ATN3_SEQ 0x46 -#define RESEL3_SEQ 0x47 -#define SND_MSG 0x20 -#define SND_STAT 0x21 -#define SND_DATA 0x22 -#define DISCONNECT_SEQ 0x23 -#define TERMINATE_SEQ 0x24 -#define TARGET_COMM_COMPLETE_SEQ 0x25 -#define DISCONN 0x27 -#define RECV_MSG_SEQ 0x28 -#define RECV_CMD 0x29 -#define RECV_DATA 0x2A -#define RECV_CMD_SEQ 0x2B -#define TARGET_ABORT_PIO 0x04 -#define TRANSFER_INFORMATION 0x10 -#define INIT_COMM_COMPLETE_SEQ 0x11 -#define MSG_ACCEPTED 0x12 -#define TRANSFER_PAD 0x18 -#define SET_ATN 0x1A -#define RESET_ATN 0x1B -#define ILLEGAL 0xFF - -#define PIO_MODE 0x80 - -#define IO_RANGE 0x20 /* 0x00 - 0x1F */ -#define ID "sym53c416" /* Attention: copied to the sym53c416.h */ -#define PIO_SIZE 128 /* Size of PIO fifo is 128 bytes */ - -#define READ_TIMEOUT 150 -#define WRITE_TIMEOUT 150 - -#ifdef MODULE - -#define sym53c416_base sym53c416 -#define sym53c416_base_1 sym53c416_1 -#define sym53c416_base_2 sym53c416_2 -#define sym53c416_base_3 sym53c416_3 - -static unsigned int sym53c416_base[2]; -static unsigned int sym53c416_base_1[2]; -static unsigned int sym53c416_base_2[2]; -static unsigned int sym53c416_base_3[2]; - -#endif - -#define MAXHOSTS 4 - -#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer))) - -enum phases -{ - idle, - data_out, - data_in, - command_ph, - status_ph, - message_out, - message_in -}; - -typedef struct -{ - int base; - int irq; - int scsi_id; -} host; - -static host hosts[MAXHOSTS] = { - {0, 0, SYM53C416_SCSI_ID}, - {0, 0, SYM53C416_SCSI_ID}, - {0, 0, SYM53C416_SCSI_ID}, - {0, 0, SYM53C416_SCSI_ID} - }; - -static int host_index = 0; -static char info[120]; -static Scsi_Cmnd *current_command = NULL; -static int fastpio = 1; - -static int probeaddrs[] = {0x200, 0x220, 0x240, 0}; - -static void sym53c416_set_transfer_counter(int base, unsigned int len) -{ - /* Program Transfer Counter */ - outb(len & 0x0000FF, base + TC_LOW); - outb((len & 0x00FF00) >> 8, base + TC_MID); - outb((len & 0xFF0000) >> 16, base + TC_HIGH); -} - -static DEFINE_SPINLOCK(sym53c416_lock); - -/* Returns the number of bytes read */ -static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len) -{ - unsigned int orig_len = len; - unsigned long flags = 0; - unsigned int bytes_left; - unsigned long i; - int timeout = READ_TIMEOUT; - - /* Do transfer */ - spin_lock_irqsave(&sym53c416_lock, flags); - while(len && timeout) - { - bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */ - if(fastpio && bytes_left > 3) - { - insl(base + PIO_FIFO_1, buffer, bytes_left >> 2); - buffer += bytes_left & 0xFC; - len -= bytes_left & 0xFC; - } - else if(bytes_left > 0) - { - len -= bytes_left; - for(; bytes_left > 0; bytes_left--) - *(buffer++) = inb(base + PIO_FIFO_1); - } - else - { - i = jiffies + timeout; - spin_unlock_irqrestore(&sym53c416_lock, flags); - while(time_before(jiffies, i) && (inb(base + PIO_INT_REG) & EMPTY) && timeout) - if(inb(base + PIO_INT_REG) & SCI) - timeout = 0; - spin_lock_irqsave(&sym53c416_lock, flags); - if(inb(base + PIO_INT_REG) & EMPTY) - timeout = 0; - } - } - spin_unlock_irqrestore(&sym53c416_lock, flags); - return orig_len - len; -} - -/* Returns the number of bytes written */ -static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len) -{ - unsigned int orig_len = len; - unsigned long flags = 0; - unsigned int bufferfree; - unsigned long i; - unsigned int timeout = WRITE_TIMEOUT; - - /* Do transfer */ - spin_lock_irqsave(&sym53c416_lock, flags); - while(len && timeout) - { - bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT); - if(bufferfree > len) - bufferfree = len; - if(fastpio && bufferfree > 3) - { - outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2); - buffer += bufferfree & 0xFC; - len -= bufferfree & 0xFC; - } - else if(bufferfree > 0) - { - len -= bufferfree; - for(; bufferfree > 0; bufferfree--) - outb(*(buffer++), base + PIO_FIFO_1); - } - else - { - i = jiffies + timeout; - spin_unlock_irqrestore(&sym53c416_lock, flags); - while(time_before(jiffies, i) && (inb(base + PIO_INT_REG) & FULL) && timeout) - ; - spin_lock_irqsave(&sym53c416_lock, flags); - if(inb(base + PIO_INT_REG) & FULL) - timeout = 0; - } - } - spin_unlock_irqrestore(&sym53c416_lock, flags); - return orig_len - len; -} - -static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id) -{ - struct Scsi_Host *dev = dev_id; - int base = dev->io_port; - int i; - unsigned long flags = 0; - unsigned char status_reg, pio_int_reg, int_reg; - struct scatterlist *sg; - unsigned int tot_trans = 0; - - spin_lock_irqsave(dev->host_lock,flags); - status_reg = inb(base + STATUS_REG); - pio_int_reg = inb(base + PIO_INT_REG); - int_reg = inb(base + INT_REG); - spin_unlock_irqrestore(dev->host_lock, flags); - - /* First, we handle error conditions */ - if(int_reg & SCI) /* SCSI Reset */ - { - printk(KERN_DEBUG "sym53c416: Reset received\n"); - current_command->SCp.phase = idle; - current_command->result = DID_RESET << 16; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - if(int_reg & ILCMD) /* Illegal Command */ - { - printk(KERN_WARNING "sym53c416: Illegal Command: 0x%02x.\n", inb(base + COMMAND_REG)); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - if(status_reg & GE) /* Gross Error */ - { - printk(KERN_WARNING "sym53c416: Controller reports gross error.\n"); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - if(status_reg & PE) /* Parity Error */ - { - printk(KERN_WARNING "sym53c416:SCSI parity error.\n"); - current_command->SCp.phase = idle; - current_command->result = DID_PARITY << 16; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - if(pio_int_reg & (CE | OUE)) - { - printk(KERN_WARNING "sym53c416: PIO interrupt error.\n"); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - if(int_reg & DIS) /* Disconnect */ - { - if(current_command->SCp.phase != message_in) - current_command->result = DID_NO_CONNECT << 16; - else - current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); - current_command->SCp.phase = idle; - spin_lock_irqsave(dev->host_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(dev->host_lock, flags); - goto out; - } - /* Now we handle SCSI phases */ - - switch(status_reg & PHBITS) /* Filter SCSI phase out of status reg */ - { - case PHASE_DATA_OUT: - { - if(int_reg & BS) - { - current_command->SCp.phase = data_out; - outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, - scsi_bufflen(current_command)); - outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - - scsi_for_each_sg(current_command, - sg, scsi_sg_count(current_command), i) { - tot_trans += sym53c416_write(base, - SG_ADDRESS(sg), - sg->length); - } - if(tot_trans < current_command->underflow) - printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); - } - break; - } - - case PHASE_DATA_IN: - { - if(int_reg & BS) - { - current_command->SCp.phase = data_in; - outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, - scsi_bufflen(current_command)); - - outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - - scsi_for_each_sg(current_command, - sg, scsi_sg_count(current_command), i) { - tot_trans += sym53c416_read(base, - SG_ADDRESS(sg), - sg->length); - } - if(tot_trans < current_command->underflow) - printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); - } - break; - } - - case PHASE_COMMAND: - { - current_command->SCp.phase = command_ph; - printk(KERN_ERR "sym53c416: Unknown interrupt in command phase.\n"); - break; - } - - case PHASE_STATUS: - { - current_command->SCp.phase = status_ph; - outb(FLUSH_FIFO, base + COMMAND_REG); - outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG); - break; - } - - case PHASE_RESERVED_1: - case PHASE_RESERVED_2: - { - printk(KERN_ERR "sym53c416: Reserved phase occurred.\n"); - break; - } - - case PHASE_MESSAGE_OUT: - { - current_command->SCp.phase = message_out; - outb(SET_ATN, base + COMMAND_REG); - outb(MSG_ACCEPTED, base + COMMAND_REG); - break; - } - - case PHASE_MESSAGE_IN: - { - current_command->SCp.phase = message_in; - current_command->SCp.Status = inb(base + SCSI_FIFO); - current_command->SCp.Message = inb(base + SCSI_FIFO); - if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT) - outb(SET_ATN, base + COMMAND_REG); - outb(MSG_ACCEPTED, base + COMMAND_REG); - break; - } - } -out: - return IRQ_HANDLED; -} - -static void sym53c416_init(int base, int scsi_id) -{ - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP, base + COMMAND_REG); - outb(0x99, base + TOM); /* Time out of 250 ms */ - outb(0x05, base + STP); - outb(0x00, base + SYNC_OFFSET); - outb(EPC | scsi_id, base + CONF_REG_1); - outb(FE | SCSI2 | TBPA, base + CONF_REG_2); - outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3); - outb(0x83 | EAN, base + CONF_REG_4); - outb(IE | WSE0, base + CONF_REG_5); - outb(0, base + FEATURE_EN); -} - -static int sym53c416_probeirq(int base, int scsi_id) -{ - int irq, irqs; - unsigned long i; - - /* Clear interrupt register */ - inb(base + INT_REG); - /* Start probing for irq's */ - irqs = probe_irq_on(); - /* Reinit chip */ - sym53c416_init(base, scsi_id); - /* Cause interrupt */ - outb(NOOP, base + COMMAND_REG); - outb(ILLEGAL, base + COMMAND_REG); - outb(0x07, base + DEST_BUS_ID); - outb(0x00, base + DEST_BUS_ID); - /* Wait for interrupt to occur */ - i = jiffies + 20; - while(time_before(jiffies, i) && !(inb(base + STATUS_REG) & SCI)) - barrier(); - if(time_before_eq(i, jiffies)) /* timed out */ - return 0; - /* Get occurred irq */ - irq = probe_irq_off(irqs); - sym53c416_init(base, scsi_id); - return irq; -} - -/* Setup: sym53c416=base,irq */ -void sym53c416_setup(char *str, int *ints) -{ - int i; - - if(host_index >= MAXHOSTS) - { - printk(KERN_WARNING "sym53c416: Too many hosts defined\n"); - return; - } - if(ints[0] < 1 || ints[0] > 2) - { - printk(KERN_ERR "sym53c416: Wrong number of parameters:\n"); - printk(KERN_ERR "sym53c416: usage: sym53c416=[,]\n"); - return; - } - for(i = 0; i < host_index && i >= 0; i++) - if(hosts[i].base == ints[1]) - i = -2; - if(i >= 0) - { - hosts[host_index].base = ints[1]; - hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0; - host_index++; - } -} - -static int sym53c416_test(int base) -{ - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP, base + COMMAND_REG); - if(inb(base + COMMAND_REG) != NOOP) - return 0; - if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF) - return 0; - if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY) - return 0; - return 1; -} - - -static struct isapnp_device_id id_table[] = { - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4161), 0 }, - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4163), 0 }, - { ISAPNP_DEVICE_SINGLE_END } -}; - -MODULE_DEVICE_TABLE(isapnp, id_table); - -static void sym53c416_probe(void) -{ - int *base = probeaddrs; - int ints[2]; - - ints[0] = 1; - for(; *base; base++) { - if (request_region(*base, IO_RANGE, ID)) { - if (sym53c416_test(*base)) { - ints[1] = *base; - sym53c416_setup(NULL, ints); - } - release_region(*base, IO_RANGE); - } - } -} - -int sym53c416_detect(struct scsi_host_template *tpnt) -{ - unsigned long flags; - struct Scsi_Host * shpnt = NULL; - int i; - int count; - struct pnp_dev *idev = NULL; - -#ifdef MODULE - int ints[3]; - - ints[0] = 2; - if(sym53c416_base[0]) - { - ints[1] = sym53c416_base[0]; - ints[2] = sym53c416_base[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_1[0]) - { - ints[1] = sym53c416_base_1[0]; - ints[2] = sym53c416_base_1[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_2[0]) - { - ints[1] = sym53c416_base_2[0]; - ints[2] = sym53c416_base_2[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_3[0]) - { - ints[1] = sym53c416_base_3[0]; - ints[2] = sym53c416_base_3[1]; - sym53c416_setup(NULL, ints); - } -#endif - printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING); - - for (i=0; id_table[i].vendor != 0; i++) { - while((idev=pnp_find_dev(NULL, id_table[i].vendor, - id_table[i].function, idev))!=NULL) - { - int i[3]; - - if(pnp_device_attach(idev)<0) - { - printk(KERN_WARNING "sym53c416: unable to attach PnP device.\n"); - continue; - } - if(pnp_activate_dev(idev) < 0) - { - printk(KERN_WARNING "sym53c416: unable to activate PnP device.\n"); - pnp_device_detach(idev); - continue; - - } - - i[0] = 2; - i[1] = pnp_port_start(idev, 0); - i[2] = pnp_irq(idev, 0); - - printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n", - i[1], i[2]); - sym53c416_setup(NULL, i); - } - } - sym53c416_probe(); - - /* Now we register and set up each host adapter found... */ - for(count = 0, i = 0; i < host_index; i++) { - if (!request_region(hosts[i].base, IO_RANGE, ID)) - continue; - if (!sym53c416_test(hosts[i].base)) { - printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base); - goto fail_release_region; - } - - /* We don't have an irq yet, so we should probe for one */ - if (!hosts[i].irq) - hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id); - if (!hosts[i].irq) - goto fail_release_region; - - shpnt = scsi_register(tpnt, 0); - if (!shpnt) - goto fail_release_region; - /* Request for specified IRQ */ - if (request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt)) - goto fail_free_host; - - spin_lock_irqsave(&sym53c416_lock, flags); - shpnt->unique_id = hosts[i].base; - shpnt->io_port = hosts[i].base; - shpnt->n_io_port = IO_RANGE; - shpnt->irq = hosts[i].irq; - shpnt->this_id = hosts[i].scsi_id; - sym53c416_init(hosts[i].base, hosts[i].scsi_id); - count++; - spin_unlock_irqrestore(&sym53c416_lock, flags); - continue; - - fail_free_host: - scsi_unregister(shpnt); - fail_release_region: - release_region(hosts[i].base, IO_RANGE); - } - return count; -} - -const char *sym53c416_info(struct Scsi_Host *SChost) -{ - int i; - int base = SChost->io_port; - int irq = SChost->irq; - int scsi_id = 0; - int rev = inb(base + TC_HIGH); - - for(i = 0; i < host_index; i++) - if(hosts[i].base == base) - scsi_id = hosts[i].scsi_id; - sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow"); - return info; -} - -static int sym53c416_queuecommand_lck(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - int base; - unsigned long flags = 0; - int i; - - /* Store base register as we can have more than one controller in the system */ - base = SCpnt->device->host->io_port; - current_command = SCpnt; /* set current command */ - current_command->scsi_done = done; /* set ptr to done function */ - current_command->SCp.phase = command_ph; /* currect phase is the command phase */ - current_command->SCp.Status = 0; - current_command->SCp.Message = 0; - - spin_lock_irqsave(&sym53c416_lock, flags); - outb(scmd_id(SCpnt), base + DEST_BUS_ID); /* Set scsi id target */ - outb(FLUSH_FIFO, base + COMMAND_REG); /* Flush SCSI and PIO FIFO's */ - /* Write SCSI command into the SCSI fifo */ - for(i = 0; i < SCpnt->cmd_len; i++) - outb(SCpnt->cmnd[i], base + SCSI_FIFO); - /* Start selection sequence */ - outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG); - /* Now an interrupt will be generated which we will catch in out interrupt routine */ - spin_unlock_irqrestore(&sym53c416_lock, flags); - return 0; -} - -DEF_SCSI_QCMD(sym53c416_queuecommand) - -static int sym53c416_host_reset(Scsi_Cmnd *SCpnt) -{ - int base; - int scsi_id = -1; - int i; - unsigned long flags; - - spin_lock_irqsave(&sym53c416_lock, flags); - - /* printk("sym53c416_reset\n"); */ - base = SCpnt->device->host->io_port; - /* search scsi_id - fixme, we shouldn't need to iterate for this! */ - for(i = 0; i < host_index && scsi_id == -1; i++) - if(hosts[i].base == base) - scsi_id = hosts[i].scsi_id; - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP | PIO_MODE, base + COMMAND_REG); - outb(RESET_SCSI_BUS, base + COMMAND_REG); - sym53c416_init(base, scsi_id); - - spin_unlock_irqrestore(&sym53c416_lock, flags); - return SUCCESS; -} - -static int sym53c416_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, shost); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - return 0; -} - -static int sym53c416_bios_param(struct scsi_device *sdev, - struct block_device *dev, - sector_t capacity, int *ip) -{ - int size; - - size = capacity; - ip[0] = 64; /* heads */ - ip[1] = 32; /* sectors */ - if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */ - { - ip[0] = 255; /* heads */ - ip[1] = 63; /* sectors */ - ip[2] = size / (255 * 63); /* cylinders */ - } - return 0; -} - -/* Loadable module support */ -#ifdef MODULE - -MODULE_AUTHOR("Lieven Willems"); -MODULE_LICENSE("GPL"); - -module_param_array(sym53c416, uint, NULL, 0); -module_param_array(sym53c416_1, uint, NULL, 0); -module_param_array(sym53c416_2, uint, NULL, 0); -module_param_array(sym53c416_3, uint, NULL, 0); - -#endif - -static struct scsi_host_template driver_template = { - .proc_name = "sym53c416", - .name = "Symbios Logic 53c416", - .detect = sym53c416_detect, - .info = sym53c416_info, - .queuecommand = sym53c416_queuecommand, - .eh_host_reset_handler =sym53c416_host_reset, - .release = sym53c416_release, - .bios_param = sym53c416_bios_param, - .can_queue = 1, - .this_id = SYM53C416_SCSI_ID, - .sg_tablesize = 32, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -}; -#include "scsi_module.c" diff --git a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h deleted file mode 100644 index 387de5d80a70..000000000000 --- a/drivers/scsi/sym53c416.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * sym53c416.h - * - * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#ifndef _SYM53C416_H -#define _SYM53C416_H - -#include - -#define SYM53C416_SCSI_ID 7 - -static int sym53c416_detect(struct scsi_host_template *); -static const char *sym53c416_info(struct Scsi_Host *); -static int sym53c416_release(struct Scsi_Host *); -static int sym53c416_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); -static int sym53c416_host_reset(Scsi_Cmnd *); -static int sym53c416_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static void sym53c416_setup(char *str, int *ints); -#endif From 83c9f08e6c6a6dc668384882de4dcf5ef4ae0ba7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Mar 2018 08:37:53 +0100 Subject: [PATCH 137/168] scsi: remove the old scsi_module.c initialization model After more than 15 years all users of this legacy interface are finally gone. Rest in peace! Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/driver-api/scsi.rst | 6 -- Documentation/scsi/scsi_mid_low_api.txt | 122 +----------------------- drivers/scsi/hosts.c | 23 ----- drivers/scsi/scsi_module.c | 73 -------------- include/scsi/scsi_host.h | 36 ------- 5 files changed, 1 insertion(+), 259 deletions(-) delete mode 100644 drivers/scsi/scsi_module.c diff --git a/Documentation/driver-api/scsi.rst b/Documentation/driver-api/scsi.rst index 3ae337929721..31ad0fed6763 100644 --- a/Documentation/driver-api/scsi.rst +++ b/Documentation/driver-api/scsi.rst @@ -154,12 +154,6 @@ lists). .. kernel-doc:: drivers/scsi/scsi_lib_dma.c :export: -drivers/scsi/scsi_module.c -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The file drivers/scsi/scsi_module.c contains legacy support for -old-style host templates. It should never be used by any new driver. - drivers/scsi/scsi_proc.c ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 2c31d9ee6776..177c031763c0 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -114,9 +114,7 @@ called "xxx" could be defined as "static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }" ** the scsi_host_alloc() function is a replacement for the rather vaguely -named scsi_register() function in most situations. The scsi_register() -and scsi_unregister() functions remain to support legacy LLDs that use -the passive initialization model. +named scsi_register() function in most situations. Hotplug initialization model @@ -228,79 +226,6 @@ slave_configure() callbacks). Such instances are "owned" by the mid-level. struct scsi_device instances are freed after slave_destroy(). -Passive initialization model -============================ -These older LLDs include a file called "scsi_module.c" [yes the ".c" is a -little surprising] in their source code. For that file to work an -instance of struct scsi_host_template with the name "driver_template" -needs to be defined. Here is a typical code sequence used in this model: - static struct scsi_host_template driver_template = { - ... - }; - #include "scsi_module.c" - -The scsi_module.c file contains two functions: - - init_this_scsi_driver() which is executed when the LLD is - initialized (i.e. boot time or module load time) - - exit_this_scsi_driver() which is executed when the LLD is shut - down (i.e. module unload time) -Note: since these functions are tagged with __init and __exit qualifiers -an LLD should not call them explicitly (since the kernel does that). - -Here is an example of an initialization sequence when two hosts are -detected (so detect() returns 2) and the SCSI bus scan on each host -finds 1 SCSI device (and a second device does not respond). - -LLD mid level LLD -===----------------------=========-----------------===------ -init_this_scsi_driver() ----+ - | - detect() -----------------+ - | | - | scsi_register() - | scsi_register() - | - slave_alloc() - slave_configure() --> scsi_change_queue_depth() - slave_alloc() *** - slave_destroy() *** - | - slave_alloc() - slave_configure() - slave_alloc() *** - slave_destroy() *** ------------------------------------------------------------- - -The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that -host as the queue length. These settings can be overridden by a -slave_configure() supplied by the LLD. - -*** For scsi devices that the mid level tries to scan but do not - respond, a slave_alloc(), slave_destroy() pair is called. - -Here is an LLD shutdown sequence: - -LLD mid level LLD -===----------------------=========-----------------===------ -exit_this_scsi_driver() ----+ - | - slave_destroy() - release() --> scsi_unregister() - | - slave_destroy() - release() --> scsi_unregister() ------------------------------------------------------------- - -An LLD need not define slave_destroy() (i.e. it is optional). - -The shortcoming of the "passive initialization model" is that host -registration and de-registration are (typically) tied to LLD initialization -and shutdown. Once the LLD is initialized then a new host that appears -(e.g. via hotplugging) cannot easily be added without a redundant -driver shutdown and re-initialization. It may be possible to write an LLD -that uses both initialization models. - - Reference Counting ================== The Scsi_Host structure has had reference counting infrastructure added. @@ -738,7 +663,6 @@ The interface functions are listed below in alphabetical order. Summary: bios_param - fetch head, sector, cylinder info for a disk - detect - detects HBAs this driver wants to control eh_timed_out - notify the host that a command timer expired eh_abort_handler - abort given command eh_bus_reset_handler - issue SCSI bus reset @@ -748,7 +672,6 @@ Summary: ioctl - driver can respond to ioctls proc_info - supports /proc/scsi/{driver_name}/{host_no} queuecommand - queue scsi command, invoke 'done' on completion - release - release all resources associated with given host slave_alloc - prior to any commands being sent to a new device slave_configure - driver fine tuning for given device after attach slave_destroy - given device is about to be shut down @@ -784,28 +707,6 @@ Details: sector_t capacity, int params[3]) -/** - * detect - detects HBAs this driver wants to control - * @shtp: host template for this driver. - * - * Returns number of hosts this driver wants to control. 0 means no - * suitable hosts found. - * - * Locks: none held - * - * Calling context: process [invoked from init_this_scsi_driver()] - * - * Notes: First function called from the SCSI mid level on this - * driver. Upper level drivers (e.g. sd) may not (yet) be present. - * For each host found, this method should call scsi_register() - * [see hosts.c]. - * - * Defined in: LLD (required if "passive initialization mode" is used, - * not invoked in "hotplug initialization mode") - **/ - int detect(struct scsi_host_template * shtp) - - /** * eh_timed_out - The timer for the command has just fired * @scp: identifies command timing out @@ -1073,27 +974,6 @@ Details: int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp) -/** - * release - release all resources associated with given host - * @shp: host to be released. - * - * Return value ignored (could soon be a function returning void). - * - * Locks: none held - * - * Calling context: process - * - * Notes: Invoked from scsi_module.c's exit_this_scsi_driver(). - * LLD's implementation of this function should call - * scsi_unregister(shp) prior to returning. - * Only needed for old-style host templates. - * - * Defined in: LLD (required in "passive initialization model", - * should not be defined in hotplug model) - **/ - int release(struct Scsi_Host * shp) - - /** * slave_alloc - prior to any commands being sent to a new device * (i.e. just prior to scan) this call is made diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 0a5362822ed6..ffd1030b6c91 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -518,29 +518,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) } EXPORT_SYMBOL(scsi_host_alloc); -struct Scsi_Host *scsi_register(struct scsi_host_template *sht, int privsize) -{ - struct Scsi_Host *shost = scsi_host_alloc(sht, privsize); - - if (!sht->detect) { - printk(KERN_WARNING "scsi_register() called on new-style " - "template for driver %s\n", sht->name); - dump_stack(); - } - - if (shost) - list_add_tail(&shost->sht_legacy_list, &sht->legacy_hosts); - return shost; -} -EXPORT_SYMBOL(scsi_register); - -void scsi_unregister(struct Scsi_Host *shost) -{ - list_del(&shost->sht_legacy_list); - scsi_host_put(shost); -} -EXPORT_SYMBOL(scsi_unregister); - static int __scsi_host_match(struct device *dev, const void *data) { struct Scsi_Host *p; diff --git a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c deleted file mode 100644 index 489175833709..000000000000 --- a/drivers/scsi/scsi_module.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2003 Christoph Hellwig. - * Released under GPL v2. - * - * Support for old-style host templates. - * - * NOTE: Do not use this for new drivers ever. - */ - -#include -#include -#include - -#include - - -static int __init init_this_scsi_driver(void) -{ - struct scsi_host_template *sht = &driver_template; - struct Scsi_Host *shost; - struct list_head *l; - int error; - - if (!sht->release) { - printk(KERN_ERR - "scsi HBA driver %s didn't set a release method.\n", - sht->name); - return -EINVAL; - } - - sht->module = THIS_MODULE; - INIT_LIST_HEAD(&sht->legacy_hosts); - - sht->detect(sht); - if (list_empty(&sht->legacy_hosts)) - return -ENODEV; - - list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) { - error = scsi_add_host(shost, NULL); - if (error) - goto fail; - scsi_scan_host(shost); - } - return 0; - fail: - l = &shost->sht_legacy_list; - while ((l = l->prev) != &sht->legacy_hosts) - scsi_remove_host(list_entry(l, struct Scsi_Host, sht_legacy_list)); - return error; -} - -static void __exit exit_this_scsi_driver(void) -{ - struct scsi_host_template *sht = &driver_template; - struct Scsi_Host *shost, *s; - - list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) - scsi_remove_host(shost); - list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list) - sht->release(shost); - - if (list_empty(&sht->legacy_hosts)) - return; - - printk(KERN_WARNING "%s did not call scsi_unregister\n", sht->name); - dump_stack(); - - list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list) - scsi_unregister(shost); -} - -module_init(init_this_scsi_driver); -module_exit(exit_this_scsi_driver); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 19317585ae48..4e418fb539f8 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -51,21 +51,6 @@ struct scsi_host_template { struct module *module; const char *name; - /* - * Used to initialize old-style drivers. For new-style drivers - * just perform all work in your module initialization function. - * - * Status: OBSOLETE - */ - int (* detect)(struct scsi_host_template *); - - /* - * Used as unload callback for hosts with old-style drivers. - * - * Status: OBSOLETE - */ - int (* release)(struct Scsi_Host *); - /* * The info function will return whatever useful information the * developer sees fit. If not provided, then the name field will @@ -482,15 +467,6 @@ struct scsi_host_template { */ const struct attribute_group **sdev_groups; - /* - * List of hosts per template. - * - * This is only for use by scsi_module.c for legacy templates. - * For these access to it is synchronized implicitly by - * module_init/module_exit. - */ - struct list_head legacy_hosts; - /* * Vendor Identifier associated with the host * @@ -713,15 +689,6 @@ struct Scsi_Host { /* ldm bits */ struct device shost_gendev, shost_dev; - /* - * List of hosts per template. - * - * This is only for use by scsi_module.c for legacy templates. - * For these access to it is synchronized implicitly by - * module_init/module_exit. - */ - struct list_head sht_legacy_list; - /* * Points to the transport data (if any) which is allocated * separately @@ -922,9 +889,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) return shost->prot_guard_type; } -/* legacy interfaces */ -extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); -extern void scsi_unregister(struct Scsi_Host *); extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state); #endif /* _SCSI_SCSI_HOST_H */ From 24268fd1ad3213079f1af09359b4243fffa95869 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 19 Mar 2018 13:33:03 +0300 Subject: [PATCH 138/168] scsi: dpt_i2o: use after free in adpt_release() The scsi_host_put() function frees "pHba" and then we dereference it on the next line when we do "scsi_host_put(pHba->host);". [mkp: included fix from hch] Fixes: 38e09e3bb056 ("scsi: dpt_i2o: stop using scsi_unregister") Signed-off-by: Dan Carpenter Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 3c667b23a801..67379e4d0bf9 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -304,10 +304,12 @@ rebuild_sys_tab: static void adpt_release(adpt_hba *pHba) { - scsi_remove_host(pHba->host); + struct Scsi_Host *shost = pHba->host; + + scsi_remove_host(shost); // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); - scsi_host_put(pHba->host); + scsi_host_put(shost); } From 10ff6be6de59e1c7d0bd5d899f896ce991f4fdc2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 19 Mar 2018 13:34:01 +0300 Subject: [PATCH 139/168] scsi: dpt_i2o: use after free in __adpt_reset() In __adpt_reset() the problem is that adpt_hba_reset() frees "pHba" on error but we dereference it to print the name in the error message. Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 67379e4d0bf9..35d45903ed2e 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -799,14 +799,17 @@ static int __adpt_reset(struct scsi_cmnd* cmd) { adpt_hba* pHba; int rcode; + char name[32]; + pHba = (adpt_hba*)cmd->device->host->hostdata[0]; - printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid ); + strncpy(name, pHba->name, sizeof(name)); + printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n", name, cmd->device->channel, pHba->channel[cmd->device->channel].tid); rcode = adpt_hba_reset(pHba); if(rcode == 0){ - printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name); + printk(KERN_WARNING"%s: HBA reset complete\n", name); return SUCCESS; } else { - printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode); + printk(KERN_WARNING"%s: HBA reset failed (%x)\n", name, rcode); return FAILED; } } From 03fea736c0d0f102b604ba410e45c76e7616a077 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 19 Mar 2018 10:53:41 +0000 Subject: [PATCH 140/168] scsi: qla2xxx: fix spelling mistake: "existant" -> "existent" Trivial fix to spelling mistake in debug message text Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 755d7a2a3eea..41863a056c9a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2028,7 +2028,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); if (!sess) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, - "qla_target(%d): task abort for non-existant session\n", + "qla_target(%d): task abort for non-existent session\n", vha->vp_idx); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); From c121107d0f8473bf9aa5fe1c32adab0a40f093e2 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 19 Mar 2018 23:01:58 -0400 Subject: [PATCH 141/168] scsi: documentation: Obsolete documentation references Remove references to fdomain, ncr53c400a, tmscsim, and DAC960 from Documentation/scsi. Signed-off-by: Martin K. Petersen --- Documentation/scsi/Mylex.txt | 5 - Documentation/scsi/scsi-parameters.txt | 9 - Documentation/scsi/tmscsim.txt | 443 ------------------------- 3 files changed, 457 deletions(-) delete mode 100644 Documentation/scsi/Mylex.txt delete mode 100644 Documentation/scsi/tmscsim.txt diff --git a/Documentation/scsi/Mylex.txt b/Documentation/scsi/Mylex.txt deleted file mode 100644 index 3797f3e6c2b5..000000000000 --- a/Documentation/scsi/Mylex.txt +++ /dev/null @@ -1,5 +0,0 @@ -Please see the file README.BusLogic for information about Linux support for -Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters. - -The Mylex DAC960 PCI RAID Controllers are now supported. Please consult -http://sourceforge.net/projects/dandelion for further information on the DAC960 driver. diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 2dc7f11179d1..25a4b4cf04a6 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -34,9 +34,6 @@ parameters may be changed at runtime by the command See drivers/scsi/BusLogic.c, comment before function BusLogic_ParseDriverOptions(). - fdomain= [HW,SCSI] - See header of drivers/scsi/fdomain.c. - gdth= [HW,SCSI] See header of drivers/scsi/gdth.c. @@ -68,8 +65,6 @@ parameters may be changed at runtime by the command ncr53c400a= [HW,SCSI] See Documentation/scsi/g_NCR5380.txt. - ncr53c406a= [HW,SCSI] - ncr53c8xx= [HW,SCSI] osst= [HW,SCSI] SCSI Tape Driver @@ -108,9 +103,5 @@ parameters may be changed at runtime by the command st= [HW,SCSI] SCSI tape parameters (buffers, etc.) See Documentation/scsi/st.txt. - tmscsim= [HW,SCSI] - See comment before function dc390_setup() in - drivers/scsi/tmscsim.c. - wd33c93= [HW,SCSI] See header of drivers/scsi/wd33c93.c. diff --git a/Documentation/scsi/tmscsim.txt b/Documentation/scsi/tmscsim.txt deleted file mode 100644 index 0e0322bf0020..000000000000 --- a/Documentation/scsi/tmscsim.txt +++ /dev/null @@ -1,443 +0,0 @@ -The tmscsim driver -================== - -1. Purpose and history -2. Installation -3. Features -4. Configuration via /proc/scsi/tmscsim/? -5. Configuration via boot/module params -6. Potential improvements -7. Bug reports, debugging and updates -8. Acknowledgements -9. Copyright - - -1. Purpose and history ----------------------- -The tmscsim driver supports PCI SCSI Host Adapters based on the AM53C974 -chip. AM53C974 based SCSI adapters include: - Tekram DC390, DC390T - Dawicontrol 2974 - QLogic Fast! PCI Basic - some on-board adapters -(This is most probably not a complete list) - -It has originally written by C.L. Huang from the Tekram corp. to support the -Tekram DC390(T) adapter. This is where the name comes from: tm = Tekram -scsi = SCSI driver, m = AMD (?) as opposed to w for the DC390W/U/F -(NCR53c8X5, X=2/7) driver. Yes, there was also a driver for the latter, -tmscsiw, which supported DC390W/U/F adapters. It's not maintained any more, -as the ncr53c8xx is perfectly supporting these adapters since some time. - -The driver first appeared in April 1996, exclusively supported the DC390 -and has been enhanced since then in various steps. In May 1998 support for -general AM53C974 based adapters and some possibilities to configure it were -added. The non-DC390 support works by assuming some values for the data -normally taken from the DC390 EEPROM. See below (chapter 5) for details. - -When using the DC390, the configuration is still be done using the DC390 -BIOS setup. The DC390 EEPROM is read and used by the driver, any boot or -module parameters (chapter 5) are ignored! However, you can change settings -dynamically, as described in chapter 4. - -For a more detailed description of the driver's history, see the first lines -of tmscsim.c. -The numbering scheme isn't consistent. The first versions went from 1.00 to -1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So -the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental), -2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send -fixes to people for testing, I create intermediate versions with a digit -appended, e.g. 2.0c3. - - -2. Installation ---------------- -If you got any recent kernel with this driver and document included in -linux/drivers/scsi, you basically have to do nothing special to use this -driver. Of course you have to choose to compile SCSI support and DC390(T) -support into your kernel or as module when configuring your kernel for -compiling. -NEW: You may as well compile this module outside your kernel, using the -supplied Makefile. - - If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of - this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from - my web page and apply the patch. Apply further patches to upgrade to the - latest version of the driver. - - If you want to do it manually, you should copy the files (dc390.h, - tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to - linux/drivers/scsi. You have to recompile your kernel/module of course. - - You should apply the three patches included in dc390-120-kernel.diff - (Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff) - The patches are against 2.1.125, so you might have to manually resolve - rejections when applying to another kernel version. - - The patches will update the kernel startup code to allow boot parameters to - be passed to the driver, update the Documentation and finally offer you the - possibility to omit the non-DC390 parts of the driver. - (By selecting "Omit support for non DC390" you basically disable the - emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes - of memory.) - -If you got a very old kernel without the tmscsim driver (pre 2.0.31) -I recommend upgrading your kernel. However, if you don't want to, please -contact me to get the appropriate patches. - - -Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has -proven stable on many systems, but it's still a good idea to take some -precautions. In an ideal world you would have a full backup of your disks. -The world isn't ideal and most people don't have full backups (me neither). -So take at least the following measures: -* make your kernel remount the FS read-only on detecting an error: - tune2fs -e remount-ro /dev/sd?? -* have copies of your SCSI disk's partition tables on some safe location: - dd if=/dev/sda of=/mnt/floppy/sda bs=512 count=1 - or just print it with: - fdisk -l | lpr -* make sure you are able to boot Linux (e.g. from floppy disk using InitRD) - if your SCSI disk gets corrupted. You can use - ftp://student.physik.uni-dortmund.de/pub/linux/kernel/bootdisk.gz - -One more warning: I used to overclock my PCI bus to 41.67 MHz. My Tekram -DC390F (Sym53c875) accepted this as well as my Millennium. But the Am53C974 -produced errors and started to corrupt my disks. So don't do that! A 37.50 -MHz PCI bus works for me, though, but I don't recommend using higher clocks -than the 33.33 MHz being in the PCI spec. - - -3.Features ----------- -- SCSI - * Tagged command queueing - * Sync speed up to 10 MHz - * Disconnection - * Multiple LUNs - -- General / Linux interface - * Support for up to 4 AM53C974 adapters. - * DC390 EEPROM usage or boot/module params - * Information via cat /proc/scsi/tmscsim/? - * Dynamically configurable by writing to /proc/scsi/tmscsim/? - * Dynamic allocation of resources - * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter - specific locks (Linux 2.5?) - * Uniform source code for Linux-2.x.y - * Support for dyn. addition/removal of devices via add/remove-single-device - (Try: echo "scsi add-single-device C B T U" >/proc/scsi/scsi - C = Controller, B = Bus, T = Target SCSI ID, U = Unit SCSI LUN.) - Use with care! - * Try to use the partition table for the determination of the mapping - - -4. Configuration via /proc/scsi/tmscsim/? ------------------------------------------ -First of all look at the output of /proc/scsi/tmscsim/? by typing - cat /proc/scsi/tmscsim/? -The "?" should be replaced by the SCSI host number. (The shell might do this -for you.) -You will see some info regarding the adapter and, at the end, a listing of -the attached devices and their settings. - -Here's an example: -garloff@kurt:/home/garloff > cat /proc/scsi/tmscsim/0 -Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0e7 2000-11-28 -SCSI Host Nr 1, AM53C974 Adapter Nr 0 -IOPortBase 0xb000, IRQ 10 -MaxID 8, MaxLUN 8, AdapterID 6, SelTimeout 250 ms, DelayReset 1 s -TagMaxNum 16, Status 0x00, ACBFlag 0x00, GlitchEater 24 ns -Statistics: Cmnds 1470165, Cmnds not sent directly 0, Out of SRB conds 0 - Lost arbitrations 587, Sel. connected 0, Connected: No -Nr of attached devices: 4, Nr of DCBs: 4 -Map of attached LUNs: 01 00 00 03 01 00 00 00 -Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd -00 00 00 Yes Yes Yes Yes Yes 100 ns 10.0 M 15 16 -01 03 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 -02 03 01 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 -03 04 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 - -Note that the settings MaxID and MaxLUN are not zero- but one-based, which -means that a setting MaxLUN=4, will result in the support of LUNs 0..3. This -is somehow inconvenient, but the way the mid-level SCSI code expects it to be. - -ACB and DCB are acronyms for Adapter Control Block and Device Control Block. -These are data structures of the driver containing information about the -adapter and the connected SCSI devices respectively. - -Idx is the device index (just a consecutive number for the driver), ID and -LUN are the SCSI ID and LUN, Prty means Parity checking, Sync synchronous -negotiation, DsCn Disconnection, SndS Send Start command on startup (not -used by the driver) and TagQ Tagged Command Queueing. NegoPeriod and -SyncSpeed are somehow redundant, because they are reciprocal values -(1 / 112 ns = 8.9 MHz). At least in theory. The driver is able to adjust the -NegoPeriod more accurate (4ns) than the SyncSpeed (1 / 25ns). I don't know -if certain devices will have problems with this discrepancy. Max. speed is -10 MHz corresp. to a min. NegoPeriod of 100 ns. -(The driver allows slightly higher speeds if the devices (Ultra SCSI) accept -it, but that's out of adapter spec, on your own risk and unlikely to improve -performance. You're likely to crash your disks.) -SyncOffs is the offset used for synchronous negotiations; max. is 15. -The last values are only shown, if Sync is enabled. (NegoPeriod is still -displayed in brackets to show the values which will be used after enabling -Sync.) -MaxCmd ist the number of commands (=tags) which can be processed at the same -time by the device. - -If you want to change a setting, you can do that by writing to -/proc/scsi/tmscsim/?. Basically you have to imitate the output of driver. -(Don't use the brackets for NegoPeriod on Sync disabled devices.) -You don't have to care about capitalisation. The driver will accept space, -tab, comma, = and : as separators. - -There are three kinds of changes: - -(1) Change driver settings: - You type the names of the parameters and the params following it. - Example: - echo "MaxLUN=8 seltimeout 200" >/proc/scsi/tmscsim/0 - - Note that you can only change MaxID, MaxLUN, AdapterID, SelTimeOut, - TagMaxNum, ACBFlag, GlitchEater and DelayReset. Don't change ACBFlag - unless you want to see what happens, if the driver hangs. - -(2) Change device settings: You write a config line to the driver. The Nr - must match the ID and LUN given. If you give "-" as parameter, it is - ignored and the corresponding setting won't be changed. - You can use "y" or "n" instead of "Yes" and "No" if you want to. - You don't need to specify a full line. The driver automatically performs - an INQUIRY on the device if necessary to check if it is capable to operate - with the given settings (Sync, TagQ). - Examples: - echo "0 0 0 y y y - y - 10 " >/proc/scsi/tmscsim/0 - echo "3 5 0 y n y " >/proc/scsi/tmscsim/0 - - To give a short explanation of the first example: - The first three numbers, "0 0 0" (Device index 0, SCSI ID 0, SCSI LUN 0), - select the device to which the following parameters apply. Note that it - would be sufficient to use the index or both SCSI ID and LUN, but I chose - to require all three to have a syntax similar to the output. - The following "y y y - y" enables Parity checking, enables Synchronous - transfers, Disconnection, leaves Send Start (not used) untouched and - enables Tagged Command Queueing for the selected device. The "-" skips - the Negotiation Period setting but the "10" sets the max sync. speed to - 10 MHz. It's useless to specify both NegoPeriod and SyncSpeed as - discussed above. The values used in this example will result in maximum - performance. - -(3) Special commands: You can force a SCSI bus reset, an INQUIRY command, the - removal or the addition of a device's DCB and a SCSI register dump. - This is only used for debugging when you meet problems. The parameter of - the INQUIRY and REMOVE commands is the device index as shown by the - output of /proc/scsi/tmscsim/? in the device listing in the first column - (Idx). ADD takes the SCSI ID and LUN. - Examples: - echo "reset" >/proc/scsi/tmscsim/0 - echo "inquiry 1" >/proc/scsi/tmscsim/0 - echo "remove 2" >/proc/scsi/tmscsim/1 - echo "add 2 3" >/proc/scsi/tmscsim/? - echo "dump" >/proc/scsi/tmscsim/0 - - Note that you will meet problems when you REMOVE a device's DCB with the - remove command if it contains partitions which are mounted. Only use it - after unmounting its partitions, telling the SCSI mid-level code to - remove it (scsi remove-single-device) and you really need a few bytes of - memory. - The ADD command allows you to configure a device before you tell the - mid-level code to try detection. - - -I'd suggest reviewing the output of /proc/scsi/tmscsim/? after changing -settings to see if everything changed as requested. - - -5. Configuration via boot/module parameters -------------------------------------------- -With the DC390, the driver reads its EEPROM settings and tries to use them. -But you may want to override the settings prior to being able to change the -driver configuration via /proc/scsi/tmscsim/?. -If you do have another AM53C974 based adapter, that's even the only -possibility to adjust settings before you are able to write to the -/proc/scsi/tmscsim/? pseudo-file, e.g. if you want to use another -adapter ID than 7. -(BTW, the log message "DC390: No EEPROM found!" is normal without a DC390.) -For this purpose, you can pass options to the driver before it is initialised -by using kernel or module parameters. See lilo(8) or modprobe(1) manual -pages on how to pass params to the kernel or a module. -[NOTE: Formerly, it was not possible to override the EEPROM supplied - settings of the DC390 with cmd line parameters. This has changed since - 2.0e7] - -The syntax of the params is much shorter than the syntax of the /proc/... -interface. This makes it a little bit more difficult to use. However, long -parameter lines have the risk to be misinterpreted and the length of kernel -parameters is limited. - -As the support for non-DC390 adapters works by simulating the values of the -DC390 EEPROM, the settings are given in a DC390 BIOS' way. - -Here's the syntax: -tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds,DelayReset - -Each of the parameters is a number, containing the described information: - -* AdaptID: The SCSI ID of the host adapter. Must be in the range 0..7 - Default is 7. - -* SpdIdx: The index of the maximum speed as in the DC390 BIOS. The values - 0..7 mean 10, 8.0, 6.7, 5.7, 5.0, 4.0, 3.1 and 2 MHz resp. Default is - 0 (10.0 MHz). - -* DevMode is a bit mapped value describing the per-device features. It - applies to all devices. (Sync, Disc and TagQ will only apply, if the - device supports it.) The meaning of the bits (* = default): - - Bit Val(hex) Val(dec) Meaning - *0 0x01 1 Parity check - *1 0x02 2 Synchronous Negotiation - *2 0x04 4 Disconnection - *3 0x08 8 Send Start command on startup. (Not used) - *4 0x10 16 Tagged Command Queueing - - As usual, the desired value is obtained by adding the wanted values. If - you want to enable all values, e.g., you would use 31(0x1f). Default is 31. - -* AdaptMode is a bit mapped value describing the enabled adapter features. - - Bit Val(hex) Val(dec) Meaning - *0 0x01 1 Support more than two drives. (Not used) - *1 0x02 2 Use DOS compatible mapping for HDs greater than 1GB. - *2 0x04 4 Reset SCSI Bus on startup. - *3 0x08 8 Active Negation: Improves SCSI Bus noise immunity. - 4 0x10 16 Immediate return on BIOS seek command. (Not used) - (*)5 0x20 32 Check for LUNs >= 1. - -* TaggedCmnds is a number indicating the maximum number of Tagged Commands. - It is the binary logarithm - 1 of the actual number. Max is 4 (32). - Value Number of Tagged Commands - 0 2 - 1 4 - 2 8 - *3 16 - 4 32 - -* DelayReset is the time in seconds (minus 0.5s), the adapter waits, after a - bus reset. Default is 1 (corresp. to 1.5s). - -Example: - modprobe tmscsim tmscsim=6,2,31 -would set the adapter ID to 6, max. speed to 6.7 MHz, enable all device -features and leave the adapter features, the number of Tagged Commands -and the Delay after a reset to the defaults. - -As you can see, you don't need to specify all of the six params. -If you want values to be ignored (i.e. the EEprom settings or the defaults -will be used), you may pass -2 (not 0!) at the corresponding position. - -The defaults (7,0,31,15,3,1) are aggressive to allow good performance. You -can use tmscsim=7,0,31,63,4,0 for maximum performance, if your SCSI chain -allows it. If you meet problems, you can use tmscsim=-1 which is a shortcut -for tmscsim=7,4,9,15,2,10. - - -6. Potential improvements -------------------------- -Most of the intended work on the driver has been done. Here are a few ideas -to further improve its usability: - -* Cleanly separate per-Target and per-LUN properties (DCB) -* More intelligent abort() routine -* Use new_eh code (Linux-2.1+) -* Have the mid-level (ML) code (and not the driver) handle more of the - various conditions. -* Command queueing in the driver: Eliminate Query list and use ML instead. -* More user friendly boot/module param syntax - -Further investigation on these problems: - -* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error) - -Known problems: -Please see http://www.garloff.de/kurt/linux/dc390/problems.html - -* Changing the parameters of multi-lun by the tmscsim/? interface will - cause problems, cause these settings are mostly per Target and not per LUN - and should be updated accordingly. To be fixed for 2.0d24. -* CDRs (eg Yam CRW4416) not recognized, because some buggy devices don't - recover from a SCSI reset in time. Use a higher delay or don't issue - a SCSI bus reset on driver initialization. See problems page. - For the CRW4416S, this seems to be solved with firmware 1.0g (reported by - Jean-Yves Barbier). -* TEAC CD-532S not being recognized. (Works with 1.11). -* Scanners (eg. Astra UMAX 1220S) don't work: Disable Sync Negotiation. - If this does not help, try echo "INQUIRY t" >/proc/scsi/tmscsim/? (t - replaced by the dev index of your scanner). You may try to reset your SCSI - bus afterwards (echo "RESET" >/proc/scsi/tmscsim/?). - The problem seems to be solved as of 2.0d18, thanks to Andreas Rick. -* If there is a valid partition table, the driver will use it for determining - the mapping. If there's none, a reasonable mapping (Symbios-like) will be - assumed. Other operating systems may not like this mapping, though - it's consistent with the BIOS' behaviour. Old DC390 drivers ignored the - partition table and used a H/S = 64/32 or 255/63 translation. So if you - want to be compatible to those, use this old mapping when creating - partition tables. Even worse, on bootup the DC390 might complain if other - mappings are found, so auto rebooting may fail. -* In some situations, the driver will get stuck in an abort loop. This is a - bad interaction between the Mid-Layer of Linux' SCSI code and the driver. - Try to disable DsCn, if you meet this problem. Please contact me for - further debugging. - - -7. Bug reports, debugging and updates -------------------------------------- -Whenever you have problems with the driver, you are invited to ask the -author for help. However, I'd suggest reading the docs and trying to solve -the problem yourself, first. -If you find something, which you believe to be a bug, please report it to me. -Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and -maybe the DC390 log messages to the report. - -Bug reports should be send to me (Kurt Garloff ) as well -as to the linux-scsi list (), as sometimes bugs -are caused by the SCSI mid-level code. - -I will ask you for some more details and probably I will also ask you to -enable some of the DEBUG options in the driver (tmscsim.c:DC390_DEBUGXXX -defines). The driver will produce some data for the syslog facility then. -Beware: If your syslog gets written to a SCSI disk connected to your -AM53C974, the logging might produce log output again, and you might end -having your box spending most of its time doing the logging. - -The latest version of the driver can be found at: - http://www.garloff.de/kurt/linux/dc390/ - ftp://ftp.suse.com/pub/people/garloff/linux/dc390/ - - -8. Acknowledgements -------------------- -Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and -all the others for the wonderful OS and software. -Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver -release and support. -Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding. -Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert -Tonneau) for intensively testing the driver (and even risking data loss -doing this during early revisions). -Recently, SuSE GmbH, Nuernberg, FRG, has been paying me for the driver -development and maintenance. Special thanks! - - -9. Copyright ------------- - This driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - If you want to use any later version of the GNU GPL, you will probably - be allowed to, but you have to ask me and Tekram - before. - -------------------------------------------------------------------------- -Written by Kurt Garloff 1998/06/11 -Last updated 2000/11/28, driver revision 2.0e7 -$Id: README.tmscsim,v 2.25.2.7 2000/12/20 01:07:12 garloff Exp $ From 3565a3d01e14c33d29512ca8129365cbe38df809 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 16 Mar 2018 14:51:50 +0100 Subject: [PATCH 142/168] scsi: hisi_sas: Remove depends on HAS_DMA in case of platform dependency Remove dependencies on HAS_DMA where a Kconfig symbol depends on another symbol that implies HAS_DMA, and, optionally, on "|| COMPILE_TEST". In most cases this other symbol is an architecture or platform specific symbol, or PCI. Generic symbols and drivers without platform dependencies keep their dependencies on HAS_DMA, to prevent compiling subsystems or drivers that cannot work anyway. This simplifies the dependencies, and allows to improve compile-testing. Signed-off-by: Geert Uytterhoeven Reviewed-by: Mark Brown Acked-by: Robin Murphy Acked-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig index d42f29a5eb65..57183fce70fb 100644 --- a/drivers/scsi/hisi_sas/Kconfig +++ b/drivers/scsi/hisi_sas/Kconfig @@ -1,6 +1,6 @@ config SCSI_HISI_SAS tristate "HiSilicon SAS" - depends on HAS_DMA && HAS_IOMEM + depends on HAS_IOMEM depends on ARM64 || COMPILE_TEST select SCSI_SAS_LIBSAS select BLK_DEV_INTEGRITY From 5f96f42b76e00e2871033745ff029056cc725c76 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Thu, 15 Mar 2018 18:32:01 +0100 Subject: [PATCH 143/168] scsi: devinfo: add HP DISK-SUBSYSTEM device, for HP XP arrays "The DISK-SUBSYSTEM is a special model name returned when LUs are not installed. For example, when LU#0 is not installed in "OPEN-" models, LU#0 is detected as the DISK-SUBSYSTEM model": https://marc.info/?l=linux-scsi&m=125424006417825 It's missing for HP XP rebranded arrays, "HP"/"OPEN-". Only the HITACHI one is present: 13f7e5acc8b329080672c13f05f252ace5b79825 627511e3e67553b04f6917c03e39b797df210e04 Cc: Anthony Cheung Cc: Takahiro Yasui Cc: Matthias Rudolph Cc: Martin K. Petersen Cc: James E.J. Bottomley Cc: SCSI ML Signed-off-by: Xose Vazquez Perez Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index f3b117246d47..4a2d276c42eb 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -189,6 +189,7 @@ static struct { {"HP", "C5713A", NULL, BLIST_NOREPORTLUN}, {"HP", "DF400", "*", BLIST_REPORTLUN2}, {"HP", "DF500", "*", BLIST_REPORTLUN2}, + {"HP", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2}, {"HP", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, From c7058ae1d5a9c7f9b1fd8c6fe790a887744935e7 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Thu, 15 Mar 2018 19:01:49 +0100 Subject: [PATCH 144/168] scsi: devinfo: remove DF arrays from HP Matthias did confirm that there are no such devices. [mkp: applied by hand] Cc: Matthias Rudolph Cc: Anthony Cheung Cc: Takahiro Yasui Cc: Mike Christie Cc: Martin K. Petersen Cc: James E.J. Bottomley Cc: SCSI ML Cc: device-mapper development Signed-off-by: Xose Vazquez Perez Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 4a2d276c42eb..ca3fe8c525ad 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -187,8 +187,6 @@ static struct { {"HP", "C1557A", NULL, BLIST_FORCELUN}, {"HP", "C3323-300", "4269", BLIST_NOTQ}, {"HP", "C5713A", NULL, BLIST_NOREPORTLUN}, - {"HP", "DF400", "*", BLIST_REPORTLUN2}, - {"HP", "DF500", "*", BLIST_REPORTLUN2}, {"HP", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2}, {"HP", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, From 723c7e3982d2d560d6b89cac5686e4c3d286d884 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Fri, 16 Mar 2018 15:57:25 +0100 Subject: [PATCH 145/168] scsi: devinfo: remove dasd devices from the scsi subsystem Only present through ccw bus. [mkp: applied by hand] Cc: Matthias Rudolph Cc: Takahiro Yasui Cc: Anthony Cheung Cc: Mike Christie Cc: Martin K. Petersen Cc: James E.J. Bottomley Cc: s390 ML Cc: SCSI ML Cc: device-mapper development Signed-off-by: Xose Vazquez Perez Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index ca3fe8c525ad..e5370d718058 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -175,11 +175,6 @@ static struct { {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2}, {"HITACHI", "HUS1530", "*", BLIST_NO_DIF}, {"HITACHI", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES}, - {"HITACHI", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HITACHI", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HITACHI", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HITACHI", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HITACHI", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ {"HP", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES}, /* HP XP Arrays */ {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, @@ -188,11 +183,6 @@ static struct { {"HP", "C3323-300", "4269", BLIST_NOTQ}, {"HP", "C5713A", NULL, BLIST_NOREPORTLUN}, {"HP", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2}, - {"HP", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HP", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HP", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HP", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HP", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"IBM", "2105", NULL, BLIST_RETRY_HWERROR}, From 8d7d7775268546972b62a11fe09d48493f824f41 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:29 -0700 Subject: [PATCH 146/168] scsi: qla2xxx: Restore ZIO threshold setting Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 6b33a1f24f56..7a292421a7d7 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -478,11 +478,6 @@ static int qla2x00_start_nvme_mq(srb_t *sp) /* Set chip new ring index. */ WRT_REG_DWORD(req->req_q_in, req->ring_index); - /* Manage unprocessed RIO/ZIO commands in response queue. */ - if (vha->flags.process_response_queue && - rsp->ring_ptr->signature != RESPONSE_PROCESSED) - qla24xx_process_response_queue(vha, rsp); - queuing_error: spin_unlock_irqrestore(&qpair->qp_lock, flags); return rval; From 1d4614e1e6cbaeac1fdbf4aef3cca222320d3d92 Mon Sep 17 00:00:00 2001 From: "himanshu.madhani@cavium.com" Date: Tue, 20 Mar 2018 23:09:30 -0700 Subject: [PATCH 147/168] scsi: qla2xxx: Remove unneeded message and minor cleanup for FC-NVMe Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 7a292421a7d7..91f8b3c2afb6 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -113,8 +113,6 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport, return 0; } - ql_log(ql_log_warn, vha, 0xffff, - "allocating q for idx=%x w/o cpu mask\n", qidx); qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true); if (qpair == NULL) { ql_log(ql_log_warn, vha, 0x2122, @@ -313,7 +311,6 @@ static int qla2x00_start_nvme_mq(srb_t *sp) uint16_t avail_dsds; uint32_t *cur_dsd; struct req_que *req = NULL; - struct rsp_que *rsp = NULL; struct scsi_qla_host *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair = sp->qpair; @@ -322,15 +319,13 @@ static int qla2x00_start_nvme_mq(srb_t *sp) struct nvmefc_fcp_req *fd = nvme->u.nvme.desc; uint32_t rval = QLA_SUCCESS; + /* Setup qpair pointers */ + req = qpair->req; tot_dsds = fd->sg_cnt; /* Acquire qpair specific lock */ spin_lock_irqsave(&qpair->qp_lock, flags); - /* Setup qpair pointers */ - req = qpair->req; - rsp = qpair->rsp; - /* Check for room in outstanding command list. */ handle = req->current_outstanding_cmd; for (index = 1; index < req->num_outstanding_cmds; index++) { @@ -365,7 +360,7 @@ static int qla2x00_start_nvme_mq(srb_t *sp) struct nvme_fc_cmd_iu *cmd = fd->cmdaddr; if (cmd->sqe.common.opcode == nvme_admin_async_event) { nvme->u.nvme.aen_op = 1; - atomic_inc(&vha->hw->nvme_active_aen_cnt); + atomic_inc(&ha->nvme_active_aen_cnt); } } From dbe18018e3ad60fc5abfe999b49c4b37f8e7bb32 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:31 -0700 Subject: [PATCH 148/168] scsi: qla2xxx: Set IIDMA and fcport state before qla_nvme_register_remote() Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 590aa904fdef..1878a6f24ddb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5107,13 +5107,14 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) fcport->deleted = 0; fcport->logout_on_delete = 1; + qla2x00_set_fcport_state(fcport, FCS_ONLINE); + qla2x00_iidma_fcport(vha, fcport); + if (fcport->fc4f_nvme) { qla_nvme_register_remote(vha, fcport); return; } - qla2x00_set_fcport_state(fcport, FCS_ONLINE); - qla2x00_iidma_fcport(vha, fcport); qla24xx_update_fcport_fcp_prio(vha, fcport); reg_port: From 9dd9686b14199a1c3e668e1cca124cd1c74b77e1 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:32 -0700 Subject: [PATCH 149/168] scsi: qla2xxx: Add changes for devloss timeout in driver Add support for error recovery within devloss timeout, now that FC-NVMe transport support devloss timeout. Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 8 ++ drivers/scsi/qla2xxx/qla_isr.c | 5 +- drivers/scsi/qla2xxx/qla_nvme.c | 142 +++++++++++++----------------- drivers/scsi/qla2xxx/qla_nvme.h | 6 +- drivers/scsi/qla2xxx/qla_target.c | 13 +-- drivers/scsi/qla2xxx/qla_target.h | 2 +- 7 files changed, 87 insertions(+), 90 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index be7d6824581a..56f78dce4d3c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2355,6 +2355,7 @@ typedef struct fc_port { #define NVME_PRLI_SP_DISCOVERY BIT_3 uint8_t nvme_flag; #define NVME_FLAG_REGISTERED 4 +#define NVME_FLAG_DELETING 2 struct fc_port *conflict; unsigned char logout_completed; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1878a6f24ddb..7f8bfa0454d2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5517,6 +5517,14 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) break; } + if (fcport->fc4f_nvme) { + if (fcport->disc_state == DSC_DELETE_PEND) { + fcport->disc_state = DSC_GNL; + vha->fcport_count--; + fcport->login_succ = 0; + } + } + if (found) { spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); continue; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 16c43bd9bb83..93f2f1df7168 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1910,7 +1910,7 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } else { switch (le16_to_cpu(sts->comp_status)) { case CS_COMPLETE: - ret = 0; + ret = QLA_SUCCESS; break; case CS_ABORTED: @@ -1922,7 +1922,8 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) "NVME-%s ERR Handling - hdl=%x completion status(%x) resid=%x ox_id=%x\n", sp->name, sp->handle, sts->comp_status, le32_to_cpu(sts->residual_len), sts->ox_id); - fd->transferred_length = fd->payload_length; + fd->transferred_length = 0; + iocb->u.nvme.rsp_pyld_len = 0; ret = QLA_ABORTED; break; diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 91f8b3c2afb6..5ee447680ddd 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -16,15 +16,13 @@ static void qla_nvme_unregister_remote_port(struct work_struct *); int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) { - struct nvme_rport *rport; + struct qla_nvme_rport *rport; + struct nvme_fc_port_info req; int ret; if (!IS_ENABLED(CONFIG_NVME_FC)) return 0; - if (fcport->nvme_flag & NVME_FLAG_REGISTERED) - return 0; - if (!vha->flags.nvme_enabled) { ql_log(ql_log_info, vha, 0x2100, "%s: Not registering target since Host NVME is not enabled\n", @@ -33,38 +31,35 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) } if (!(fcport->nvme_prli_service_param & - (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY))) + (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY)) || + (fcport->nvme_flag & NVME_FLAG_REGISTERED)) return 0; INIT_WORK(&fcport->nvme_del_work, qla_nvme_unregister_remote_port); - rport = kzalloc(sizeof(*rport), GFP_KERNEL); - if (!rport) { - ql_log(ql_log_warn, vha, 0x2101, - "%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - rport->req.port_name = wwn_to_u64(fcport->port_name); - rport->req.node_name = wwn_to_u64(fcport->node_name); - rport->req.port_role = 0; + memset(&req, 0, sizeof(struct nvme_fc_port_info)); + req.port_name = wwn_to_u64(fcport->port_name); + req.node_name = wwn_to_u64(fcport->node_name); + req.port_role = 0; + req.dev_loss_tmo = NVME_FC_DEV_LOSS_TMO; if (fcport->nvme_prli_service_param & NVME_PRLI_SP_INITIATOR) - rport->req.port_role = FC_PORT_ROLE_NVME_INITIATOR; + req.port_role = FC_PORT_ROLE_NVME_INITIATOR; if (fcport->nvme_prli_service_param & NVME_PRLI_SP_TARGET) - rport->req.port_role |= FC_PORT_ROLE_NVME_TARGET; + req.port_role |= FC_PORT_ROLE_NVME_TARGET; if (fcport->nvme_prli_service_param & NVME_PRLI_SP_DISCOVERY) - rport->req.port_role |= FC_PORT_ROLE_NVME_DISCOVERY; + req.port_role |= FC_PORT_ROLE_NVME_DISCOVERY; - rport->req.port_id = fcport->d_id.b24; + req.port_id = fcport->d_id.b24; ql_log(ql_log_info, vha, 0x2102, "%s: traddr=nn-0x%016llx:pn-0x%016llx PortID:%06x\n", - __func__, rport->req.node_name, rport->req.port_name, - rport->req.port_id); + __func__, req.node_name, req.port_name, + req.port_id); - ret = nvme_fc_register_remoteport(vha->nvme_local_port, &rport->req, + ret = nvme_fc_register_remoteport(vha->nvme_local_port, &req, &fcport->nvme_remote_port); if (ret) { ql_log(ql_log_warn, vha, 0x212e, @@ -73,10 +68,11 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) return ret; } - fcport->nvme_remote_port->private = fcport; - fcport->nvme_flag |= NVME_FLAG_REGISTERED; + rport = fcport->nvme_remote_port->private; rport->fcport = fcport; list_add_tail(&rport->list, &vha->nvme_rport_list); + + fcport->nvme_flag |= NVME_FLAG_REGISTERED; return 0; } @@ -174,26 +170,23 @@ static void qla_nvme_sp_done(void *ptr, int res) if (!atomic_dec_and_test(&sp->ref_count)) return; - if (!(sp->fcport->nvme_flag & NVME_FLAG_REGISTERED)) - goto rel; - - if (unlikely(res == QLA_FUNCTION_FAILED)) - fd->status = NVME_SC_INTERNAL; - else + if (res == QLA_SUCCESS) fd->status = 0; + else + fd->status = NVME_SC_INTERNAL; fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; list_add_tail(&nvme->u.nvme.entry, &sp->qpair->nvme_done_list); + return; -rel: - qla2xxx_rel_qpair_sp(sp->qpair, sp); } static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) { struct nvme_private *priv = fd->private; - fc_port_t *fcport = rport->private; + struct qla_nvme_rport *qla_rport = rport->private; + fc_port_t *fcport = qla_rport->fcport; srb_t *sp = priv->sp; int rval; struct qla_hw_data *ha = fcport->vha->hw; @@ -218,7 +211,8 @@ static void qla_nvme_ls_complete(struct work_struct *work) static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) { - fc_port_t *fcport = rport->private; + struct qla_nvme_rport *qla_rport = rport->private; + fc_port_t *fcport = qla_rport->fcport; struct srb_iocb *nvme; struct nvme_private *priv = fd->private; struct scsi_qla_host *vha; @@ -226,9 +220,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, struct qla_hw_data *ha; srb_t *sp; - if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED)) - return rval; - vha = fcport->vha; ha = vha->hw; /* Alloc SRB structure */ @@ -275,7 +266,8 @@ static void qla_nvme_fcp_abort(struct nvme_fc_local_port *lport, struct nvme_private *priv = fd->private; srb_t *sp = priv->sp; int rval; - fc_port_t *fcport = rport->private; + struct qla_nvme_rport *qla_rport = rport->private; + fc_port_t *fcport = qla_rport->fcport; struct qla_hw_data *ha = fcport->vha->hw; rval = ha->isp_ops->abort_command(sp); @@ -288,11 +280,10 @@ static void qla_nvme_fcp_abort(struct nvme_fc_local_port *lport, static void qla_nvme_poll(struct nvme_fc_local_port *lport, void *hw_queue_handle) { - struct scsi_qla_host *vha = lport->private; - unsigned long flags; struct qla_qpair *qpair = hw_queue_handle; + unsigned long flags; + struct scsi_qla_host *vha = lport->private; - /* Acquire ring specific lock */ spin_lock_irqsave(&qpair->qp_lock, flags); qla24xx_process_response_queue(vha, qpair->rsp); spin_unlock_irqrestore(&qpair->qp_lock, flags); @@ -490,6 +481,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, srb_t *sp; struct qla_qpair *qpair = hw_queue_handle; struct nvme_private *priv; + struct qla_nvme_rport *qla_rport = rport->private; if (!fd) { ql_log(ql_log_warn, NULL, 0x2134, "NO NVMe FCP request\n"); @@ -497,14 +489,14 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, } priv = fd->private; - fcport = rport->private; + fcport = qla_rport->fcport; if (!fcport) { ql_log(ql_log_warn, NULL, 0x210e, "No fcport ptr\n"); return rval; } vha = fcport->vha; - if ((!qpair) || (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))) + if (!qpair) return -EBUSY; /* Alloc SRB structure */ @@ -547,22 +539,27 @@ static void qla_nvme_localport_delete(struct nvme_fc_local_port *lport) static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport) { fc_port_t *fcport; - struct nvme_rport *r_port, *trport; + struct qla_nvme_rport *qla_rport = rport->private, *trport; - fcport = rport->private; + fcport = qla_rport->fcport; fcport->nvme_remote_port = NULL; fcport->nvme_flag &= ~NVME_FLAG_REGISTERED; - list_for_each_entry_safe(r_port, trport, + list_for_each_entry_safe(qla_rport, trport, &fcport->vha->nvme_rport_list, list) { - if (r_port->fcport == fcport) { - list_del(&r_port->list); + if (qla_rport->fcport == fcport) { + list_del(&qla_rport->list); break; } } - kfree(r_port); complete(&fcport->nvme_del_done); + if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) { + INIT_WORK(&fcport->free_work, qlt_free_session_done); + schedule_work(&fcport->free_work); + } + + fcport->nvme_flag &= ~(NVME_FLAG_REGISTERED | NVME_FLAG_DELETING); ql_log(ql_log_info, fcport->vha, 0x2110, "remoteport_delete of %p completed.\n", fcport); } @@ -582,7 +579,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .max_dif_sgl_segments = 64, .dma_boundary = 0xFFFFFFFF, .local_priv_sz = 8, - .remote_priv_sz = 0, + .remote_priv_sz = sizeof(struct qla_nvme_rport), .lsrqst_priv_sz = sizeof(struct nvme_private), .fcprqst_priv_sz = sizeof(struct nvme_private), }; @@ -601,22 +598,6 @@ static int qla_nvme_wait_on_command(srb_t *sp) return ret; } -static int qla_nvme_wait_on_rport_del(fc_port_t *fcport) -{ - int ret = QLA_SUCCESS; - int timeout; - - timeout = wait_for_completion_timeout(&fcport->nvme_del_done, - msecs_to_jiffies(2000)); - if (!timeout) { - ret = QLA_FUNCTION_FAILED; - ql_log(ql_log_info, fcport->vha, 0x2111, - "timed out waiting for fcport=%p to delete\n", fcport); - } - - return ret; -} - void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp) { int rval; @@ -631,7 +612,7 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work) { struct fc_port *fcport = container_of(work, struct fc_port, nvme_del_work); - struct nvme_rport *rport, *trport; + struct qla_nvme_rport *qla_rport, *trport; if (!IS_ENABLED(CONFIG_NVME_FC)) return; @@ -639,51 +620,52 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work) ql_log(ql_log_warn, NULL, 0x2112, "%s: unregister remoteport on %p\n",__func__, fcport); - list_for_each_entry_safe(rport, trport, + list_for_each_entry_safe(qla_rport, trport, &fcport->vha->nvme_rport_list, list) { - if (rport->fcport == fcport) { + if (qla_rport->fcport == fcport) { ql_log(ql_log_info, fcport->vha, 0x2113, "%s: fcport=%p\n", __func__, fcport); init_completion(&fcport->nvme_del_done); nvme_fc_unregister_remoteport( fcport->nvme_remote_port); - qla_nvme_wait_on_rport_del(fcport); + wait_for_completion(&fcport->nvme_del_done); + break; } } } void qla_nvme_delete(struct scsi_qla_host *vha) { - struct nvme_rport *rport, *trport; + struct qla_nvme_rport *qla_rport, *trport; fc_port_t *fcport; int nv_ret; if (!IS_ENABLED(CONFIG_NVME_FC)) return; - list_for_each_entry_safe(rport, trport, &vha->nvme_rport_list, list) { - fcport = rport->fcport; + list_for_each_entry_safe(qla_rport, trport, + &vha->nvme_rport_list, list) { + fcport = qla_rport->fcport; ql_log(ql_log_info, fcport->vha, 0x2114, "%s: fcport=%p\n", __func__, fcport); init_completion(&fcport->nvme_del_done); nvme_fc_unregister_remoteport(fcport->nvme_remote_port); - qla_nvme_wait_on_rport_del(fcport); + wait_for_completion(&fcport->nvme_del_done); } if (vha->nvme_local_port) { init_completion(&vha->nvme_del_done); + ql_log(ql_log_info, vha, 0x2116, + "unregister localport=%p\n", + vha->nvme_local_port); nv_ret = nvme_fc_unregister_localport(vha->nvme_local_port); - if (nv_ret == 0) - ql_log(ql_log_info, vha, 0x2116, - "unregistered localport=%p\n", - vha->nvme_local_port); - else + if (nv_ret) ql_log(ql_log_info, vha, 0x2115, "Unregister of localport failed\n"); - wait_for_completion_timeout(&vha->nvme_del_done, - msecs_to_jiffies(5000)); + else + wait_for_completion(&vha->nvme_del_done); } } diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 7f05fa1c77db..7becfc1b3e69 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -14,6 +14,9 @@ #include "qla_def.h" +/* default dev loss time (seconds) before transport tears down ctrl */ +#define NVME_FC_DEV_LOSS_TMO 30 + #define NVME_ATIO_CMD_OFF 32 #define NVME_FIRST_PACKET_CMDLEN (64 - NVME_ATIO_CMD_OFF) #define Q2T_NVME_NUM_TAGS 2048 @@ -31,8 +34,7 @@ struct nvme_private { int comp_status; }; -struct nvme_rport { - struct nvme_fc_port_info req; +struct qla_nvme_rport { struct list_head list; struct fc_port *fcport; }; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 41863a056c9a..ead6813ea9b3 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -961,7 +961,7 @@ qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo) logo->cmd_count, res); } -static void qlt_free_session_done(struct work_struct *work) +void qlt_free_session_done(struct work_struct *work) { struct fc_port *sess = container_of(work, struct fc_port, free_work); @@ -1169,11 +1169,14 @@ void qlt_unreg_sess(struct fc_port *sess) sess->last_rscn_gen = sess->rscn_gen; sess->last_login_gen = sess->login_gen; - if (sess->nvme_flag & NVME_FLAG_REGISTERED) + if (sess->nvme_flag & NVME_FLAG_REGISTERED && + !(sess->nvme_flag & NVME_FLAG_DELETING)) { + sess->nvme_flag |= NVME_FLAG_DELETING; schedule_work(&sess->nvme_del_work); - - INIT_WORK(&sess->free_work, qlt_free_session_done); - schedule_work(&sess->free_work); + } else { + INIT_WORK(&sess->free_work, qlt_free_session_done); + schedule_work(&sess->free_work); + } } EXPORT_SYMBOL(qlt_unreg_sess); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index bb67b5a284a8..728ce74358e7 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -1016,7 +1016,7 @@ extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int); extern int __init qlt_init(void); extern void qlt_exit(void); extern void qlt_update_vp_map(struct scsi_qla_host *, int); - +extern void qlt_free_session_done(struct work_struct *); /* * This macro is used during early initializations when host->active_mode * is not set. Right now, ha value is ignored. From e473b3074104ee09227cfbba5f872e3ea15dd280 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:33 -0700 Subject: [PATCH 150/168] scsi: qla2xxx: Add FC-NVMe abort processing Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 36 ++++++++++++++++----------------- drivers/scsi/qla2xxx/qla_nvme.h | 1 + 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 5ee447680ddd..951fbbab961f 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -181,24 +181,32 @@ static void qla_nvme_sp_done(void *ptr, int res) return; } -static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, - struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) +static void qla_nvme_abort_work(struct work_struct *work) { - struct nvme_private *priv = fd->private; - struct qla_nvme_rport *qla_rport = rport->private; - fc_port_t *fcport = qla_rport->fcport; + struct nvme_private *priv = + container_of(work, struct nvme_private, abort_work); srb_t *sp = priv->sp; - int rval; + fc_port_t *fcport = sp->fcport; struct qla_hw_data *ha = fcport->vha->hw; + int rval; rval = ha->isp_ops->abort_command(sp); ql_dbg(ql_dbg_io, fcport->vha, 0x212b, - "%s: %s LS command for sp=%p on fcport=%p rval=%x\n", __func__, + "%s: %s command for sp=%p on fcport=%p rval=%x\n", __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", sp, fcport, rval); } +static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, + struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) +{ + struct nvme_private *priv = fd->private; + + INIT_WORK(&priv->abort_work, qla_nvme_abort_work); + schedule_work(&priv->abort_work); +} + static void qla_nvme_ls_complete(struct work_struct *work) { struct nvme_private *priv = @@ -264,18 +272,9 @@ static void qla_nvme_fcp_abort(struct nvme_fc_local_port *lport, struct nvmefc_fcp_req *fd) { struct nvme_private *priv = fd->private; - srb_t *sp = priv->sp; - int rval; - struct qla_nvme_rport *qla_rport = rport->private; - fc_port_t *fcport = qla_rport->fcport; - struct qla_hw_data *ha = fcport->vha->hw; - rval = ha->isp_ops->abort_command(sp); - - ql_dbg(ql_dbg_io, fcport->vha, 0x2127, - "%s: %s command for sp=%p on fcport=%p rval=%x\n", __func__, - (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", - sp, fcport, rval); + INIT_WORK(&priv->abort_work, qla_nvme_abort_work); + schedule_work(&priv->abort_work); } static void qla_nvme_poll(struct nvme_fc_local_port *lport, void *hw_queue_handle) @@ -650,6 +649,7 @@ void qla_nvme_delete(struct scsi_qla_host *vha) ql_log(ql_log_info, fcport->vha, 0x2114, "%s: fcport=%p\n", __func__, fcport); + nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0); init_completion(&fcport->nvme_del_done); nvme_fc_unregister_remoteport(fcport->nvme_remote_port); wait_for_completion(&fcport->nvme_del_done); diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 7becfc1b3e69..8df379478269 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -31,6 +31,7 @@ struct nvme_private { struct srb *sp; struct nvmefc_ls_req *fd; struct work_struct ls_work; + struct work_struct abort_work; int comp_status; }; From 1763c1fd76d8e26c5e6d5a3e415e7deeeda3c5da Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:34 -0700 Subject: [PATCH 151/168] scsi: qla2xxx: Fix n2n_ae flag to prevent dev_loss on PDB change On a port db changes, this patch will set n2n_ae flag for N2N connection when requesting for Report ID Acquition MBX, instead of Loop Initialization or point to point asynchronous events. Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 2 -- drivers/scsi/qla2xxx/qla_isr.c | 3 --- drivers/scsi/qla2xxx/qla_mbx.c | 3 +++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 56f78dce4d3c..cba749d27154 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4281,8 +4281,6 @@ typedef struct scsi_qla_host { struct nvme_fc_local_port *nvme_local_port; struct completion nvme_del_done; struct list_head nvme_rport_list; - atomic_t nvme_active_aen_cnt; - uint16_t nvme_last_rptd_aen; uint16_t fcoe_vlan_id; uint16_t fcoe_fcf_idx; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 93f2f1df7168..913cd6cf5907 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -767,7 +767,6 @@ skip_rio: case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ ha->flags.lip_ae = 1; - ha->flags.n2n_ae = 0; ql_dbg(ql_dbg_async, vha, 0x5009, "LIP occurred (%x).\n", mb[1]); @@ -811,7 +810,6 @@ skip_rio: case MBA_LOOP_DOWN: /* Loop Down Event */ SAVE_TOPO(ha); - ha->flags.n2n_ae = 0; ha->flags.lip_ae = 0; ha->current_topology = 0; @@ -885,7 +883,6 @@ skip_rio: /* case MBA_DCBX_COMPLETE: */ case MBA_POINT_TO_POINT: /* Point-to-Point */ ha->flags.lip_ae = 0; - ha->flags.n2n_ae = 1; if (IS_QLA2100(ha)) break; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 41b0ee47c6a1..735079ba691c 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3747,6 +3747,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, id.b.area = rptid_entry->port_id[1]; id.b.al_pa = rptid_entry->port_id[0]; id.b.rsvd_1 = 0; + ha->flags.n2n_ae = 0; if (rptid_entry->format == 0) { /* loop */ @@ -3799,6 +3800,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags); set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + ha->flags.n2n_ae = 1; return; } @@ -3875,6 +3877,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, vha->d_id.b.area = rptid_entry->port_id[1]; vha->d_id.b.al_pa = rptid_entry->port_id[0]; + ha->flags.n2n_ae = 1; spin_lock_irqsave(&ha->vport_slock, flags); qlt_update_vp_map(vha, SET_AL_PA); spin_unlock_irqrestore(&ha->vport_slock, flags); From 870fe24f3c0b2cf40998f8ab21d4cf4e4e9cf619 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:35 -0700 Subject: [PATCH 152/168] scsi: qla2xxx: Return busy if rport going away This patch adds mechanism to return EBUSY if rport is going away to prevent exhausting FC-NVMe layer's retry counter. Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 4 +++- drivers/scsi/qla2xxx/qla_nvme.c | 31 ++++++++++++++++++++----------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index cba749d27154..59c449b141cd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2356,6 +2356,7 @@ typedef struct fc_port { uint8_t nvme_flag; #define NVME_FLAG_REGISTERED 4 #define NVME_FLAG_DELETING 2 +#define NVME_FLAG_RESETTING 1 struct fc_port *conflict; unsigned char logout_completed; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 913cd6cf5907..bc2c7ded6949 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1910,9 +1910,11 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) ret = QLA_SUCCESS; break; - case CS_ABORTED: case CS_RESET: case CS_PORT_UNAVAILABLE: + fcport->nvme_flag |= NVME_FLAG_RESETTING; + /* fall through */ + case CS_ABORTED: case CS_PORT_LOGGED_OUT: case CS_PORT_BUSY: ql_log(ql_log_warn, fcport->vha, 0x5060, diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 951fbbab961f..adeda6a4e4fd 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -36,6 +36,7 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) return 0; INIT_WORK(&fcport->nvme_del_work, qla_nvme_unregister_remote_port); + fcport->nvme_flag &= ~NVME_FLAG_RESETTING; memset(&req, 0, sizeof(struct nvme_fc_port_info)); req.port_name = wwn_to_u64(fcport->port_name); @@ -193,9 +194,9 @@ static void qla_nvme_abort_work(struct work_struct *work) rval = ha->isp_ops->abort_command(sp); ql_dbg(ql_dbg_io, fcport->vha, 0x212b, - "%s: %s command for sp=%p on fcport=%p rval=%x\n", __func__, - (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", - sp, fcport, rval); + "%s: %s command for sp=%p, handle=%x on fcport=%p rval=%x\n", + __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", + sp, sp->handle, fcport, rval); } static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, @@ -327,7 +328,7 @@ static int qla2x00_start_nvme_mq(srb_t *sp) } if (index == req->num_outstanding_cmds) { - rval = -1; + rval = -EBUSY; goto queuing_error; } req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); @@ -341,7 +342,7 @@ static int qla2x00_start_nvme_mq(srb_t *sp) req->cnt = req->length - (req->ring_index - cnt); if (req->cnt < (req_cnt + 2)){ - rval = -1; + rval = -EBUSY; goto queuing_error; } } @@ -476,14 +477,15 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, fc_port_t *fcport; struct srb_iocb *nvme; struct scsi_qla_host *vha; - int rval = QLA_FUNCTION_FAILED; + int rval = -ENODEV; srb_t *sp; struct qla_qpair *qpair = hw_queue_handle; struct nvme_private *priv; struct qla_nvme_rport *qla_rport = rport->private; - if (!fd) { - ql_log(ql_log_warn, NULL, 0x2134, "NO NVMe FCP request\n"); + if (!fd || !qpair) { + ql_log(ql_log_warn, NULL, 0x2134, + "NO NVMe request or Queue Handle\n"); return rval; } @@ -495,13 +497,21 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, } vha = fcport->vha; - if (!qpair) + + /* + * If we know the dev is going away while the transport is still sending + * IO's return busy back to stall the IO Q. This happens when the + * link goes away and fw hasn't notified us yet, but IO's are being + * returned. If the dev comes back quickly we won't exhaust the IO + * retry count at the core. + */ + if (fcport->nvme_flag & NVME_FLAG_RESETTING) return -EBUSY; /* Alloc SRB structure */ sp = qla2xxx_get_qpair_sp(qpair, fcport, GFP_ATOMIC); if (!sp) - return -EIO; + return -EBUSY; atomic_set(&sp->ref_count, 1); init_waitqueue_head(&sp->nvme_ls_waitq); @@ -519,7 +529,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, "qla2x00_start_nvme_mq failed = %d\n", rval); atomic_dec(&sp->ref_count); wake_up(&sp->nvme_ls_waitq); - return -EIO; } return rval; From 2e4c5d2ef76b6f04a3cb7a15bc0fee0ab029dedf Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:36 -0700 Subject: [PATCH 153/168] scsi: qla2xxx: Remove nvme_done_list Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_gbl.h | 2 -- drivers/scsi/qla2xxx/qla_init.c | 1 - drivers/scsi/qla2xxx/qla_mid.c | 6 ------ drivers/scsi/qla2xxx/qla_nvme.c | 13 ++----------- drivers/scsi/qla2xxx/qla_os.c | 1 - 6 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 59c449b141cd..6aae126add0c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3464,7 +3464,6 @@ struct qla_qpair { struct work_struct q_work; struct list_head qp_list_elem; /* vha->qp_list */ struct list_head hints_list; - struct list_head nvme_done_list; uint16_t cpuid; struct qla_tgt_counters tgt_counters; }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index e9295398050c..19f44e12926b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -896,6 +896,4 @@ void qlt_update_host_map(struct scsi_qla_host *, port_id_t); void qlt_remove_target_resources(struct qla_hw_data *); void qlt_clr_qp_table(struct scsi_qla_host *vha); -void qla_nvme_cmpl_io(struct srb_iocb *); - #endif /* _QLA_GBL_H */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7f8bfa0454d2..33823d74c782 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8405,7 +8405,6 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->vp_idx = vp_idx; qpair->fw_started = ha->flags.fw_started; INIT_LIST_HEAD(&qpair->hints_list); - INIT_LIST_HEAD(&qpair->nvme_done_list); qpair->chip_reset = ha->base_qpair->chip_reset; qpair->enable_class_2 = ha->base_qpair->enable_class_2; qpair->enable_explicit_conf = diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index e965b16f21e3..da85cd89639f 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -778,18 +778,12 @@ static void qla_do_work(struct work_struct *work) struct qla_qpair *qpair = container_of(work, struct qla_qpair, q_work); struct scsi_qla_host *vha; struct qla_hw_data *ha = qpair->hw; - struct srb_iocb *nvme, *nxt_nvme; spin_lock_irqsave(&qpair->qp_lock, flags); vha = pci_get_drvdata(ha->pdev); qla24xx_process_response_queue(vha, qpair->rsp); spin_unlock_irqrestore(&qpair->qp_lock, flags); - list_for_each_entry_safe(nvme, nxt_nvme, &qpair->nvme_done_list, - u.nvme.entry) { - list_del_init(&nvme->u.nvme.entry); - qla_nvme_cmpl_io(nvme); - } } /* create response queue */ diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index adeda6a4e4fd..8c05df30c083 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -149,16 +149,6 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) qla2x00_rel_sp(sp); } -void qla_nvme_cmpl_io(struct srb_iocb *nvme) -{ - srb_t *sp; - struct nvmefc_fcp_req *fd = nvme->u.nvme.desc; - - sp = container_of(nvme, srb_t, u.iocb_cmd); - fd->done(fd); - qla2xxx_rel_qpair_sp(sp->qpair, sp); -} - static void qla_nvme_sp_done(void *ptr, int res) { srb_t *sp = ptr; @@ -177,7 +167,8 @@ static void qla_nvme_sp_done(void *ptr, int res) fd->status = NVME_SC_INTERNAL; fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; - list_add_tail(&nvme->u.nvme.entry, &sp->qpair->nvme_done_list); + fd->done(fd); + qla2xxx_rel_qpair_sp(sp->qpair, sp); return; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 12ee6e02d146..bd37a243c0bd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -397,7 +397,6 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, ha->base_qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0; ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q]; INIT_LIST_HEAD(&ha->base_qpair->hints_list); - INIT_LIST_HEAD(&ha->base_qpair->nvme_done_list); ha->base_qpair->enable_class_2 = ql2xenableclass2; /* init qpair to this cpu. Will adjust at run time. */ qla_cpu_update(rsp->qpair, raw_smp_processor_id()); From 1cbc0efcd9bee74670d0b637f53e67c47373f544 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:37 -0700 Subject: [PATCH 154/168] scsi: qla2xxx: Fix retry for PRLI RJT with reason of BUSY Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 13 ++++++++++++- drivers/scsi/qla2xxx/qla_mbx.c | 7 +++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 7e9d8f08b9d5..1abc8a9064b3 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -60,7 +60,7 @@ * | | | 0xb13c-0xb140 | * | | | 0xb149 | * | MultiQ | 0xc010 | | - * | Misc | 0xd302 | 0xd031-0xd0ff | + * | Misc | 0xd303 | 0xd031-0xd0ff | * | | | 0xd101-0xd1fe | * | | | 0xd214-0xd2fe | * | Target Mode | 0xe081 | | diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 33823d74c782..15a96dc205d0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -880,7 +880,6 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport) return rval; if (fcport->fw_login_state == DSC_LS_PLOGI_PEND || - fcport->fw_login_state == DSC_LS_PLOGI_COMP || fcport->fw_login_state == DSC_LS_PRLI_PEND) return rval; @@ -1238,6 +1237,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) qla2x00_post_async_adisc_work(vha, fcport, data); break; + case DSC_LOGIN_PEND: + if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) + qla24xx_post_prli_work(vha, fcport); + break; + default: break; } @@ -1640,6 +1644,13 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) qla24xx_post_gpdb_work(vha, ea->fcport, 0); break; default: + if ((ea->iop[0] == LSC_SCODE_ELS_REJECT) && + (ea->iop[1] == 0x50000)) { /* reson 5=busy expl:0x0 */ + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + ea->fcport->fw_login_state = DSC_LS_PLOGI_COMP; + break; + } + if (ea->fcport->n2n_flag) { ql_dbg(ql_dbg_disc, vha, 0x2118, "%s %d %8phC post fc4 prli\n", diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 735079ba691c..c9a134ae0d2b 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1025,9 +1025,12 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) * FW supports nvme and driver load parameter requested nvme. * BIT 26 of fw_attributes indicates NVMe support. */ - if ((ha->fw_attributes_h & 0x400) && ql2xnvmeenable) + if ((ha->fw_attributes_h & 0x400) && ql2xnvmeenable) { vha->flags.nvme_enabled = 1; - + ql_log(ql_log_info, vha, 0xd302, + "%s: FC-NVMe is Enabled (0x%x)\n", + __func__, ha->fw_attributes_h); + } } if (IS_QLA27XX(ha)) { From 623ee824e579d234b9f68c7b28ff5ab43f7c78e5 Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:38 -0700 Subject: [PATCH 155/168] scsi: qla2xxx: Fix FC-NVMe IO abort during driver reset Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 17 ++++++++++++----- drivers/scsi/qla2xxx/qla_nvme.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 8c05df30c083..57275bc9fe14 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -489,6 +489,9 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, vha = fcport->vha; + if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) + return rval; + /* * If we know the dev is going away while the transport is still sending * IO's return busy back to stall the IO Q. This happens when the @@ -597,14 +600,18 @@ static int qla_nvme_wait_on_command(srb_t *sp) return ret; } -void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp) +void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp, int res) { int rval; - rval = ha->isp_ops->abort_command(sp); - if (!rval && !qla_nvme_wait_on_command(sp)) - ql_log(ql_log_warn, NULL, 0x2112, - "nvme_wait_on_comand timed out waiting on sp=%p\n", sp); + if (!test_bit(ABORT_ISP_ACTIVE, &sp->vha->dpc_flags)) { + rval = ha->isp_ops->abort_command(sp); + if (!rval && !qla_nvme_wait_on_command(sp)) + ql_log(ql_log_warn, NULL, 0x2112, + "timed out waiting on sp=%p\n", sp); + } else { + sp->done(sp, res); + } } static void qla_nvme_unregister_remote_port(struct work_struct *work) diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 8df379478269..816854ada654 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -145,7 +145,7 @@ struct pt_ls4_rx_unsol { void qla_nvme_register_hba(struct scsi_qla_host *); int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *); void qla_nvme_delete(struct scsi_qla_host *); -void qla_nvme_abort(struct qla_hw_data *, struct srb *sp); +void qla_nvme_abort(struct qla_hw_data *, struct srb *sp, int res); void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *, struct req_que *); void qla24xx_async_gffid_sp_done(void *, int); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index bd37a243c0bd..54f93f9cba48 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1734,7 +1734,7 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) sp_get(sp); spin_unlock_irqrestore(qp->qp_lock_ptr, flags); - qla_nvme_abort(ha, sp); + qla_nvme_abort(ha, sp, res); spin_lock_irqsave(qp->qp_lock_ptr, flags); } else if (GET_CMD_SP(sp) && From 60dd6e8e42077a4c25f221cf124e8ba038b86e2e Mon Sep 17 00:00:00 2001 From: Darren Trapp Date: Tue, 20 Mar 2018 23:09:39 -0700 Subject: [PATCH 156/168] scsi: qla2xxx: Cleanup code to improve FC-NVMe error handling This patch cleans up ABTS handling for FC-NVMe by - Removing allocation of sp, instead pass the sp pointer for abort IOCB - Fix error handling from Trasport failure - set outstanding_cmds array to NULL for nvme completion Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 78 ++++++++++++--------------------- drivers/scsi/qla2xxx/qla_nvme.c | 2 +- 2 files changed, 29 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index bc2c7ded6949..5fbb8f4b4dc7 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1837,31 +1837,23 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) sp->done(sp, 0); } -static void -qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) +static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, + void *tsk, srb_t *sp) { - const char func[] = "NVME-IOCB"; fc_port_t *fcport; - srb_t *sp; struct srb_iocb *iocb; struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; uint16_t state_flags; struct nvmefc_fcp_req *fd; uint16_t ret = 0; - struct srb_iocb *nvme; - - sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); - if (!sp) - return; iocb = &sp->u.iocb_cmd; fcport = sp->fcport; iocb->u.nvme.comp_status = le16_to_cpu(sts->comp_status); state_flags = le16_to_cpu(sts->state_flags); fd = iocb->u.nvme.desc; - nvme = &sp->u.iocb_cmd; - if (unlikely(nvme->u.nvme.aen_op)) + if (unlikely(iocb->u.nvme.aen_op)) atomic_dec(&sp->vha->hw->nvme_active_aen_cnt); /* @@ -1895,45 +1887,30 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) fd->transferred_length = fd->payload_length - le32_to_cpu(sts->residual_len); - /* - * If transport error then Failure (HBA rejects request) - * otherwise transport will handle. - */ - if (sts->entry_status) { - ql_log(ql_log_warn, fcport->vha, 0x5038, - "NVME-%s error - hdl=%x entry-status(%x).\n", - sp->name, sp->handle, sts->entry_status); + switch (le16_to_cpu(sts->comp_status)) { + case CS_COMPLETE: + ret = QLA_SUCCESS; + break; + case CS_ABORTED: + case CS_RESET: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_BUSY: + ql_log(ql_log_warn, fcport->vha, 0x5060, + "NVME-%s ERR Handling - hdl=%x completion status(%x) resid=%x ox_id=%x\n", + sp->name, sp->handle, sts->comp_status, + le32_to_cpu(sts->residual_len), sts->ox_id); + fd->transferred_length = 0; + iocb->u.nvme.rsp_pyld_len = 0; + ret = QLA_ABORTED; + break; + default: + ql_log(ql_log_warn, fcport->vha, 0x5060, + "NVME-%s error - hdl=%x completion status(%x) resid=%x ox_id=%x\n", + sp->name, sp->handle, sts->comp_status, + le32_to_cpu(sts->residual_len), sts->ox_id); ret = QLA_FUNCTION_FAILED; - } else { - switch (le16_to_cpu(sts->comp_status)) { - case CS_COMPLETE: - ret = QLA_SUCCESS; - break; - - case CS_RESET: - case CS_PORT_UNAVAILABLE: - fcport->nvme_flag |= NVME_FLAG_RESETTING; - /* fall through */ - case CS_ABORTED: - case CS_PORT_LOGGED_OUT: - case CS_PORT_BUSY: - ql_log(ql_log_warn, fcport->vha, 0x5060, - "NVME-%s ERR Handling - hdl=%x completion status(%x) resid=%x ox_id=%x\n", - sp->name, sp->handle, sts->comp_status, - le32_to_cpu(sts->residual_len), sts->ox_id); - fd->transferred_length = 0; - iocb->u.nvme.rsp_pyld_len = 0; - ret = QLA_ABORTED; - break; - - default: - ql_log(ql_log_warn, fcport->vha, 0x5060, - "NVME-%s error - hdl=%x completion status(%x) resid=%x ox_id=%x\n", - sp->name, sp->handle, sts->comp_status, - le32_to_cpu(sts->residual_len), sts->ox_id); - ret = QLA_FUNCTION_FAILED; - break; - } + break; } sp->done(sp, ret); } @@ -2461,7 +2438,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) /* NVME completion. */ if (sp->type == SRB_NVME_CMD) { - qla24xx_nvme_iocb_entry(vha, req, pkt); + req->outstanding_cmds[handle] = NULL; + qla24xx_nvme_iocb_entry(vha, req, pkt, sp); return; } diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 57275bc9fe14..c5a963c2c86e 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -280,7 +280,7 @@ static void qla_nvme_poll(struct nvme_fc_local_port *lport, void *hw_queue_handl spin_unlock_irqrestore(&qpair->qp_lock, flags); } -static int qla2x00_start_nvme_mq(srb_t *sp) +static inline int qla2x00_start_nvme_mq(srb_t *sp) { unsigned long flags; uint32_t *clr_ptr; From 33b28357dd0033ef0e146861cd575a9c5ed2fb5e Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 20 Mar 2018 23:09:40 -0700 Subject: [PATCH 157/168] scsi: qla2xxx: Fix Async GPN_FT for FCP and FC-NVMe scan This patch combines FCP and FC-NVMe scan into single scan when driver detects FC-NVMe capability on same port. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 8 + drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_gs.c | 274 ++++++++++++++++++++++++-------- drivers/scsi/qla2xxx/qla_init.c | 8 +- drivers/scsi/qla2xxx/qla_os.c | 10 +- 5 files changed, 230 insertions(+), 72 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6aae126add0c..54625eb2904f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2217,6 +2217,7 @@ typedef struct { /* FCP-4 types */ #define FC4_TYPE_FCP_SCSI 0x08 +#define FC4_TYPE_NVME 0x28 #define FC4_TYPE_OTHER 0x0 #define FC4_TYPE_UNKNOWN 0xff @@ -2982,8 +2983,14 @@ enum scan_flags_t { SF_QUEUED = BIT_1, }; +enum fc4type_t { + FS_FC4TYPE_FCP = BIT_0, + FS_FC4TYPE_NVME = BIT_1, +}; + struct fab_scan_rp { port_id_t id; + enum fc4type_t fc4type; u8 port_name[8]; u8 node_name[8]; }; @@ -3275,6 +3282,7 @@ struct qla_work_evt { } nack; struct { u8 fc4_type; + srb_t *sp; } gpnft; } u; }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 19f44e12926b..3c4c84ed0f0f 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -658,7 +658,7 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *); int qla2x00_mgmt_svr_login(scsi_qla_host_t *); void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea); int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport); -int qla24xx_async_gpnft(scsi_qla_host_t *, u8); +int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *); void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *); void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *); int qla24xx_async_gnnid(scsi_qla_host_t *, fc_port_t *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index e4d404c24506..39dd62b8c649 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3858,7 +3858,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) fc_port_t *fcport; u32 i, rc; bool found; - u8 fc4type = sp->gen2; struct fab_scan_rp *rp; unsigned long flags; @@ -3931,7 +3930,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) "%s %d %8phC post new sess\n", __func__, __LINE__, rp->port_name); qla24xx_post_newsess_work(vha, &rp->id, rp->port_name, - rp->node_name, NULL, fc4type); + rp->node_name, NULL, rp->fc4type); } } @@ -3971,6 +3970,102 @@ out: spin_unlock_irqrestore(&vha->work_lock, flags); } +static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, + struct srb *sp) +{ + struct qla_hw_data *ha = vha->hw; + int num_fibre_dev = ha->max_fibre_devices; + struct ct_sns_req *ct_req = + (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; + struct ct_sns_gpnft_rsp *ct_rsp = + (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp; + struct ct_sns_gpn_ft_data *d; + struct fab_scan_rp *rp; + u16 cmd = be16_to_cpu(ct_req->command); + u8 fc4_type = sp->gen2; + int i, j, k; + port_id_t id; + u8 found; + u64 wwn; + + j = 0; + for (i = 0; i < num_fibre_dev; i++) { + d = &ct_rsp->entries[i]; + + id.b.rsvd_1 = 0; + id.b.domain = d->port_id[0]; + id.b.area = d->port_id[1]; + id.b.al_pa = d->port_id[2]; + wwn = wwn_to_u64(d->port_name); + + if (id.b24 == 0 || wwn == 0) + continue; + + if (fc4_type == FC4_TYPE_FCP_SCSI) { + if (cmd == GPN_FT_CMD) { + rp = &vha->scan.l[j]; + rp->id = id; + memcpy(rp->port_name, d->port_name, 8); + j++; + rp->fc4type = FS_FC4TYPE_FCP; + } else { + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (id.b24 == rp->id.b24) { + memcpy(rp->node_name, + d->port_name, 8); + break; + } + } + } + } else { + /* Search if the fibre device supports FC4_TYPE_NVME */ + if (cmd == GPN_FT_CMD) { + found = 0; + + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (!memcmp(rp->port_name, + d->port_name, 8)) { + /* + * Supports FC-NVMe & FCP + */ + rp->fc4type |= FS_FC4TYPE_NVME; + found = 1; + break; + } + } + + /* We found new FC-NVMe only port */ + if (!found) { + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (wwn_to_u64(rp->port_name)) { + continue; + } else { + rp->id = id; + memcpy(rp->port_name, + d->port_name, 8); + rp->fc4type = + FS_FC4TYPE_NVME; + break; + } + } + } + } else { + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (id.b24 == rp->id.b24) { + memcpy(rp->node_name, + d->port_name, 8); + break; + } + } + } + } + } +} + static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) { struct srb *sp = s; @@ -3978,12 +4073,9 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) struct qla_work_evt *e; struct ct_sns_req *ct_req = (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; - struct ct_sns_gpnft_rsp *ct_rsp = - (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp; - struct ct_sns_gpn_ft_data *d; - struct fab_scan_rp *rp; - int i, j, k; u16 cmd = be16_to_cpu(ct_req->command); + u8 fc4_type = sp->gen2; + unsigned long flags; /* gen2 field is holding the fc4type */ ql_dbg(ql_dbg_disc, vha, 0xffff, @@ -4011,40 +4103,51 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) return; } - if (!res) { - port_id_t id; - u64 wwn; + if (!res) + qla2x00_find_free_fcp_nvme_slot(vha, sp); - j = 0; - for (i = 0; i < vha->hw->max_fibre_devices; i++) { - d = &ct_rsp->entries[i]; + if ((fc4_type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled && + cmd == GNN_FT_CMD) { + del_timer(&sp->u.iocb_cmd.timer); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); - id.b.rsvd_1 = 0; - id.b.domain = d->port_id[0]; - id.b.area = d->port_id[1]; - id.b.al_pa = d->port_id[2]; - wwn = wwn_to_u64(d->port_name); - - if (id.b24 == 0 || wwn == 0) - continue; - - if (cmd == GPN_FT_CMD) { - rp = &vha->scan.l[j]; - rp->id = id; - memcpy(rp->port_name, d->port_name, 8); - j++; - } else {/* GNN_FT_CMD */ - for (k = 0; k < vha->hw->max_fibre_devices; - k++) { - rp = &vha->scan.l[k]; - if (id.b24 == rp->id.b24) { - memcpy(rp->node_name, - d->port_name, 8); - break; - } - } + e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT); + if (!e) { + /* + * please ignore kernel warning. Otherwise, + * we have mem leak. + */ + if (sp->u.iocb_cmd.u.ctarg.req) { + dma_free_coherent(&vha->hw->pdev->dev, + sizeof(struct ct_sns_pkt), + sp->u.iocb_cmd.u.ctarg.req, + sp->u.iocb_cmd.u.ctarg.req_dma); + sp->u.iocb_cmd.u.ctarg.req = NULL; } + if (sp->u.iocb_cmd.u.ctarg.rsp) { + dma_free_coherent(&vha->hw->pdev->dev, + sizeof(struct ct_sns_pkt), + sp->u.iocb_cmd.u.ctarg.rsp, + sp->u.iocb_cmd.u.ctarg.rsp_dma); + sp->u.iocb_cmd.u.ctarg.rsp = NULL; + } + + ql_dbg(ql_dbg_disc, vha, 0xffff, + "Async done-%s unable to alloc work element\n", + sp->name); + sp->free(sp); + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + return; } + e->u.gpnft.fc4_type = FC4_TYPE_NVME; + sp->rc = res; + e->u.gpnft.sp = sp; + + qla2x00_post_work(vha, e); + return; } if (cmd == GPN_FT_CMD) @@ -4095,9 +4198,12 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp, int rval = QLA_FUNCTION_FAILED; struct ct_sns_req *ct_req; struct ct_sns_pkt *ct_sns; + unsigned long flags; if (!vha->flags.online) { + spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); goto done_free_sp; } @@ -4106,10 +4212,18 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp, "%s: req %p rsp %p are not setup\n", __func__, sp->u.iocb_cmd.u.ctarg.req, sp->u.iocb_cmd.u.ctarg.rsp); + spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); WARN_ON(1); goto done_free_sp; } + + ql_dbg(ql_dbg_disc, vha, 0xfffff, + "%s: FC4Type %x, CT-PASSTRHU %s command ctarg rsp size %d, ctarg req size %d\n", + __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size, + sp->u.iocb_cmd.u.ctarg.req_size); + sp->type = SRB_CT_PTHRU_CMD; sp->name = "gnnft"; sp->gen1 = vha->hw->base_qpair->chip_reset; @@ -4172,15 +4286,17 @@ void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp) } /* Get WWPN list for certain fc4_type */ -int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type) +int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) { int rval = QLA_FUNCTION_FAILED; struct ct_sns_req *ct_req; - srb_t *sp; struct ct_sns_pkt *ct_sns; u32 rspsz; unsigned long flags; + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s enter\n", __func__); + if (!vha->flags.online) return rval; @@ -4193,9 +4309,58 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type) vha->scan.scan_flags |= SF_SCANNING; spin_unlock_irqrestore(&vha->work_lock, flags); - sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL); - if (!sp) { - vha->scan.scan_flags &= ~SF_SCANNING; + if (fc4_type == FC4_TYPE_FCP_SCSI) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s: Performing FCP Scan\n", __func__); + + if (sp) + sp->free(sp); /* should not happen */ + + sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL); + if (!sp) { + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); + return rval; + } + + sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent( + &vha->hw->pdev->dev, sizeof(struct ct_sns_pkt), + &sp->u.iocb_cmd.u.ctarg.req_dma, GFP_KERNEL); + if (!sp->u.iocb_cmd.u.ctarg.req) { + ql_log(ql_log_warn, vha, 0xffff, + "Failed to allocate ct_sns request.\n"); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); + goto done_free_sp; + } + sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; + + rspsz = sizeof(struct ct_sns_gpnft_rsp) + + ((vha->hw->max_fibre_devices - 1) * + sizeof(struct ct_sns_gpn_ft_data)); + + sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent( + &vha->hw->pdev->dev, rspsz, + &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL); + if (!sp->u.iocb_cmd.u.ctarg.rsp) { + ql_log(ql_log_warn, vha, 0xffff, + "Failed to allocate ct_sns request.\n"); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); + goto done_free_sp; + } + sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz; + + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s scan list size %d\n", __func__, vha->scan.size); + + memset(vha->scan.l, 0, vha->scan.size); + } else if (!sp) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "NVME scan did not provide SP\n"); return rval; } @@ -4205,31 +4370,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type) sp->gen2 = fc4_type; qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); - sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(&vha->hw->pdev->dev, - sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma, - GFP_KERNEL); - if (!sp->u.iocb_cmd.u.ctarg.req) { - ql_log(ql_log_warn, vha, 0xffff, - "Failed to allocate ct_sns request.\n"); - vha->scan.scan_flags &= ~SF_SCANNING; - goto done_free_sp; - } - rspsz = sizeof(struct ct_sns_gpnft_rsp) + ((vha->hw->max_fibre_devices - 1) * sizeof(struct ct_sns_gpn_ft_data)); - sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(&vha->hw->pdev->dev, - rspsz, &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL); - if (!sp->u.iocb_cmd.u.ctarg.rsp) { - ql_log(ql_log_warn, vha, 0xffff, - "Failed to allocate ct_sns request.\n"); - vha->scan.scan_flags &= ~SF_SCANNING; - goto done_free_sp; - } - - memset(vha->scan.l, 0, vha->scan.size); - ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req; /* CT_IU preamble */ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz); @@ -4237,8 +4381,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type) /* GPN_FT req */ ct_req->req.gpn_ft.port_type = fc4_type; - sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; - sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz; sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS; sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; @@ -4246,7 +4388,9 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type) rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { + spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); goto done_free_sp; } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 15a96dc205d0..77c9177d0c25 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5036,9 +5036,9 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]); } else { ql_dbg(ql_dbg_disc, vha, 0x2005, - "iIDMA adjusted to %s GB/s on %8phN.\n", + "iIDMA adjusted to %s GB/s (%X) on %8phN.\n", qla2x00_get_link_speed_str(ha, fcport->fp_speed), - fcport->port_name); + fcport->fp_speed, fcport->port_name); } } @@ -5264,8 +5264,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) qlt_do_generation_tick(vha, &discovery_gen); if (USE_ASYNC_SCAN(ha)) { - rval = QLA_SUCCESS; - rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI); + rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI, + NULL); if (rval) set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); } else { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 54f93f9cba48..6fa2467e2a16 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4803,9 +4803,14 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) fcport->d_id = e->u.new_sess.id; fcport->flags |= FCF_FABRIC_DEVICE; fcport->fw_login_state = DSC_LS_PLOGI_PEND; - if (e->u.new_sess.fc4_type == FC4_TYPE_FCP_SCSI) + if (e->u.new_sess.fc4_type & FS_FC4TYPE_FCP) fcport->fc4_type = FC4_TYPE_FCP_SCSI; + if (e->u.new_sess.fc4_type & FS_FC4TYPE_NVME) { + fcport->fc4_type = FC4_TYPE_OTHER; + fcport->fc4f_nvme = FC4_TYPE_NVME; + } + memcpy(fcport->port_name, e->u.new_sess.port_name, WWN_SIZE); } else { @@ -5021,7 +5026,8 @@ qla2x00_do_work(struct scsi_qla_host *vha) e->u.logio.data); break; case QLA_EVT_GPNFT: - qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type); + qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type, + e->u.gpnft.sp); break; case QLA_EVT_GPNFT_DONE: qla24xx_async_gpnft_done(vha, e->u.iosb.sp); From 9b143231250d705b287ac3896f41eb12a14d7826 Mon Sep 17 00:00:00 2001 From: "himanshu.madhani@cavium.com" Date: Tue, 20 Mar 2018 23:09:41 -0700 Subject: [PATCH 158/168] scsi: qla2xxx: Update driver version to 10.00.00.06-k Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 549bef9afddd..0c55d7057280 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.05-k" +#define QLA2XXX_VERSION "10.00.00.06-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 0 From 50b08240de61fcae54f6b35a25198209ac13c947 Mon Sep 17 00:00:00 2001 From: Ching Huang Date: Thu, 15 Mar 2018 14:26:15 +0800 Subject: [PATCH 159/168] scsi: arcmsr: Rename ACB_F_BUS_HANG_ON to ACB_F_ADAPTER_REMOVED for adapter hot-plug Rename ACB_F_BUS_HANG_ON to ACB_F_ADAPTER_REMOVED for adapter hot-plug. Signed-off-by: Ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index f375f3557c18..842b77abdfd3 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -779,12 +779,12 @@ struct AdapterControlBlock /* message clear rqbuffer */ #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 #define ACB_F_BUS_RESET 0x0080 -#define ACB_F_BUS_HANG_ON 0x0800/* need hardware reset bus */ #define ACB_F_IOP_INITED 0x0100 /* iop init */ #define ACB_F_ABORT 0x0200 #define ACB_F_FIRMWARE_TRAP 0x0400 +#define ACB_F_ADAPTER_REMOVED 0x0800 #define ACB_F_MSG_GET_CONFIG 0x1000 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ From c4c1adb3490ea4b8b13da2dae8d563350ded4988 Mon Sep 17 00:00:00 2001 From: Ching Huang Date: Thu, 15 Mar 2018 14:33:36 +0800 Subject: [PATCH 160/168] scsi: arcmsr: Handle adapter removed due to thunderbolt cable disconnection. Handle adapter removed due to thunderbolt cable disconnection. Signed-off-by: Ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 80 ++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 75e828bd30e3..2f52c53e4faa 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1446,12 +1446,80 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) } } +static void arcmsr_remove_scsi_devices(struct AdapterControlBlock *acb) +{ + char *acb_dev_map = (char *)acb->device_map; + int target, lun, i; + struct scsi_device *psdev; + struct CommandControlBlock *ccb; + char temp; + + for (i = 0; i < acb->maxFreeCCB; i++) { + ccb = acb->pccb_pool[i]; + if (ccb->startdone == ARCMSR_CCB_START) { + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_pci_unmap_dma(ccb); + ccb->pcmd->scsi_done(ccb->pcmd); + } + } + for (target = 0; target < ARCMSR_MAX_TARGETID; target++) { + temp = *acb_dev_map; + if (temp) { + for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { + if (temp & 1) { + psdev = scsi_device_lookup(acb->host, + 0, target, lun); + if (psdev != NULL) { + scsi_remove_device(psdev); + scsi_device_put(psdev); + } + } + temp >>= 1; + } + *acb_dev_map = 0; + } + acb_dev_map++; + } +} + +static void arcmsr_free_pcidev(struct AdapterControlBlock *acb) +{ + struct pci_dev *pdev; + struct Scsi_Host *host; + + host = acb->host; + arcmsr_free_sysfs_attr(acb); + scsi_remove_host(host); + flush_work(&acb->arcmsr_do_message_isr_bh); + del_timer_sync(&acb->eternal_timer); + if (set_date_time) + del_timer_sync(&acb->refresh_timer); + pdev = acb->pdev; + arcmsr_free_irq(pdev, acb); + arcmsr_free_ccb_pool(acb); + arcmsr_free_mu(acb); + arcmsr_unmap_pciregion(acb); + pci_release_regions(pdev); + scsi_host_put(host); + pci_disable_device(pdev); +} + static void arcmsr_remove(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; int poll_count = 0; + uint16_t dev_id; + + pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); + if (dev_id == 0xffff) { + acb->acb_flags &= ~ACB_F_IOP_INITED; + acb->acb_flags |= ACB_F_ADAPTER_REMOVED; + arcmsr_remove_scsi_devices(acb); + arcmsr_free_pcidev(acb); + return; + } arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); flush_work(&acb->arcmsr_do_message_isr_bh); @@ -1499,6 +1567,8 @@ static void arcmsr_shutdown(struct pci_dev *pdev) struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; + if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) + return; del_timer_sync(&acb->eternal_timer); if (set_date_time) del_timer_sync(&acb->refresh_timer); @@ -2931,6 +3001,12 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct CommandControlBlock *ccb; int target = cmd->device->id; + + if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) { + cmd->result = (DID_NO_CONNECT << 16); + cmd->scsi_done(cmd); + return 0; + } cmd->scsi_done = done; cmd->host_scribble = NULL; cmd->result = 0; @@ -4177,6 +4253,8 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) int retry_count = 0; int rtn = FAILED; acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; + if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) + return SUCCESS; pr_notice("arcmsr: executing bus reset eh.....num_resets = %d," " num_aborts = %d \n", acb->num_resets, acb->num_aborts); acb->num_resets++; @@ -4243,6 +4321,8 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) int rtn = FAILED; uint32_t intmask_org; + if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) + return SUCCESS; printk(KERN_NOTICE "arcmsr%d: abort device command of scsi id = %d lun = %d\n", acb->host->host_no, cmd->device->id, (u32)cmd->device->lun); From c2c62ebca18bc48cb7312f519e132b79cf42ea0e Mon Sep 17 00:00:00 2001 From: Ching Huang Date: Thu, 15 Mar 2018 14:37:40 +0800 Subject: [PATCH 161/168] scsi: arcmsr: Sleep to avoid CPU stuck too long for waiting adapter ready Sleep to avoid CPU stuck too long for waiting adapter ready. Signed-off-by: Ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 2f52c53e4faa..732b5d9242f1 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -3807,6 +3807,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_A: { struct MessageUnit_A __iomem *reg = acb->pmuA; do { + if (!(acb->acb_flags & ACB_F_IOP_INITED)) + msleep(20); firmware_state = readl(®->outbound_msgaddr1); } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); } @@ -3815,6 +3817,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; do { + if (!(acb->acb_flags & ACB_F_IOP_INITED)) + msleep(20); firmware_state = readl(reg->iop2drv_doorbell); } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); @@ -3823,6 +3827,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_C: { struct MessageUnit_C __iomem *reg = acb->pmuC; do { + if (!(acb->acb_flags & ACB_F_IOP_INITED)) + msleep(20); firmware_state = readl(®->outbound_msgaddr1); } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); } @@ -3830,6 +3836,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_D: { struct MessageUnit_D *reg = acb->pmuD; do { + if (!(acb->acb_flags & ACB_F_IOP_INITED)) + msleep(20); firmware_state = readl(reg->outbound_msgaddr1); } while ((firmware_state & ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0); @@ -3838,6 +3846,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_E: { struct MessageUnit_E __iomem *reg = acb->pmuE; do { + if (!(acb->acb_flags & ACB_F_IOP_INITED)) + msleep(20); firmware_state = readl(®->outbound_msgaddr1); } while ((firmware_state & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0); } From 45dce24df5b7ef569484caed9b44856dbf447e00 Mon Sep 17 00:00:00 2001 From: Ching Huang Date: Thu, 15 Mar 2018 14:40:25 +0800 Subject: [PATCH 162/168] scsi: arcmsr: Change driver version to v1.40.00.05-20180309 Change driver version to v1.40.00.05-20180309 Signed-off-by: Ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 842b77abdfd3..2e51ccc510e8 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -49,7 +49,7 @@ struct device_attribute; #define ARCMSR_MAX_OUTSTANDING_CMD 1024 #define ARCMSR_DEFAULT_OUTSTANDING_CMD 128 #define ARCMSR_MIN_OUTSTANDING_CMD 32 -#define ARCMSR_DRIVER_VERSION "v1.40.00.04-20171130" +#define ARCMSR_DRIVER_VERSION "v1.40.00.05-20180309" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 From 339faa8150fd56891105bc69fc18f5d51b8a63dd Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 21 Mar 2018 13:32:31 -0500 Subject: [PATCH 163/168] scsi: smartpqi: workaround fw bug for oq deletion Skip deleting PQI operational queues when there is an error creating a new queue group. It's not really necessary to delete the queues anyway because they get deleted during the PQI reset that is part of the error recovery path. Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 39 +++------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index b3aeb88456d8..af4a2ab5e5aa 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -3898,29 +3898,6 @@ static int pqi_validate_device_capability(struct pqi_ctrl_info *ctrl_info) return 0; } -static int pqi_delete_operational_queue(struct pqi_ctrl_info *ctrl_info, - bool inbound_queue, u16 queue_id) -{ - struct pqi_general_admin_request request; - struct pqi_general_admin_response response; - - memset(&request, 0, sizeof(request)); - request.header.iu_type = PQI_REQUEST_IU_GENERAL_ADMIN; - put_unaligned_le16(PQI_GENERAL_ADMIN_IU_LENGTH, - &request.header.iu_length); - if (inbound_queue) - request.function_code = - PQI_GENERAL_ADMIN_FUNCTION_DELETE_IQ; - else - request.function_code = - PQI_GENERAL_ADMIN_FUNCTION_DELETE_OQ; - put_unaligned_le16(queue_id, - &request.data.delete_operational_queue.queue_id); - - return pqi_submit_admin_request_synchronous(ctrl_info, &request, - &response); -} - static int pqi_create_event_queue(struct pqi_ctrl_info *ctrl_info) { int rc; @@ -4038,7 +4015,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info, if (rc) { dev_err(&ctrl_info->pci_dev->dev, "error creating inbound AIO queue\n"); - goto delete_inbound_queue_raid; + return rc; } queue_group->iq_pi[AIO_PATH] = ctrl_info->iomem_base + @@ -4066,7 +4043,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info, if (rc) { dev_err(&ctrl_info->pci_dev->dev, "error changing queue property\n"); - goto delete_inbound_queue_aio; + return rc; } /* @@ -4096,7 +4073,7 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info, if (rc) { dev_err(&ctrl_info->pci_dev->dev, "error creating outbound queue\n"); - goto delete_inbound_queue_aio; + return rc; } queue_group->oq_ci = ctrl_info->iomem_base + @@ -4105,16 +4082,6 @@ static int pqi_create_queue_group(struct pqi_ctrl_info *ctrl_info, &response.data.create_operational_oq.oq_ci_offset); return 0; - -delete_inbound_queue_aio: - pqi_delete_operational_queue(ctrl_info, true, - queue_group->iq_id[AIO_PATH]); - -delete_inbound_queue_raid: - pqi_delete_operational_queue(ctrl_info, true, - queue_group->iq_id[RAID_PATH]); - - return rc; } static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info) From 61c187e46ebb27f51b52bd0eb68b7f534a300184 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 21 Mar 2018 13:32:37 -0500 Subject: [PATCH 164/168] scsi: smartpqi: update driver version Reviewed-by: Scott Teel Reviewed-by: Gerry Morong Reviewed-by: Scott Benesh Signed-off-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index af4a2ab5e5aa..879f92881cc8 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -40,11 +40,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "1.1.2-126" +#define DRIVER_VERSION "1.1.4-115" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 1 -#define DRIVER_RELEASE 2 -#define DRIVER_REVISION 126 +#define DRIVER_RELEASE 4 +#define DRIVER_REVISION 115 #define DRIVER_NAME "Microsemi PQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" From f7e59e994fc69ace89f828686d82d528529ea025 Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Thu, 8 Mar 2018 15:44:07 +0200 Subject: [PATCH 165/168] scsi: qla2xxx: fix error message on Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 3e9dc54b89a3..d52ee990707d 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -14,7 +14,7 @@ * | Module Init and Probe | 0x0193 | 0x0146 | * | | | 0x015b-0x0160 | * | | | 0x016e | - * | Mailbox commands | 0x1205 | 0x11a2-0x11ff | + * | Mailbox commands | 0x1206 | 0x11a2-0x11ff | * | Device Discovery | 0x2134 | 0x210e-0x2116 | * | | | 0x211a | * | | | 0x211c-0x2128 | diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7397aeddd96c..9a97f2ceffba 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -503,11 +503,19 @@ mbx_done: } pr_warn(" cmd=%x ****\n", command); } - ql_dbg(ql_dbg_mbx, vha, 0x1198, - "host_status=%#x intr_ctrl=%#x intr_status=%#x\n", - RD_REG_DWORD(®->isp24.host_status), - RD_REG_DWORD(®->isp24.ictrl), - RD_REG_DWORD(®->isp24.istatus)); + if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) { + ql_dbg(ql_dbg_mbx, vha, 0x1198, + "host_status=%#x intr_ctrl=%#x intr_status=%#x\n", + RD_REG_DWORD(®->isp24.host_status), + RD_REG_DWORD(®->isp24.ictrl), + RD_REG_DWORD(®->isp24.istatus)); + } else { + ql_dbg(ql_dbg_mbx, vha, 0x1206, + "ctrl_status=%#x ictrl=%#x istatus=%#x\n", + RD_REG_WORD(®->isp.ctrl_status), + RD_REG_WORD(®->isp.ictrl), + RD_REG_WORD(®->isp.istatus)); + } } else { ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__); } From 3f6c9be27ae1932410d0af044b074fd2c27945c4 Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Thu, 8 Mar 2018 15:44:37 +0200 Subject: [PATCH 166/168] scsi: qla2xxx: fx00 copypaste typo Fix an obvious copy-paste error in freeing QLAFX00 response queue - the code checked for rsp->ring but freed rsp->ring_fx00. [mkp: applied by hand] Signed-off-by: Meelis Roos Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5c5dcca4d1da..b12fea6367b5 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -496,7 +496,7 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp) return; if (IS_QLAFX00(ha)) { - if (rsp && rsp->ring) + if (rsp && rsp->ring_fx00) dma_free_coherent(&ha->pdev->dev, (rsp->length_fx00 + 1) * sizeof(request_t), rsp->ring_fx00, rsp->dma_fx00); From 114c1aa210494a02c26aa33f793e5b641df01989 Mon Sep 17 00:00:00 2001 From: Stanislav Nijnikov Date: Thu, 1 Mar 2018 12:48:06 +0200 Subject: [PATCH 167/168] scsi: ufs: sysfs: reworking of the rpm_lvl and spm_lvl entries Read from these files will return the integer value of the chosen power management level now. Separate entries were added to show the target UFS device and UIC link states. The description of the possible power managements levels was added to the ABI file. The on-write behaviour of these entries wasn't changed. [mkp: typo] Signed-off-by: Stanislav Nijnikov Acked-by: Adrian Hunter Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 67 ++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.c | 90 +++++++++++----------- 2 files changed, 113 insertions(+), 44 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 07f1c2f8dbfc..83735f79e572 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -802,3 +802,70 @@ Description: This file shows the The amount of physical memory needed the particular logical unit. The full information about the attribute could be found at UFS specifications 2.1. The file is read only. + + +What: /sys/bus/platform/drivers/ufshcd/*/rpm_lvl +Date: September 2014 +Contact: Subhash Jadavani +Description: This entry could be used to set or show the UFS device + runtime power management level. The current driver + implementation supports 6 levels with next target states: + 0 - an UFS device will stay active, an UIC link will + stay active + 1 - an UFS device will stay active, an UIC link will + hibernate + 2 - an UFS device will moved to sleep, an UIC link will + stay active + 3 - an UFS device will moved to sleep, an UIC link will + hibernate + 4 - an UFS device will be powered off, an UIC link will + hibernate + 5 - an UFS device will be powered off, an UIC link will + be powered off + +What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state +Date: February 2018 +Contact: Subhash Jadavani +Description: This entry shows the target power mode of an UFS device + for the chosen runtime power management level. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state +Date: February 2018 +Contact: Subhash Jadavani +Description: This entry shows the target state of an UFS UIC link + for the chosen runtime power management level. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/spm_lvl +Date: September 2014 +Contact: Subhash Jadavani +Description: This entry could be used to set or show the UFS device + system power management level. The current driver + implementation supports 6 levels with next target states: + 0 - an UFS device will stay active, an UIC link will + stay active + 1 - an UFS device will stay active, an UIC link will + hibernate + 2 - an UFS device will moved to sleep, an UIC link will + stay active + 3 - an UFS device will moved to sleep, an UIC link will + hibernate + 4 - an UFS device will be powered off, an UIC link will + hibernate + 5 - an UFS device will be powered off, an UIC link will + be powered off + +What: /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state +Date: February 2018 +Contact: Subhash Jadavani +Description: This entry shows the target power mode of an UFS device + for the chosen system power management level. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state +Date: February 2018 +Contact: Subhash Jadavani +Description: This entry shows the target state of an UFS UIC link + for the chosen system power management level. + The file is read only. diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index cd7174d2d225..4ff9e0b7eba1 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -57,29 +57,8 @@ static ssize_t rpm_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->rpm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available Runtime PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; + return sprintf(buf, "%d\n", hba->rpm_lvl); } static ssize_t rpm_lvl_store(struct device *dev, @@ -88,33 +67,30 @@ static ssize_t rpm_lvl_store(struct device *dev, return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true); } +static ssize_t rpm_target_dev_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].dev_state)); +} + +static ssize_t rpm_target_link_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].link_state)); +} + static ssize_t spm_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->spm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->spm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->spm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available System PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; + return sprintf(buf, "%d\n", hba->spm_lvl); } static ssize_t spm_lvl_store(struct device *dev, @@ -123,12 +99,38 @@ static ssize_t spm_lvl_store(struct device *dev, return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false); } +static ssize_t spm_target_dev_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->spm_lvl].dev_state)); +} + +static ssize_t spm_target_link_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->spm_lvl].link_state)); +} + static DEVICE_ATTR_RW(rpm_lvl); +static DEVICE_ATTR_RO(rpm_target_dev_state); +static DEVICE_ATTR_RO(rpm_target_link_state); static DEVICE_ATTR_RW(spm_lvl); +static DEVICE_ATTR_RO(spm_target_dev_state); +static DEVICE_ATTR_RO(spm_target_link_state); static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, + &dev_attr_rpm_target_dev_state.attr, + &dev_attr_rpm_target_link_state.attr, &dev_attr_spm_lvl.attr, + &dev_attr_spm_target_dev_state.attr, + &dev_attr_spm_target_link_state.attr, NULL }; From ad448378825f5746c5fa37718724bc8f4e7b6945 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 20 Mar 2018 15:07:38 +0200 Subject: [PATCH 168/168] scsi: ufs: Add support for Auto-Hibernate Idle Timer UFS host controllers may support an autonomous power management feature called the Auto-Hibernate Idle Timer. The timer is set to the number of microseconds of idle time before the UFS host controller will autonomously put the link into Hibernate state. That will save power at the expense of increased latency. Any access to the host controller interface registers will automatically put the link out of Hibernate state. So once configured, the feature is transparent to the driver. Expose the Auto-Hibernate Idle Timer value via SysFS to allow users to choose between power efficiency or lower latency. Set a default value of 150 ms. Signed-off-by: Adrian Hunter Acked-by: Stanislav Nijnikov Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 14 ++++ drivers/scsi/ufs/ufs-sysfs.c | 76 ++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 26 ++++++++ drivers/scsi/ufs/ufshcd.h | 3 + drivers/scsi/ufs/ufshci.h | 7 ++ 5 files changed, 126 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 83735f79e572..016724ec26d5 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -1,3 +1,17 @@ +What: /sys/bus/*/drivers/ufshcd/*/auto_hibern8 +Date: March 2018 +Contact: linux-scsi@vger.kernel.org +Description: + This file contains the auto-hibernate idle timer setting of a + UFS host controller. A value of '0' means auto-hibernate is not + enabled. Otherwise the value is the number of microseconds of + idle time before the UFS host controller will autonomously put + the link into hibernate state. That will save power at the + expense of increased latency. Note that the hardware supports + 10-bit values with a power-of-ten multiplier which allows a + maximum value of 102300000. Refer to the UFS Host Controller + Interface specification for more details. + What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type Date: February 2018 Contact: Stanislav Nijnikov diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 4ff9e0b7eba1..8d9332bb7d0c 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -3,6 +3,7 @@ #include #include +#include #include #include "ufs.h" @@ -117,12 +118,86 @@ static ssize_t spm_target_link_state_show(struct device *dev, ufs_pm_lvl_states[hba->spm_lvl].link_state)); } +static void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) +{ + unsigned long flags; + + if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT)) + return; + + spin_lock_irqsave(hba->host->host_lock, flags); + if (hba->ahit == ahit) + goto out_unlock; + hba->ahit = ahit; + if (!pm_runtime_suspended(hba->dev)) + ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); +out_unlock: + spin_unlock_irqrestore(hba->host->host_lock, flags); +} + +/* Convert Auto-Hibernate Idle Timer register value to microseconds */ +static int ufshcd_ahit_to_us(u32 ahit) +{ + int timer = FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, ahit); + int scale = FIELD_GET(UFSHCI_AHIBERN8_SCALE_MASK, ahit); + + for (; scale > 0; --scale) + timer *= UFSHCI_AHIBERN8_SCALE_FACTOR; + + return timer; +} + +/* Convert microseconds to Auto-Hibernate Idle Timer register value */ +static u32 ufshcd_us_to_ahit(unsigned int timer) +{ + unsigned int scale; + + for (scale = 0; timer > UFSHCI_AHIBERN8_TIMER_MASK; ++scale) + timer /= UFSHCI_AHIBERN8_SCALE_FACTOR; + + return FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, timer) | + FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale); +} + +static ssize_t auto_hibern8_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT)) + return -EOPNOTSUPP; + + return snprintf(buf, PAGE_SIZE, "%d\n", ufshcd_ahit_to_us(hba->ahit)); +} + +static ssize_t auto_hibern8_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned int timer; + + if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT)) + return -EOPNOTSUPP; + + if (kstrtouint(buf, 0, &timer)) + return -EINVAL; + + if (timer > UFSHCI_AHIBERN8_MAX) + return -EINVAL; + + ufshcd_auto_hibern8_update(hba, ufshcd_us_to_ahit(timer)); + + return count; +} + static DEVICE_ATTR_RW(rpm_lvl); static DEVICE_ATTR_RO(rpm_target_dev_state); static DEVICE_ATTR_RO(rpm_target_link_state); static DEVICE_ATTR_RW(spm_lvl); static DEVICE_ATTR_RO(spm_target_dev_state); static DEVICE_ATTR_RO(spm_target_link_state); +static DEVICE_ATTR_RW(auto_hibern8); static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, @@ -131,6 +206,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_spm_lvl.attr, &dev_attr_spm_target_dev_state.attr, &dev_attr_spm_target_link_state.attr, + &dev_attr_auto_hibern8.attr, NULL }; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 3abcd31646eb..facee2b97926 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" @@ -3708,6 +3709,18 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) return ret; } +static void ufshcd_auto_hibern8_enable(struct ufs_hba *hba) +{ + unsigned long flags; + + if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) || !hba->ahit) + return; + + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); + spin_unlock_irqrestore(hba->host->host_lock, flags); +} + /** * ufshcd_init_pwr_info - setting the POR (power on reset) * values in hba power info @@ -6307,6 +6320,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) /* UniPro link is active now */ ufshcd_set_link_active(hba); + /* Enable Auto-Hibernate if configured */ + ufshcd_auto_hibern8_enable(hba); + ret = ufshcd_verify_dev_init(hba); if (ret) goto out; @@ -7391,6 +7407,10 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) /* Schedule clock gating in case of no access to UFS device yet */ ufshcd_release(hba); + + /* Enable Auto-Hibernate if configured */ + ufshcd_auto_hibern8_enable(hba); + goto out; set_old_link_state: @@ -7834,6 +7854,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); + /* Set the default auto-hiberate idle timer value to 150 ms */ + if (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) { + hba->ahit = FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, 150) | + FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, 3); + } + /* Hold auto suspend until async scan completes */ pm_runtime_get_sync(dev); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index deb3c5d382e9..8110dcd04d22 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -531,6 +531,9 @@ struct ufs_hba { struct device_attribute spm_lvl_attr; int pm_op_in_progress; + /* Auto-Hibernate Idle Timer register value */ + u32 ahit; + struct ufshcd_lrb *lrb; unsigned long lrb_in_use; diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 1a1b5d9fe514..bb5d9c7f3353 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -86,6 +86,7 @@ enum { enum { MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F, MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, + MASK_AUTO_HIBERN8_SUPPORT = 0x00800000, MASK_64_ADDRESSING_SUPPORT = 0x01000000, MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, @@ -119,6 +120,12 @@ enum { #define MANUFACTURE_ID_MASK UFS_MASK(0xFFFF, 0) #define PRODUCT_ID_MASK UFS_MASK(0xFFFF, 16) +/* AHIT - Auto-Hibernate Idle Timer */ +#define UFSHCI_AHIBERN8_TIMER_MASK GENMASK(9, 0) +#define UFSHCI_AHIBERN8_SCALE_MASK GENMASK(12, 10) +#define UFSHCI_AHIBERN8_SCALE_FACTOR 10 +#define UFSHCI_AHIBERN8_MAX (1023 * 100000) + /* * IS - Interrupt Status - 20h */