diff options
author | Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com> | 2017-12-26 20:34:30 -0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-01-03 23:26:42 -0500 |
commit | 8fb391827f57e5aea4157f7e1b8b005cd126545a (patch) | |
tree | 1d9475ac15457d52e79eb5899416db10c6b31088 /drivers/scsi | |
parent | 216ced02fa1638088d7908149d6500627b79b9f0 (diff) | |
download | linux-8fb391827f57e5aea4157f7e1b8b005cd126545a.tar.gz linux-8fb391827f57e5aea4157f7e1b8b005cd126545a.tar.bz2 linux-8fb391827f57e5aea4157f7e1b8b005cd126545a.zip |
scsi: aacraid: Create bmic submission function from bmic identify
safw command submission is duplicated across many functions.
Move the safw submission code from bmic identify into its own function
for common use
Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 147 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 7 |
2 files changed, 105 insertions, 49 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7173ae53c526..e02158d9cf65 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1667,60 +1667,116 @@ static int aac_adapter_hba(struct fib *fib, struct scsi_cmnd *cmd) (void *) cmd); } -int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target) +static int aac_send_safw_bmic_cmd(struct aac_dev *dev, + struct aac_srb_unit *srbu, void *xfer_buf, int xfer_len) { - struct fib *fibptr; - struct aac_srb *srbcmd; - struct sgmap64 *sg64; - struct aac_ciss_identify_pd *identify_resp; - dma_addr_t addr; - u32 vbus, vid; - u16 fibsize, datasize; - int rcode = -ENOMEM; - + struct fib *fibptr; + dma_addr_t addr; + int rcode; + int fibsize; + struct aac_srb *srb; + struct aac_srb_reply *srb_reply; + struct sgmap64 *sg64; + u32 vbus; + u32 vid; + + if (!dev->sa_firmware) + return 0; + /* allocate FIB */ fibptr = aac_fib_alloc(dev); if (!fibptr) - goto out; + return -ENOMEM; - fibsize = sizeof(struct aac_srb) - - sizeof(struct sgentry) + sizeof(struct sgentry64); - datasize = sizeof(struct aac_ciss_identify_pd); + aac_fib_init(fibptr); + fibptr->hw_fib_va->header.XferState &= + ~cpu_to_le32(FastResponseCapable); - identify_resp = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr, - GFP_KERNEL); - if (!identify_resp) - goto fib_free_ptr; + fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) + + sizeof(struct sgentry64); - vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.virt_device_bus); - vid = (u32)le16_to_cpu(dev->supplement_adapter_info.virt_device_target); + /* allocate DMA buffer for response */ + addr = dma_map_single(&dev->pdev->dev, xfer_buf, xfer_len, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto fib_error; + } - aac_fib_init(fibptr); + srb = fib_data(fibptr); + memcpy(srb, &srbu->srb, sizeof(struct aac_srb)); - srbcmd = (struct aac_srb *) fib_data(fibptr); - srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); - srbcmd->channel = cpu_to_le32(vbus); - srbcmd->id = cpu_to_le32(vid); - srbcmd->lun = 0; - srbcmd->flags = cpu_to_le32(SRB_DataIn); - srbcmd->timeout = cpu_to_le32(10); - srbcmd->retry_limit = 0; - srbcmd->cdb_size = cpu_to_le32(12); - srbcmd->count = cpu_to_le32(datasize); + vbus = (u32)le16_to_cpu( + dev->supplement_adapter_info.virt_device_bus); + vid = (u32)le16_to_cpu( + dev->supplement_adapter_info.virt_device_target); - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - srbcmd->cdb[0] = 0x26; - srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF); - srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE; + /* set the common request fields */ + srb->channel = cpu_to_le32(vbus); + srb->id = cpu_to_le32(vid); + srb->lun = 0; + srb->function = cpu_to_le32(SRBF_ExecuteScsi); + srb->timeout = 0; + srb->retry_limit = 0; + srb->cdb_size = cpu_to_le32(16); + srb->count = cpu_to_le32(xfer_len); + + sg64 = (struct sgmap64 *)&srb->sg; + sg64->count = cpu_to_le32(1); + sg64->sg[0].addr[1] = cpu_to_le32(upper_32_bits(addr)); + sg64->sg[0].addr[0] = cpu_to_le32(lower_32_bits(addr)); + sg64->sg[0].count = cpu_to_le32(xfer_len); - sg64 = (struct sgmap64 *)&srbcmd->sg; - sg64->count = cpu_to_le32(1); - sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16)); - sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); - sg64->sg[0].count = cpu_to_le32(datasize); + /* + * Copy the updated data for other dumping or other usage if needed + */ + memcpy(&srbu->srb, srb, sizeof(struct aac_srb)); + + /* issue request to the controller */ + rcode = aac_fib_send(ScsiPortCommand64, fibptr, fibsize, FsaNormal, + 1, 1, NULL, NULL); + + if (rcode == -ERESTARTSYS) + rcode = -ERESTART; + + if (unlikely(rcode < 0)) + goto bmic_error; + + srb_reply = (struct aac_srb_reply *)fib_data(fibptr); + memcpy(&srbu->srb_reply, srb_reply, sizeof(struct aac_srb_reply)); + +bmic_error: + dma_unmap_single(&dev->pdev->dev, addr, xfer_len, DMA_BIDIRECTIONAL); +fib_error: + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + return rcode; +} + +static int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target) +{ + int rcode = -ENOMEM; + u16 datasize; + struct aac_srb_unit srbu; + struct aac_srb *srbcmd; + struct aac_ciss_identify_pd *identify_resp; + + datasize = sizeof(struct aac_ciss_identify_pd); + identify_resp = kmalloc(datasize, GFP_KERNEL); + if (!identify_resp) + goto out; + + memset(&srbu, 0, sizeof(struct aac_srb_unit)); - rcode = aac_fib_send(ScsiPortCommand64, - fibptr, fibsize, FsaNormal, 1, 1, NULL, NULL); + srbcmd = &srbu.srb; + srbcmd->flags = cpu_to_le32(SRB_DataIn); + srbcmd->cdb[0] = 0x26; + srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF); + srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE; + + rcode = aac_send_safw_bmic_cmd(dev, &srbu, identify_resp, datasize); + if (unlikely(rcode < 0)) + goto out; if (identify_resp->current_queue_depth_limit <= 0 || identify_resp->current_queue_depth_limit > 32) @@ -1729,12 +1785,7 @@ int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target) dev->hba_map[bus][target].qd_limit = identify_resp->current_queue_depth_limit; - dma_free_coherent(&dev->pdev->dev, datasize, identify_resp, addr); - - aac_fib_complete(fibptr); - -fib_free_ptr: - aac_fib_free(fibptr); + kfree(identify_resp); out: return rcode; } diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 403a639574e5..bc2a0bc31540 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2021,6 +2021,12 @@ struct aac_srb_reply __le32 sense_data_size; u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE }; + +struct aac_srb_unit { + struct aac_srb srb; + struct aac_srb_reply srb_reply; +}; + /* * SRB Flags */ @@ -2634,7 +2640,6 @@ static inline int aac_adapter_check_health(struct aac_dev *dev) int aac_acquire_irq(struct aac_dev *dev); void aac_free_irq(struct aac_dev *dev); int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan); -int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target); const char *aac_driverinfo(struct Scsi_Host *); void aac_fib_vector_assign(struct aac_dev *dev); struct fib *aac_fib_alloc(struct aac_dev *dev); |