diff options
author | Jayamohan Kallickal <jayamohank@serverengines.com> | 2010-01-04 18:40:46 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-01-18 11:48:23 -0500 |
commit | 756d29c8c7ed8887ed7d752371ce2f6d12399267 (patch) | |
tree | eb70b756dc22a798538b306010647b72709a6206 /drivers/scsi/be2iscsi/be_main.c | |
parent | 51a462500fbed4a1e8110dc60a421a3f12b9580b (diff) |
[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: Jayamohan Kallickal <jayamohank@serverengines.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 6170548a5289..a6a2c6469677 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -442,7 +442,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) | |||
442 | if (phba->todo_mcc_cq) | 442 | if (phba->todo_mcc_cq) |
443 | queue_work(phba->wq, &phba->work_cqs); | 443 | queue_work(phba->wq, &phba->work_cqs); |
444 | 444 | ||
445 | if ((num_mcceq_processed) && (!num_ioeq_processed)) | 445 | if ((num_mcceq_processed) && (!num_ioeq_processed)) |
446 | hwi_ring_eq_db(phba, eq->id, 0, | 446 | hwi_ring_eq_db(phba, eq->id, 0, |
447 | (num_ioeq_processed + | 447 | (num_ioeq_processed + |
448 | num_mcceq_processed) , 1, 1); | 448 | num_mcceq_processed) , 1, 1); |
@@ -651,7 +651,6 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid) | |||
651 | pwrb_context->alloc_index = 0; | 651 | pwrb_context->alloc_index = 0; |
652 | else | 652 | else |
653 | pwrb_context->alloc_index++; | 653 | pwrb_context->alloc_index++; |
654 | |||
655 | pwrb_handle_tmp = pwrb_context->pwrb_handle_base[ | 654 | pwrb_handle_tmp = pwrb_context->pwrb_handle_base[ |
656 | pwrb_context->alloc_index]; | 655 | pwrb_context->alloc_index]; |
657 | pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index; | 656 | pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index; |
@@ -791,6 +790,7 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, | |||
791 | memcpy(task->sc->sense_buffer, sense, | 790 | memcpy(task->sc->sense_buffer, sense, |
792 | min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); | 791 | min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); |
793 | } | 792 | } |
793 | |||
794 | if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { | 794 | if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { |
795 | if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] | 795 | if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] |
796 | & SOL_RES_CNT_MASK) | 796 | & SOL_RES_CNT_MASK) |
@@ -1432,6 +1432,48 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | |||
1432 | hwi_post_async_buffers(phba, pasync_handle->is_header); | 1432 | hwi_post_async_buffers(phba, pasync_handle->is_header); |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) | ||
1436 | { | ||
1437 | struct be_queue_info *mcc_cq; | ||
1438 | struct be_mcc_compl *mcc_compl; | ||
1439 | unsigned int num_processed = 0; | ||
1440 | |||
1441 | mcc_cq = &phba->ctrl.mcc_obj.cq; | ||
1442 | mcc_compl = queue_tail_node(mcc_cq); | ||
1443 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); | ||
1444 | while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { | ||
1445 | |||
1446 | if (num_processed >= 32) { | ||
1447 | hwi_ring_cq_db(phba, mcc_cq->id, | ||
1448 | num_processed, 0, 0); | ||
1449 | num_processed = 0; | ||
1450 | } | ||
1451 | if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { | ||
1452 | /* Interpret flags as an async trailer */ | ||
1453 | if (is_link_state_evt(mcc_compl->flags)) | ||
1454 | /* Interpret compl as a async link evt */ | ||
1455 | beiscsi_async_link_state_process(phba, | ||
1456 | (struct be_async_event_link_state *) mcc_compl); | ||
1457 | else | ||
1458 | SE_DEBUG(DBG_LVL_1, | ||
1459 | " Unsupported Async Event, flags" | ||
1460 | " = 0x%08x \n", mcc_compl->flags); | ||
1461 | } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) { | ||
1462 | be_mcc_compl_process_isr(&phba->ctrl, mcc_compl); | ||
1463 | atomic_dec(&phba->ctrl.mcc_obj.q.used); | ||
1464 | } | ||
1465 | |||
1466 | mcc_compl->flags = 0; | ||
1467 | queue_tail_inc(mcc_cq); | ||
1468 | mcc_compl = queue_tail_node(mcc_cq); | ||
1469 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); | ||
1470 | num_processed++; | ||
1471 | } | ||
1472 | |||
1473 | if (num_processed > 0) | ||
1474 | hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); | ||
1475 | |||
1476 | } | ||
1435 | 1477 | ||
1436 | static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | 1478 | static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) |
1437 | { | 1479 | { |
@@ -1468,6 +1510,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
1468 | } | 1510 | } |
1469 | beiscsi_ep = ep->dd_data; | 1511 | beiscsi_ep = ep->dd_data; |
1470 | beiscsi_conn = beiscsi_ep->conn; | 1512 | beiscsi_conn = beiscsi_ep->conn; |
1513 | |||
1471 | if (num_processed >= 32) { | 1514 | if (num_processed >= 32) { |
1472 | hwi_ring_cq_db(phba, cq->id, | 1515 | hwi_ring_cq_db(phba, cq->id, |
1473 | num_processed, 0, 0); | 1516 | num_processed, 0, 0); |
@@ -1603,7 +1646,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
1603 | return tot_nump; | 1646 | return tot_nump; |
1604 | } | 1647 | } |
1605 | 1648 | ||
1606 | static void beiscsi_process_all_cqs(struct work_struct *work) | 1649 | void beiscsi_process_all_cqs(struct work_struct *work) |
1607 | { | 1650 | { |
1608 | unsigned long flags; | 1651 | unsigned long flags; |
1609 | struct hwi_controller *phwi_ctrlr; | 1652 | struct hwi_controller *phwi_ctrlr; |
@@ -1623,6 +1666,7 @@ static void beiscsi_process_all_cqs(struct work_struct *work) | |||
1623 | spin_lock_irqsave(&phba->isr_lock, flags); | 1666 | spin_lock_irqsave(&phba->isr_lock, flags); |
1624 | phba->todo_mcc_cq = 0; | 1667 | phba->todo_mcc_cq = 0; |
1625 | spin_unlock_irqrestore(&phba->isr_lock, flags); | 1668 | spin_unlock_irqrestore(&phba->isr_lock, flags); |
1669 | beiscsi_process_mcc_isr(phba); | ||
1626 | } | 1670 | } |
1627 | 1671 | ||
1628 | if (phba->todo_cq) { | 1672 | if (phba->todo_cq) { |
@@ -3160,6 +3204,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) | |||
3160 | struct be_queue_info *eq; | 3204 | struct be_queue_info *eq; |
3161 | struct be_eq_entry *eqe = NULL; | 3205 | struct be_eq_entry *eqe = NULL; |
3162 | int i, eq_msix; | 3206 | int i, eq_msix; |
3207 | unsigned int num_processed; | ||
3163 | 3208 | ||
3164 | phwi_ctrlr = phba->phwi_ctrlr; | 3209 | phwi_ctrlr = phba->phwi_ctrlr; |
3165 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3210 | phwi_context = phwi_ctrlr->phwi_ctxt; |
@@ -3171,13 +3216,17 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) | |||
3171 | for (i = 0; i < (phba->num_cpus + eq_msix); i++) { | 3216 | for (i = 0; i < (phba->num_cpus + eq_msix); i++) { |
3172 | eq = &phwi_context->be_eq[i].q; | 3217 | eq = &phwi_context->be_eq[i].q; |
3173 | eqe = queue_tail_node(eq); | 3218 | eqe = queue_tail_node(eq); |
3174 | 3219 | num_processed = 0; | |
3175 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 3220 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
3176 | & EQE_VALID_MASK) { | 3221 | & EQE_VALID_MASK) { |
3177 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 3222 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
3178 | queue_tail_inc(eq); | 3223 | queue_tail_inc(eq); |
3179 | eqe = queue_tail_node(eq); | 3224 | eqe = queue_tail_node(eq); |
3225 | num_processed++; | ||
3180 | } | 3226 | } |
3227 | |||
3228 | if (num_processed) | ||
3229 | hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1); | ||
3181 | } | 3230 | } |
3182 | } | 3231 | } |
3183 | 3232 | ||
@@ -3189,8 +3238,9 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) | |||
3189 | if (mgmt_status) | 3238 | if (mgmt_status) |
3190 | shost_printk(KERN_WARNING, phba->shost, | 3239 | shost_printk(KERN_WARNING, phba->shost, |
3191 | "mgmt_epfw_cleanup FAILED \n"); | 3240 | "mgmt_epfw_cleanup FAILED \n"); |
3192 | hwi_cleanup(phba); | 3241 | |
3193 | hwi_purge_eq(phba); | 3242 | hwi_purge_eq(phba); |
3243 | hwi_cleanup(phba); | ||
3194 | if (ring_mode) | 3244 | if (ring_mode) |
3195 | kfree(phba->sgl_hndl_array); | 3245 | kfree(phba->sgl_hndl_array); |
3196 | kfree(phba->io_sgl_hndl_base); | 3246 | kfree(phba->io_sgl_hndl_base); |
@@ -3519,6 +3569,7 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3519 | unsigned int doorbell = 0; | 3569 | unsigned int doorbell = 0; |
3520 | unsigned int i, cid; | 3570 | unsigned int i, cid; |
3521 | struct iscsi_task *aborted_task; | 3571 | struct iscsi_task *aborted_task; |
3572 | unsigned int tag; | ||
3522 | 3573 | ||
3523 | cid = beiscsi_conn->beiscsi_conn_cid; | 3574 | cid = beiscsi_conn->beiscsi_conn_cid; |
3524 | pwrb = io_task->pwrb_handle->pwrb; | 3575 | pwrb = io_task->pwrb_handle->pwrb; |
@@ -3550,7 +3601,6 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3550 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3601 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
3551 | else | 3602 | else |
3552 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1); | 3603 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1); |
3553 | |||
3554 | hwi_write_buffer(pwrb, task); | 3604 | hwi_write_buffer(pwrb, task); |
3555 | break; | 3605 | break; |
3556 | case ISCSI_OP_TEXT: | 3606 | case ISCSI_OP_TEXT: |
@@ -3579,9 +3629,18 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3579 | if (!aborted_io_task->scsi_cmnd) | 3629 | if (!aborted_io_task->scsi_cmnd) |
3580 | return 0; | 3630 | return 0; |
3581 | 3631 | ||
3582 | mgmt_invalidate_icds(phba, | 3632 | tag = mgmt_invalidate_icds(phba, |
3583 | aborted_io_task->psgl_handle->sgl_index, | 3633 | aborted_io_task->psgl_handle->sgl_index, |
3584 | cid); | 3634 | cid); |
3635 | if (!tag) { | ||
3636 | shost_printk(KERN_WARNING, phba->shost, | ||
3637 | "mgmt_invalidate_icds could not be" | ||
3638 | " submitted\n"); | ||
3639 | } else { | ||
3640 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
3641 | phba->ctrl.mcc_numtag[tag]); | ||
3642 | free_mcc_tag(&phba->ctrl, tag); | ||
3643 | } | ||
3585 | if (ring_mode) | 3644 | if (ring_mode) |
3586 | io_task->psgl_handle->type = INI_TMF_CMD; | 3645 | io_task->psgl_handle->type = INI_TMF_CMD; |
3587 | else | 3646 | else |
@@ -3656,7 +3715,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task) | |||
3656 | return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); | 3715 | return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); |
3657 | } | 3716 | } |
3658 | 3717 | ||
3659 | |||
3660 | static void beiscsi_remove(struct pci_dev *pcidev) | 3718 | static void beiscsi_remove(struct pci_dev *pcidev) |
3661 | { | 3719 | { |
3662 | struct beiscsi_hba *phba = NULL; | 3720 | struct beiscsi_hba *phba = NULL; |
@@ -3776,6 +3834,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3776 | goto free_port; | 3834 | goto free_port; |
3777 | } | 3835 | } |
3778 | 3836 | ||
3837 | for (i = 0; i < MAX_MCC_CMD ; i++) { | ||
3838 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
3839 | phba->ctrl.mcc_tag[i] = i + 1; | ||
3840 | phba->ctrl.mcc_numtag[i + 1] = 0; | ||
3841 | phba->ctrl.mcc_tag_available++; | ||
3842 | } | ||
3843 | |||
3844 | phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; | ||
3845 | |||
3779 | snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", | 3846 | snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", |
3780 | phba->shost->host_no); | 3847 | phba->shost->host_no); |
3781 | phba->wq = create_workqueue(phba->wq_name); | 3848 | phba->wq = create_workqueue(phba->wq_name); |