diff options
| -rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 3 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_dbf.h | 1 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fc.h | 3 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 109 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.h | 24 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 4 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_qdio.h | 16 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 53 | ||||
| -rw-r--r-- | drivers/scsi/Kconfig | 4 |
10 files changed, 189 insertions, 30 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a08d33a96ec9..a86117b0d6e1 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
| @@ -155,6 +155,8 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, | |||
| 155 | if (scsi_cmnd) { | 155 | if (scsi_cmnd) { |
| 156 | response->u.fcp.cmnd = (unsigned long)scsi_cmnd; | 156 | response->u.fcp.cmnd = (unsigned long)scsi_cmnd; |
| 157 | response->u.fcp.serial = scsi_cmnd->serial_number; | 157 | response->u.fcp.serial = scsi_cmnd->serial_number; |
| 158 | response->u.fcp.data_dir = | ||
| 159 | qtcb->bottom.io.data_direction; | ||
| 158 | } | 160 | } |
| 159 | break; | 161 | break; |
| 160 | 162 | ||
| @@ -326,6 +328,7 @@ static void zfcp_dbf_hba_view_response(char **p, | |||
| 326 | case FSF_QTCB_FCP_CMND: | 328 | case FSF_QTCB_FCP_CMND: |
| 327 | if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | 329 | if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) |
| 328 | break; | 330 | break; |
| 331 | zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir); | ||
| 329 | zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); | 332 | zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); |
| 330 | zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); | 333 | zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); |
| 331 | *p += sprintf(*p, "\n"); | 334 | *p += sprintf(*p, "\n"); |
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 457e046f2d28..2bcc3403126a 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
| @@ -111,6 +111,7 @@ struct zfcp_dbf_hba_record_response { | |||
| 111 | struct { | 111 | struct { |
| 112 | u64 cmnd; | 112 | u64 cmnd; |
| 113 | u64 serial; | 113 | u64 serial; |
| 114 | u32 data_dir; | ||
| 114 | } fcp; | 115 | } fcp; |
| 115 | struct { | 116 | struct { |
| 116 | u64 wwpn; | 117 | u64 wwpn; |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index a8bb7488dc98..de0925f25dcc 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
| @@ -164,6 +164,8 @@ extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); | |||
| 164 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); | 164 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); |
| 165 | extern void zfcp_scsi_scan(struct zfcp_unit *); | 165 | extern void zfcp_scsi_scan(struct zfcp_unit *); |
| 166 | extern void zfcp_scsi_scan_work(struct work_struct *); | 166 | extern void zfcp_scsi_scan_work(struct work_struct *); |
| 167 | extern void zfcp_scsi_set_prot(struct zfcp_adapter *); | ||
| 168 | extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); | ||
| 167 | 169 | ||
| 168 | /* zfcp_sysfs.c */ | 170 | /* zfcp_sysfs.c */ |
| 169 | extern struct attribute_group zfcp_sysfs_unit_attrs; | 171 | extern struct attribute_group zfcp_sysfs_unit_attrs; |
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 85c37d2b82c2..938d50360166 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h | |||
| @@ -220,6 +220,9 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) | |||
| 220 | memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len); | 220 | memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len); |
| 221 | 221 | ||
| 222 | fcp->fc_dl = scsi_bufflen(scsi); | 222 | fcp->fc_dl = scsi_bufflen(scsi); |
| 223 | |||
| 224 | if (scsi_get_prot_type(scsi) == SCSI_PROT_DIF_TYPE1) | ||
| 225 | fcp->fc_dl += fcp->fc_dl / scsi->device->sector_size * 8; | ||
| 223 | } | 226 | } |
| 224 | 227 | ||
| 225 | /** | 228 | /** |
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 | ||
| 2216 | static 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); |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index ca110e386761..db8c85382dca 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
| @@ -80,11 +80,15 @@ | |||
| 80 | #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 | 80 | #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 |
| 81 | #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 | 81 | #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 |
| 82 | #define FSF_SBAL_MISMATCH 0x00000063 | 82 | #define FSF_SBAL_MISMATCH 0x00000063 |
| 83 | #define FSF_INCONSISTENT_PROT_DATA 0x00000070 | ||
| 84 | #define FSF_INVALID_PROT_PARM 0x00000071 | ||
| 85 | #define FSF_BLOCK_GUARD_CHECK_FAILURE 0x00000081 | ||
| 86 | #define FSF_APP_TAG_CHECK_FAILURE 0x00000082 | ||
| 87 | #define FSF_REF_TAG_CHECK_FAILURE 0x00000083 | ||
| 83 | #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD | 88 | #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD |
| 84 | #define FSF_UNKNOWN_COMMAND 0x000000E2 | 89 | #define FSF_UNKNOWN_COMMAND 0x000000E2 |
| 85 | #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 | 90 | #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 |
| 86 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 | 91 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 |
| 87 | /* #define FSF_ERROR 0x000000FF */ | ||
| 88 | 92 | ||
| 89 | #define FSF_PROT_STATUS_QUAL_SIZE 16 | 93 | #define FSF_PROT_STATUS_QUAL_SIZE 16 |
| 90 | #define FSF_STATUS_QUALIFIER_SIZE 16 | 94 | #define FSF_STATUS_QUALIFIER_SIZE 16 |
| @@ -147,6 +151,13 @@ | |||
| 147 | #define FSF_DATADIR_WRITE 0x00000001 | 151 | #define FSF_DATADIR_WRITE 0x00000001 |
| 148 | #define FSF_DATADIR_READ 0x00000002 | 152 | #define FSF_DATADIR_READ 0x00000002 |
| 149 | #define FSF_DATADIR_CMND 0x00000004 | 153 | #define FSF_DATADIR_CMND 0x00000004 |
| 154 | #define FSF_DATADIR_DIF_WRITE_INSERT 0x00000009 | ||
| 155 | #define FSF_DATADIR_DIF_READ_STRIP 0x0000000a | ||
| 156 | #define FSF_DATADIR_DIF_WRITE_CONVERT 0x0000000b | ||
| 157 | #define FSF_DATADIR_DIF_READ_CONVERT 0X0000000c | ||
| 158 | |||
| 159 | /* data protection control flags */ | ||
| 160 | #define FSF_APP_TAG_CHECK_ENABLE 0x10 | ||
| 150 | 161 | ||
| 151 | /* fc service class */ | 162 | /* fc service class */ |
| 152 | #define FSF_CLASS_3 0x00000003 | 163 | #define FSF_CLASS_3 0x00000003 |
| @@ -162,6 +173,8 @@ | |||
| 162 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 | 173 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 |
| 163 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 | 174 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 |
| 164 | #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 | 175 | #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 |
| 176 | #define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000 | ||
| 177 | #define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000 | ||
| 165 | 178 | ||
| 166 | /* host connection features */ | 179 | /* host connection features */ |
| 167 | #define FSF_FEATURE_NPIV_MODE 0x00000001 | 180 | #define FSF_FEATURE_NPIV_MODE 0x00000001 |
| @@ -316,9 +329,14 @@ struct fsf_qtcb_header { | |||
| 316 | struct fsf_qtcb_bottom_io { | 329 | struct fsf_qtcb_bottom_io { |
| 317 | u32 data_direction; | 330 | u32 data_direction; |
| 318 | u32 service_class; | 331 | u32 service_class; |
| 319 | u8 res1[8]; | 332 | u8 res1; |
| 333 | u8 data_prot_flags; | ||
| 334 | u16 app_tag_value; | ||
| 335 | u32 ref_tag_value; | ||
| 320 | u32 fcp_cmnd_length; | 336 | u32 fcp_cmnd_length; |
| 321 | u8 res2[12]; | 337 | u32 data_block_length; |
| 338 | u32 prot_data_length; | ||
| 339 | u8 res2[4]; | ||
| 322 | u8 fcp_cmnd[FSF_FCP_CMND_SIZE]; | 340 | u8 fcp_cmnd[FSF_FCP_CMND_SIZE]; |
| 323 | u8 fcp_rsp[FSF_FCP_RSP_SIZE]; | 341 | u8 fcp_rsp[FSF_FCP_RSP_SIZE]; |
| 324 | u8 res3[64]; | 342 | u8 res3[64]; |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index c4559b29bebc..aceced8ec7e4 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
| @@ -193,10 +193,6 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
| 193 | bytes += sg->length; | 193 | bytes += sg->length; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | /* assume that no other SBALEs are to follow in the same SBAL */ | ||
| 197 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | ||
| 198 | sbale->flags |= SBAL_FLAGS_LAST_ENTRY; | ||
| 199 | |||
| 200 | return bytes; | 196 | return bytes; |
| 201 | } | 197 | } |
| 202 | 198 | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 10d0df99dbf4..2297d8d3e947 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h | |||
| @@ -215,4 +215,20 @@ void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, | |||
| 215 | QDIO_MAX_BUFFERS_PER_Q; | 215 | QDIO_MAX_BUFFERS_PER_Q; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | /** | ||
| 219 | * zfcp_qdio_set_data_div - set data division count | ||
| 220 | * @qdio: pointer to struct zfcp_qdio | ||
| 221 | * @q_req: The current zfcp_qdio_req | ||
| 222 | * @count: The data division count | ||
| 223 | */ | ||
| 224 | static inline | ||
| 225 | void zfcp_qdio_set_data_div(struct zfcp_qdio *qdio, | ||
| 226 | struct zfcp_qdio_req *q_req, u32 count) | ||
| 227 | { | ||
| 228 | struct qdio_buffer_element *sbale; | ||
| 229 | |||
| 230 | sbale = &qdio->req_q[q_req->sbal_first]->element[0]; | ||
| 231 | sbale->length = count; | ||
| 232 | } | ||
| 233 | |||
| 218 | #endif /* ZFCP_QDIO_H */ | 234 | #endif /* ZFCP_QDIO_H */ |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index eb471a1723cd..cb000c9833bb 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <scsi/fc/fc_fcp.h> | 14 | #include <scsi/fc/fc_fcp.h> |
| 15 | #include <scsi/scsi_eh.h> | ||
| 15 | #include <asm/atomic.h> | 16 | #include <asm/atomic.h> |
| 16 | #include "zfcp_ext.h" | 17 | #include "zfcp_ext.h" |
| 17 | #include "zfcp_dbf.h" | 18 | #include "zfcp_dbf.h" |
| @@ -22,6 +23,13 @@ static unsigned int default_depth = 32; | |||
| 22 | module_param_named(queue_depth, default_depth, uint, 0600); | 23 | module_param_named(queue_depth, default_depth, uint, 0600); |
| 23 | MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices"); | 24 | MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices"); |
| 24 | 25 | ||
| 26 | static bool enable_dif; | ||
| 27 | |||
| 28 | #ifdef CONFIG_ZFCP_DIF | ||
| 29 | module_param_named(dif, enable_dif, bool, 0600); | ||
| 30 | MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); | ||
| 31 | #endif | ||
| 32 | |||
| 25 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, | 33 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, |
| 26 | int reason) | 34 | int reason) |
| 27 | { | 35 | { |
| @@ -652,6 +660,51 @@ void zfcp_scsi_scan_work(struct work_struct *work) | |||
| 652 | put_device(&unit->dev); | 660 | put_device(&unit->dev); |
| 653 | } | 661 | } |
| 654 | 662 | ||
| 663 | /** | ||
| 664 | * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host | ||
| 665 | * @adapter: The adapter where to configure DIF/DIX for the SCSI host | ||
| 666 | */ | ||
| 667 | void zfcp_scsi_set_prot(struct zfcp_adapter *adapter) | ||
| 668 | { | ||
| 669 | unsigned int mask = 0; | ||
| 670 | unsigned int data_div; | ||
| 671 | struct Scsi_Host *shost = adapter->scsi_host; | ||
| 672 | |||
| 673 | data_div = atomic_read(&adapter->status) & | ||
| 674 | ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED; | ||
| 675 | |||
| 676 | if (enable_dif && | ||
| 677 | adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1) | ||
| 678 | mask |= SHOST_DIF_TYPE1_PROTECTION; | ||
| 679 | |||
| 680 | if (enable_dif && data_div && | ||
| 681 | adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { | ||
| 682 | mask |= SHOST_DIX_TYPE1_PROTECTION; | ||
| 683 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); | ||
| 684 | shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; | ||
| 685 | shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2; | ||
| 686 | } | ||
| 687 | |||
| 688 | scsi_host_set_prot(shost, mask); | ||
| 689 | } | ||
| 690 | |||
| 691 | /** | ||
| 692 | * zfcp_scsi_dif_sense_error - Report DIF/DIX error as driver sense error | ||
| 693 | * @scmd: The SCSI command to report the error for | ||
| 694 | * @ascq: The ASCQ to put in the sense buffer | ||
| 695 | * | ||
| 696 | * See the error handling in sd_done for the sense codes used here. | ||
| 697 | * Set DID_SOFT_ERROR to retry the request, if possible. | ||
| 698 | */ | ||
| 699 | void zfcp_scsi_dif_sense_error(struct scsi_cmnd *scmd, int ascq) | ||
| 700 | { | ||
| 701 | scsi_build_sense_buffer(1, scmd->sense_buffer, | ||
| 702 | ILLEGAL_REQUEST, 0x10, ascq); | ||
| 703 | set_driver_byte(scmd, DRIVER_SENSE); | ||
| 704 | scmd->result |= SAM_STAT_CHECK_CONDITION; | ||
| 705 | set_host_byte(scmd, DID_SOFT_ERROR); | ||
| 706 | } | ||
| 707 | |||
| 655 | struct fc_function_template zfcp_transport_functions = { | 708 | struct fc_function_template zfcp_transport_functions = { |
| 656 | .show_starget_port_id = 1, | 709 | .show_starget_port_id = 1, |
| 657 | .show_starget_port_name = 1, | 710 | .show_starget_port_name = 1, |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 75f2336807cb..158284f05732 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -1847,6 +1847,10 @@ config ZFCP | |||
| 1847 | called zfcp. If you want to compile it as a module, say M here | 1847 | called zfcp. If you want to compile it as a module, say M here |
| 1848 | and read <file:Documentation/kbuild/modules.txt>. | 1848 | and read <file:Documentation/kbuild/modules.txt>. |
| 1849 | 1849 | ||
| 1850 | config ZFCP_DIF | ||
| 1851 | tristate "T10 DIF/DIX support for the zfcp driver (EXPERIMENTAL)" | ||
| 1852 | depends on ZFCP && EXPERIMENTAL | ||
| 1853 | |||
| 1850 | config SCSI_PMCRAID | 1854 | config SCSI_PMCRAID |
| 1851 | tristate "PMC SIERRA Linux MaxRAID adapter support" | 1855 | tristate "PMC SIERRA Linux MaxRAID adapter support" |
| 1852 | depends on PCI && SCSI | 1856 | depends on PCI && SCSI |
