diff options
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 134 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 7 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 14 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 8 |
4 files changed, 145 insertions, 18 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 4d269b434a78..eab31a515de3 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) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int beiscsi_eh_abort(struct scsi_cmnd *sc) | ||
62 | { | ||
63 | struct iscsi_cls_session *cls_session; | ||
64 | struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; | ||
65 | struct beiscsi_io_task *aborted_io_task; | ||
66 | struct iscsi_conn *conn; | ||
67 | struct beiscsi_conn *beiscsi_conn; | ||
68 | struct beiscsi_hba *phba; | ||
69 | struct iscsi_session *session; | ||
70 | struct invalidate_command_table *inv_tbl; | ||
71 | unsigned int cid, tag, num_invalidate; | ||
72 | |||
73 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
74 | session = cls_session->dd_data; | ||
75 | |||
76 | spin_lock_bh(&session->lock); | ||
77 | if (!aborted_task || !aborted_task->sc) { | ||
78 | /* we raced */ | ||
79 | spin_unlock_bh(&session->lock); | ||
80 | return SUCCESS; | ||
81 | } | ||
82 | |||
83 | aborted_io_task = aborted_task->dd_data; | ||
84 | if (!aborted_io_task->scsi_cmnd) { | ||
85 | /* raced or invalid command */ | ||
86 | spin_unlock_bh(&session->lock); | ||
87 | return SUCCESS; | ||
88 | } | ||
89 | spin_unlock_bh(&session->lock); | ||
90 | conn = aborted_task->conn; | ||
91 | beiscsi_conn = conn->dd_data; | ||
92 | phba = beiscsi_conn->phba; | ||
93 | |||
94 | /* invalidate iocb */ | ||
95 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
96 | inv_tbl = phba->inv_tbl; | ||
97 | memset(inv_tbl, 0x0, sizeof(*inv_tbl)); | ||
98 | inv_tbl->cid = cid; | ||
99 | inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; | ||
100 | num_invalidate = 1; | ||
101 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
102 | if (!tag) { | ||
103 | shost_printk(KERN_WARNING, phba->shost, | ||
104 | "mgmt_invalidate_icds could not be" | ||
105 | " submitted\n"); | ||
106 | return FAILED; | ||
107 | } else { | ||
108 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
109 | phba->ctrl.mcc_numtag[tag]); | ||
110 | free_mcc_tag(&phba->ctrl, tag); | ||
111 | } | ||
112 | |||
113 | return iscsi_eh_abort(sc); | ||
114 | } | ||
115 | |||
116 | static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) | ||
117 | { | ||
118 | struct iscsi_task *abrt_task; | ||
119 | struct beiscsi_io_task *abrt_io_task; | ||
120 | struct iscsi_conn *conn; | ||
121 | struct beiscsi_conn *beiscsi_conn; | ||
122 | struct beiscsi_hba *phba; | ||
123 | struct iscsi_session *session; | ||
124 | struct iscsi_cls_session *cls_session; | ||
125 | struct invalidate_command_table *inv_tbl; | ||
126 | unsigned int cid, tag, i, num_invalidate; | ||
127 | int rc = FAILED; | ||
128 | |||
129 | /* invalidate iocbs */ | ||
130 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
131 | session = cls_session->dd_data; | ||
132 | spin_lock_bh(&session->lock); | ||
133 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) | ||
134 | goto unlock; | ||
135 | |||
136 | conn = session->leadconn; | ||
137 | beiscsi_conn = conn->dd_data; | ||
138 | phba = beiscsi_conn->phba; | ||
139 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
140 | inv_tbl = phba->inv_tbl; | ||
141 | memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); | ||
142 | num_invalidate = 0; | ||
143 | for (i = 0; i < conn->session->cmds_max; i++) { | ||
144 | abrt_task = conn->session->cmds[i]; | ||
145 | abrt_io_task = abrt_task->dd_data; | ||
146 | if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) | ||
147 | continue; | ||
148 | |||
149 | if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) | ||
150 | continue; | ||
151 | |||
152 | inv_tbl->cid = cid; | ||
153 | inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; | ||
154 | num_invalidate++; | ||
155 | inv_tbl++; | ||
156 | } | ||
157 | spin_unlock_bh(&session->lock); | ||
158 | inv_tbl = phba->inv_tbl; | ||
159 | |||
160 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
161 | if (!tag) { | ||
162 | shost_printk(KERN_WARNING, phba->shost, | ||
163 | "mgmt_invalidate_icds could not be" | ||
164 | " submitted\n"); | ||
165 | return FAILED; | ||
166 | } else { | ||
167 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
168 | phba->ctrl.mcc_numtag[tag]); | ||
169 | free_mcc_tag(&phba->ctrl, tag); | ||
170 | } | ||
171 | |||
172 | return iscsi_eh_device_reset(sc); | ||
173 | unlock: | ||
174 | spin_unlock_bh(&session->lock); | ||
175 | return rc; | ||
176 | } | ||
177 | |||
61 | /*------------------- PCI Driver operations and data ----------------- */ | 178 | /*------------------- PCI Driver operations and data ----------------- */ |
62 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 179 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
63 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 180 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
@@ -74,11 +191,11 @@ static struct scsi_host_template beiscsi_sht = { | |||
74 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", | 191 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", |
75 | .proc_name = DRV_NAME, | 192 | .proc_name = DRV_NAME, |
76 | .queuecommand = iscsi_queuecommand, | 193 | .queuecommand = iscsi_queuecommand, |
77 | .eh_abort_handler = iscsi_eh_abort, | ||
78 | .change_queue_depth = iscsi_change_queue_depth, | 194 | .change_queue_depth = iscsi_change_queue_depth, |
79 | .slave_configure = beiscsi_slave_configure, | 195 | .slave_configure = beiscsi_slave_configure, |
80 | .target_alloc = iscsi_target_alloc, | 196 | .target_alloc = iscsi_target_alloc, |
81 | .eh_device_reset_handler = iscsi_eh_device_reset, | 197 | .eh_abort_handler = beiscsi_eh_abort, |
198 | .eh_device_reset_handler = beiscsi_eh_device_reset, | ||
82 | .eh_target_reset_handler = iscsi_eh_session_reset, | 199 | .eh_target_reset_handler = iscsi_eh_session_reset, |
83 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, | 200 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, |
84 | .can_queue = BE2_IO_DEPTH, | 201 | .can_queue = BE2_IO_DEPTH, |
@@ -3486,9 +3603,9 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3486 | struct hwi_wrb_context *pwrb_context; | 3603 | struct hwi_wrb_context *pwrb_context; |
3487 | struct wrb_handle *pwrb_handle; | 3604 | struct wrb_handle *pwrb_handle; |
3488 | unsigned int doorbell = 0; | 3605 | unsigned int doorbell = 0; |
3489 | unsigned int i, cid; | 3606 | struct invalidate_command_table *inv_tbl; |
3490 | struct iscsi_task *aborted_task; | 3607 | struct iscsi_task *aborted_task; |
3491 | unsigned int tag; | 3608 | unsigned int i, cid, tag, num_invalidate; |
3492 | 3609 | ||
3493 | cid = beiscsi_conn->beiscsi_conn_cid; | 3610 | cid = beiscsi_conn->beiscsi_conn_cid; |
3494 | pwrb = io_task->pwrb_handle->pwrb; | 3611 | pwrb = io_task->pwrb_handle->pwrb; |
@@ -3538,9 +3655,12 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3538 | if (!aborted_io_task->scsi_cmnd) | 3655 | if (!aborted_io_task->scsi_cmnd) |
3539 | return 0; | 3656 | return 0; |
3540 | 3657 | ||
3541 | tag = mgmt_invalidate_icds(phba, | 3658 | inv_tbl = phba->inv_tbl; |
3542 | aborted_io_task->psgl_handle->sgl_index, | 3659 | memset(inv_tbl, 0x0, sizeof(*inv_tbl)); |
3543 | cid); | 3660 | inv_tbl->cid = cid; |
3661 | inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; | ||
3662 | num_invalidate = 1; | ||
3663 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
3544 | if (!tag) { | 3664 | if (!tag) { |
3545 | shost_printk(KERN_WARNING, phba->shost, | 3665 | shost_printk(KERN_WARNING, phba->shost, |
3546 | "mgmt_invalidate_icds could not be" | 3666 | "mgmt_invalidate_icds could not be" |
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c53a80ab796c..d4d31dc09088 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -257,6 +257,11 @@ struct hba_parameters { | |||
257 | unsigned int num_sge; | 257 | unsigned int num_sge; |
258 | }; | 258 | }; |
259 | 259 | ||
260 | struct invalidate_command_table { | ||
261 | unsigned short icd; | ||
262 | unsigned short cid; | ||
263 | } __packed; | ||
264 | |||
260 | struct beiscsi_hba { | 265 | struct beiscsi_hba { |
261 | struct hba_parameters params; | 266 | struct hba_parameters params; |
262 | struct hwi_controller *phwi_ctrlr; | 267 | struct hwi_controller *phwi_ctrlr; |
@@ -329,6 +334,8 @@ struct beiscsi_hba { | |||
329 | struct work_struct work_cqs; /* The work being queued */ | 334 | struct work_struct work_cqs; /* The work being queued */ |
330 | struct be_ctrl_info ctrl; | 335 | struct be_ctrl_info ctrl; |
331 | unsigned int generation; | 336 | unsigned int generation; |
337 | struct invalidate_command_table inv_tbl[128]; | ||
338 | |||
332 | }; | 339 | }; |
333 | 340 | ||
334 | struct beiscsi_session { | 341 | struct beiscsi_session { |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 317bcd042ced..72617b650a7e 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) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | 147 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, |
148 | unsigned int icd, unsigned int cid) | 148 | struct invalidate_command_table *inv_tbl, |
149 | unsigned int num_invalidate, unsigned int cid) | ||
149 | { | 150 | { |
150 | struct be_dma_mem nonemb_cmd; | 151 | struct be_dma_mem nonemb_cmd; |
151 | struct be_ctrl_info *ctrl = &phba->ctrl; | 152 | struct be_ctrl_info *ctrl = &phba->ctrl; |
152 | struct be_mcc_wrb *wrb; | 153 | struct be_mcc_wrb *wrb; |
153 | struct be_sge *sge; | 154 | struct be_sge *sge; |
154 | struct invalidate_commands_params_in *req; | 155 | struct invalidate_commands_params_in *req; |
155 | unsigned int tag = 0; | 156 | unsigned int i, tag = 0; |
156 | 157 | ||
157 | spin_lock(&ctrl->mbox_lock); | 158 | spin_lock(&ctrl->mbox_lock); |
158 | tag = alloc_mcc_tag(phba); | 159 | tag = alloc_mcc_tag(phba); |
@@ -183,9 +184,12 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | |||
183 | sizeof(*req)); | 184 | sizeof(*req)); |
184 | req->ref_handle = 0; | 185 | req->ref_handle = 0; |
185 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | 186 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; |
186 | req->icd_count = 0; | 187 | for (i = 0; i < num_invalidate; i++) { |
187 | req->table[req->icd_count].icd = icd; | 188 | req->table[i].icd = inv_tbl->icd; |
188 | req->table[req->icd_count].cid = cid; | 189 | req->table[i].cid = inv_tbl->cid; |
190 | req->icd_count++; | ||
191 | inv_tbl++; | ||
192 | } | ||
189 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | 193 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); |
190 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | 194 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); |
191 | sge->len = cpu_to_le32(nonemb_cmd.size); | 195 | 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 ecead6a5aa56..3d316b82feb1 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, | |||
94 | unsigned short cid, | 94 | unsigned short cid, |
95 | unsigned int upload_flag); | 95 | unsigned int upload_flag); |
96 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | 96 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, |
97 | unsigned int icd, unsigned int cid); | 97 | struct invalidate_command_table *inv_tbl, |
98 | unsigned int num_invalidate, unsigned int cid); | ||
98 | 99 | ||
99 | struct iscsi_invalidate_connection_params_in { | 100 | struct iscsi_invalidate_connection_params_in { |
100 | struct be_cmd_req_hdr hdr; | 101 | struct be_cmd_req_hdr hdr; |
@@ -116,11 +117,6 @@ union iscsi_invalidate_connection_params { | |||
116 | struct iscsi_invalidate_connection_params_out response; | 117 | struct iscsi_invalidate_connection_params_out response; |
117 | } __packed; | 118 | } __packed; |
118 | 119 | ||
119 | struct invalidate_command_table { | ||
120 | unsigned short icd; | ||
121 | unsigned short cid; | ||
122 | } __packed; | ||
123 | |||
124 | struct invalidate_commands_params_in { | 120 | struct invalidate_commands_params_in { |
125 | struct be_cmd_req_hdr hdr; | 121 | struct be_cmd_req_hdr hdr; |
126 | unsigned int ref_handle; | 122 | unsigned int ref_handle; |