diff options
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 202 |
1 files changed, 143 insertions, 59 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7c22616ab141..dd5b105f8f47 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
@@ -58,6 +59,123 @@ static int beiscsi_slave_configure(struct scsi_device *sdev) | |||
58 | return 0; | 59 | return 0; |
59 | } | 60 | } |
60 | 61 | ||
62 | static int beiscsi_eh_abort(struct scsi_cmnd *sc) | ||
63 | { | ||
64 | struct iscsi_cls_session *cls_session; | ||
65 | struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; | ||
66 | struct beiscsi_io_task *aborted_io_task; | ||
67 | struct iscsi_conn *conn; | ||
68 | struct beiscsi_conn *beiscsi_conn; | ||
69 | struct beiscsi_hba *phba; | ||
70 | struct iscsi_session *session; | ||
71 | struct invalidate_command_table *inv_tbl; | ||
72 | unsigned int cid, tag, num_invalidate; | ||
73 | |||
74 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
75 | session = cls_session->dd_data; | ||
76 | |||
77 | spin_lock_bh(&session->lock); | ||
78 | if (!aborted_task || !aborted_task->sc) { | ||
79 | /* we raced */ | ||
80 | spin_unlock_bh(&session->lock); | ||
81 | return SUCCESS; | ||
82 | } | ||
83 | |||
84 | aborted_io_task = aborted_task->dd_data; | ||
85 | if (!aborted_io_task->scsi_cmnd) { | ||
86 | /* raced or invalid command */ | ||
87 | spin_unlock_bh(&session->lock); | ||
88 | return SUCCESS; | ||
89 | } | ||
90 | spin_unlock_bh(&session->lock); | ||
91 | conn = aborted_task->conn; | ||
92 | beiscsi_conn = conn->dd_data; | ||
93 | phba = beiscsi_conn->phba; | ||
94 | |||
95 | /* invalidate iocb */ | ||
96 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
97 | inv_tbl = phba->inv_tbl; | ||
98 | memset(inv_tbl, 0x0, sizeof(*inv_tbl)); | ||
99 | inv_tbl->cid = cid; | ||
100 | inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; | ||
101 | num_invalidate = 1; | ||
102 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
103 | if (!tag) { | ||
104 | shost_printk(KERN_WARNING, phba->shost, | ||
105 | "mgmt_invalidate_icds could not be" | ||
106 | " submitted\n"); | ||
107 | return FAILED; | ||
108 | } else { | ||
109 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
110 | phba->ctrl.mcc_numtag[tag]); | ||
111 | free_mcc_tag(&phba->ctrl, tag); | ||
112 | } | ||
113 | |||
114 | return iscsi_eh_abort(sc); | ||
115 | } | ||
116 | |||
117 | static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) | ||
118 | { | ||
119 | struct iscsi_task *abrt_task; | ||
120 | struct beiscsi_io_task *abrt_io_task; | ||
121 | struct iscsi_conn *conn; | ||
122 | struct beiscsi_conn *beiscsi_conn; | ||
123 | struct beiscsi_hba *phba; | ||
124 | struct iscsi_session *session; | ||
125 | struct iscsi_cls_session *cls_session; | ||
126 | struct invalidate_command_table *inv_tbl; | ||
127 | unsigned int cid, tag, i, num_invalidate; | ||
128 | int rc = FAILED; | ||
129 | |||
130 | /* invalidate iocbs */ | ||
131 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
132 | session = cls_session->dd_data; | ||
133 | spin_lock_bh(&session->lock); | ||
134 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) | ||
135 | goto unlock; | ||
136 | |||
137 | conn = session->leadconn; | ||
138 | beiscsi_conn = conn->dd_data; | ||
139 | phba = beiscsi_conn->phba; | ||
140 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
141 | inv_tbl = phba->inv_tbl; | ||
142 | memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); | ||
143 | num_invalidate = 0; | ||
144 | for (i = 0; i < conn->session->cmds_max; i++) { | ||
145 | abrt_task = conn->session->cmds[i]; | ||
146 | abrt_io_task = abrt_task->dd_data; | ||
147 | if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) | ||
148 | continue; | ||
149 | |||
150 | if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) | ||
151 | continue; | ||
152 | |||
153 | inv_tbl->cid = cid; | ||
154 | inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; | ||
155 | num_invalidate++; | ||
156 | inv_tbl++; | ||
157 | } | ||
158 | spin_unlock_bh(&session->lock); | ||
159 | inv_tbl = phba->inv_tbl; | ||
160 | |||
161 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
162 | if (!tag) { | ||
163 | shost_printk(KERN_WARNING, phba->shost, | ||
164 | "mgmt_invalidate_icds could not be" | ||
165 | " submitted\n"); | ||
166 | return FAILED; | ||
167 | } else { | ||
168 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
169 | phba->ctrl.mcc_numtag[tag]); | ||
170 | free_mcc_tag(&phba->ctrl, tag); | ||
171 | } | ||
172 | |||
173 | return iscsi_eh_device_reset(sc); | ||
174 | unlock: | ||
175 | spin_unlock_bh(&session->lock); | ||
176 | return rc; | ||
177 | } | ||
178 | |||
61 | /*------------------- PCI Driver operations and data ----------------- */ | 179 | /*------------------- PCI Driver operations and data ----------------- */ |
62 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 180 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
63 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 181 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
@@ -74,12 +192,12 @@ static struct scsi_host_template beiscsi_sht = { | |||
74 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", | 192 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", |
75 | .proc_name = DRV_NAME, | 193 | .proc_name = DRV_NAME, |
76 | .queuecommand = iscsi_queuecommand, | 194 | .queuecommand = iscsi_queuecommand, |
77 | .eh_abort_handler = iscsi_eh_abort, | ||
78 | .change_queue_depth = iscsi_change_queue_depth, | 195 | .change_queue_depth = iscsi_change_queue_depth, |
79 | .slave_configure = beiscsi_slave_configure, | 196 | .slave_configure = beiscsi_slave_configure, |
80 | .target_alloc = iscsi_target_alloc, | 197 | .target_alloc = iscsi_target_alloc, |
81 | .eh_device_reset_handler = iscsi_eh_device_reset, | 198 | .eh_abort_handler = beiscsi_eh_abort, |
82 | .eh_target_reset_handler = iscsi_eh_target_reset, | 199 | .eh_device_reset_handler = beiscsi_eh_device_reset, |
200 | .eh_target_reset_handler = iscsi_eh_session_reset, | ||
83 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, | 201 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, |
84 | .can_queue = BE2_IO_DEPTH, | 202 | .can_queue = BE2_IO_DEPTH, |
85 | .this_id = -1, | 203 | .this_id = -1, |
@@ -242,7 +360,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) | |||
242 | + BE2_TMFS | 360 | + BE2_TMFS |
243 | + BE2_NOPOUT_REQ)); | 361 | + BE2_NOPOUT_REQ)); |
244 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; | 362 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; |
245 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count;; | 363 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2; |
246 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;; | 364 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;; |
247 | phba->params.num_sge_per_io = BE2_SGE; | 365 | phba->params.num_sge_per_io = BE2_SGE; |
248 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; | 366 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; |
@@ -946,14 +1064,18 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | |||
946 | case HWH_TYPE_IO: | 1064 | case HWH_TYPE_IO: |
947 | case HWH_TYPE_IO_RD: | 1065 | case HWH_TYPE_IO_RD: |
948 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == | 1066 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == |
949 | ISCSI_OP_NOOP_OUT) { | 1067 | ISCSI_OP_NOOP_OUT) |
950 | be_complete_nopin_resp(beiscsi_conn, task, psol); | 1068 | be_complete_nopin_resp(beiscsi_conn, task, psol); |
951 | } else | 1069 | else |
952 | be_complete_io(beiscsi_conn, task, psol); | 1070 | be_complete_io(beiscsi_conn, task, psol); |
953 | break; | 1071 | break; |
954 | 1072 | ||
955 | case HWH_TYPE_LOGOUT: | 1073 | case HWH_TYPE_LOGOUT: |
956 | be_complete_logout(beiscsi_conn, task, psol); | 1074 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) |
1075 | be_complete_logout(beiscsi_conn, task, psol); | ||
1076 | else | ||
1077 | be_complete_tmf(beiscsi_conn, task, psol); | ||
1078 | |||
957 | break; | 1079 | break; |
958 | 1080 | ||
959 | case HWH_TYPE_LOGIN: | 1081 | case HWH_TYPE_LOGIN: |
@@ -962,10 +1084,6 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | |||
962 | "- Solicited path \n"); | 1084 | "- Solicited path \n"); |
963 | break; | 1085 | break; |
964 | 1086 | ||
965 | case HWH_TYPE_TMF: | ||
966 | be_complete_tmf(beiscsi_conn, task, psol); | ||
967 | break; | ||
968 | |||
969 | case HWH_TYPE_NOP: | 1087 | case HWH_TYPE_NOP: |
970 | be_complete_nopin_resp(beiscsi_conn, task, psol); | 1088 | be_complete_nopin_resp(beiscsi_conn, task, psol); |
971 | break; | 1089 | break; |
@@ -2052,7 +2170,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
2052 | num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / | 2170 | num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / |
2053 | ((sizeof(struct iscsi_wrb) * | 2171 | ((sizeof(struct iscsi_wrb) * |
2054 | phba->params.wrbs_per_cxn)); | 2172 | phba->params.wrbs_per_cxn)); |
2055 | for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) { | 2173 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { |
2056 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 2174 | pwrb_context = &phwi_ctrlr->wrb_context[index]; |
2057 | if (num_cxn_wrb) { | 2175 | if (num_cxn_wrb) { |
2058 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | 2176 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { |
@@ -3073,14 +3191,18 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) | |||
3073 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 3191 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
3074 | SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); | 3192 | SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); |
3075 | iowrite32(reg, addr); | 3193 | iowrite32(reg, addr); |
3076 | for (i = 0; i <= phba->num_cpus; i++) { | 3194 | if (!phba->msix_enabled) { |
3077 | eq = &phwi_context->be_eq[i].q; | 3195 | eq = &phwi_context->be_eq[0].q; |
3078 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); | 3196 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); |
3079 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); | 3197 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); |
3198 | } else { | ||
3199 | for (i = 0; i <= phba->num_cpus; i++) { | ||
3200 | eq = &phwi_context->be_eq[i].q; | ||
3201 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); | ||
3202 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); | ||
3203 | } | ||
3080 | } | 3204 | } |
3081 | } else | 3205 | } |
3082 | shost_printk(KERN_WARNING, phba->shost, | ||
3083 | "In hwi_enable_intr, Not Enabled \n"); | ||
3084 | return true; | 3206 | return true; |
3085 | } | 3207 | } |
3086 | 3208 | ||
@@ -3476,19 +3598,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | |||
3476 | 3598 | ||
3477 | static int beiscsi_mtask(struct iscsi_task *task) | 3599 | static int beiscsi_mtask(struct iscsi_task *task) |
3478 | { | 3600 | { |
3479 | struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data; | 3601 | struct beiscsi_io_task *io_task = task->dd_data; |
3480 | struct iscsi_conn *conn = task->conn; | 3602 | struct iscsi_conn *conn = task->conn; |
3481 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 3603 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
3482 | struct beiscsi_hba *phba = beiscsi_conn->phba; | 3604 | struct beiscsi_hba *phba = beiscsi_conn->phba; |
3483 | struct iscsi_session *session; | ||
3484 | struct iscsi_wrb *pwrb = NULL; | 3605 | struct iscsi_wrb *pwrb = NULL; |
3485 | struct hwi_controller *phwi_ctrlr; | ||
3486 | struct hwi_wrb_context *pwrb_context; | ||
3487 | struct wrb_handle *pwrb_handle; | ||
3488 | unsigned int doorbell = 0; | 3606 | unsigned int doorbell = 0; |
3489 | unsigned int i, cid; | 3607 | unsigned int cid; |
3490 | struct iscsi_task *aborted_task; | ||
3491 | unsigned int tag; | ||
3492 | 3608 | ||
3493 | cid = beiscsi_conn->beiscsi_conn_cid; | 3609 | cid = beiscsi_conn->beiscsi_conn_cid; |
3494 | pwrb = io_task->pwrb_handle->pwrb; | 3610 | pwrb = io_task->pwrb_handle->pwrb; |
@@ -3499,6 +3615,7 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3499 | io_task->pwrb_handle->wrb_index); | 3615 | io_task->pwrb_handle->wrb_index); |
3500 | AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, | 3616 | AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, |
3501 | io_task->psgl_handle->sgl_index); | 3617 | io_task->psgl_handle->sgl_index); |
3618 | |||
3502 | switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { | 3619 | switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { |
3503 | case ISCSI_OP_LOGIN: | 3620 | case ISCSI_OP_LOGIN: |
3504 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, | 3621 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
@@ -3523,33 +3640,6 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3523 | hwi_write_buffer(pwrb, task); | 3640 | hwi_write_buffer(pwrb, task); |
3524 | break; | 3641 | break; |
3525 | case ISCSI_OP_SCSI_TMFUNC: | 3642 | case ISCSI_OP_SCSI_TMFUNC: |
3526 | session = conn->session; | ||
3527 | i = ((struct iscsi_tm *)task->hdr)->rtt; | ||
3528 | phwi_ctrlr = phba->phwi_ctrlr; | ||
3529 | pwrb_context = &phwi_ctrlr->wrb_context[cid - | ||
3530 | phba->fw_config.iscsi_cid_start]; | ||
3531 | pwrb_handle = pwrb_context->pwrb_handle_basestd[be32_to_cpu(i) | ||
3532 | >> 16]; | ||
3533 | aborted_task = pwrb_handle->pio_handle; | ||
3534 | if (!aborted_task) | ||
3535 | return 0; | ||
3536 | |||
3537 | aborted_io_task = aborted_task->dd_data; | ||
3538 | if (!aborted_io_task->scsi_cmnd) | ||
3539 | return 0; | ||
3540 | |||
3541 | tag = mgmt_invalidate_icds(phba, | ||
3542 | aborted_io_task->psgl_handle->sgl_index, | ||
3543 | cid); | ||
3544 | if (!tag) { | ||
3545 | shost_printk(KERN_WARNING, phba->shost, | ||
3546 | "mgmt_invalidate_icds could not be" | ||
3547 | " submitted\n"); | ||
3548 | } else { | ||
3549 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
3550 | phba->ctrl.mcc_numtag[tag]); | ||
3551 | free_mcc_tag(&phba->ctrl, tag); | ||
3552 | } | ||
3553 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, | 3643 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3554 | INI_TMF_CMD); | 3644 | INI_TMF_CMD); |
3555 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3645 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
@@ -3558,7 +3648,7 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3558 | case ISCSI_OP_LOGOUT: | 3648 | case ISCSI_OP_LOGOUT: |
3559 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3649 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
3560 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, | 3650 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3561 | HWH_TYPE_LOGOUT); | 3651 | HWH_TYPE_LOGOUT); |
3562 | hwi_write_buffer(pwrb, task); | 3652 | hwi_write_buffer(pwrb, task); |
3563 | break; | 3653 | break; |
3564 | 3654 | ||
@@ -3584,17 +3674,12 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3584 | 3674 | ||
3585 | static int beiscsi_task_xmit(struct iscsi_task *task) | 3675 | static int beiscsi_task_xmit(struct iscsi_task *task) |
3586 | { | 3676 | { |
3587 | struct iscsi_conn *conn = task->conn; | ||
3588 | struct beiscsi_io_task *io_task = task->dd_data; | 3677 | struct beiscsi_io_task *io_task = task->dd_data; |
3589 | struct scsi_cmnd *sc = task->sc; | 3678 | struct scsi_cmnd *sc = task->sc; |
3590 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
3591 | struct scatterlist *sg; | 3679 | struct scatterlist *sg; |
3592 | int num_sg; | 3680 | int num_sg; |
3593 | unsigned int writedir = 0, xferlen = 0; | 3681 | unsigned int writedir = 0, xferlen = 0; |
3594 | 3682 | ||
3595 | SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t" | ||
3596 | "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid, | ||
3597 | task, conn, beiscsi_conn); | ||
3598 | if (!sc) | 3683 | if (!sc) |
3599 | return beiscsi_mtask(task); | 3684 | return beiscsi_mtask(task); |
3600 | 3685 | ||
@@ -3699,7 +3784,6 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3699 | " Failed in beiscsi_hba_alloc \n"); | 3784 | " Failed in beiscsi_hba_alloc \n"); |
3700 | goto disable_pci; | 3785 | goto disable_pci; |
3701 | } | 3786 | } |
3702 | SE_DEBUG(DBG_LVL_8, " phba = %p \n", phba); | ||
3703 | 3787 | ||
3704 | switch (pcidev->device) { | 3788 | switch (pcidev->device) { |
3705 | case BE_DEVICE_ID1: | 3789 | case BE_DEVICE_ID1: |