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

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

[SCSI] be2iscsi: Enable async mode for mcc rings



This patches enables async mode for mcc rings so that
multiple requests can be queued.

Signed-off-by: default avatarJayamohan Kallickal <jayamohank@serverengines.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 51a46250
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define FW_VER_LEN	32
#define MCC_Q_LEN	128
#define MCC_CQ_LEN	256
#define MAX_MCC_CMD	16

struct be_dma_mem {
	void *va;
@@ -57,6 +58,11 @@ static inline void *queue_head_node(struct be_queue_info *q)
	return q->dma_mem.va + q->head * q->entry_size;
}

static inline void *queue_get_wrb(struct be_queue_info *q, unsigned int wrb_num)
{
	return q->dma_mem.va + wrb_num * q->entry_size;
}

static inline void *queue_tail_node(struct be_queue_info *q)
{
	return q->dma_mem.va + q->tail * q->entry_size;
@@ -104,15 +110,19 @@ struct be_ctrl_info {
	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
	spinlock_t mcc_cq_lock;

	/* MCC Async callback */
	void (*async_cb) (void *adapter, bool link_up);
	void *adapter_ctxt;
	wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1];
	unsigned int mcc_tag[MAX_MCC_CMD];
	unsigned int mcc_numtag[MAX_MCC_CMD + 1];
	unsigned short mcc_alloc_index;
	unsigned short mcc_free_index;
	unsigned int mcc_tag_available;
};

#include "be_cmds.h"

#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
#define mcc_timeout		120000 /* 5s timeout */

/* Returns number of pages spanned by the data starting at the given addr */
#define PAGES_4K_SPANNED(_address, size) 				\
+73 −9
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include "be_mgmt.h"
#include "be_main.h"

static void be_mcc_notify(struct beiscsi_hba *phba)
void be_mcc_notify(struct beiscsi_hba *phba)
{
	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
	u32 val = 0;
@@ -29,6 +29,52 @@ static void be_mcc_notify(struct beiscsi_hba *phba)
	iowrite32(val, phba->db_va + DB_MCCQ_OFFSET);
}

unsigned int alloc_mcc_tag(struct beiscsi_hba *phba)
{
	unsigned int tag = 0;
	unsigned int num = 0;

mcc_tag_rdy:
	if (phba->ctrl.mcc_tag_available) {
		tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index];
		phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0;
		phba->ctrl.mcc_numtag[tag] = 0;
	} else {
		udelay(100);
		num++;
		if (num < mcc_timeout)
			goto mcc_tag_rdy;
	}
	if (tag) {
		phba->ctrl.mcc_tag_available--;
		if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1))
			phba->ctrl.mcc_alloc_index = 0;
		else
			phba->ctrl.mcc_alloc_index++;
	}
	return tag;
}

void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag)
{
	spin_lock(&ctrl->mbox_lock);
	tag = tag & 0x000000FF;
	ctrl->mcc_tag[ctrl->mcc_free_index] = tag;
	if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1))
		ctrl->mcc_free_index = 0;
	else
		ctrl->mcc_free_index++;
	ctrl->mcc_tag_available++;
	spin_unlock(&ctrl->mbox_lock);
}

bool is_link_state_evt(u32 trailer)
{
	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
		  ASYNC_TRAILER_EVENT_CODE_MASK) ==
		  ASYNC_EVENT_CODE_LINK_STATE);
}

static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
{
	if (compl->flags != 0) {
@@ -64,12 +110,30 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
	return 0;
}


static inline bool is_link_state_evt(u32 trailer)
int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
				    struct be_mcc_compl *compl)
{
	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
		  ASYNC_TRAILER_EVENT_CODE_MASK) ==
		  ASYNC_EVENT_CODE_LINK_STATE);
	u16 compl_status, extd_status;
	unsigned short tag;

	be_dws_le_to_cpu(compl, 4);

	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
					CQE_STATUS_COMPL_MASK;
	/* The ctrl.mcc_numtag[tag] is filled with
	 * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status,
	 * [7:0] = compl_status
	 */
	tag = (compl->tag0 & 0x000000FF);
	extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
					CQE_STATUS_EXTD_MASK;

	ctrl->mcc_numtag[tag]  = 0x80000000;
	ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000);
	ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8;
	ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF);
	wake_up_interruptible(&ctrl->mcc_wait[tag]);
	return 0;
}

static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba)
@@ -89,7 +153,7 @@ static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
}

