aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fsf.c
diff options
context:
space:
mode:
authorFelix Beck <felix.beck@de.ibm.com>2010-07-16 09:37:42 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:48:56 -0400
commitef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4 (patch)
tree9903cbae6c03184687c51b4be926572913cda93f /drivers/s390/scsi/zfcp_fsf.c
parentdcc18f48a2f1a44c5e8848f30d0cf53a8066c62a (diff)
[SCSI] zfcp: Introduce experimental support for DIF/DIX
Introduce support for DIF/DIX in zfcp: Report the capabilities for the Scsi_host, map the protection data when issuing I/O requests and handle the new error codes. Also add the fsf data_direction field to the hba trace, it is useful information for debugging in that area. This is an EXPERIMENTAL feature for now. Signed-off-by: Felix Beck <felix.beck@de.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390/scsi/zfcp_fsf.c')
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c109
1 files changed, 86 insertions, 23 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 63402fd5f9ae..f9be5d60d92a 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -526,6 +526,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
526 return -EIO; 526 return -EIO;
527 } 527 }
528 528
529 zfcp_scsi_set_prot(adapter);
530
529 return 0; 531 return 0;
530} 532}
531 533
@@ -988,6 +990,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
988 bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req); 990 bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req);
989 if (bytes <= 0) 991 if (bytes <= 0)
990 return -EIO; 992 return -EIO;
993 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
991 req->qtcb->bottom.support.req_buf_length = bytes; 994 req->qtcb->bottom.support.req_buf_length = bytes;
992 zfcp_qdio_skip_to_last_sbale(&req->qdio_req); 995 zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
993 996
@@ -996,6 +999,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
996 req->qtcb->bottom.support.resp_buf_length = bytes; 999 req->qtcb->bottom.support.resp_buf_length = bytes;
997 if (bytes <= 0) 1000 if (bytes <= 0)
998 return -EIO; 1001 return -EIO;
1002 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
999 1003
1000 return 0; 1004 return 0;
1001} 1005}
@@ -2038,9 +2042,13 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
2038 blktrc.fabric_lat = lat_in->fabric_lat * ticks; 2042 blktrc.fabric_lat = lat_in->fabric_lat * ticks;
2039 2043
2040 switch (req->qtcb->bottom.io.data_direction) { 2044 switch (req->qtcb->bottom.io.data_direction) {
2045 case FSF_DATADIR_DIF_READ_STRIP:
2046 case FSF_DATADIR_DIF_READ_CONVERT:
2041 case FSF_DATADIR_READ: 2047 case FSF_DATADIR_READ:
2042 lat = &unit->latencies.read; 2048 lat = &unit->latencies.read;
2043 break; 2049 break;
2050 case FSF_DATADIR_DIF_WRITE_INSERT:
2051 case FSF_DATADIR_DIF_WRITE_CONVERT:
2044 case FSF_DATADIR_WRITE: 2052 case FSF_DATADIR_WRITE:
2045 lat = &unit->latencies.write; 2053 lat = &unit->latencies.write;
2046 break; 2054 break;
@@ -2081,6 +2089,21 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
2081 goto skip_fsfstatus; 2089 goto skip_fsfstatus;
2082 } 2090 }
2083 2091
2092 switch (req->qtcb->header.fsf_status) {
2093 case FSF_INCONSISTENT_PROT_DATA:
2094 case FSF_INVALID_PROT_PARM:
2095 set_host_byte(scpnt, DID_ERROR);
2096 goto skip_fsfstatus;
2097 case FSF_BLOCK_GUARD_CHECK_FAILURE:
2098 zfcp_scsi_dif_sense_error(scpnt, 0x1);
2099 goto skip_fsfstatus;
2100 case FSF_APP_TAG_CHECK_FAILURE:
2101 zfcp_scsi_dif_sense_error(scpnt, 0x2);
2102 goto skip_fsfstatus;
2103 case FSF_REF_TAG_CHECK_FAILURE:
2104 zfcp_scsi_dif_sense_error(scpnt, 0x3);
2105 goto skip_fsfstatus;
2106 }
2084 fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; 2107 fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
2085 zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt); 2108 zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);
2086 2109
@@ -2190,6 +2213,44 @@ skip_fsfstatus:
2190 } 2213 }
2191} 2214}
2192 2215
2216static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
2217{
2218 switch (scsi_get_prot_op(scsi_cmnd)) {
2219 case SCSI_PROT_NORMAL:
2220 switch (scsi_cmnd->sc_data_direction) {
2221 case DMA_NONE:
2222 *data_dir = FSF_DATADIR_CMND;
2223 break;
2224 case DMA_FROM_DEVICE:
2225 *data_dir = FSF_DATADIR_READ;
2226 break;
2227 case DMA_TO_DEVICE:
2228 *data_dir = FSF_DATADIR_WRITE;
2229 break;
2230 case DMA_BIDIRECTIONAL:
2231 return -EINVAL;
2232 }
2233 break;
2234
2235 case SCSI_PROT_READ_STRIP:
2236 *data_dir = FSF_DATADIR_DIF_READ_STRIP;
2237 break;
2238 case SCSI_PROT_WRITE_INSERT:
2239 *data_dir = FSF_DATADIR_DIF_WRITE_INSERT;
2240 break;
2241 case SCSI_PROT_READ_PASS:
2242 *data_dir = FSF_DATADIR_DIF_READ_CONVERT;
2243 break;
2244 case SCSI_PROT_WRITE_PASS:
2245 *data_dir = FSF_DATADIR_DIF_WRITE_CONVERT;
2246 break;
2247 default:
2248 return -EINVAL;
2249 }
2250
2251 return 0;
2252}
2253
2193/** 2254/**
2194 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) 2255 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
2195 * @unit: unit where command is sent to 2256 * @unit: unit where command is sent to
@@ -2201,9 +2262,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
2201 struct zfcp_fsf_req *req; 2262 struct zfcp_fsf_req *req;
2202 struct fcp_cmnd *fcp_cmnd; 2263 struct fcp_cmnd *fcp_cmnd;
2203 unsigned int sbtype = SBAL_FLAGS0_TYPE_READ; 2264 unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
2204 int real_bytes, retval = -EIO; 2265 int real_bytes, retval = -EIO, dix_bytes = 0;
2205 struct zfcp_adapter *adapter = unit->port->adapter; 2266 struct zfcp_adapter *adapter = unit->port->adapter;
2206 struct zfcp_qdio *qdio = adapter->qdio; 2267 struct zfcp_qdio *qdio = adapter->qdio;
2268 struct fsf_qtcb_bottom_io *io;
2207 2269
2208 if (unlikely(!(atomic_read(&unit->status) & 2270 if (unlikely(!(atomic_read(&unit->status) &
2209 ZFCP_STATUS_COMMON_UNBLOCKED))) 2271 ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2226,46 +2288,46 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
2226 goto out; 2288 goto out;
2227 } 2289 }
2228 2290
2291 scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
2292
2293 io = &req->qtcb->bottom.io;
2229 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 2294 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2230 req->unit = unit; 2295 req->unit = unit;
2231 req->data = scsi_cmnd; 2296 req->data = scsi_cmnd;
2232 req->handler = zfcp_fsf_send_fcp_command_handler; 2297 req->handler = zfcp_fsf_send_fcp_command_handler;
2233 req->qtcb->header.lun_handle = unit->handle; 2298 req->qtcb->header.lun_handle = unit->handle;
2234 req->qtcb->header.port_handle = unit->port->handle; 2299 req->qtcb->header.port_handle = unit->port->handle;
2235 req->qtcb->bottom.io.service_class = FSF_CLASS_3; 2300 io->service_class = FSF_CLASS_3;
2236 req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; 2301 io->fcp_cmnd_length = FCP_CMND_LEN;
2237 2302
2238 scsi_cmnd->host_scribble = (unsigned char *) req->req_id; 2303 if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) {
2239 2304 io->data_block_length = scsi_cmnd->device->sector_size;
2240 /* 2305 io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
2241 * set depending on data direction:
2242 * data direction bits in SBALE (SB Type)
2243 * data direction bits in QTCB
2244 */
2245 switch (scsi_cmnd->sc_data_direction) {
2246 case DMA_NONE:
2247 req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
2248 break;
2249 case DMA_FROM_DEVICE:
2250 req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
2251 break;
2252 case DMA_TO_DEVICE:
2253 req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
2254 break;
2255 case DMA_BIDIRECTIONAL:
2256 goto failed_scsi_cmnd;
2257 } 2306 }
2258 2307
2308 zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
2309
2259 get_device(&unit->dev); 2310 get_device(&unit->dev);
2260 2311
2261 fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; 2312 fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
2262 zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); 2313 zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
2263 2314
2315 if (scsi_prot_sg_count(scsi_cmnd)) {
2316 zfcp_qdio_set_data_div(qdio, &req->qdio_req,
2317 scsi_prot_sg_count(scsi_cmnd));
2318 dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2319 scsi_prot_sglist(scsi_cmnd));
2320 io->prot_data_length = dix_bytes;
2321 }
2322
2264 real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, 2323 real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2265 scsi_sglist(scsi_cmnd)); 2324 scsi_sglist(scsi_cmnd));
2266 if (unlikely(real_bytes < 0)) 2325
2326 if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0))
2267 goto failed_scsi_cmnd; 2327 goto failed_scsi_cmnd;
2268 2328
2329 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2330
2269 retval = zfcp_fsf_req_send(req); 2331 retval = zfcp_fsf_req_send(req);
2270 if (unlikely(retval)) 2332 if (unlikely(retval))
2271 goto failed_scsi_cmnd; 2333 goto failed_scsi_cmnd;
@@ -2389,6 +2451,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2389 zfcp_fsf_req_free(req); 2451 zfcp_fsf_req_free(req);
2390 goto out; 2452 goto out;
2391 } 2453 }
2454 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2392 2455
2393 zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 2456 zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2394 retval = zfcp_fsf_req_send(req); 2457 retval = zfcp_fsf_req_send(req);