aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi
diff options
context:
space:
mode:
authorJayamohan Kallickal <jayamohan.kallickal@emulex.com>2012-04-04 00:41:50 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-04-25 04:33:15 -0400
commitffce3e2e8ce4ff2ee96df0944ee5daa783d5b2d0 (patch)
treedc7513194f40ab3baee11adc30c22a735158dc70 /drivers/scsi/be2iscsi
parent2177199d5150cf61bf26badcb6901176cc13787b (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.h2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c76
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c70
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h15
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
412static struct scsi_transport_template *beiscsi_scsi_transport; 417static 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 */
4147static 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
4138static void beiscsi_quiesce(struct beiscsi_hba *phba) 4213static 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
4452static struct pci_driver beiscsi_pci_driver = { 4528static 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
24unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) 26unsigned 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
192unsigned 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
190int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) 258int 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);
102unsigned 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
102struct iscsi_invalidate_connection_params_in { 107struct 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
212struct 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
228struct beiscsi_endpoint { 243struct beiscsi_endpoint {
229 struct beiscsi_hba *phba; 244 struct beiscsi_hba *phba;
230 struct beiscsi_sess *sess; 245 struct beiscsi_sess *sess;