xref: /openbmc/linux/drivers/scsi/qla4xxx/ql4_bsg.c (revision ef7830bb)
1 /*
2  * QLogic iSCSI HBA Driver
3  * Copyright (c) 2011 QLogic Corporation
4  *
5  * See LICENSE.qla4xxx for copyright and licensing details.
6  */
7 
8 #include "ql4_def.h"
9 #include "ql4_glbl.h"
10 #include "ql4_bsg.h"
11 
12 static int
13 qla4xxx_read_flash(struct bsg_job *bsg_job)
14 {
15 	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
16 	struct scsi_qla_host *ha = to_qla_host(host);
17 	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
18 	struct iscsi_bsg_request *bsg_req = bsg_job->request;
19 	uint32_t offset = 0;
20 	uint32_t length = 0;
21 	dma_addr_t flash_dma;
22 	uint8_t *flash = NULL;
23 	int rval = -EINVAL;
24 
25 	bsg_reply->reply_payload_rcv_len = 0;
26 
27 	if (unlikely(pci_channel_offline(ha->pdev)))
28 		goto leave;
29 
30 	if (ql4xxx_reset_active(ha)) {
31 		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
32 		rval = -EBUSY;
33 		goto leave;
34 	}
35 
36 	if (ha->flash_state != QLFLASH_WAITING) {
37 		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
38 			   "active\n", __func__);
39 		rval = -EBUSY;
40 		goto leave;
41 	}
42 
43 	ha->flash_state = QLFLASH_READING;
44 	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
45 	length = bsg_job->reply_payload.payload_len;
46 
47 	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
48 				   GFP_KERNEL);
49 	if (!flash) {
50 		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
51 			   "data\n", __func__);
52 		rval = -ENOMEM;
53 		goto leave;
54 	}
55 
56 	rval = qla4xxx_get_flash(ha, flash_dma, offset, length);
57 	if (rval) {
58 		ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__);
59 		bsg_reply->result = DID_ERROR << 16;
60 		rval = -EIO;
61 	} else {
62 		bsg_reply->reply_payload_rcv_len =
63 			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
64 					    bsg_job->reply_payload.sg_cnt,
65 					    flash, length);
66 		bsg_reply->result = DID_OK << 16;
67 	}
68 
69 	bsg_job_done(bsg_job, bsg_reply->result,
70 		     bsg_reply->reply_payload_rcv_len);
71 	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
72 leave:
73 	ha->flash_state = QLFLASH_WAITING;
74 	return rval;
75 }
76 
77 static int
78 qla4xxx_update_flash(struct bsg_job *bsg_job)
79 {
80 	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
81 	struct scsi_qla_host *ha = to_qla_host(host);
82 	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
83 	struct iscsi_bsg_request *bsg_req = bsg_job->request;
84 	uint32_t length = 0;
85 	uint32_t offset = 0;
86 	uint32_t options = 0;
87 	dma_addr_t flash_dma;
88 	uint8_t *flash = NULL;
89 	int rval = -EINVAL;
90 
91 	bsg_reply->reply_payload_rcv_len = 0;
92 
93 	if (unlikely(pci_channel_offline(ha->pdev)))
94 		goto leave;
95 
96 	if (ql4xxx_reset_active(ha)) {
97 		ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
98 		rval = -EBUSY;
99 		goto leave;
100 	}
101 
102 	if (ha->flash_state != QLFLASH_WAITING) {
103 		ql4_printk(KERN_ERR, ha, "%s: another flash operation "
104 			   "active\n", __func__);
105 		rval = -EBUSY;
106 		goto leave;
107 	}
108 
109 	ha->flash_state = QLFLASH_WRITING;
110 	length = bsg_job->request_payload.payload_len;
111 	offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
112 	options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
113 
114 	flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
115 				   GFP_KERNEL);
116 	if (!flash) {
117 		ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
118 			   "data\n", __func__);
119 		rval = -ENOMEM;
120 		goto leave;
121 	}
122 
123 	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
124 			  bsg_job->request_payload.sg_cnt, flash, length);
125 
126 	rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options);
127 	if (rval) {
128 		ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__);
129 		bsg_reply->result = DID_ERROR << 16;
130 		rval = -EIO;
131 	} else
132 		bsg_reply->result = DID_OK << 16;
133 
134 	bsg_job_done(bsg_job, bsg_reply->result,
135 		     bsg_reply->reply_payload_rcv_len);
136 	dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
137 leave:
138 	ha->flash_state = QLFLASH_WAITING;
139 	return rval;
140 }
141 
142 /**
143  * qla4xxx_process_vendor_specific - handle vendor specific bsg request
144  * @job: iscsi_bsg_job to handle
145  **/
146 int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
147 {
148 	struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
149 	struct iscsi_bsg_request *bsg_req = bsg_job->request;
150 	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
151 	struct scsi_qla_host *ha = to_qla_host(host);
152 
153 	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
154 	case QLISCSI_VND_READ_FLASH:
155 		return qla4xxx_read_flash(bsg_job);
156 
157 	case QLISCSI_VND_UPDATE_FLASH:
158 		return qla4xxx_update_flash(bsg_job);
159 
160 	default:
161 		ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
162 			   "0x%x\n", __func__, bsg_req->msgcode);
163 		bsg_reply->result = (DID_ERROR << 16);
164 		bsg_reply->reply_payload_rcv_len = 0;
165 		bsg_job_done(bsg_job, bsg_reply->result,
166 			     bsg_reply->reply_payload_rcv_len);
167 		return -ENOSYS;
168 	}
169 }
170 
171 /**
172  * qla4xxx_bsg_request - handle bsg request from ISCSI transport
173  * @job: iscsi_bsg_job to handle
174  */
175 int qla4xxx_bsg_request(struct bsg_job *bsg_job)
176 {
177 	struct iscsi_bsg_request *bsg_req = bsg_job->request;
178 	struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
179 	struct scsi_qla_host *ha = to_qla_host(host);
180 
181 	switch (bsg_req->msgcode) {
182 	case ISCSI_BSG_HST_VENDOR:
183 		return qla4xxx_process_vendor_specific(bsg_job);
184 
185 	default:
186 		ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
187 			   __func__, bsg_req->msgcode);
188 	}
189 
190 	return -ENOSYS;
191 }
192