static void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
		struct be_async_event_link_state *evt)
{
	switch (evt->port_link_status) {
@@ -162,7 +226,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
/* Wait till no more pending mcc requests are present */
static int be_mcc_wait_compl(struct beiscsi_hba *phba)
{
#define mcc_timeout		120000 /* 5s timeout */
	int i, status;
	for (i = 0; i < mcc_timeout; i++) {
		status = beiscsi_process_mcc(phba);
@@ -372,9 +435,10 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba)

	BUG_ON(atomic_read(&mccq->used) >= mccq->len);
	wrb = queue_head_node(mccq);
	memset(wrb, 0, sizeof(*wrb));
	wrb->tag0 = (mccq->head & 0x000000FF) << 16;
	queue_head_inc(mccq);
	atomic_inc(&mccq->used);
	memset(wrb, 0, sizeof(*wrb));
	return wrb;
}

+10 −2
Original line number Diff line number Diff line
@@ -425,14 +425,20 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
int be_poll_mcc(struct be_ctrl_info *ctrl);
unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
				      struct beiscsi_hba *phba);
int be_cmd_get_mac_addr(struct beiscsi_hba *phba, u8 *mac_addr);

unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba);
void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
/*ISCSI Functuions */
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);

struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba);
int be_mcc_notify_wait(struct beiscsi_hba *phba);
void be_mcc_notify(struct beiscsi_hba *phba);
unsigned int alloc_mcc_tag(struct beiscsi_hba *phba);
void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
		struct be_async_event_link_state *evt);
int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
				    struct be_mcc_compl *compl);

int be_mbox_notify(struct be_ctrl_info *ctrl);

@@ -448,6 +454,8 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
		       struct be_queue_info *wrbq);

bool is_link_state_evt(u32 trailer);

struct be_default_pdu_context {
	u32 dw[4];
} __packed;
+88 −12
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
	struct iscsi_session *sess = cls_session->dd_data;
	struct beiscsi_session *beiscsi_sess = sess->dd_data;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_session_destroy\n");
	pci_pool_destroy(beiscsi_sess->bhs_pool);
	iscsi_session_teardown(cls_session);
}
@@ -224,6 +225,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
	int len = 0;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param);
	beiscsi_ep = beiscsi_conn->ep;
	if (!beiscsi_ep) {
		SE_DEBUG(DBG_LVL_1,
@@ -254,6 +256,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
	struct iscsi_session *session = conn->session;
	int ret;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_set_param, param= %d\n", param);
	ret = iscsi_set_param(cls_conn, param, buf, buflen);
	if (ret)
		return ret;
@@ -293,12 +296,41 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
			   enum iscsi_host_param param, char *buf)
{
	struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
	struct be_cmd_resp_get_mac_addr *resp;
	struct be_mcc_wrb *wrb;
	unsigned int tag, wrb_num;
	int len = 0;
	unsigned short status, extd_status;
	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);
	switch (param) {
	case ISCSI_HOST_PARAM_HWADDRESS:
		be_cmd_get_mac_addr(phba, phba->mac_address);
		len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
		tag = be_cmd_get_mac_addr(phba);
		if (!tag) {
			SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed \n");
			return -1;
		} else
			wait_event_interruptible(phba->ctrl.mcc_wait[tag],
						 phba->ctrl.mcc_numtag[tag]);

		wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
		extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
		status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
		if (status || extd_status) {
			SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
					    " status = %d extd_status = %d \n",
					    status, extd_status);
			free_mcc_tag(&phba->ctrl, tag);
			return -1;
		} else {
			wrb = queue_get_wrb(mccq, wrb_num);
			free_mcc_tag(&phba->ctrl, tag);
			resp = embedded_payload(wrb);
			memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
			len = sysfs_format_mac(buf, phba->mac_address,
					       ETH_ALEN);
		}
		break;
	default:
		return iscsi_host_get_param(shost, param, buf);
@@ -378,6 +410,7 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
	struct beiscsi_endpoint *beiscsi_ep;
	struct beiscsi_offload_params params;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_start\n");
	memset(&params, 0, sizeof(struct beiscsi_offload_params));
	beiscsi_ep = beiscsi_conn->ep;
	if (!beiscsi_ep)
@@ -422,8 +455,14 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
{
	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
	struct beiscsi_hba *phba = beiscsi_ep->phba;
	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
	struct be_mcc_wrb *wrb;
	struct tcp_connect_and_offload_out *ptcpcnct_out;
	unsigned short status, extd_status;
	unsigned int tag, wrb_num;
	int ret = -1;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n");
	beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
	if (beiscsi_ep->ep_cid == 0xFFFF) {
		SE_DEBUG(DBG_LVL_1, "No free cid available\n");
@@ -440,7 +479,35 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
	}

	beiscsi_ep->cid_vld = 0;
	return mgmt_open_connection(phba, dst_addr, beiscsi_ep);
	tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep);
	if (!tag) {
		SE_DEBUG(DBG_LVL_1,
			 "mgmt_invalidate_connection Failed for cid=%d \n",
			 beiscsi_ep->ep_cid);
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
					 phba->ctrl.mcc_numtag[tag]);
	}
	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
	if (status || extd_status) {
		SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
				    " status = %d extd_status = %d \n",
				    status, extd_status);
		free_mcc_tag(&phba->ctrl, tag);
		return -1;
	} else {
		wrb = queue_get_wrb(mccq, wrb_num);
		free_mcc_tag(&phba->ctrl, tag);

		ptcpcnct_out = 	embedded_payload(wrb);
		beiscsi_ep = ep->dd_data;
		beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
		beiscsi_ep->cid_vld = 1;
		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
	}
	return 0;
}

