Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[SCSI] be2iscsi: Adding bsg interface for be2iscsi

parent 2177199d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+76 −0
Original line number Diff line number Diff line
@@ -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 = {
+69 −1
Original line number Diff line number Diff line
@@ -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;
+15 −0
Original line number Diff line number Diff line
@@ -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;