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 {
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
#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 --- */
#define CMD_ISCSI_COMMAND_INVALIDATE 1
......
......@@ -28,8 +28,11 @@
#include <linux/semaphore.h>
#include <linux/iscsi_boot_sysfs.h>
#include <linux/module.h>
#include <linux/bsg-lib.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.h>
#include <scsi/scsi_cmnd.h>
......@@ -407,6 +410,8 @@ static struct scsi_host_template beiscsi_sht = {
.max_sectors = BEISCSI_MAX_SECTORS,
.cmd_per_lun = BEISCSI_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
};
static struct scsi_transport_template *beiscsi_scsi_transport;
......@@ -4135,6 +4140,76 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
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)
{
struct hwi_controller *phwi_ctrlr;
......@@ -4447,6 +4522,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.ep_poll = beiscsi_ep_poll,
.ep_disconnect = beiscsi_ep_disconnect,
.session_recovery_timedout = iscsi_session_recovery_timedout,
.bsg_request = beiscsi_bsg_request,
};
static struct pci_driver beiscsi_pci_driver = {
......
......@@ -17,9 +17,11 @@
* 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_iscsi.h"
#include <scsi/scsi_transport_iscsi.h>
unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
{
......@@ -187,6 +189,72 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
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)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
......
......@@ -22,6 +22,7 @@
#include <linux/types.h>
#include <linux/list.h>
#include <scsi/scsi_bsg_iscsi.h>
#include "be_iscsi.h"
#include "be_main.h"
......@@ -98,6 +99,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid,
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 be_cmd_req_hdr hdr;
......@@ -204,6 +209,13 @@ struct be_mgmt_controller_attributes_resp {
struct mgmt_controller_attributes params;
} __packed;
struct be_bsg_vendor_cmd {
struct be_cmd_req_hdr hdr;
unsigned short region;
unsigned short offset;
unsigned short sector;
} __packed;
/* configuration management */
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
......@@ -225,6 +237,9 @@ struct be_mgmt_controller_attributes_resp {
bus_address.u.a32.address_hi; \
}
#define BEISCSI_WRITE_FLASH 0
#define BEISCSI_READ_FLASH 1
struct beiscsi_endpoint {
struct beiscsi_hba *phba;
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