/**
@@ -509,7 +576,6 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
	beiscsi_ep = ep->dd_data;
	beiscsi_ep->phba = phba;
	beiscsi_ep->openiscsi_ep = ep;

	if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
		SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n");
		ret = -ENOMEM;
@@ -549,16 +615,19 @@ int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
{
	int ret = 0;
	unsigned int tag;
	struct beiscsi_hba *phba = beiscsi_ep->phba;

	if (MGMT_STATUS_SUCCESS !=
	    mgmt_upload_connection(phba, beiscsi_ep->ep_cid,
		flag)) {
	tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
	if (!tag) {
		SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
			 beiscsi_ep->ep_cid);
		ret = -1;
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
					 phba->ctrl.mcc_numtag[tag]);
		free_mcc_tag(&phba->ctrl, tag);
	}

	return ret;
}

@@ -576,6 +645,8 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)

	beiscsi_ep = ep->dd_data;
	phba = beiscsi_ep->phba;
	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n",
			     beiscsi_ep->ep_cid);

	if (beiscsi_ep->conn) {
		beiscsi_conn = beiscsi_ep->conn;
@@ -614,22 +685,27 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
	struct iscsi_session *session = conn->session;
	struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
	struct beiscsi_hba *phba = iscsi_host_priv(shost);
	unsigned int status;
	unsigned int tag;
	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
	beiscsi_ep = beiscsi_conn->ep;
	if (!beiscsi_ep) {
		SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
		return;
	}
	status = mgmt_invalidate_connection(phba, beiscsi_ep,
	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop  ep_cid = %d\n",
			     beiscsi_ep->ep_cid);
	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
					    beiscsi_ep->ep_cid, 1,
					    savecfg_flag);
	if (status != MGMT_STATUS_SUCCESS) {
	if (!tag) {
		SE_DEBUG(DBG_LVL_1,
			 "mgmt_invalidate_connection Failed for cid=%d \n",
			 beiscsi_ep->ep_cid);
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
					 phba->ctrl.mcc_numtag[tag]);
		free_mcc_tag(&phba->ctrl, tag);
	}
	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
	beiscsi_free_ep(beiscsi_ep);
+75 −8
Original line number Diff line number Diff line
@@ -651,7 +651,6 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
			pwrb_context->alloc_index = 0;
		else
			pwrb_context->alloc_index++;

		pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
						pwrb_context->alloc_index];
		pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
@@ -791,6 +790,7 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
		memcpy(task->sc->sense_buffer, sense,
		       min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
	}

	if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
		if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
							& SOL_RES_CNT_MASK)
@@ -1432,6 +1432,48 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
	hwi_post_async_buffers(phba, pasync_handle->is_header);
}

static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
{
	struct be_queue_info *mcc_cq;
	struct  be_mcc_compl *mcc_compl;
	unsigned int num_processed = 0;

	mcc_cq = &phba->ctrl.mcc_obj.cq;
	mcc_compl = queue_tail_node(mcc_cq);
	mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
	while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) {

		if (num_processed >= 32) {
			hwi_ring_cq_db(phba, mcc_cq->id,
					num_processed, 0, 0);
			num_processed = 0;
		}
		if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) {
			/* Interpret flags as an async trailer */
			if (is_link_state_evt(mcc_compl->flags))
				/* Interpret compl as a async link evt */
				beiscsi_async_link_state_process(phba,
				(struct be_async_event_link_state *) mcc_compl);
			else
				SE_DEBUG(DBG_LVL_1,
					" Unsupported Async Event, flags"
					" = 0x%08x \n", mcc_compl->flags);
		} else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
			be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
			atomic_dec(&phba->ctrl.mcc_obj.q.used);
		}

		mcc_compl->flags = 0;
		queue_tail_inc(mcc_cq);
		mcc_compl = queue_tail_node(mcc_cq);
		mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
		num_processed++;
	}

	if (num_processed > 0)
		hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0);

}

