[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>
This commit is contained in:
parent
2177199d51
commit
ffce3e2e8c
|
@ -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 @@
|
||||||
#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 = {
|
||||||
.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)
|
||||||
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 = {
|
||||||
.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 @@
|
||||||
* 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,
|
||||||
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 @@
|
||||||
|
|
||||||
#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,
|
||||||
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 {
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue