diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 03:23:44 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 03:23:44 +0300 |
commit | 670ffccb2f9183eb6cb32fe92257aea52b3f8a7d (patch) | |
tree | 54962412913a69e17cc680c57f3e26f7305d99d2 /drivers/scsi/qla2xxx/qla_iocb.c | |
parent | 47f521ba18190e4bfbb65ead3977af5756884427 (diff) | |
parent | 341b2aa83368e6f23bf0cc3d04604896337ad7cb (diff) | |
download | linux-670ffccb2f9183eb6cb32fe92257aea52b3f8a7d.tar.xz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly updates of the usual suspects: lpfc, qla2xxx, hisi_sas,
megaraid_sas, pm80xx, mpt3sas, be2iscsi, hpsa. and a host of minor
updates.
There's no major behaviour change or additions to the core in all of
this, so the potential for regressions should be small (biggest
potential being in the scsi error handler changes)"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (203 commits)
scsi: lpfc: Fix hard lock up NMI in els timeout handling.
scsi: mpt3sas: remove a stray KERN_INFO
scsi: mpt3sas: cleanup _scsih_pcie_enumeration_event()
scsi: aacraid: use timespec64 instead of timeval
scsi: scsi_transport_fc: add 64GBIT and 128GBIT port speed definitions
scsi: qla2xxx: Suppress a kernel complaint in qla_init_base_qpair()
scsi: mpt3sas: fix dma_addr_t casts
scsi: be2iscsi: Use kasprintf
scsi: storvsc: Avoid excessive host scan on controller change
scsi: lpfc: fix kzalloc-simple.cocci warnings
scsi: mpt3sas: Update mpt3sas driver version.
scsi: mpt3sas: Fix sparse warnings
scsi: mpt3sas: Fix nvme drives checking for tlr.
scsi: mpt3sas: NVMe drive support for BTDHMAPPING ioctl command and log info
scsi: mpt3sas: Add-Task-management-debug-info-for-NVMe-drives.
scsi: mpt3sas: scan and add nvme device after controller reset
scsi: mpt3sas: Set NVMe device queue depth as 128
scsi: mpt3sas: Handle NVMe PCIe device related events generated from firmware.
scsi: mpt3sas: API's to remove nvme drive from sml
scsi: mpt3sas: API 's to support NVMe drive addition to SML
...
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 195 |
1 files changed, 185 insertions, 10 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 2f94159186d7..d810a447cb4a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { scsi_qla_host_t *vha = sp->vha; struct srb_iocb *elsio = &sp->u.iocb_cmd; + uint32_t dsd_len = 24; els_iocb->entry_type = ELS_IOCB_TYPE; els_iocb->entry_count = 1; @@ -2534,24 +2535,198 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; els_iocb->port_id[1] = sp->fcport->d_id.b.area; els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->s_id[0] = vha->d_id.b.al_pa; + els_iocb->s_id[1] = vha->d_id.b.area; + els_iocb->s_id[2] = vha->d_id.b.domain; els_iocb->control_flags = 0; - els_iocb->tx_byte_count = sizeof(struct els_logo_payload); - els_iocb->tx_address[0] = - cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); - els_iocb->tx_address[1] = - cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); - els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); + if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { + els_iocb->tx_byte_count = sizeof(struct els_plogi_payload); + els_iocb->tx_address[0] = + cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma)); + els_iocb->tx_address[1] = + cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma)); + els_iocb->tx_len = dsd_len; + + els_iocb->rx_dsd_count = 1; + els_iocb->rx_byte_count = sizeof(struct els_plogi_payload); + els_iocb->rx_address[0] = + cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma)); + els_iocb->rx_address[1] = + cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma)); + els_iocb->rx_len = dsd_len; + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, + "PLOGI ELS IOCB:\n"); + ql_dump_buffer(ql_log_info, vha, 0x0109, + (uint8_t *)els_iocb, 0x70); + } else { + els_iocb->tx_byte_count = sizeof(struct els_logo_payload); + els_iocb->tx_address[0] = + cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); + els_iocb->tx_address[1] = + cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); + els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); - els_iocb->rx_byte_count = 0; - els_iocb->rx_address[0] = 0; - els_iocb->rx_address[1] = 0; - els_iocb->rx_len = 0; + els_iocb->rx_byte_count = 0; + els_iocb->rx_address[0] = 0; + els_iocb->rx_address[1] = 0; + els_iocb->rx_len = 0; + } sp->vha->qla_stats.control_requests++; } static void +qla2x00_els_dcmd2_sp_free(void *data) +{ + srb_t *sp = data; + struct srb_iocb *elsio = &sp->u.iocb_cmd; + + if (elsio->u.els_plogi.els_plogi_pyld) + dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE, + elsio->u.els_plogi.els_plogi_pyld, + elsio->u.els_plogi.els_plogi_pyld_dma); + + if (elsio->u.els_plogi.els_resp_pyld) + dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE, + elsio->u.els_plogi.els_resp_pyld, + elsio->u.els_plogi.els_resp_pyld_dma); + + del_timer(&elsio->timer); + qla2x00_rel_sp(sp); +} + +static void +qla2x00_els_dcmd2_iocb_timeout(void *data) +{ + srb_t *sp = data; + fc_port_t *fcport = sp->fcport; + struct scsi_qla_host *vha = sp->vha; + struct qla_hw_data *ha = vha->hw; + struct srb_iocb *lio = &sp->u.iocb_cmd; + unsigned long flags = 0; + int res; + + ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069, + "%s hdl=%x ELS Timeout, %8phC portid=%06x\n", + sp->name, sp->handle, fcport->port_name, fcport->d_id.b24); + + /* Abort the exchange */ + spin_lock_irqsave(&ha->hardware_lock, flags); + res = ha->isp_ops->abort_command(sp); + ql_dbg(ql_dbg_io, vha, 0x3070, + "mbx abort_command %s\n", + (res == QLA_SUCCESS) ? "successful" : "failed"); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + complete(&lio->u.els_plogi.comp); +} + +static void +qla2x00_els_dcmd2_sp_done(void *ptr, int res) +{ + srb_t *sp = ptr; + fc_port_t *fcport = sp->fcport; + struct srb_iocb *lio = &sp->u.iocb_cmd; + struct scsi_qla_host *vha = sp->vha; + + ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072, + "%s ELS hdl=%x, portid=%06x done %8pC\n", + sp->name, sp->handle, fcport->d_id.b24, fcport->port_name); + + complete(&lio->u.els_plogi.comp); +} + +int +qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, + fc_port_t *fcport, port_id_t remote_did) +{ + srb_t *sp; + struct srb_iocb *elsio = NULL; + struct qla_hw_data *ha = vha->hw; + int rval = QLA_SUCCESS; + void *ptr, *resp_ptr; + dma_addr_t ptr_dma; + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) { + ql_log(ql_log_info, vha, 0x70e6, + "SRB allocation failed\n"); + return -ENOMEM; + } + + elsio = &sp->u.iocb_cmd; + fcport->d_id.b.domain = remote_did.b.domain; + fcport->d_id.b.area = remote_did.b.area; + fcport->d_id.b.al_pa = remote_did.b.al_pa; + + ql_dbg(ql_dbg_io, vha, 0x3073, + "Enter: PLOGI portid=%06x\n", fcport->d_id.b24); + + sp->type = SRB_ELS_DCMD; + sp->name = "ELS_DCMD"; + sp->fcport = fcport; + qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT); + elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; + sp->done = qla2x00_els_dcmd2_sp_done; + sp->free = qla2x00_els_dcmd2_sp_free; + + ptr = elsio->u.els_plogi.els_plogi_pyld = + dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); + ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma; + + if (!elsio->u.els_plogi.els_plogi_pyld) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + resp_ptr = elsio->u.els_plogi.els_resp_pyld = + dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); + + if (!elsio->u.els_plogi.els_resp_pyld) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr); + + memset(ptr, 0, sizeof(struct els_plogi_payload)); + memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); + elsio->u.els_plogi.els_cmd = els_opcode; + elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; + qla24xx_get_port_login_templ(vha, ptr_dma + 4, + &elsio->u.els_plogi.els_plogi_pyld->data[0], + sizeof(struct els_plogi_payload)); + + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n"); + ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109, + (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70); + + init_completion(&elsio->u.els_plogi.comp); + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + ql_dbg(ql_dbg_io, vha, 0x3074, + "%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n", + sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24); + + wait_for_completion(&elsio->u.els_plogi.comp); + + if (elsio->u.els_plogi.comp_status != CS_COMPLETE) + rval = QLA_FUNCTION_FAILED; + +out: + sp->free(sp); + return rval; +} + +static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { struct bsg_job *bsg_job = sp->u.bsg_job; |