Commit ffce3e2e authored by Jayamohan Kallickal's avatar Jayamohan Kallickal Committed by James Bottomley

[SCSI] be2iscsi: Adding bsg interface for be2iscsi

Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 2177199d
...@@ -822,6 +822,8 @@ struct be_all_if_id { ...@@ -822,6 +822,8 @@ struct be_all_if_id {
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52
#define OPCODE_COMMON_WRITE_FLASH 96
#define OPCODE_COMMON_READ_FLASH 97
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
#define CMD_ISCSI_COMMAND_INVALIDATE 1 #define CMD_ISCSI_COMMAND_INVALIDATE 1
......
...@@ -28,8 +28,11 @@ ...@@ -28,8 +28,11 @@
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/iscsi_boot_sysfs.h> #include <linux/iscsi_boot_sysfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/bsg-lib.h>
#include <scsi/libiscsi.h> #include <scsi/libiscsi.h>
#include <scsi/scsi_bsg_iscsi.h>
#include <scsi/scsi_netlink.h>
#include <scsi/scsi_transport_iscsi.h> #include <scsi/scsi_transport_iscsi.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
...@@ -407,6 +410,8 @@ static struct scsi_host_template beiscsi_sht = { ...@@ -407,6 +410,8 @@ static struct scsi_host_template beiscsi_sht = {
.max_sectors = BEISCSI_MAX_SECTORS, .max_sectors = BEISCSI_MAX_SECTORS,
.cmd_per_lun = BEISCSI_CMD_PER_LUN, .cmd_per_lun = BEISCSI_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
}; };
static struct scsi_transport_template *beiscsi_scsi_transport; static struct scsi_transport_template *beiscsi_scsi_transport;
...@@ -4135,6 +4140,76 @@ static int beiscsi_task_xmit(struct iscsi_task *task) ...@@ -4135,6 +4140,76 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
} }
/**
* beiscsi_bsg_request - handle bsg request from ISCSI transport
* @job: job to handle
*/
static int beiscsi_bsg_request(struct bsg_job *job)
{
struct Scsi_Host *shost;
struct beiscsi_hba *phba;
struct iscsi_bsg_request *bsg_req = job->request;
int rc = -EINVAL;
unsigned int tag;
struct be_dma_mem nonemb_cmd;
struct be_cmd_resp_hdr *resp;
struct iscsi_bsg_reply *bsg_reply = job->reply;
unsigned short status, extd_status;
shost = iscsi_job_to_shost(job);
phba = iscsi_host_priv(shost);
switch (bsg_req->msgcode) {
case ISCSI_BSG_HST_VENDOR:
nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
job->request_payload.payload_len,
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for "
"beiscsi_bsg_request\n");
return -EIO;
}
tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job,
&nonemb_cmd);
if (!tag) {
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return -EAGAIN;
} else
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
phba->ctrl.mcc_numtag[tag]);
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
free_mcc_tag(&phba->ctrl, tag);
resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va;
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt,
nonemb_cmd.va, (resp->response_length
+ sizeof(*resp)));
bsg_reply->reply_payload_rcv_len = resp->response_length;
bsg_reply->result = status;
bsg_job_done(job, bsg_reply->result,
bsg_reply->reply_payload_rcv_len);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
if (status || extd_status) {
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
" status = %d extd_status = %d\n",
status, extd_status);
return -EIO;
}
break;
default:
SE_DEBUG(DBG_LVL_1, "Unsupported bsg command: 0x%x\n",
bsg_req->msgcode);
break;
}
return rc;
}
static void beiscsi_quiesce(struct beiscsi_hba *phba) static void beiscsi_quiesce(struct beiscsi_hba *phba)
{ {
struct hwi_controller *phwi_ctrlr; struct hwi_controller *phwi_ctrlr;
...@@ -4447,6 +4522,7 @@ struct iscsi_transport beiscsi_iscsi_transport = { ...@@ -4447,6 +4522,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.ep_poll = beiscsi_ep_poll, .ep_poll = beiscsi_ep_poll,
.ep_disconnect = beiscsi_ep_disconnect, .ep_disconnect = beiscsi_ep_disconnect,
.session_recovery_timedout = iscsi_session_recovery_timedout, .session_recovery_timedout = iscsi_session_recovery_timedout,
.bsg_request = beiscsi_bsg_request,
}; };
static struct pci_driver beiscsi_pci_driver = { static struct pci_driver beiscsi_pci_driver = {
......
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
* Costa Mesa, CA 92626 * Costa Mesa, CA 92626
*/ */
#include <linux/bsg-lib.h>
#include <scsi/scsi_transport_iscsi.h>
#include <scsi/scsi_bsg_iscsi.h>
#include "be_mgmt.h" #include "be_mgmt.h"
#include "be_iscsi.h" #include "be_iscsi.h"
#include <scsi/scsi_transport_iscsi.h>
unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
{ {
...@@ -187,6 +189,72 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, ...@@ -187,6 +189,72 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
return status; return status;
} }
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba,
struct bsg_job *job,
struct be_dma_mem *nonemb_cmd)
{
struct be_cmd_resp_hdr *resp;
struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
struct be_sge *mcc_sge = nonembedded_sgl(wrb);
unsigned int tag = 0;
struct iscsi_bsg_request *bsg_req = job->request;
struct be_bsg_vendor_cmd *req = nonemb_cmd->va;
unsigned short region, sector_size, sector, offset;
nonemb_cmd->size = job->request_payload.payload_len;
memset(nonemb_cmd->va, 0, nonemb_cmd->size);
resp = nonemb_cmd->va;
region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4];
req->region = region;
req->sector = sector;
req->offset = offset;
spin_lock(&ctrl->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
case BEISCSI_WRITE_FLASH:
offset = sector * sector_size + offset;
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_WRITE_FLASH, sizeof(*req));
sg_copy_to_buffer(job->request_payload.sg_list,
job->request_payload.sg_cnt,
nonemb_cmd->va + offset, job->request_len);
break;
case BEISCSI_READ_FLASH:
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_READ_FLASH, sizeof(*req));
break;
default:
shost_printk(KERN_WARNING, phba->shost,
"Unsupported cmd = 0x%x\n\n", bsg_req->rqst_data.
h_vendor.vendor_cmd[0]);
spin_unlock(&ctrl->mbox_lock);
return -ENOSYS;
}
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
}
be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false,
job->request_payload.sg_cnt);
mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
mcc_sge->len = cpu_to_le32(nonemb_cmd->size);
wrb->tag0 |= tag;
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
return tag;
}
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
{ {
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <scsi/scsi_bsg_iscsi.h>
#include "be_iscsi.h" #include "be_iscsi.h"
#include "be_main.h" #include "be_main.h"
...@@ -98,6 +99,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, ...@@ -98,6 +99,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl, struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid, unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd); struct be_dma_mem *nonemb_cmd);
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba,
struct bsg_job *job,
struct be_dma_mem *nonemb_cmd);
struct iscsi_invalidate_connection_params_in { struct iscsi_invalidate_connection_params_in {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
...@@ -204,6 +209,13 @@ struct be_mgmt_controller_attributes_resp { ...@@ -204,6 +209,13 @@ struct be_mgmt_controller_attributes_resp {
struct mgmt_controller_attributes params; struct mgmt_controller_attributes params;
} __packed; } __packed;
struct be_bsg_vendor_cmd {
struct be_cmd_req_hdr hdr;
unsigned short region;
unsigned short offset;
unsigned short sector;
} __packed;
/* configuration management */ /* configuration management */
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
...@@ -225,6 +237,9 @@ struct be_mgmt_controller_attributes_resp { ...@@ -225,6 +237,9 @@ struct be_mgmt_controller_attributes_resp {
bus_address.u.a32.address_hi; \ bus_address.u.a32.address_hi; \
} }
#define BEISCSI_WRITE_FLASH 0
#define BEISCSI_READ_FLASH 1
struct beiscsi_endpoint { struct beiscsi_endpoint {
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
struct beiscsi_sess *sess; struct beiscsi_sess *sess;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment