1a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary/*
2a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * QLogic iSCSI HBA Driver
3a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * Copyright (c) 2011 QLogic Corporation
4a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary *
5a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * See LICENSE.qla4xxx for copyright and licensing details.
6a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary */
7a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
8a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary#include "ql4_def.h"
9a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary#include "ql4_glbl.h"
10a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary#include "ql4_bsg.h"
11a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
12a355943ca847ca3a264d468e408217562234d019Vikas Chaudharystatic int
13a355943ca847ca3a264d468e408217562234d019Vikas Chaudharyqla4xxx_read_flash(struct bsg_job *bsg_job)
14a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary{
15a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
16a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct scsi_qla_host *ha = to_qla_host(host);
17a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
18a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_request *bsg_req = bsg_job->request;
19a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint32_t offset = 0;
20a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint32_t length = 0;
21a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	dma_addr_t flash_dma;
22a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint8_t *flash = NULL;
23ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	int rval = -EINVAL;
24a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
25a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	bsg_reply->reply_payload_rcv_len = 0;
26a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
27a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	if (unlikely(pci_channel_offline(ha->pdev)))
28ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
29a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
30ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (ql4xxx_reset_active(ha)) {
31ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
32ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EBUSY;
33ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
34ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	}
35a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
36ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (ha->flash_state != QLFLASH_WAITING) {
37ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
38ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao			   "active\n", __func__);
39ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EBUSY;
40ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
41a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
42a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
43ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	ha->flash_state = QLFLASH_READING;
44a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
45a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	length = bsg_job->reply_payload.payload_len;
46a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
47a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
48a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary				   GFP_KERNEL);
49a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	if (!flash) {
50a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
51a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			   "data\n", __func__);
52a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		rval = -ENOMEM;
53ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
54a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
55a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
56ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	rval = qla4xxx_get_flash(ha, flash_dma, offset, length);
57ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (rval) {
58ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__);
59ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
60ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EIO;
61ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	} else {
62ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		bsg_reply->reply_payload_rcv_len =
63ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
64ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao					    bsg_job->reply_payload.sg_cnt,
65ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao					    flash, length);
66ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		bsg_reply->result = DID_OK << 16;
67a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
68a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
69ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
70ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
71ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
72ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarraoleave:
73a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	ha->flash_state = QLFLASH_WAITING;
74a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	return rval;
75a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary}
76a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
77a355943ca847ca3a264d468e408217562234d019Vikas Chaudharystatic int
78a355943ca847ca3a264d468e408217562234d019Vikas Chaudharyqla4xxx_update_flash(struct bsg_job *bsg_job)
79a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary{
80a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
81a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct scsi_qla_host *ha = to_qla_host(host);
82a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
83a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_request *bsg_req = bsg_job->request;
84a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint32_t length = 0;
85a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint32_t offset = 0;
86a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint32_t options = 0;
87a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	dma_addr_t flash_dma;
88a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	uint8_t *flash = NULL;
89ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	int rval = -EINVAL;
90a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
91a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	bsg_reply->reply_payload_rcv_len = 0;
92a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
93a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	if (unlikely(pci_channel_offline(ha->pdev)))
94ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
95a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
96ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (ql4xxx_reset_active(ha)) {
97ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
98ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EBUSY;
99ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
100ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	}
101a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
102ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (ha->flash_state != QLFLASH_WAITING) {
103ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
104ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao			   "active\n", __func__);
105ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EBUSY;
106ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
107a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
108a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
109ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	ha->flash_state = QLFLASH_WRITING;
110a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	length = bsg_job->request_payload.payload_len;
111a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
112a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
113a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
114a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
115a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary				   GFP_KERNEL);
116a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	if (!flash) {
117a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
118a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			   "data\n", __func__);
119a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		rval = -ENOMEM;
120ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		goto leave;
121a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
122a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
123a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
124a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			  bsg_job->request_payload.sg_cnt, flash, length);
125a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
126ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options);
127ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	if (rval) {
128ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__);
129ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
130ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		rval = -EIO;
131ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	} else
132ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		bsg_reply->result = DID_OK << 16;
133ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao
134ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
135ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
136ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarrao	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
137ef7830bb62c9edf34fc4e849a53d7e87bf51de4aHarish Zunjarraoleave:
138a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	ha->flash_state = QLFLASH_WAITING;
139a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	return rval;
140a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary}
141a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
1428b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarraostatic int
1438b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarraoqla4xxx_get_acb_state(struct bsg_job *bsg_job)
1448b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao{
1458b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
1468b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	struct scsi_qla_host *ha = to_qla_host(host);
1478b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	struct iscsi_bsg_request *bsg_req = bsg_job->request;
1488b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
1498b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	uint32_t status[MBOX_REG_COUNT];
1508b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	uint32_t acb_idx;
1518b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	uint32_t ip_idx;
1528b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	int rval = -EINVAL;
1538b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1548b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	bsg_reply->reply_payload_rcv_len = 0;
1558b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1568b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	if (unlikely(pci_channel_offline(ha->pdev)))
1578b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		goto leave;
1588b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1598b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	/* Only 4022 and above adapters are supported */
1608b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	if (is_qla4010(ha))
1618b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		goto leave;
1628b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1638b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	if (ql4xxx_reset_active(ha)) {
1648b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
1658b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		rval = -EBUSY;
1668b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		goto leave;
1678b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	}
1688b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1698b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	if (bsg_job->reply_payload.payload_len < sizeof(status)) {
1708b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n",
1718b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao			   __func__, bsg_job->reply_payload.payload_len);
1728b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		rval = -EINVAL;
1738b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		goto leave;
1748b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	}
1758b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1768b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
1778b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
1788b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1798b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status);
1808b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	if (rval) {
1818b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n",
1828b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao			   __func__);
1838b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
1848b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		rval = -EIO;
1858b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	} else {
1868b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		bsg_reply->reply_payload_rcv_len =
1878b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1888b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao					    bsg_job->reply_payload.sg_cnt,
1898b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao					    status, sizeof(status));
1908b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		bsg_reply->result = DID_OK << 16;
1918b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	}
1928b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1938b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
1948b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
1958b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarraoleave:
1968b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	return rval;
1978b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao}
1988b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
1997c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraostatic int
2007c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraoqla4xxx_read_nvram(struct bsg_job *bsg_job)
2017c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao{
2027c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
2037c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct scsi_qla_host *ha = to_qla_host(host);
2047c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct iscsi_bsg_request *bsg_req = bsg_job->request;
2057c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
2067c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t offset = 0;
2077c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t len = 0;
2087c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t total_len = 0;
2097c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	dma_addr_t nvram_dma;
2107c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint8_t *nvram = NULL;
2117c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	int rval = -EINVAL;
2127c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2137c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	bsg_reply->reply_payload_rcv_len = 0;
2147c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2157c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (unlikely(pci_channel_offline(ha->pdev)))
2167c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2177c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2187c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	/* Only 40xx adapters are supported */
2197c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
2207c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2217c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2227c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (ql4xxx_reset_active(ha)) {
2237c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
2247c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -EBUSY;
2257c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2267c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
2277c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2287c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
2297c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	len = bsg_job->reply_payload.payload_len;
2307c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	total_len = offset + len;
2317c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2327c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	/* total len should not be greater than max NVRAM size */
2337c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
2347c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	    ((is_qla4022(ha) || is_qla4032(ha)) &&
2357c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	     total_len > QL40X2_NVRAM_SIZE)) {
2367c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
2377c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   " nvram size, offset=%d len=%d\n",
2387c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   __func__, offset, len);
2397c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2407c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
2417c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2427c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
2437c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao				   GFP_KERNEL);
2447c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (!nvram) {
2457c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram "
2467c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   "data\n", __func__);
2477c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -ENOMEM;
2487c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2497c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
2507c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2517c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len);
2527c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (rval) {
2537c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__);
2547c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
2557c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -EIO;
2567c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	} else {
2577c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		bsg_reply->reply_payload_rcv_len =
2587c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2597c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao					    bsg_job->reply_payload.sg_cnt,
2607c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao					    nvram, len);
2617c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		bsg_reply->result = DID_OK << 16;
2627c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
2637c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2647c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
2657c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
2667c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
2677c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraoleave:
2687c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	return rval;
2697c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao}
2707c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2717c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraostatic int
2727c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraoqla4xxx_update_nvram(struct bsg_job *bsg_job)
2737c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao{
2747c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
2757c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct scsi_qla_host *ha = to_qla_host(host);
2767c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct iscsi_bsg_request *bsg_req = bsg_job->request;
2777c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
2787c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t offset = 0;
2797c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t len = 0;
2807c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint32_t total_len = 0;
2817c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	dma_addr_t nvram_dma;
2827c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	uint8_t *nvram = NULL;
2837c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	int rval = -EINVAL;
2847c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2857c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	bsg_reply->reply_payload_rcv_len = 0;
2867c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2877c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (unlikely(pci_channel_offline(ha->pdev)))
2887c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2897c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2907c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
2917c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2927c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2937c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (ql4xxx_reset_active(ha)) {
2947c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
2957c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -EBUSY;
2967c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
2977c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
2987c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
2997c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
3007c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	len = bsg_job->request_payload.payload_len;
3017c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	total_len = offset + len;
3027c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3037c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	/* total len should not be greater than max NVRAM size */
3047c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
3057c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	    ((is_qla4022(ha) || is_qla4032(ha)) &&
3067c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	     total_len > QL40X2_NVRAM_SIZE)) {
3077c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
3087c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   " nvram size, offset=%d len=%d\n",
3097c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   __func__, offset, len);
3107c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
3117c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
3127c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3137c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
3147c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao				   GFP_KERNEL);
3157c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (!nvram) {
3167c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
3177c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			   "data\n", __func__);
3187c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -ENOMEM;
3197c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		goto leave;
3207c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	}
3217c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3227c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
3237c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao			  bsg_job->request_payload.sg_cnt, nvram, len);
3247c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3257c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len);
3267c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	if (rval) {
3277c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
3287c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
3297c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		rval = -EIO;
3307c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	} else
3317c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		bsg_reply->result = DID_OK << 16;
3327c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3337c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
3347c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
3357c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
3367c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarraoleave:
3377c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	return rval;
3387c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao}
3397c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
3405232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarraostatic int
3415232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarraoqla4xxx_restore_defaults(struct bsg_job *bsg_job)
3425232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao{
3435232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
3445232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	struct scsi_qla_host *ha = to_qla_host(host);
3455232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	struct iscsi_bsg_request *bsg_req = bsg_job->request;
3465232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
3475232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	uint32_t region = 0;
3485232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	uint32_t field0 = 0;
3495232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	uint32_t field1 = 0;
3505232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	int rval = -EINVAL;
3515232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3525232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	bsg_reply->reply_payload_rcv_len = 0;
3535232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3545232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	if (unlikely(pci_channel_offline(ha->pdev)))
3555232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		goto leave;
3565232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3575232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	if (is_qla4010(ha))
3585232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		goto leave;
3595232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3605232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	if (ql4xxx_reset_active(ha)) {
3615232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
3625232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		rval = -EBUSY;
3635232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		goto leave;
3645232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	}
3655232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3665232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
3675232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
3685232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
3695232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3705232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1);
3715232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	if (rval) {
3725232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
3735232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
3745232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		rval = -EIO;
3755232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	} else
3765232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		bsg_reply->result = DID_OK << 16;
3775232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3785232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
3795232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
3805232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarraoleave:
3815232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	return rval;
3825232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao}
3835232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
3846085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarraostatic int
3856085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarraoqla4xxx_bsg_get_acb(struct bsg_job *bsg_job)
3866085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao{
3876085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
3886085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	struct scsi_qla_host *ha = to_qla_host(host);
3896085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	struct iscsi_bsg_request *bsg_req = bsg_job->request;
3906085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
3916085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	uint32_t acb_type = 0;
3926085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	uint32_t len = 0;
3936085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	dma_addr_t acb_dma;
3946085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	uint8_t *acb = NULL;
3956085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	int rval = -EINVAL;
3966085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
3976085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	bsg_reply->reply_payload_rcv_len = 0;
3986085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
3996085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (unlikely(pci_channel_offline(ha->pdev)))
4006085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		goto leave;
4016085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4026085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	/* Only 4022 and above adapters are supported */
4036085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (is_qla4010(ha))
4046085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		goto leave;
4056085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4066085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (ql4xxx_reset_active(ha)) {
4076085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
4086085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		rval = -EBUSY;
4096085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		goto leave;
4106085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	}
4116085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4126085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
4136085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	len = bsg_job->reply_payload.payload_len;
4146085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (len < sizeof(struct addr_ctrl_blk)) {
4156085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n",
4166085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao			   __func__, len);
4176085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		rval = -EINVAL;
4186085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		goto leave;
4196085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	}
4206085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4216085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL);
4226085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (!acb) {
4236085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb "
4246085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao			   "data\n", __func__);
4256085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		rval = -ENOMEM;
4266085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		goto leave;
4276085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	}
4286085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4296085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len);
4306085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	if (rval) {
4316085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__);
4326085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		bsg_reply->result = DID_ERROR << 16;
4336085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		rval = -EIO;
4346085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	} else {
4356085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		bsg_reply->reply_payload_rcv_len =
4366085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
4376085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao					    bsg_job->reply_payload.sg_cnt,
4386085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao					    acb, len);
4396085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		bsg_reply->result = DID_OK << 16;
4406085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	}
4416085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
4426085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	bsg_job_done(bsg_job, bsg_reply->result,
4436085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		     bsg_reply->reply_payload_rcv_len);
4446085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma);
4456085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarraoleave:
4466085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	return rval;
4476085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao}
4486085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
449a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary/**
450a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * qla4xxx_process_vendor_specific - handle vendor specific bsg request
451a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * @job: iscsi_bsg_job to handle
452a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary **/
453a355943ca847ca3a264d468e408217562234d019Vikas Chaudharyint qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
454a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary{
455a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
456a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_request *bsg_req = bsg_job->request;
457a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
458a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct scsi_qla_host *ha = to_qla_host(host);
459a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
460a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
461a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	case QLISCSI_VND_READ_FLASH:
462a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		return qla4xxx_read_flash(bsg_job);
463a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
464a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	case QLISCSI_VND_UPDATE_FLASH:
465a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		return qla4xxx_update_flash(bsg_job);
466a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
4678b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao	case QLISCSI_VND_GET_ACB_STATE:
4688b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao		return qla4xxx_get_acb_state(bsg_job);
4698b0402e1383cd51121f05a1d249cde0212c28c99Harish Zunjarrao
4707c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	case QLISCSI_VND_READ_NVRAM:
4717c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		return qla4xxx_read_nvram(bsg_job);
4727c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
4737c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao	case QLISCSI_VND_UPDATE_NVRAM:
4747c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao		return qla4xxx_update_nvram(bsg_job);
4757c07d139cfec3172e813b468a8a173ad73bb5da9Harish Zunjarrao
4765232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao	case QLISCSI_VND_RESTORE_DEFAULTS:
4775232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao		return qla4xxx_restore_defaults(bsg_job);
4785232f801bd0cfb4122e9a28ff942965c3c485fa7Harish Zunjarrao
4796085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao	case QLISCSI_VND_GET_ACB:
4806085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao		return qla4xxx_bsg_get_acb(bsg_job);
4816085491c34b37fa806f70ccd3fb2bf08416e9e98Harish Zunjarrao
482a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	default:
483a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
484a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			   "0x%x\n", __func__, bsg_req->msgcode);
485a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		bsg_reply->result = (DID_ERROR << 16);
486a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		bsg_reply->reply_payload_rcv_len = 0;
487a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		bsg_job_done(bsg_job, bsg_reply->result,
488a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			     bsg_reply->reply_payload_rcv_len);
489a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		return -ENOSYS;
490a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
491a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary}
492a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
493a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary/**
494a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * qla4xxx_bsg_request - handle bsg request from ISCSI transport
495a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary * @job: iscsi_bsg_job to handle
496a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary */
497a355943ca847ca3a264d468e408217562234d019Vikas Chaudharyint qla4xxx_bsg_request(struct bsg_job *bsg_job)
498a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary{
499a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct iscsi_bsg_request *bsg_req = bsg_job->request;
500a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
501a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	struct scsi_qla_host *ha = to_qla_host(host);
502a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
503a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	switch (bsg_req->msgcode) {
504a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	case ISCSI_BSG_HST_VENDOR:
505a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		return qla4xxx_process_vendor_specific(bsg_job);
506a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
507a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	default:
508a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary		ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
509a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary			   __func__, bsg_req->msgcode);
510a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	}
511a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary
512a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary	return -ENOSYS;
513a355943ca847ca3a264d468e408217562234d019Vikas Chaudhary}
514