diff options
author | Jayamohan Kallickal <jayamohan.kallickal@emulex.com> | 2012-04-04 00:41:50 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-04-25 04:33:15 -0400 |
commit | ffce3e2e8ce4ff2ee96df0944ee5daa783d5b2d0 (patch) | |
tree | dc7513194f40ab3baee11adc30c22a735158dc70 /drivers/scsi/be2iscsi | |
parent | 2177199d5150cf61bf26badcb6901176cc13787b (diff) |
[SCSI] be2iscsi: Adding bsg interface for be2iscsi
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 2 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 76 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 70 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 15 |
4 files changed, 162 insertions, 1 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index f343ed6a9e54..b15de3eaddf0 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -822,6 +822,8 @@ struct be_all_if_id { | |||
822 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | 822 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 |
823 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 | 823 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 |
824 | #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 | 824 | #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 |
825 | #define OPCODE_COMMON_WRITE_FLASH 96 | ||
826 | #define OPCODE_COMMON_READ_FLASH 97 | ||
825 | 827 | ||
826 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | 828 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ |
827 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | 829 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index d0c7d97769c3..ff6f851d6fb8 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -28,8 +28,11 @@ | |||
28 | #include <linux/semaphore.h> | 28 | #include <linux/semaphore.h> |
29 | #include <linux/iscsi_boot_sysfs.h> | 29 | #include <linux/iscsi_boot_sysfs.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/bsg-lib.h> | ||
31 | 32 | ||
32 | #include <scsi/libiscsi.h> | 33 | #include <scsi/libiscsi.h> |
34 | #include <scsi/scsi_bsg_iscsi.h> | ||
35 | #include <scsi/scsi_netlink.h> | ||
33 | #include <scsi/scsi_transport_iscsi.h> | 36 | #include <scsi/scsi_transport_iscsi.h> |
34 | #include <scsi/scsi_transport.h> | 37 | #include <scsi/scsi_transport.h> |
35 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
@@ -407,6 +410,8 @@ static struct scsi_host_template beiscsi_sht = { | |||
407 | .max_sectors = BEISCSI_MAX_SECTORS, | 410 | .max_sectors = BEISCSI_MAX_SECTORS, |
408 | .cmd_per_lun = BEISCSI_CMD_PER_LUN, | 411 | .cmd_per_lun = BEISCSI_CMD_PER_LUN, |
409 | .use_clustering = ENABLE_CLUSTERING, | 412 | .use_clustering = ENABLE_CLUSTERING, |
413 | .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID, | ||
414 | |||
410 | }; | 415 | }; |
411 | 416 | ||
412 | static struct scsi_transport_template *beiscsi_scsi_transport; | 417 | static struct scsi_transport_template *beiscsi_scsi_transport; |
@@ -4135,6 +4140,76 @@ static int beiscsi_task_xmit(struct iscsi_task *task) | |||
4135 | return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); | 4140 | return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); |
4136 | } | 4141 | } |
4137 | 4142 | ||
4143 | /** | ||
4144 | * beiscsi_bsg_request - handle bsg request from ISCSI transport | ||
4145 | * @job: job to handle | ||
4146 | */ | ||
4147 | static int beiscsi_bsg_request(struct bsg_job *job) | ||
4148 | { | ||
4149 | struct Scsi_Host *shost; | ||
4150 | struct beiscsi_hba *phba; | ||
4151 | struct iscsi_bsg_request *bsg_req = job->request; | ||
4152 | int rc = -EINVAL; | ||
4153 | unsigned int tag; | ||
4154 | struct be_dma_mem nonemb_cmd; | ||
4155 | struct be_cmd_resp_hdr *resp; | ||
4156 | struct iscsi_bsg_reply *bsg_reply = job->reply; | ||
4157 | unsigned short status, extd_status; | ||
4158 | |||
4159 | shost = iscsi_job_to_shost(job); | ||
4160 | phba = iscsi_host_priv(shost); | ||
4161 | |||
4162 | switch (bsg_req->msgcode) { | ||
4163 | case ISCSI_BSG_HST_VENDOR: | ||
4164 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | ||
4165 | job->request_payload.payload_len, | ||
4166 | &nonemb_cmd.dma); | ||
4167 | if (nonemb_cmd.va == NULL) { | ||
4168 | SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for " | ||
4169 | "beiscsi_bsg_request\n"); | ||
4170 | return -EIO; | ||
4171 | } | ||
4172 | tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job, | ||
4173 | &nonemb_cmd); | ||
4174 | if (!tag) { | ||
4175 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
4176 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
4177 | nonemb_cmd.va, nonemb_cmd.dma); | ||
4178 | return -EAGAIN; | ||
4179 | } else | ||
4180 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
4181 | phba->ctrl.mcc_numtag[tag]); | ||
4182 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
4183 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
4184 | free_mcc_tag(&phba->ctrl, tag); | ||
4185 | resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va; | ||
4186 | sg_copy_from_buffer(job->reply_payload.sg_list, | ||
4187 | job->reply_payload.sg_cnt, | ||
4188 | nonemb_cmd.va, (resp->response_length | ||
4189 | + sizeof(*resp))); | ||
4190 | bsg_reply->reply_payload_rcv_len = resp->response_length; | ||
4191 | bsg_reply->result = status; | ||
4192 | bsg_job_done(job, bsg_reply->result, | ||
4193 | bsg_reply->reply_payload_rcv_len); | ||
4194 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
4195 | nonemb_cmd.va, nonemb_cmd.dma); | ||
4196 | if (status || extd_status) { | ||
4197 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
4198 | " status = %d extd_status = %d\n", | ||
4199 | status, extd_status); | ||
4200 | return -EIO; | ||
4201 | } | ||
4202 | break; | ||
4203 | |||
4204 | default: | ||
4205 | SE_DEBUG(DBG_LVL_1, "Unsupported bsg command: 0x%x\n", | ||
4206 | bsg_req->msgcode); | ||
4207 | break; | ||
4208 | } | ||
4209 | |||
4210 | return rc; | ||
4211 | } | ||
4212 | |||
4138 | static void beiscsi_quiesce(struct beiscsi_hba *phba) | 4213 | static void beiscsi_quiesce(struct beiscsi_hba *phba) |
4139 | { | 4214 | { |
4140 | struct hwi_controller *phwi_ctrlr; | 4215 | struct hwi_controller *phwi_ctrlr; |
@@ -4447,6 +4522,7 @@ struct iscsi_transport beiscsi_iscsi_transport = { | |||
4447 | .ep_poll = beiscsi_ep_poll, | 4522 | .ep_poll = beiscsi_ep_poll, |
4448 | .ep_disconnect = beiscsi_ep_disconnect, | 4523 | .ep_disconnect = beiscsi_ep_disconnect, |
4449 | .session_recovery_timedout = iscsi_session_recovery_timedout, | 4524 | .session_recovery_timedout = iscsi_session_recovery_timedout, |
4525 | .bsg_request = beiscsi_bsg_request, | ||
4450 | }; | 4526 | }; |
4451 | 4527 | ||
4452 | static struct pci_driver beiscsi_pci_driver = { | 4528 | static struct pci_driver beiscsi_pci_driver = { |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index f7d27e9014c6..ccc3852a7f30 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -17,9 +17,11 @@ | |||
17 | * Costa Mesa, CA 92626 | 17 | * Costa Mesa, CA 92626 |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/bsg-lib.h> | ||
21 | #include <scsi/scsi_transport_iscsi.h> | ||
22 | #include <scsi/scsi_bsg_iscsi.h> | ||
20 | #include "be_mgmt.h" | 23 | #include "be_mgmt.h" |
21 | #include "be_iscsi.h" | 24 | #include "be_iscsi.h" |
22 | #include <scsi/scsi_transport_iscsi.h> | ||
23 | 25 | ||
24 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) | 26 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) |
25 | { | 27 | { |
@@ -187,6 +189,72 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | |||
187 | return status; | 189 | return status; |
188 | } | 190 | } |
189 | 191 | ||
192 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, | ||
193 | struct beiscsi_hba *phba, | ||
194 | struct bsg_job *job, | ||
195 | struct be_dma_mem *nonemb_cmd) | ||
196 | { | ||
197 | struct be_cmd_resp_hdr *resp; | ||
198 | struct be_mcc_wrb *wrb = wrb_from_mccq(phba); | ||
199 | struct be_sge *mcc_sge = nonembedded_sgl(wrb); | ||
200 | unsigned int tag = 0; | ||
201 | struct iscsi_bsg_request *bsg_req = job->request; | ||
202 | struct be_bsg_vendor_cmd *req = nonemb_cmd->va; | ||
203 | unsigned short region, sector_size, sector, offset; | ||
204 | |||
205 | nonemb_cmd->size = job->request_payload.payload_len; | ||
206 | memset(nonemb_cmd->va, 0, nonemb_cmd->size); | ||
207 | resp = nonemb_cmd->va; | ||
208 | region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; | ||
209 | sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; | ||
210 | sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; | ||
211 | offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4]; | ||
212 | req->region = region; | ||
213 | req->sector = sector; | ||
214 | req->offset = offset; | ||
215 | spin_lock(&ctrl->mbox_lock); | ||
216 | memset(wrb, 0, sizeof(*wrb)); | ||
217 | |||
218 | switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { | ||
219 | case BEISCSI_WRITE_FLASH: | ||
220 | offset = sector * sector_size + offset; | ||
221 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
222 | OPCODE_COMMON_WRITE_FLASH, sizeof(*req)); | ||
223 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
224 | job->request_payload.sg_cnt, | ||
225 | nonemb_cmd->va + offset, job->request_len); | ||
226 | break; | ||
227 | case BEISCSI_READ_FLASH: | ||
228 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
229 | OPCODE_COMMON_READ_FLASH, sizeof(*req)); | ||
230 | break; | ||
231 | default: | ||
232 | shost_printk(KERN_WARNING, phba->shost, | ||
233 | "Unsupported cmd = 0x%x\n\n", bsg_req->rqst_data. | ||
234 | h_vendor.vendor_cmd[0]); | ||
235 | spin_unlock(&ctrl->mbox_lock); | ||
236 | return -ENOSYS; | ||
237 | } | ||
238 | |||
239 | tag = alloc_mcc_tag(phba); | ||
240 | if (!tag) { | ||
241 | spin_unlock(&ctrl->mbox_lock); | ||
242 | return tag; | ||
243 | } | ||
244 | |||
245 | be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, | ||
246 | job->request_payload.sg_cnt); | ||
247 | mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
248 | mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
249 | mcc_sge->len = cpu_to_le32(nonemb_cmd->size); | ||
250 | wrb->tag0 |= tag; | ||
251 | |||
252 | be_mcc_notify(phba); | ||
253 | |||
254 | spin_unlock(&ctrl->mbox_lock); | ||
255 | return tag; | ||
256 | } | ||
257 | |||
190 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | 258 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) |
191 | { | 259 | { |
192 | struct be_ctrl_info *ctrl = &phba->ctrl; | 260 | struct be_ctrl_info *ctrl = &phba->ctrl; |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index d7fdfceb6564..03400f3f666f 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <scsi/scsi_bsg_iscsi.h> | ||
25 | #include "be_iscsi.h" | 26 | #include "be_iscsi.h" |
26 | #include "be_main.h" | 27 | #include "be_main.h" |
27 | 28 | ||
@@ -98,6 +99,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, | |||
98 | struct invalidate_command_table *inv_tbl, | 99 | struct invalidate_command_table *inv_tbl, |
99 | unsigned int num_invalidate, unsigned int cid, | 100 | unsigned int num_invalidate, unsigned int cid, |
100 | struct be_dma_mem *nonemb_cmd); | 101 | struct be_dma_mem *nonemb_cmd); |
102 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, | ||
103 | struct beiscsi_hba *phba, | ||
104 | struct bsg_job *job, | ||
105 | struct be_dma_mem *nonemb_cmd); | ||
101 | 106 | ||
102 | struct iscsi_invalidate_connection_params_in { | 107 | struct iscsi_invalidate_connection_params_in { |
103 | struct be_cmd_req_hdr hdr; | 108 | struct be_cmd_req_hdr hdr; |
@@ -204,6 +209,13 @@ struct be_mgmt_controller_attributes_resp { | |||
204 | struct mgmt_controller_attributes params; | 209 | struct mgmt_controller_attributes params; |
205 | } __packed; | 210 | } __packed; |
206 | 211 | ||
212 | struct be_bsg_vendor_cmd { | ||
213 | struct be_cmd_req_hdr hdr; | ||
214 | unsigned short region; | ||
215 | unsigned short offset; | ||
216 | unsigned short sector; | ||
217 | } __packed; | ||
218 | |||
207 | /* configuration management */ | 219 | /* configuration management */ |
208 | 220 | ||
209 | #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) | 221 | #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) |
@@ -225,6 +237,9 @@ struct be_mgmt_controller_attributes_resp { | |||
225 | bus_address.u.a32.address_hi; \ | 237 | bus_address.u.a32.address_hi; \ |
226 | } | 238 | } |
227 | 239 | ||
240 | #define BEISCSI_WRITE_FLASH 0 | ||
241 | #define BEISCSI_READ_FLASH 1 | ||
242 | |||
228 | struct beiscsi_endpoint { | 243 | struct beiscsi_endpoint { |
229 | struct beiscsi_hba *phba; | 244 | struct beiscsi_hba *phba; |
230 | struct beiscsi_sess *sess; | 245 | struct beiscsi_sess *sess; |