diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 147 |
1 files changed, 72 insertions, 75 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 48aa16a40d93..2b9dfea9f254 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -2080,73 +2080,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) | |||
2080 | sizeof(blktrc)); | 2080 | sizeof(blktrc)); |
2081 | } | 2081 | } |
2082 | 2082 | ||
2083 | static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) | 2083 | static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) |
2084 | { | ||
2085 | struct scsi_cmnd *scpnt; | ||
2086 | struct fcp_resp_with_ext *fcp_rsp; | ||
2087 | unsigned long flags; | ||
2088 | |||
2089 | read_lock_irqsave(&req->adapter->abort_lock, flags); | ||
2090 | |||
2091 | scpnt = req->data; | ||
2092 | if (unlikely(!scpnt)) { | ||
2093 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); | ||
2094 | return; | ||
2095 | } | ||
2096 | |||
2097 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | ||
2098 | set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); | ||
2099 | goto skip_fsfstatus; | ||
2100 | } | ||
2101 | |||
2102 | switch (req->qtcb->header.fsf_status) { | ||
2103 | case FSF_INCONSISTENT_PROT_DATA: | ||
2104 | case FSF_INVALID_PROT_PARM: | ||
2105 | set_host_byte(scpnt, DID_ERROR); | ||
2106 | goto skip_fsfstatus; | ||
2107 | case FSF_BLOCK_GUARD_CHECK_FAILURE: | ||
2108 | zfcp_scsi_dif_sense_error(scpnt, 0x1); | ||
2109 | goto skip_fsfstatus; | ||
2110 | case FSF_APP_TAG_CHECK_FAILURE: | ||
2111 | zfcp_scsi_dif_sense_error(scpnt, 0x2); | ||
2112 | goto skip_fsfstatus; | ||
2113 | case FSF_REF_TAG_CHECK_FAILURE: | ||
2114 | zfcp_scsi_dif_sense_error(scpnt, 0x3); | ||
2115 | goto skip_fsfstatus; | ||
2116 | } | ||
2117 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2118 | zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt); | ||
2119 | |||
2120 | skip_fsfstatus: | ||
2121 | zfcp_fsf_req_trace(req, scpnt); | ||
2122 | zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req); | ||
2123 | |||
2124 | scpnt->host_scribble = NULL; | ||
2125 | (scpnt->scsi_done) (scpnt); | ||
2126 | /* | ||
2127 | * We must hold this lock until scsi_done has been called. | ||
2128 | * Otherwise we may call scsi_done after abort regarding this | ||
2129 | * command has completed. | ||
2130 | * Note: scsi_done must not block! | ||
2131 | */ | ||
2132 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); | ||
2133 | } | ||
2134 | |||
2135 | static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req) | ||
2136 | { | ||
2137 | struct fcp_resp_with_ext *fcp_rsp; | ||
2138 | struct fcp_resp_rsp_info *rsp_info; | ||
2139 | |||
2140 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2141 | rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; | ||
2142 | |||
2143 | if ((rsp_info->rsp_code != FCP_TMF_CMPL) || | ||
2144 | (req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2145 | req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; | ||
2146 | } | ||
2147 | |||
2148 | |||
2149 | static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) | ||
2150 | { | 2084 | { |
2151 | struct scsi_cmnd *scmnd = req->data; | 2085 | struct scsi_cmnd *scmnd = req->data; |
2152 | struct scsi_device *sdev = scmnd->device; | 2086 | struct scsi_device *sdev = scmnd->device; |
@@ -2154,7 +2088,7 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) | |||
2154 | struct fsf_qtcb_header *header = &req->qtcb->header; | 2088 | struct fsf_qtcb_header *header = &req->qtcb->header; |
2155 | 2089 | ||
2156 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) | 2090 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) |
2157 | goto skip_fsfstatus; | 2091 | return; |
2158 | 2092 | ||
2159 | switch (header->fsf_status) { | 2093 | switch (header->fsf_status) { |
2160 | case FSF_HANDLE_MISMATCH: | 2094 | case FSF_HANDLE_MISMATCH: |
@@ -2211,12 +2145,60 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) | |||
2211 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 2145 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
2212 | break; | 2146 | break; |
2213 | } | 2147 | } |
2214 | skip_fsfstatus: | 2148 | } |
2215 | if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | 2149 | |
2216 | zfcp_fsf_send_fcp_ctm_handler(req); | 2150 | static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) |
2217 | else { | 2151 | { |
2218 | zfcp_fsf_send_fcp_command_task_handler(req); | 2152 | struct scsi_cmnd *scpnt; |
2153 | struct fcp_resp_with_ext *fcp_rsp; | ||
2154 | unsigned long flags; | ||
2155 | |||
2156 | zfcp_fsf_fcp_handler_common(req); | ||
2157 | |||
2158 | read_lock_irqsave(&req->adapter->abort_lock, flags); | ||
2159 | |||
2160 | scpnt = req->data; | ||
2161 | if (unlikely(!scpnt)) { | ||
2162 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); | ||
2163 | return; | ||
2219 | } | 2164 | } |
2165 | |||
2166 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | ||
2167 | set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); | ||
2168 | goto skip_fsfstatus; | ||
2169 | } | ||
2170 | |||
2171 | switch (req->qtcb->header.fsf_status) { | ||
2172 | case FSF_INCONSISTENT_PROT_DATA: | ||
2173 | case FSF_INVALID_PROT_PARM: | ||
2174 | set_host_byte(scpnt, DID_ERROR); | ||
2175 | goto skip_fsfstatus; | ||
2176 | case FSF_BLOCK_GUARD_CHECK_FAILURE: | ||
2177 | zfcp_scsi_dif_sense_error(scpnt, 0x1); | ||
2178 | goto skip_fsfstatus; | ||
2179 | case FSF_APP_TAG_CHECK_FAILURE: | ||
2180 | zfcp_scsi_dif_sense_error(scpnt, 0x2); | ||
2181 | goto skip_fsfstatus; | ||
2182 | case FSF_REF_TAG_CHECK_FAILURE: | ||
2183 | zfcp_scsi_dif_sense_error(scpnt, 0x3); | ||
2184 | goto skip_fsfstatus; | ||
2185 | } | ||
2186 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2187 | zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt); | ||
2188 | |||
2189 | skip_fsfstatus: | ||
2190 | zfcp_fsf_req_trace(req, scpnt); | ||
2191 | zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req); | ||
2192 | |||
2193 | scpnt->host_scribble = NULL; | ||
2194 | (scpnt->scsi_done) (scpnt); | ||
2195 | /* | ||
2196 | * We must hold this lock until scsi_done has been called. | ||
2197 | * Otherwise we may call scsi_done after abort regarding this | ||
2198 | * command has completed. | ||
2199 | * Note: scsi_done must not block! | ||
2200 | */ | ||
2201 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); | ||
2220 | } | 2202 | } |
2221 | 2203 | ||
2222 | static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) | 2204 | static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) |
@@ -2299,7 +2281,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) | |||
2299 | io = &req->qtcb->bottom.io; | 2281 | io = &req->qtcb->bottom.io; |
2300 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 2282 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
2301 | req->data = scsi_cmnd; | 2283 | req->data = scsi_cmnd; |
2302 | req->handler = zfcp_fsf_send_fcp_command_handler; | 2284 | req->handler = zfcp_fsf_fcp_cmnd_handler; |
2303 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; | 2285 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
2304 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; | 2286 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
2305 | io->service_class = FSF_CLASS_3; | 2287 | io->service_class = FSF_CLASS_3; |
@@ -2345,6 +2327,21 @@ out: | |||
2345 | return retval; | 2327 | return retval; |
2346 | } | 2328 | } |
2347 | 2329 | ||
2330 | static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) | ||
2331 | { | ||
2332 | struct fcp_resp_with_ext *fcp_rsp; | ||
2333 | struct fcp_resp_rsp_info *rsp_info; | ||
2334 | |||
2335 | zfcp_fsf_fcp_handler_common(req); | ||
2336 | |||
2337 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2338 | rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; | ||
2339 | |||
2340 | if ((rsp_info->rsp_code != FCP_TMF_CMPL) || | ||
2341 | (req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2342 | req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; | ||
2343 | } | ||
2344 | |||
2348 | /** | 2345 | /** |
2349 | * zfcp_fsf_fcp_task_mgmt - send SCSI task management command | 2346 | * zfcp_fsf_fcp_task_mgmt - send SCSI task management command |
2350 | * @scmnd: SCSI command to send the task management command for | 2347 | * @scmnd: SCSI command to send the task management command for |
@@ -2378,7 +2375,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, | |||
2378 | 2375 | ||
2379 | req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; | 2376 | req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; |
2380 | req->data = scmnd; | 2377 | req->data = scmnd; |
2381 | req->handler = zfcp_fsf_send_fcp_command_handler; | 2378 | req->handler = zfcp_fsf_fcp_task_mgmt_handler; |
2382 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; | 2379 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
2383 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; | 2380 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
2384 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; | 2381 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; |