xref: /openbmc/linux/drivers/scsi/qla4xxx/ql4_bsg.c (revision 7c07d139)
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