diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-04-02 20:02:55 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-04-02 20:03:08 +0200 |
commit | c9494727cf293ae2ec66af57547a3e79c724fec2 (patch) | |
tree | 44ae197b64fa7530ee695a90ad31326dda06f1e1 /drivers/scsi/be2iscsi | |
parent | 6427462bfa50f50dc6c088c07037264fcc73eca1 (diff) | |
parent | 42be79e37e264557f12860fa4cc84b4de3685954 (diff) |
Merge branch 'linus' into sched/core
Merge reason: update to latest upstream
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 7 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 201 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 11 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 14 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 8 |
6 files changed, 163 insertions, 82 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 67098578fba..cda6642c736 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -32,18 +32,11 @@ void be_mcc_notify(struct beiscsi_hba *phba) 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--; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 29a3aaf35f9..c3928cb8b04 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -482,7 +482,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *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", + "mgmt_open_connection Failed for cid=%d \n", beiscsi_ep->ep_cid); } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], @@ -701,7 +701,7 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) if (!tag) { SE_DEBUG(DBG_LVL_1, "mgmt_invalidate_connection Failed for cid=%d \n", - beiscsi_ep->ep_cid); + beiscsi_ep->ep_cid); } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7c22616ab14..fcfb29e02d8 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -58,6 +58,123 @@ static int beiscsi_slave_configure(struct scsi_device *sdev) return 0; } +static int beiscsi_eh_abort(struct scsi_cmnd *sc) +{ + struct iscsi_cls_session *cls_session; + struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; + struct beiscsi_io_task *aborted_io_task; + struct iscsi_conn *conn; + struct beiscsi_conn *beiscsi_conn; + struct beiscsi_hba *phba; + struct iscsi_session *session; + struct invalidate_command_table *inv_tbl; + unsigned int cid, tag, num_invalidate; + + cls_session = starget_to_session(scsi_target(sc->device)); + session = cls_session->dd_data; + + spin_lock_bh(&session->lock); + if (!aborted_task || !aborted_task->sc) { + /* we raced */ + spin_unlock_bh(&session->lock); + return SUCCESS; + } + + aborted_io_task = aborted_task->dd_data; + if (!aborted_io_task->scsi_cmnd) { + /* raced or invalid command */ + spin_unlock_bh(&session->lock); + return SUCCESS; + } + spin_unlock_bh(&session->lock); + conn = aborted_task->conn; + beiscsi_conn = conn->dd_data; + phba = beiscsi_conn->phba; + + /* invalidate iocb */ + cid = beiscsi_conn->beiscsi_conn_cid; + inv_tbl = phba->inv_tbl; + memset(inv_tbl, 0x0, sizeof(*inv_tbl)); + inv_tbl->cid = cid; + inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; + num_invalidate = 1; + tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); + if (!tag) { + shost_printk(KERN_WARNING, phba->shost, + "mgmt_invalidate_icds could not be" + " submitted\n"); + return FAILED; + } else { + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + free_mcc_tag(&phba->ctrl, tag); + } + + return iscsi_eh_abort(sc); +} + +static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) +{ + struct iscsi_task *abrt_task; + struct beiscsi_io_task *abrt_io_task; + struct iscsi_conn *conn; + struct beiscsi_conn *beiscsi_conn; + struct beiscsi_hba *phba; + struct iscsi_session *session; + struct iscsi_cls_session *cls_session; + struct invalidate_command_table *inv_tbl; + unsigned int cid, tag, i, num_invalidate; + int rc = FAILED; + + /* invalidate iocbs */ + cls_session = starget_to_session(scsi_target(sc->device)); + session = cls_session->dd_data; + spin_lock_bh(&session->lock); + if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) + goto unlock; + + conn = session->leadconn; + beiscsi_conn = conn->dd_data; + phba = beiscsi_conn->phba; + cid = beiscsi_conn->beiscsi_conn_cid; + inv_tbl = phba->inv_tbl; + memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); + num_invalidate = 0; + for (i = 0; i < conn->session->cmds_max; i++) { + abrt_task = conn->session->cmds[i]; + abrt_io_task = abrt_task->dd_data; + if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) + continue; + + if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) + continue; + + inv_tbl->cid = cid; + inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; + num_invalidate++; + inv_tbl++; + } + spin_unlock_bh(&session->lock); + inv_tbl = phba->inv_tbl; + + tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); + if (!tag) { + shost_printk(KERN_WARNING, phba->shost, + "mgmt_invalidate_icds could not be" + " submitted\n"); + return FAILED; + } else { + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + free_mcc_tag(&phba->ctrl, tag); + } + + return iscsi_eh_device_reset(sc); +unlock: + spin_unlock_bh(&session->lock); + return rc; +} + /*------------------- PCI Driver operations and data ----------------- */ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, @@ -74,12 +191,12 @@ static struct scsi_host_template beiscsi_sht = { .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", .proc_name = DRV_NAME, .queuecommand = iscsi_queuecommand, - .eh_abort_handler = iscsi_eh_abort, .change_queue_depth = iscsi_change_queue_depth, .slave_configure = beiscsi_slave_configure, .target_alloc = iscsi_target_alloc, - .eh_device_reset_handler = iscsi_eh_device_reset, - .eh_target_reset_handler = iscsi_eh_target_reset, + .eh_abort_handler = beiscsi_eh_abort, + .eh_device_reset_handler = beiscsi_eh_device_reset, + .eh_target_reset_handler = iscsi_eh_session_reset, .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, .can_queue = BE2_IO_DEPTH, .this_id = -1, @@ -242,7 +359,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) + BE2_TMFS + BE2_NOPOUT_REQ)); phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; - phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count;; + phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2; phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;; phba->params.num_sge_per_io = BE2_SGE; phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; @@ -946,14 +1063,18 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, case HWH_TYPE_IO: case HWH_TYPE_IO_RD: if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == - ISCSI_OP_NOOP_OUT) { + ISCSI_OP_NOOP_OUT) be_complete_nopin_resp(beiscsi_conn, task, psol); - } else + else be_complete_io(beiscsi_conn, task, psol); break; case HWH_TYPE_LOGOUT: - be_complete_logout(beiscsi_conn, task, psol); + if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) + be_complete_logout(beiscsi_conn, task, psol); + else + be_complete_tmf(beiscsi_conn, task, psol); + break; case HWH_TYPE_LOGIN: @@ -962,10 +1083,6 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, "- Solicited path \n"); break; - case HWH_TYPE_TMF: - be_complete_tmf(beiscsi_conn, task, psol); - break; - case HWH_TYPE_NOP: be_complete_nopin_resp(beiscsi_conn, task, psol); break; @@ -2052,7 +2169,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / ((sizeof(struct iscsi_wrb) * phba->params.wrbs_per_cxn)); - for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) { + for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { pwrb_context = &phwi_ctrlr->wrb_context[index]; if (num_cxn_wrb) { for (j = 0; j < phba->params.wrbs_per_cxn; j++) { @@ -3073,14 +3190,18 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); iowrite32(reg, addr); - for (i = 0; i <= phba->num_cpus; i++) { - eq = &phwi_context->be_eq[i].q; + if (!phba->msix_enabled) { + eq = &phwi_context->be_eq[0].q; SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); + } else { + for (i = 0; i <= phba->num_cpus; i++) { + eq = &phwi_context->be_eq[i].q; + SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); + hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); + } } - } else - shost_printk(KERN_WARNING, phba->shost, - "In hwi_enable_intr, Not Enabled \n"); + } return true; } @@ -3476,19 +3597,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, static int beiscsi_mtask(struct iscsi_task *task) { - struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data; + struct beiscsi_io_task *io_task = task->dd_data; struct iscsi_conn *conn = task->conn; struct beiscsi_conn *beiscsi_conn = conn->dd_data; struct beiscsi_hba *phba = beiscsi_conn->phba; - struct iscsi_session *session; struct iscsi_wrb *pwrb = NULL; - struct hwi_controller *phwi_ctrlr; - struct hwi_wrb_context *pwrb_context; - struct wrb_handle *pwrb_handle; unsigned int doorbell = 0; - unsigned int i, cid; - struct iscsi_task *aborted_task; - unsigned int tag; + unsigned int cid; cid = beiscsi_conn->beiscsi_conn_cid; pwrb = io_task->pwrb_handle->pwrb; @@ -3499,6 +3614,7 @@ static int beiscsi_mtask(struct iscsi_task *task) io_task->pwrb_handle->wrb_index); AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, io_task->psgl_handle->sgl_index); + switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { case ISCSI_OP_LOGIN: AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, @@ -3523,33 +3639,6 @@ static int beiscsi_mtask(struct iscsi_task *task) hwi_write_buffer(pwrb, task); break; case ISCSI_OP_SCSI_TMFUNC: - session = conn->session; - i = ((struct iscsi_tm *)task->hdr)->rtt; - phwi_ctrlr = phba->phwi_ctrlr; - pwrb_context = &phwi_ctrlr->wrb_context[cid - - phba->fw_config.iscsi_cid_start]; - pwrb_handle = pwrb_context->pwrb_handle_basestd[be32_to_cpu(i) - >> 16]; - aborted_task = pwrb_handle->pio_handle; - if (!aborted_task) - return 0; - - aborted_io_task = aborted_task->dd_data; - if (!aborted_io_task->scsi_cmnd) - return 0; - - 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); - } AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD); AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); @@ -3558,7 +3647,7 @@ static int beiscsi_mtask(struct iscsi_task *task) case ISCSI_OP_LOGOUT: AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - HWH_TYPE_LOGOUT); + HWH_TYPE_LOGOUT); hwi_write_buffer(pwrb, task); break; @@ -3584,17 +3673,12 @@ static int beiscsi_mtask(struct iscsi_task *task) static int beiscsi_task_xmit(struct iscsi_task *task) { - struct iscsi_conn *conn = task->conn; struct beiscsi_io_task *io_task = task->dd_data; struct scsi_cmnd *sc = task->sc; - struct beiscsi_conn *beiscsi_conn = conn->dd_data; struct scatterlist *sg; int num_sg; unsigned int writedir = 0, xferlen = 0; - SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t" - "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid, - task, conn, beiscsi_conn); if (!sc) return beiscsi_mtask(task); @@ -3699,7 +3783,6 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, " Failed in beiscsi_hba_alloc \n"); goto disable_pci; } - SE_DEBUG(DBG_LVL_8, " phba = %p \n", phba); switch (pcidev->device) { case BE_DEVICE_ID1: diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c53a80ab796..87ec21280a3 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -257,6 +257,11 @@ struct hba_parameters { unsigned int num_sge; }; +struct invalidate_command_table { + unsigned short icd; + unsigned short cid; +} __packed; + struct beiscsi_hba { struct hba_parameters params; struct hwi_controller *phwi_ctrlr; @@ -329,6 +334,8 @@ struct beiscsi_hba { struct work_struct work_cqs; /* The work being queued */ struct be_ctrl_info ctrl; unsigned int generation; + struct invalidate_command_table inv_tbl[128]; + }; struct beiscsi_session { @@ -491,8 +498,6 @@ struct hwi_async_entry { struct list_head data_busy_list; }; -#define BE_MIN_ASYNC_ENTRIES 128 - struct hwi_async_pdu_context { struct { struct be_bus_address pa_base; @@ -533,7 +538,7 @@ struct hwi_async_pdu_context { * This is a varying size list! Do not add anything * after this entry!! */ - struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES]; + struct hwi_async_entry async_entry[BE2_MAX_SESSIONS * 2]; }; #define PDUCQE_CODE_MASK 0x0000003F diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 317bcd042ce..72617b650a7 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -145,14 +145,15 @@ unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) } unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, - unsigned int icd, unsigned int cid) + struct invalidate_command_table *inv_tbl, + unsigned int num_invalidate, unsigned int cid) { struct be_dma_mem nonemb_cmd; struct be_ctrl_info *ctrl = &phba->ctrl; struct be_mcc_wrb *wrb; struct be_sge *sge; struct invalidate_commands_params_in *req; - unsigned int tag = 0; + unsigned int i, tag = 0; spin_lock(&ctrl->mbox_lock); tag = alloc_mcc_tag(phba); @@ -183,9 +184,12 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, sizeof(*req)); req->ref_handle = 0; req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; - req->icd_count = 0; - req->table[req->icd_count].icd = icd; - req->table[req->icd_count].cid = cid; + for (i = 0; i < num_invalidate; i++) { + req->table[i].icd = inv_tbl->icd; + req->table[i].cid = inv_tbl->cid; + req->icd_count++; + inv_tbl++; + } sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); sge->len = cpu_to_le32(nonemb_cmd.size); diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index ecead6a5aa5..3d316b82feb 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -94,7 +94,8 @@ unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, unsigned short cid, unsigned int upload_flag); unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, - unsigned int icd, unsigned int cid); + struct invalidate_command_table *inv_tbl, + unsigned int num_invalidate, unsigned int cid); struct iscsi_invalidate_connection_params_in { struct be_cmd_req_hdr hdr; @@ -116,11 +117,6 @@ union iscsi_invalidate_connection_params { struct iscsi_invalidate_connection_params_out response; } __packed; -struct invalidate_command_table { - unsigned short icd; - unsigned short cid; -} __packed; - struct invalidate_commands_params_in { struct be_cmd_req_hdr hdr; unsigned int ref_handle; |