static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
{
@@ -1468,6 +1510,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
		}
		beiscsi_ep = ep->dd_data;
		beiscsi_conn = beiscsi_ep->conn;

		if (num_processed >= 32) {
			hwi_ring_cq_db(phba, cq->id,
					num_processed, 0, 0);
@@ -1603,7 +1646,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
	return tot_nump;
}

static void beiscsi_process_all_cqs(struct work_struct *work)
void beiscsi_process_all_cqs(struct work_struct *work)
{
	unsigned long flags;
	struct hwi_controller *phwi_ctrlr;
@@ -1623,6 +1666,7 @@ static void beiscsi_process_all_cqs(struct work_struct *work)
		spin_lock_irqsave(&phba->isr_lock, flags);
		phba->todo_mcc_cq = 0;
		spin_unlock_irqrestore(&phba->isr_lock, flags);
		beiscsi_process_mcc_isr(phba);
	}

	if (phba->todo_cq) {
@@ -3160,6 +3204,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
	struct be_queue_info *eq;
	struct be_eq_entry *eqe = NULL;
	int i, eq_msix;
	unsigned int num_processed;

	phwi_ctrlr = phba->phwi_ctrlr;
	phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -3171,13 +3216,17 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
	for (i = 0; i < (phba->num_cpus + eq_msix); i++) {
		eq = &phwi_context->be_eq[i].q;
		eqe = queue_tail_node(eq);

		num_processed = 0;
		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
					& EQE_VALID_MASK) {
			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
			queue_tail_inc(eq);
			eqe = queue_tail_node(eq);
			num_processed++;
		}

		if (num_processed)
			hwi_ring_eq_db(phba, eq->id, 1,	num_processed, 1, 1);
	}
}

@@ -3189,8 +3238,9 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
	if (mgmt_status)
		shost_printk(KERN_WARNING, phba->shost,
			     "mgmt_epfw_cleanup FAILED \n");
	hwi_cleanup(phba);

	hwi_purge_eq(phba);
	hwi_cleanup(phba);
	if (ring_mode)
		kfree(phba->sgl_hndl_array);
	kfree(phba->io_sgl_hndl_base);
@@ -3519,6 +3569,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
	unsigned int doorbell = 0;
	unsigned int i, cid;
	struct iscsi_task *aborted_task;
	unsigned int tag;

	cid = beiscsi_conn->beiscsi_conn_cid;
	pwrb = io_task->pwrb_handle->pwrb;
@@ -3550,7 +3601,6 @@ static int beiscsi_mtask(struct iscsi_task *task)
			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
		else
			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);

		hwi_write_buffer(pwrb, task);
		break;
	case ISCSI_OP_TEXT:
@@ -3579,9 +3629,18 @@ static int beiscsi_mtask(struct iscsi_task *task)
		if (!aborted_io_task->scsi_cmnd)
			return 0;

		mgmt_invalidate_icds(phba,
		tag = mgmt_invalidate_icds(phba,
				     aborted_io_task->psgl_handle->sgl_index,
				     cid);
		if (!tag) {
			shost_printk(KERN_WARNING, phba->shost,
				     "mgmt_invalidate_icds could not be"
				     " submitted\n");
		} else {
			wait_event_interruptible(phba->ctrl.mcc_wait[tag],
						 phba->ctrl.mcc_numtag[tag]);
			free_mcc_tag(&phba->ctrl, tag);
		}
		if (ring_mode)
			io_task->psgl_handle->type = INI_TMF_CMD;
		else
@@ -3656,7 +3715,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
	return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
}


static void beiscsi_remove(struct pci_dev *pcidev)
{
	struct beiscsi_hba *phba = NULL;
@@ -3776,6 +3834,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
		goto free_port;
	}

	for (i = 0; i < MAX_MCC_CMD ; i++) {
		init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);
		phba->ctrl.mcc_tag[i] = i + 1;
		phba->ctrl.mcc_numtag[i + 1] = 0;
		phba->ctrl.mcc_tag_available++;
	}

	phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;

	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
		 phba->shost->host_no);
	phba->wq = create_workqueue(phba->wq_name);
Loading