|
3 | 3 | *
|
4 | 4 | * Interface to Linux SCSI midlayer.
|
5 | 5 | *
|
6 |
| - * Copyright IBM Corp. 2002, 2015 |
| 6 | + * Copyright IBM Corp. 2002, 2016 |
7 | 7 | */
|
8 | 8 |
|
9 | 9 | #define KMSG_COMPONENT "zfcp"
|
@@ -209,6 +209,57 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
|
209 | 209 | return retval;
|
210 | 210 | }
|
211 | 211 |
|
| 212 | +struct zfcp_scsi_req_filter { |
| 213 | + u8 tmf_scope; |
| 214 | + u32 lun_handle; |
| 215 | + u32 port_handle; |
| 216 | +}; |
| 217 | + |
| 218 | +static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data) |
| 219 | +{ |
| 220 | + struct zfcp_scsi_req_filter *filter = |
| 221 | + (struct zfcp_scsi_req_filter *)data; |
| 222 | + |
| 223 | + /* already aborted - prevent side-effects - or not a SCSI command */ |
| 224 | + if (old_req->data == NULL || old_req->fsf_command != FSF_QTCB_FCP_CMND) |
| 225 | + return; |
| 226 | + |
| 227 | + /* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */ |
| 228 | + if (old_req->qtcb->header.port_handle != filter->port_handle) |
| 229 | + return; |
| 230 | + |
| 231 | + if (filter->tmf_scope == FCP_TMF_LUN_RESET && |
| 232 | + old_req->qtcb->header.lun_handle != filter->lun_handle) |
| 233 | + return; |
| 234 | + |
| 235 | + zfcp_dbf_scsi_nullcmnd((struct scsi_cmnd *)old_req->data, old_req); |
| 236 | + old_req->data = NULL; |
| 237 | +} |
| 238 | + |
| 239 | +static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags) |
| 240 | +{ |
| 241 | + struct zfcp_adapter *adapter = zsdev->port->adapter; |
| 242 | + struct zfcp_scsi_req_filter filter = { |
| 243 | + .tmf_scope = FCP_TMF_TGT_RESET, |
| 244 | + .port_handle = zsdev->port->handle, |
| 245 | + }; |
| 246 | + unsigned long flags; |
| 247 | + |
| 248 | + if (tm_flags == FCP_TMF_LUN_RESET) { |
| 249 | + filter.tmf_scope = FCP_TMF_LUN_RESET; |
| 250 | + filter.lun_handle = zsdev->lun_handle; |
| 251 | + } |
| 252 | + |
| 253 | + /* |
| 254 | + * abort_lock secures against other processings - in the abort-function |
| 255 | + * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data |
| 256 | + */ |
| 257 | + write_lock_irqsave(&adapter->abort_lock, flags); |
| 258 | + zfcp_reqlist_apply_for_all(adapter->req_list, zfcp_scsi_forget_cmnd, |
| 259 | + &filter); |
| 260 | + write_unlock_irqrestore(&adapter->abort_lock, flags); |
| 261 | +} |
| 262 | + |
212 | 263 | static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
|
213 | 264 | {
|
214 | 265 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
|
@@ -241,8 +292,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
|
241 | 292 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
|
242 | 293 | zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
|
243 | 294 | retval = FAILED;
|
244 |
| - } else |
| 295 | + } else { |
245 | 296 | zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
|
| 297 | + zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags); |
| 298 | + } |
246 | 299 |
|
247 | 300 | zfcp_fsf_req_free(fsf_req);
|
248 | 301 | return retval;
|
|
0 commit comments