1a355943cSVikas Chaudhary /* 2a355943cSVikas Chaudhary * QLogic iSCSI HBA Driver 3a355943cSVikas Chaudhary * Copyright (c) 2011 QLogic Corporation 4a355943cSVikas Chaudhary * 5a355943cSVikas Chaudhary * See LICENSE.qla4xxx for copyright and licensing details. 6a355943cSVikas Chaudhary */ 7a355943cSVikas Chaudhary 8a355943cSVikas Chaudhary #include "ql4_def.h" 9a355943cSVikas Chaudhary #include "ql4_glbl.h" 10a355943cSVikas Chaudhary #include "ql4_bsg.h" 11a355943cSVikas Chaudhary 12a355943cSVikas Chaudhary static int 13a355943cSVikas Chaudhary qla4xxx_read_flash(struct bsg_job *bsg_job) 14a355943cSVikas Chaudhary { 15a355943cSVikas Chaudhary struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 16a355943cSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(host); 17a355943cSVikas Chaudhary struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 18a355943cSVikas Chaudhary struct iscsi_bsg_request *bsg_req = bsg_job->request; 19a355943cSVikas Chaudhary uint32_t offset = 0; 20a355943cSVikas Chaudhary uint32_t length = 0; 21a355943cSVikas Chaudhary dma_addr_t flash_dma; 22a355943cSVikas Chaudhary uint8_t *flash = NULL; 23ef7830bbSHarish Zunjarrao int rval = -EINVAL; 24a355943cSVikas Chaudhary 25a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len = 0; 26a355943cSVikas Chaudhary 27a355943cSVikas Chaudhary if (unlikely(pci_channel_offline(ha->pdev))) 28ef7830bbSHarish Zunjarrao goto leave; 29a355943cSVikas Chaudhary 30ef7830bbSHarish Zunjarrao if (ql4xxx_reset_active(ha)) { 31ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 32ef7830bbSHarish Zunjarrao rval = -EBUSY; 33ef7830bbSHarish Zunjarrao goto leave; 34a355943cSVikas Chaudhary } 35a355943cSVikas Chaudhary 36ef7830bbSHarish Zunjarrao if (ha->flash_state != QLFLASH_WAITING) { 37ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: another flash operation " 38ef7830bbSHarish Zunjarrao "active\n", __func__); 39ef7830bbSHarish Zunjarrao rval = -EBUSY; 40ef7830bbSHarish Zunjarrao goto leave; 41ef7830bbSHarish Zunjarrao } 42ef7830bbSHarish Zunjarrao 43ef7830bbSHarish Zunjarrao ha->flash_state = QLFLASH_READING; 44a355943cSVikas Chaudhary offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 45a355943cSVikas Chaudhary length = bsg_job->reply_payload.payload_len; 46a355943cSVikas Chaudhary 47a355943cSVikas Chaudhary flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, 48a355943cSVikas Chaudhary GFP_KERNEL); 49a355943cSVikas Chaudhary if (!flash) { 50a355943cSVikas Chaudhary ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 51a355943cSVikas Chaudhary "data\n", __func__); 52a355943cSVikas Chaudhary rval = -ENOMEM; 53ef7830bbSHarish Zunjarrao goto leave; 54a355943cSVikas Chaudhary } 55a355943cSVikas Chaudhary 56ef7830bbSHarish Zunjarrao rval = qla4xxx_get_flash(ha, flash_dma, offset, length); 57ef7830bbSHarish Zunjarrao if (rval) { 58ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__); 59ef7830bbSHarish Zunjarrao bsg_reply->result = DID_ERROR << 16; 60ef7830bbSHarish Zunjarrao rval = -EIO; 61ef7830bbSHarish Zunjarrao } else { 62ef7830bbSHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 63a355943cSVikas Chaudhary sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 64a355943cSVikas Chaudhary bsg_job->reply_payload.sg_cnt, 65a355943cSVikas Chaudhary flash, length); 66ef7830bbSHarish Zunjarrao bsg_reply->result = DID_OK << 16; 67a355943cSVikas Chaudhary } 68a355943cSVikas Chaudhary 69a355943cSVikas Chaudhary bsg_job_done(bsg_job, bsg_reply->result, 70a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len); 71ef7830bbSHarish Zunjarrao dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); 72ef7830bbSHarish Zunjarrao leave: 73ef7830bbSHarish Zunjarrao ha->flash_state = QLFLASH_WAITING; 74a355943cSVikas Chaudhary return rval; 75a355943cSVikas Chaudhary } 76a355943cSVikas Chaudhary 77a355943cSVikas Chaudhary static int 78a355943cSVikas Chaudhary qla4xxx_update_flash(struct bsg_job *bsg_job) 79a355943cSVikas Chaudhary { 80a355943cSVikas Chaudhary struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 81a355943cSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(host); 82a355943cSVikas Chaudhary struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 83a355943cSVikas Chaudhary struct iscsi_bsg_request *bsg_req = bsg_job->request; 84a355943cSVikas Chaudhary uint32_t length = 0; 85a355943cSVikas Chaudhary uint32_t offset = 0; 86a355943cSVikas Chaudhary uint32_t options = 0; 87a355943cSVikas Chaudhary dma_addr_t flash_dma; 88a355943cSVikas Chaudhary uint8_t *flash = NULL; 89ef7830bbSHarish Zunjarrao int rval = -EINVAL; 90a355943cSVikas Chaudhary 91a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len = 0; 92a355943cSVikas Chaudhary 93a355943cSVikas Chaudhary if (unlikely(pci_channel_offline(ha->pdev))) 94ef7830bbSHarish Zunjarrao goto leave; 95a355943cSVikas Chaudhary 96ef7830bbSHarish Zunjarrao if (ql4xxx_reset_active(ha)) { 97ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 98ef7830bbSHarish Zunjarrao rval = -EBUSY; 99ef7830bbSHarish Zunjarrao goto leave; 100a355943cSVikas Chaudhary } 101a355943cSVikas Chaudhary 102ef7830bbSHarish Zunjarrao if (ha->flash_state != QLFLASH_WAITING) { 103ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: another flash operation " 104ef7830bbSHarish Zunjarrao "active\n", __func__); 105ef7830bbSHarish Zunjarrao rval = -EBUSY; 106ef7830bbSHarish Zunjarrao goto leave; 107ef7830bbSHarish Zunjarrao } 108ef7830bbSHarish Zunjarrao 109ef7830bbSHarish Zunjarrao ha->flash_state = QLFLASH_WRITING; 110a355943cSVikas Chaudhary length = bsg_job->request_payload.payload_len; 111a355943cSVikas Chaudhary offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 112a355943cSVikas Chaudhary options = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 113a355943cSVikas Chaudhary 114a355943cSVikas Chaudhary flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma, 115a355943cSVikas Chaudhary GFP_KERNEL); 116a355943cSVikas Chaudhary if (!flash) { 117a355943cSVikas Chaudhary ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 118a355943cSVikas Chaudhary "data\n", __func__); 119a355943cSVikas Chaudhary rval = -ENOMEM; 120ef7830bbSHarish Zunjarrao goto leave; 121a355943cSVikas Chaudhary } 122a355943cSVikas Chaudhary 123a355943cSVikas Chaudhary sg_copy_to_buffer(bsg_job->request_payload.sg_list, 124a355943cSVikas Chaudhary bsg_job->request_payload.sg_cnt, flash, length); 125a355943cSVikas Chaudhary 126ef7830bbSHarish Zunjarrao rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options); 127ef7830bbSHarish Zunjarrao if (rval) { 128ef7830bbSHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__); 129ef7830bbSHarish Zunjarrao bsg_reply->result = DID_ERROR << 16; 130ef7830bbSHarish Zunjarrao rval = -EIO; 131ef7830bbSHarish Zunjarrao } else 132ef7830bbSHarish Zunjarrao bsg_reply->result = DID_OK << 16; 133a355943cSVikas Chaudhary 134a355943cSVikas Chaudhary bsg_job_done(bsg_job, bsg_reply->result, 135a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len); 136ef7830bbSHarish Zunjarrao dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma); 137ef7830bbSHarish Zunjarrao leave: 138ef7830bbSHarish Zunjarrao ha->flash_state = QLFLASH_WAITING; 139a355943cSVikas Chaudhary return rval; 140a355943cSVikas Chaudhary } 141a355943cSVikas Chaudhary 1428b0402e1SHarish Zunjarrao static int 1438b0402e1SHarish Zunjarrao qla4xxx_get_acb_state(struct bsg_job *bsg_job) 1448b0402e1SHarish Zunjarrao { 1458b0402e1SHarish Zunjarrao struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 1468b0402e1SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(host); 1478b0402e1SHarish Zunjarrao struct iscsi_bsg_request *bsg_req = bsg_job->request; 1488b0402e1SHarish Zunjarrao struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 1498b0402e1SHarish Zunjarrao uint32_t status[MBOX_REG_COUNT]; 1508b0402e1SHarish Zunjarrao uint32_t acb_idx; 1518b0402e1SHarish Zunjarrao uint32_t ip_idx; 1528b0402e1SHarish Zunjarrao int rval = -EINVAL; 1538b0402e1SHarish Zunjarrao 1548b0402e1SHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 0; 1558b0402e1SHarish Zunjarrao 1568b0402e1SHarish Zunjarrao if (unlikely(pci_channel_offline(ha->pdev))) 1578b0402e1SHarish Zunjarrao goto leave; 1588b0402e1SHarish Zunjarrao 1598b0402e1SHarish Zunjarrao /* Only 4022 and above adapters are supported */ 1608b0402e1SHarish Zunjarrao if (is_qla4010(ha)) 1618b0402e1SHarish Zunjarrao goto leave; 1628b0402e1SHarish Zunjarrao 1638b0402e1SHarish Zunjarrao if (ql4xxx_reset_active(ha)) { 1648b0402e1SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 1658b0402e1SHarish Zunjarrao rval = -EBUSY; 1668b0402e1SHarish Zunjarrao goto leave; 1678b0402e1SHarish Zunjarrao } 1688b0402e1SHarish Zunjarrao 1698b0402e1SHarish Zunjarrao if (bsg_job->reply_payload.payload_len < sizeof(status)) { 1708b0402e1SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n", 1718b0402e1SHarish Zunjarrao __func__, bsg_job->reply_payload.payload_len); 1728b0402e1SHarish Zunjarrao rval = -EINVAL; 1738b0402e1SHarish Zunjarrao goto leave; 1748b0402e1SHarish Zunjarrao } 1758b0402e1SHarish Zunjarrao 1768b0402e1SHarish Zunjarrao acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 1778b0402e1SHarish Zunjarrao ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 1788b0402e1SHarish Zunjarrao 1798b0402e1SHarish Zunjarrao rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status); 1808b0402e1SHarish Zunjarrao if (rval) { 1818b0402e1SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n", 1828b0402e1SHarish Zunjarrao __func__); 1838b0402e1SHarish Zunjarrao bsg_reply->result = DID_ERROR << 16; 1848b0402e1SHarish Zunjarrao rval = -EIO; 1858b0402e1SHarish Zunjarrao } else { 1868b0402e1SHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 1878b0402e1SHarish Zunjarrao sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 1888b0402e1SHarish Zunjarrao bsg_job->reply_payload.sg_cnt, 1898b0402e1SHarish Zunjarrao status, sizeof(status)); 1908b0402e1SHarish Zunjarrao bsg_reply->result = DID_OK << 16; 1918b0402e1SHarish Zunjarrao } 1928b0402e1SHarish Zunjarrao 1938b0402e1SHarish Zunjarrao bsg_job_done(bsg_job, bsg_reply->result, 1948b0402e1SHarish Zunjarrao bsg_reply->reply_payload_rcv_len); 1958b0402e1SHarish Zunjarrao leave: 1968b0402e1SHarish Zunjarrao return rval; 1978b0402e1SHarish Zunjarrao } 1988b0402e1SHarish Zunjarrao 1997c07d139SHarish Zunjarrao static int 2007c07d139SHarish Zunjarrao qla4xxx_read_nvram(struct bsg_job *bsg_job) 2017c07d139SHarish Zunjarrao { 2027c07d139SHarish Zunjarrao struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 2037c07d139SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(host); 2047c07d139SHarish Zunjarrao struct iscsi_bsg_request *bsg_req = bsg_job->request; 2057c07d139SHarish Zunjarrao struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 2067c07d139SHarish Zunjarrao uint32_t offset = 0; 2077c07d139SHarish Zunjarrao uint32_t len = 0; 2087c07d139SHarish Zunjarrao uint32_t total_len = 0; 2097c07d139SHarish Zunjarrao dma_addr_t nvram_dma; 2107c07d139SHarish Zunjarrao uint8_t *nvram = NULL; 2117c07d139SHarish Zunjarrao int rval = -EINVAL; 2127c07d139SHarish Zunjarrao 2137c07d139SHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 0; 2147c07d139SHarish Zunjarrao 2157c07d139SHarish Zunjarrao if (unlikely(pci_channel_offline(ha->pdev))) 2167c07d139SHarish Zunjarrao goto leave; 2177c07d139SHarish Zunjarrao 2187c07d139SHarish Zunjarrao /* Only 40xx adapters are supported */ 2197c07d139SHarish Zunjarrao if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) 2207c07d139SHarish Zunjarrao goto leave; 2217c07d139SHarish Zunjarrao 2227c07d139SHarish Zunjarrao if (ql4xxx_reset_active(ha)) { 2237c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 2247c07d139SHarish Zunjarrao rval = -EBUSY; 2257c07d139SHarish Zunjarrao goto leave; 2267c07d139SHarish Zunjarrao } 2277c07d139SHarish Zunjarrao 2287c07d139SHarish Zunjarrao offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 2297c07d139SHarish Zunjarrao len = bsg_job->reply_payload.payload_len; 2307c07d139SHarish Zunjarrao total_len = offset + len; 2317c07d139SHarish Zunjarrao 2327c07d139SHarish Zunjarrao /* total len should not be greater than max NVRAM size */ 2337c07d139SHarish Zunjarrao if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || 2347c07d139SHarish Zunjarrao ((is_qla4022(ha) || is_qla4032(ha)) && 2357c07d139SHarish Zunjarrao total_len > QL40X2_NVRAM_SIZE)) { 2367c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" 2377c07d139SHarish Zunjarrao " nvram size, offset=%d len=%d\n", 2387c07d139SHarish Zunjarrao __func__, offset, len); 2397c07d139SHarish Zunjarrao goto leave; 2407c07d139SHarish Zunjarrao } 2417c07d139SHarish Zunjarrao 2427c07d139SHarish Zunjarrao nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, 2437c07d139SHarish Zunjarrao GFP_KERNEL); 2447c07d139SHarish Zunjarrao if (!nvram) { 2457c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram " 2467c07d139SHarish Zunjarrao "data\n", __func__); 2477c07d139SHarish Zunjarrao rval = -ENOMEM; 2487c07d139SHarish Zunjarrao goto leave; 2497c07d139SHarish Zunjarrao } 2507c07d139SHarish Zunjarrao 2517c07d139SHarish Zunjarrao rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len); 2527c07d139SHarish Zunjarrao if (rval) { 2537c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__); 2547c07d139SHarish Zunjarrao bsg_reply->result = DID_ERROR << 16; 2557c07d139SHarish Zunjarrao rval = -EIO; 2567c07d139SHarish Zunjarrao } else { 2577c07d139SHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 2587c07d139SHarish Zunjarrao sg_copy_from_buffer(bsg_job->reply_payload.sg_list, 2597c07d139SHarish Zunjarrao bsg_job->reply_payload.sg_cnt, 2607c07d139SHarish Zunjarrao nvram, len); 2617c07d139SHarish Zunjarrao bsg_reply->result = DID_OK << 16; 2627c07d139SHarish Zunjarrao } 2637c07d139SHarish Zunjarrao 2647c07d139SHarish Zunjarrao bsg_job_done(bsg_job, bsg_reply->result, 2657c07d139SHarish Zunjarrao bsg_reply->reply_payload_rcv_len); 2667c07d139SHarish Zunjarrao dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); 2677c07d139SHarish Zunjarrao leave: 2687c07d139SHarish Zunjarrao return rval; 2697c07d139SHarish Zunjarrao } 2707c07d139SHarish Zunjarrao 2717c07d139SHarish Zunjarrao static int 2727c07d139SHarish Zunjarrao qla4xxx_update_nvram(struct bsg_job *bsg_job) 2737c07d139SHarish Zunjarrao { 2747c07d139SHarish Zunjarrao struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 2757c07d139SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(host); 2767c07d139SHarish Zunjarrao struct iscsi_bsg_request *bsg_req = bsg_job->request; 2777c07d139SHarish Zunjarrao struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 2787c07d139SHarish Zunjarrao uint32_t offset = 0; 2797c07d139SHarish Zunjarrao uint32_t len = 0; 2807c07d139SHarish Zunjarrao uint32_t total_len = 0; 2817c07d139SHarish Zunjarrao dma_addr_t nvram_dma; 2827c07d139SHarish Zunjarrao uint8_t *nvram = NULL; 2837c07d139SHarish Zunjarrao int rval = -EINVAL; 2847c07d139SHarish Zunjarrao 2857c07d139SHarish Zunjarrao bsg_reply->reply_payload_rcv_len = 0; 2867c07d139SHarish Zunjarrao 2877c07d139SHarish Zunjarrao if (unlikely(pci_channel_offline(ha->pdev))) 2887c07d139SHarish Zunjarrao goto leave; 2897c07d139SHarish Zunjarrao 2907c07d139SHarish Zunjarrao if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha))) 2917c07d139SHarish Zunjarrao goto leave; 2927c07d139SHarish Zunjarrao 2937c07d139SHarish Zunjarrao if (ql4xxx_reset_active(ha)) { 2947c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__); 2957c07d139SHarish Zunjarrao rval = -EBUSY; 2967c07d139SHarish Zunjarrao goto leave; 2977c07d139SHarish Zunjarrao } 2987c07d139SHarish Zunjarrao 2997c07d139SHarish Zunjarrao offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 3007c07d139SHarish Zunjarrao len = bsg_job->request_payload.payload_len; 3017c07d139SHarish Zunjarrao total_len = offset + len; 3027c07d139SHarish Zunjarrao 3037c07d139SHarish Zunjarrao /* total len should not be greater than max NVRAM size */ 3047c07d139SHarish Zunjarrao if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) || 3057c07d139SHarish Zunjarrao ((is_qla4022(ha) || is_qla4032(ha)) && 3067c07d139SHarish Zunjarrao total_len > QL40X2_NVRAM_SIZE)) { 3077c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max" 3087c07d139SHarish Zunjarrao " nvram size, offset=%d len=%d\n", 3097c07d139SHarish Zunjarrao __func__, offset, len); 3107c07d139SHarish Zunjarrao goto leave; 3117c07d139SHarish Zunjarrao } 3127c07d139SHarish Zunjarrao 3137c07d139SHarish Zunjarrao nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma, 3147c07d139SHarish Zunjarrao GFP_KERNEL); 3157c07d139SHarish Zunjarrao if (!nvram) { 3167c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash " 3177c07d139SHarish Zunjarrao "data\n", __func__); 3187c07d139SHarish Zunjarrao rval = -ENOMEM; 3197c07d139SHarish Zunjarrao goto leave; 3207c07d139SHarish Zunjarrao } 3217c07d139SHarish Zunjarrao 3227c07d139SHarish Zunjarrao sg_copy_to_buffer(bsg_job->request_payload.sg_list, 3237c07d139SHarish Zunjarrao bsg_job->request_payload.sg_cnt, nvram, len); 3247c07d139SHarish Zunjarrao 3257c07d139SHarish Zunjarrao rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len); 3267c07d139SHarish Zunjarrao if (rval) { 3277c07d139SHarish Zunjarrao ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__); 3287c07d139SHarish Zunjarrao bsg_reply->result = DID_ERROR << 16; 3297c07d139SHarish Zunjarrao rval = -EIO; 3307c07d139SHarish Zunjarrao } else 3317c07d139SHarish Zunjarrao bsg_reply->result = DID_OK << 16; 3327c07d139SHarish Zunjarrao 3337c07d139SHarish Zunjarrao bsg_job_done(bsg_job, bsg_reply->result, 3347c07d139SHarish Zunjarrao bsg_reply->reply_payload_rcv_len); 3357c07d139SHarish Zunjarrao dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma); 3367c07d139SHarish Zunjarrao leave: 3377c07d139SHarish Zunjarrao return rval; 3387c07d139SHarish Zunjarrao } 3397c07d139SHarish Zunjarrao 340a355943cSVikas Chaudhary /** 341a355943cSVikas Chaudhary * qla4xxx_process_vendor_specific - handle vendor specific bsg request 342a355943cSVikas Chaudhary * @job: iscsi_bsg_job to handle 343a355943cSVikas Chaudhary **/ 344a355943cSVikas Chaudhary int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) 345a355943cSVikas Chaudhary { 346a355943cSVikas Chaudhary struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; 347a355943cSVikas Chaudhary struct iscsi_bsg_request *bsg_req = bsg_job->request; 348a355943cSVikas Chaudhary struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 349a355943cSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(host); 350a355943cSVikas Chaudhary 351a355943cSVikas Chaudhary switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { 352a355943cSVikas Chaudhary case QLISCSI_VND_READ_FLASH: 353a355943cSVikas Chaudhary return qla4xxx_read_flash(bsg_job); 354a355943cSVikas Chaudhary 355a355943cSVikas Chaudhary case QLISCSI_VND_UPDATE_FLASH: 356a355943cSVikas Chaudhary return qla4xxx_update_flash(bsg_job); 357a355943cSVikas Chaudhary 3588b0402e1SHarish Zunjarrao case QLISCSI_VND_GET_ACB_STATE: 3598b0402e1SHarish Zunjarrao return qla4xxx_get_acb_state(bsg_job); 3608b0402e1SHarish Zunjarrao 3617c07d139SHarish Zunjarrao case QLISCSI_VND_READ_NVRAM: 3627c07d139SHarish Zunjarrao return qla4xxx_read_nvram(bsg_job); 3637c07d139SHarish Zunjarrao 3647c07d139SHarish Zunjarrao case QLISCSI_VND_UPDATE_NVRAM: 3657c07d139SHarish Zunjarrao return qla4xxx_update_nvram(bsg_job); 3667c07d139SHarish Zunjarrao 367a355943cSVikas Chaudhary default: 368a355943cSVikas Chaudhary ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " 369a355943cSVikas Chaudhary "0x%x\n", __func__, bsg_req->msgcode); 370a355943cSVikas Chaudhary bsg_reply->result = (DID_ERROR << 16); 371a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len = 0; 372a355943cSVikas Chaudhary bsg_job_done(bsg_job, bsg_reply->result, 373a355943cSVikas Chaudhary bsg_reply->reply_payload_rcv_len); 374a355943cSVikas Chaudhary return -ENOSYS; 375a355943cSVikas Chaudhary } 376a355943cSVikas Chaudhary } 377a355943cSVikas Chaudhary 378a355943cSVikas Chaudhary /** 379a355943cSVikas Chaudhary * qla4xxx_bsg_request - handle bsg request from ISCSI transport 380a355943cSVikas Chaudhary * @job: iscsi_bsg_job to handle 381a355943cSVikas Chaudhary */ 382a355943cSVikas Chaudhary int qla4xxx_bsg_request(struct bsg_job *bsg_job) 383a355943cSVikas Chaudhary { 384a355943cSVikas Chaudhary struct iscsi_bsg_request *bsg_req = bsg_job->request; 385a355943cSVikas Chaudhary struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); 386a355943cSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(host); 387a355943cSVikas Chaudhary 388a355943cSVikas Chaudhary switch (bsg_req->msgcode) { 389a355943cSVikas Chaudhary case ISCSI_BSG_HST_VENDOR: 390a355943cSVikas Chaudhary return qla4xxx_process_vendor_specific(bsg_job); 391a355943cSVikas Chaudhary 392a355943cSVikas Chaudhary default: 393a355943cSVikas Chaudhary ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n", 394a355943cSVikas Chaudhary __func__, bsg_req->msgcode); 395a355943cSVikas Chaudhary } 396a355943cSVikas Chaudhary 397a355943cSVikas Chaudhary return -ENOSYS; 398a355943cSVikas Chaudhary } 399