From a355943ca847ca3a264d468e408217562234d019 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Mon, 25 Jul 2011 13:48:51 -0500 Subject: [SCSI] qla4xxx: add bsg support This patch adds bsg support to qla4xxx. Signed-off-by: Vikas Chaudhary Signed-off-by: Harish Zunjarrao Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 209 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 drivers/scsi/qla4xxx/ql4_bsg.c (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c new file mode 100644 index 000000000000..daa2b0f8e309 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -0,0 +1,209 @@ +/* + * QLogic iSCSI HBA Driver + * Copyright (c) 2011 QLogic Corporation + * + * See LICENSE.qla4xxx for copyright and licensing details. + */ + +#include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_bsg.h" + +static int +qla4xxx_read_flash(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + struct iscsi_bsg_request *bsg_req = bsg_job->request; + uint32_t sg_cnt; + uint32_t offset = 0; + uint32_t length = 0; + dma_addr_t flash_dma; + uint8_t *flash = NULL; + int rval = 0; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + return -EINVAL; + + if (ha->flash_state != QLFLASH_WAITING) + return -EBUSY; + + /* TODO: Add check for adapter online, reset active?? */ + sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); + + if (!sg_cnt) + return -ENOMEM; + + if (sg_cnt != bsg_job->reply_payload.sg_cnt) { + ql4_printk(KERN_ERR, ha, "dma mapping resulted in different" + " sg counts, sg_cnt: %x dma_sg_cnt: %x\n", + bsg_job->reply_payload.sg_cnt, sg_cnt); + rval = -EAGAIN; + goto unmap_sg; + } + + offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + length = bsg_job->reply_payload.payload_len; + + flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, + GFP_KERNEL); + if (!flash) { + ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " + "data\n", __func__); + rval = -ENOMEM; + goto unmap_sg; + } + + ha->flash_state = QLFLASH_READING; + if (qla4xxx_get_flash(ha, flash_dma, offset, length)) + bsg_reply->result = (DID_ERROR << 16); + else { + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + flash, length); + + bsg_reply->result = DID_OK; + bsg_reply->reply_payload_rcv_len = length; + } + + if (flash) + dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); + + ha->flash_state = QLFLASH_WAITING; +unmap_sg: + dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); + if (!rval) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + return rval; +} + +static int +qla4xxx_update_flash(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + struct iscsi_bsg_request *bsg_req = bsg_job->request; + uint32_t sg_cnt; + uint32_t length = 0; + uint32_t offset = 0; + uint32_t options = 0; + dma_addr_t flash_dma; + uint8_t *flash = NULL; + int rval = 0; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + return -EINVAL; + + if (ha->flash_state != QLFLASH_WAITING) + return -EBUSY; + + sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); + + if (!sg_cnt) + return -ENOMEM; + + if (sg_cnt != bsg_job->request_payload.sg_cnt) { + ql4_printk(KERN_ERR, ha, "dma mapping resulted in different " + "sg counts request_sg_cnt: %x dma_request_sg_cnt: " + "%x\n", bsg_job->request_payload.sg_cnt, sg_cnt); + rval = -EAGAIN; + goto unmap_sg; + } + + length = bsg_job->request_payload.payload_len; + offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + options = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; + + flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, + GFP_KERNEL); + if (!flash) { + ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " + "data\n", __func__); + rval = -ENOMEM; + goto unmap_sg; + } + + ha->flash_state = QLFLASH_WRITING; + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, flash, length); + + if (qla4xxx_set_flash(ha, flash_dma, offset, length, options)) + bsg_reply->result = (DID_ERROR << 16); + else { + bsg_reply->result = DID_OK; + bsg_reply->reply_payload_rcv_len = length; + } + + if (flash) + dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); + ha->flash_state = QLFLASH_WAITING; +unmap_sg: + dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_TO_DEVICE); + + if (!rval) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + return rval; +} + +/** + * qla4xxx_process_vendor_specific - handle vendor specific bsg request + * @job: iscsi_bsg_job to handle + **/ +int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) +{ + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + + switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { + case QLISCSI_VND_READ_FLASH: + return qla4xxx_read_flash(bsg_job); + + case QLISCSI_VND_UPDATE_FLASH: + return qla4xxx_update_flash(bsg_job); + + default: + ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " + "0x%x\n", __func__, bsg_req->msgcode); + bsg_reply->result = (DID_ERROR << 16); + bsg_reply->reply_payload_rcv_len = 0; + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + return -ENOSYS; + } +} + +/** + * qla4xxx_bsg_request - handle bsg request from ISCSI transport + * @job: iscsi_bsg_job to handle + */ +int qla4xxx_bsg_request(struct bsg_job *bsg_job) +{ + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + + switch (bsg_req->msgcode) { + case ISCSI_BSG_HST_VENDOR: + return qla4xxx_process_vendor_specific(bsg_job); + + default: + ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n", + __func__, bsg_req->msgcode); + } + + return -ENOSYS; +} -- cgit v1.2.3-59-g8ed1b From ef7830bb62c9edf34fc4e849a53d7e87bf51de4a Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Mon, 1 Aug 2011 03:26:14 -0700 Subject: [SCSI] qla4xxx: Code cleanup for read/update flash using BSG - Corrected return status - Added reset active check - Removed unused dma_map_sg calls - Added debug prints on failure Signed-off-by: Harish Zunjarrao Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 128 ++++++++++++++++++----------------------- drivers/scsi/qla4xxx/ql4_def.h | 10 ++++ 2 files changed, 65 insertions(+), 73 deletions(-) (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index daa2b0f8e309..15032f130f22 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -16,36 +16,31 @@ qla4xxx_read_flash(struct bsg_job *bsg_job) struct scsi_qla_host *ha = to_qla_host(host); struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; struct iscsi_bsg_request *bsg_req = bsg_job->request; - uint32_t sg_cnt; uint32_t offset = 0; uint32_t length = 0; dma_addr_t flash_dma; uint8_t *flash = NULL; - int rval = 0; + int rval = -EINVAL; bsg_reply->reply_payload_rcv_len = 0; if (unlikely(pci_channel_offline(ha->pdev))) - return -EINVAL; + goto leave; - if (ha->flash_state != QLFLASH_WAITING) - return -EBUSY; - - /* TODO: Add check for adapter online, reset active?? */ - sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); - - if (!sg_cnt) - return -ENOMEM; + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } - if (sg_cnt != bsg_job->reply_payload.sg_cnt) { - ql4_printk(KERN_ERR, ha, "dma mapping resulted in different" - " sg counts, sg_cnt: %x dma_sg_cnt: %x\n", - bsg_job->reply_payload.sg_cnt, sg_cnt); - rval = -EAGAIN; - goto unmap_sg; + if (ha->flash_state != QLFLASH_WAITING) { + ql4_printk(KERN_ERR, ha, "%s: another flash operation " + "active\n", __func__); + rval = -EBUSY; + goto leave; } + ha->flash_state = QLFLASH_READING; offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; length = bsg_job->reply_payload.payload_len; @@ -55,31 +50,27 @@ qla4xxx_read_flash(struct bsg_job *bsg_job) ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " "data\n", __func__); rval = -ENOMEM; - goto unmap_sg; + goto leave; } - ha->flash_state = QLFLASH_READING; - if (qla4xxx_get_flash(ha, flash_dma, offset, length)) - bsg_reply->result = (DID_ERROR << 16); - else { - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, - flash, length); - - bsg_reply->result = DID_OK; - bsg_reply->reply_payload_rcv_len = length; + rval = qla4xxx_get_flash(ha, flash_dma, offset, length); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else { + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + flash, length); + bsg_reply->result = DID_OK << 16; } - if (flash) - dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); - + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); +leave: ha->flash_state = QLFLASH_WAITING; -unmap_sg: - dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); - if (!rval) - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); return rval; } @@ -90,36 +81,32 @@ qla4xxx_update_flash(struct bsg_job *bsg_job) struct scsi_qla_host *ha = to_qla_host(host); struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; struct iscsi_bsg_request *bsg_req = bsg_job->request; - uint32_t sg_cnt; uint32_t length = 0; uint32_t offset = 0; uint32_t options = 0; dma_addr_t flash_dma; uint8_t *flash = NULL; - int rval = 0; + int rval = -EINVAL; bsg_reply->reply_payload_rcv_len = 0; if (unlikely(pci_channel_offline(ha->pdev))) - return -EINVAL; - - if (ha->flash_state != QLFLASH_WAITING) - return -EBUSY; + goto leave; - sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, - bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); - - if (!sg_cnt) - return -ENOMEM; + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } - if (sg_cnt != bsg_job->request_payload.sg_cnt) { - ql4_printk(KERN_ERR, ha, "dma mapping resulted in different " - "sg counts request_sg_cnt: %x dma_request_sg_cnt: " - "%x\n", bsg_job->request_payload.sg_cnt, sg_cnt); - rval = -EAGAIN; - goto unmap_sg; + if (ha->flash_state != QLFLASH_WAITING) { + ql4_printk(KERN_ERR, ha, "%s: another flash operation " + "active\n", __func__); + rval = -EBUSY; + goto leave; } + ha->flash_state = QLFLASH_WRITING; length = bsg_job->request_payload.payload_len; offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; options = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; @@ -130,30 +117,25 @@ qla4xxx_update_flash(struct bsg_job *bsg_job) ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " "data\n", __func__); rval = -ENOMEM; - goto unmap_sg; + goto leave; } - ha->flash_state = QLFLASH_WRITING; sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, flash, length); - if (qla4xxx_set_flash(ha, flash_dma, offset, length, options)) - bsg_reply->result = (DID_ERROR << 16); - else { - bsg_reply->result = DID_OK; - bsg_reply->reply_payload_rcv_len = length; - } - - if (flash) - dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); + rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else + bsg_reply->result = DID_OK << 16; + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); +leave: ha->flash_state = QLFLASH_WAITING; -unmap_sg: - dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, DMA_TO_DEVICE); - - if (!rval) - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); return rval; } diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 90dc621a926a..74c71af7cb5d 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -803,6 +803,16 @@ static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); } +static inline int ql4xxx_reset_active(struct scsi_qla_host *ha) +{ + return test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || + test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); + +} /*---------------------------------------------------------------------------*/ /* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */ -- cgit v1.2.3-59-g8ed1b From 8b0402e1383cd51121f05a1d249cde0212c28c99 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Mon, 1 Aug 2011 03:26:15 -0700 Subject: [SCSI] qla4xxx: Add get ACB state support using BSG Signed-off-by: Harish Zunjarrao Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 60 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_bsg.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 2 ++ drivers/scsi/qla4xxx/ql4_mbx.c | 23 ++++++++++++++++ 4 files changed, 86 insertions(+) (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index 15032f130f22..de4db299bfcb 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -139,6 +139,63 @@ leave: return rval; } +static int +qla4xxx_get_acb_state(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint32_t status[MBOX_REG_COUNT]; + uint32_t acb_idx; + uint32_t ip_idx; + int rval = -EINVAL; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto leave; + + /* Only 4022 and above adapters are supported */ + if (is_qla4010(ha)) + goto leave; + + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } + + if (bsg_job->reply_payload.payload_len < sizeof(status)) { + ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n", + __func__, bsg_job->reply_payload.payload_len); + rval = -EINVAL; + goto leave; + } + + acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; + + rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n", + __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else { + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + status, sizeof(status)); + bsg_reply->result = DID_OK << 16; + } + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); +leave: + return rval; +} + /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request * @job: iscsi_bsg_job to handle @@ -157,6 +214,9 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) case QLISCSI_VND_UPDATE_FLASH: return qla4xxx_update_flash(bsg_job); + case QLISCSI_VND_GET_ACB_STATE: + return qla4xxx_get_acb_state(bsg_job); + default: ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " "0x%x\n", __func__, bsg_req->msgcode); diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index 5f6424ee6c1e..0400e1a0b670 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h @@ -10,5 +10,6 @@ /* BSG Vendor specific commands */ #define QLISCSI_VND_READ_FLASH 1 #define QLISCSI_VND_UPDATE_FLASH 2 +#define QLISCSI_VND_GET_ACB_STATE 3 #endif diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 98d4b17e8b10..5c8769651666 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -58,6 +58,8 @@ int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t acb_dma); int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t acb_dma); +int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, + uint32_t ip_idx, uint32_t *sts); void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session); u16 rd_nvram_word(struct scsi_qla_host *ha, int offset); u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 8741cfa98427..aec72309f60f 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1667,3 +1667,26 @@ int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, } return status; } + +int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, + uint32_t ip_idx, uint32_t *sts) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int status = QLA_SUCCESS; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE; + mbox_cmd[1] = acb_idx; + mbox_cmd[2] = ip_idx; + + status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]); + if (status != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: " + "MBOX_CMD_GET_IP_ADDR_STATE failed w/ " + "status %04X\n", __func__, mbox_sts[0])); + } + memcpy(sts, mbox_sts, sizeof(mbox_sts)); + return status; +} -- cgit v1.2.3-59-g8ed1b From 7c07d139cfec3172e813b468a8a173ad73bb5da9 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Mon, 1 Aug 2011 03:26:16 -0700 Subject: [SCSI] qla4xxx: Add read/update NVRAM support for 40xx adapters using BSG Signed-off-by: Harish Zunjarrao Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 147 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_bsg.h | 2 + drivers/scsi/qla4xxx/ql4_fw.h | 5 ++ drivers/scsi/qla4xxx/ql4_glbl.h | 4 ++ drivers/scsi/qla4xxx/ql4_mbx.c | 52 ++++++++++++++ 5 files changed, 210 insertions(+) (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index de4db299bfcb..c47545356f7b 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -196,6 +196,147 @@ leave: return rval; } +static int +qla4xxx_read_nvram(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint32_t offset = 0; + uint32_t len = 0; + uint32_t total_len = 0; + dma_addr_t nvram_dma; + uint8_t *nvram = NULL; + int rval = -EINVAL; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto leave; + + /* Only 40xx adapters are supported */ + if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) + goto leave; + + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } + + offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + len = bsg_job->reply_payload.payload_len; + total_len = offset + len; + + /* total len should not be greater than max NVRAM size */ + if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || + ((is_qla4022(ha) || is_qla4032(ha)) && + total_len > QL40X2_NVRAM_SIZE)) { + ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" + " nvram size, offset=%d len=%d\n", + __func__, offset, len); + goto leave; + } + + nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, + GFP_KERNEL); + if (!nvram) { + ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram " + "data\n", __func__); + rval = -ENOMEM; + goto leave; + } + + rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else { + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + nvram, len); + bsg_reply->result = DID_OK << 16; + } + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); +leave: + return rval; +} + +static int +qla4xxx_update_nvram(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint32_t offset = 0; + uint32_t len = 0; + uint32_t total_len = 0; + dma_addr_t nvram_dma; + uint8_t *nvram = NULL; + int rval = -EINVAL; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto leave; + + if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) + goto leave; + + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } + + offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + len = bsg_job->request_payload.payload_len; + total_len = offset + len; + + /* total len should not be greater than max NVRAM size */ + if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || + ((is_qla4022(ha) || is_qla4032(ha)) && + total_len > QL40X2_NVRAM_SIZE)) { + ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" + " nvram size, offset=%d len=%d\n", + __func__, offset, len); + goto leave; + } + + nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, + GFP_KERNEL); + if (!nvram) { + ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " + "data\n", __func__); + rval = -ENOMEM; + goto leave; + } + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, nvram, len); + + rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else + bsg_reply->result = DID_OK << 16; + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); +leave: + return rval; +} + /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request * @job: iscsi_bsg_job to handle @@ -217,6 +358,12 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) case QLISCSI_VND_GET_ACB_STATE: return qla4xxx_get_acb_state(bsg_job); + case QLISCSI_VND_READ_NVRAM: + return qla4xxx_read_nvram(bsg_job); + + case QLISCSI_VND_UPDATE_NVRAM: + return qla4xxx_update_nvram(bsg_job); + default: ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " "0x%x\n", __func__, bsg_req->msgcode); diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index 0400e1a0b670..71df80d612da 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h @@ -11,5 +11,7 @@ #define QLISCSI_VND_READ_FLASH 1 #define QLISCSI_VND_UPDATE_FLASH 2 #define QLISCSI_VND_GET_ACB_STATE 3 +#define QLISCSI_VND_READ_NVRAM 4 +#define QLISCSI_VND_UPDATE_NVRAM 5 #endif diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 9dc439b0d75f..581ff7e4621c 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -201,6 +201,9 @@ static inline uint32_t clr_rmask(uint32_t val) /* ISP 4022 nvram definitions */ #define NVR_WRITE_ENABLE 0x00000010 /* 4022 */ +#define QL4010_NVRAM_SIZE 0x200 +#define QL40X2_NVRAM_SIZE 0x800 + /* ISP port_status definitions */ /* ISP Semaphore definitions */ @@ -359,6 +362,8 @@ struct qla_flt_region { #define MBOX_CMD_GET_FW_STATE 0x0069 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A #define MBOX_CMD_GET_SYS_INFO 0x0078 +#define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */ +#define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */ #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 #define MBOX_CMD_SET_ACB 0x0088 #define MBOX_CMD_GET_ACB 0x0089 diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5c8769651666..35bd0c1ede38 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -162,6 +162,10 @@ int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index); int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, uint16_t idx); +int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, + uint32_t offset, uint32_t size); +int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, + uint32_t offset, uint32_t size); /* BSG Functions */ int qla4xxx_bsg_request(struct bsg_job *bsg_job); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index aec72309f60f..011c822f5ff6 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1690,3 +1690,55 @@ int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, memcpy(sts, mbox_sts, sizeof(mbox_sts)); return status; } + +int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, + uint32_t offset, uint32_t size) +{ + int status = QLA_SUCCESS; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_GET_NVRAM; + mbox_cmd[1] = LSDW(nvram_dma); + mbox_cmd[2] = MSDW(nvram_dma); + mbox_cmd[3] = offset; + mbox_cmd[4] = size; + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], + &mbox_sts[0]); + if (status != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " + "status %04X\n", ha->host_no, __func__, + mbox_sts[0])); + } + return status; +} + +int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, + uint32_t offset, uint32_t size) +{ + int status = QLA_SUCCESS; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_SET_NVRAM; + mbox_cmd[1] = LSDW(nvram_dma); + mbox_cmd[2] = MSDW(nvram_dma); + mbox_cmd[3] = offset; + mbox_cmd[4] = size; + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], + &mbox_sts[0]); + if (status != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " + "status %04X\n", ha->host_no, __func__, + mbox_sts[0])); + } + return status; +} -- cgit v1.2.3-59-g8ed1b From 5232f801bd0cfb4122e9a28ff942965c3c485fa7 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 12 Aug 2011 02:51:26 -0700 Subject: [SCSI] qla4xxx: Added restore factory defaults support using BSG This command will causes the firmware to update all configurations to pre-defined factory default settings. Signed-off-by: Harish Zunjarrao Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 47 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_bsg.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 3 +++ drivers/scsi/qla4xxx/ql4_mbx.c | 26 +++++++++++++++++++++++ 4 files changed, 77 insertions(+) (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index c47545356f7b..4704a52eaecd 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -337,6 +337,50 @@ leave: return rval; } +static int +qla4xxx_restore_defaults(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint32_t region = 0; + uint32_t field0 = 0; + uint32_t field1 = 0; + int rval = -EINVAL; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto leave; + + if (is_qla4010(ha)) + goto leave; + + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } + + region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; + field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; + + rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else + bsg_reply->result = DID_OK << 16; + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); +leave: + return rval; +} + /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request * @job: iscsi_bsg_job to handle @@ -364,6 +408,9 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) case QLISCSI_VND_UPDATE_NVRAM: return qla4xxx_update_nvram(bsg_job); + case QLISCSI_VND_RESTORE_DEFAULTS: + return qla4xxx_restore_defaults(bsg_job); + default: ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " "0x%x\n", __func__, bsg_req->msgcode); diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index 71df80d612da..84a1391f9865 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h @@ -13,5 +13,6 @@ #define QLISCSI_VND_GET_ACB_STATE 3 #define QLISCSI_VND_READ_NVRAM 4 #define QLISCSI_VND_UPDATE_NVRAM 5 +#define QLISCSI_VND_RESTORE_DEFAULTS 6 #endif diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 35bd0c1ede38..1a0f60187ad6 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -166,6 +166,9 @@ int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, uint32_t offset, uint32_t size); int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, uint32_t offset, uint32_t size); +int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, + uint32_t region, uint32_t field0, + uint32_t field1); /* BSG Functions */ int qla4xxx_bsg_request(struct bsg_job *bsg_job); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index e843758da3d4..dfc38aa8740d 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1744,3 +1744,29 @@ int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, } return status; } + +int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, + uint32_t region, uint32_t field0, + uint32_t field1) +{ + int status = QLA_SUCCESS; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS; + mbox_cmd[3] = region; + mbox_cmd[4] = field0; + mbox_cmd[5] = field1; + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], + &mbox_sts[0]); + if (status != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " + "status %04X\n", ha->host_no, __func__, + mbox_sts[0])); + } + return status; +} -- cgit v1.2.3-59-g8ed1b From 6085491c34b37fa806f70ccd3fb2bf08416e9e98 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 12 Aug 2011 02:51:27 -0700 Subject: [SCSI] qla4xxx: Added Get ACB support using BSG This command is used to read ACB params from firmware Signed-off-by: Harish Zunjarrao Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_bsg.c | 68 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_bsg.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 4 +-- drivers/scsi/qla4xxx/ql4_mbx.c | 15 +++++---- 4 files changed, 80 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/qla4xxx/ql4_bsg.c') diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index 4704a52eaecd..8acdc582ff6d 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -381,6 +381,71 @@ leave: return rval; } +static int +qla4xxx_bsg_get_acb(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint32_t acb_type = 0; + uint32_t len = 0; + dma_addr_t acb_dma; + uint8_t *acb = NULL; + int rval = -EINVAL; + + bsg_reply->reply_payload_rcv_len = 0; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto leave; + + /* Only 4022 and above adapters are supported */ + if (is_qla4010(ha)) + goto leave; + + if (ql4xxx_reset_active(ha)) { + ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); + rval = -EBUSY; + goto leave; + } + + acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + len = bsg_job->reply_payload.payload_len; + if (len < sizeof(struct addr_ctrl_blk)) { + ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n", + __func__, len); + rval = -EINVAL; + goto leave; + } + + acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL); + if (!acb) { + ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb " + "data\n", __func__); + rval = -ENOMEM; + goto leave; + } + + rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len); + if (rval) { + ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__); + bsg_reply->result = DID_ERROR << 16; + rval = -EIO; + } else { + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + acb, len); + bsg_reply->result = DID_OK << 16; + } + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma); +leave: + return rval; +} + /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request * @job: iscsi_bsg_job to handle @@ -411,6 +476,9 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) case QLISCSI_VND_RESTORE_DEFAULTS: return qla4xxx_restore_defaults(bsg_job); + case QLISCSI_VND_GET_ACB: + return qla4xxx_bsg_get_acb(bsg_job); + default: ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " "0x%x\n", __func__, bsg_req->msgcode); diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index 84a1391f9865..c6a0364509fd 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h @@ -14,5 +14,6 @@ #define QLISCSI_VND_READ_NVRAM 4 #define QLISCSI_VND_UPDATE_NVRAM 5 #define QLISCSI_VND_RESTORE_DEFAULTS 6 +#define QLISCSI_VND_GET_ACB 7 #endif diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 1a0f60187ad6..160db9d5ea21 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -56,8 +56,8 @@ int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha, int qla4xxx_disable_acb(struct scsi_qla_host *ha); int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t acb_dma); -int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, - uint32_t *mbox_sts, dma_addr_t acb_dma); +int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, + uint32_t acb_type, uint32_t len); int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, uint32_t ip_idx, uint32_t *sts); void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index dfc38aa8740d..de733a777803 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1425,18 +1425,21 @@ int qla4xxx_disable_acb(struct scsi_qla_host *ha) return status; } -int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, - uint32_t *mbox_sts, dma_addr_t acb_dma) +int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, + uint32_t acb_type, uint32_t len) { + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_SUCCESS; - memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); - memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_ACB; - mbox_cmd[1] = 0; /* Primary ACB */ + mbox_cmd[1] = acb_type; mbox_cmd[2] = LSDW(acb_dma); mbox_cmd[3] = MSDW(acb_dma); - mbox_cmd[4] = sizeof(struct addr_ctrl_blk); + mbox_cmd[4] = len; status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); if (status != QLA_SUCCESS) { -- cgit v1.2.3-59-g8ed1b