diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 55 | 
1 files changed, 49 insertions, 6 deletions
| diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 88d1b5f44e59..ff5d56b3ee4d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -65,7 +65,7 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = { | |||
| 65 | }; | 65 | }; | 
| 66 | #undef SP | 66 | #undef SP | 
| 67 | 67 | ||
| 68 | static struct kmem_cache *scsi_sdb_cache; | 68 | struct kmem_cache *scsi_sdb_cache; | 
| 69 | 69 | ||
| 70 | static void scsi_run_queue(struct request_queue *q); | 70 | static void scsi_run_queue(struct request_queue *q); | 
| 71 | 71 | ||
| @@ -787,6 +787,9 @@ void scsi_release_buffers(struct scsi_cmnd *cmd) | |||
| 787 | kmem_cache_free(scsi_sdb_cache, bidi_sdb); | 787 | kmem_cache_free(scsi_sdb_cache, bidi_sdb); | 
| 788 | cmd->request->next_rq->special = NULL; | 788 | cmd->request->next_rq->special = NULL; | 
| 789 | } | 789 | } | 
| 790 | |||
| 791 | if (scsi_prot_sg_count(cmd)) | ||
| 792 | scsi_free_sgtable(cmd->prot_sdb); | ||
| 790 | } | 793 | } | 
| 791 | EXPORT_SYMBOL(scsi_release_buffers); | 794 | EXPORT_SYMBOL(scsi_release_buffers); | 
| 792 | 795 | ||
| @@ -947,9 +950,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 947 | * 6-byte command. | 950 | * 6-byte command. | 
| 948 | */ | 951 | */ | 
| 949 | scsi_requeue_command(q, cmd); | 952 | scsi_requeue_command(q, cmd); | 
| 950 | return; | 953 | } else if (sshdr.asc == 0x10) /* DIX */ | 
| 951 | } else { | 954 | scsi_end_request(cmd, -EIO, this_count, 0); | 
| 955 | else | ||
| 952 | scsi_end_request(cmd, -EIO, this_count, 1); | 956 | scsi_end_request(cmd, -EIO, this_count, 1); | 
| 957 | return; | ||
| 958 | case ABORTED_COMMAND: | ||
| 959 | if (sshdr.asc == 0x10) { /* DIF */ | ||
| 960 | scsi_end_request(cmd, -EIO, this_count, 0); | ||
| 953 | return; | 961 | return; | 
| 954 | } | 962 | } | 
| 955 | break; | 963 | break; | 
| @@ -1072,6 +1080,26 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) | |||
| 1072 | goto err_exit; | 1080 | goto err_exit; | 
| 1073 | } | 1081 | } | 
| 1074 | 1082 | ||
| 1083 | if (blk_integrity_rq(cmd->request)) { | ||
| 1084 | struct scsi_data_buffer *prot_sdb = cmd->prot_sdb; | ||
| 1085 | int ivecs, count; | ||
| 1086 | |||
| 1087 | BUG_ON(prot_sdb == NULL); | ||
| 1088 | ivecs = blk_rq_count_integrity_sg(cmd->request); | ||
| 1089 | |||
| 1090 | if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) { | ||
| 1091 | error = BLKPREP_DEFER; | ||
| 1092 | goto err_exit; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | count = blk_rq_map_integrity_sg(cmd->request, | ||
| 1096 | prot_sdb->table.sgl); | ||
| 1097 | BUG_ON(unlikely(count > ivecs)); | ||
| 1098 | |||
| 1099 | cmd->prot_sdb = prot_sdb; | ||
| 1100 | cmd->prot_sdb->table.nents = count; | ||
| 1101 | } | ||
| 1102 | |||
| 1075 | return BLKPREP_OK ; | 1103 | return BLKPREP_OK ; | 
| 1076 | 1104 | ||
| 1077 | err_exit: | 1105 | err_exit: | 
| @@ -1367,7 +1395,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) | |||
| 1367 | 1395 | ||
| 1368 | if (unlikely(cmd == NULL)) { | 1396 | if (unlikely(cmd == NULL)) { | 
| 1369 | printk(KERN_CRIT "impossible request in %s.\n", | 1397 | printk(KERN_CRIT "impossible request in %s.\n", | 
| 1370 | __FUNCTION__); | 1398 | __func__); | 
| 1371 | BUG(); | 1399 | BUG(); | 
| 1372 | } | 1400 | } | 
| 1373 | 1401 | ||
| @@ -1491,12 +1519,27 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1491 | printk(KERN_CRIT "impossible request in %s.\n" | 1519 | printk(KERN_CRIT "impossible request in %s.\n" | 
| 1492 | "please mail a stack trace to " | 1520 | "please mail a stack trace to " | 
| 1493 | "linux-scsi@vger.kernel.org\n", | 1521 | "linux-scsi@vger.kernel.org\n", | 
| 1494 | __FUNCTION__); | 1522 | __func__); | 
| 1495 | blk_dump_rq_flags(req, "foo"); | 1523 | blk_dump_rq_flags(req, "foo"); | 
| 1496 | BUG(); | 1524 | BUG(); | 
| 1497 | } | 1525 | } | 
| 1498 | spin_lock(shost->host_lock); | 1526 | spin_lock(shost->host_lock); | 
| 1499 | 1527 | ||
| 1528 | /* | ||
| 1529 | * We hit this when the driver is using a host wide | ||
| 1530 | * tag map. For device level tag maps the queue_depth check | ||
| 1531 | * in the device ready fn would prevent us from trying | ||
| 1532 | * to allocate a tag. Since the map is a shared host resource | ||
| 1533 | * we add the dev to the starved list so it eventually gets | ||
| 1534 | * a run when a tag is freed. | ||
| 1535 | */ | ||
| 1536 | if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { | ||
| 1537 | if (list_empty(&sdev->starved_entry)) | ||
| 1538 | list_add_tail(&sdev->starved_entry, | ||
| 1539 | &shost->starved_list); | ||
| 1540 | goto not_ready; | ||
| 1541 | } | ||
| 1542 | |||
| 1500 | if (!scsi_host_queue_ready(q, shost, sdev)) | 1543 | if (!scsi_host_queue_ready(q, shost, sdev)) | 
| 1501 | goto not_ready; | 1544 | goto not_ready; | 
| 1502 | if (scsi_target(sdev)->single_lun) { | 1545 | if (scsi_target(sdev)->single_lun) { | 
| @@ -2486,7 +2529,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count, | |||
| 2486 | if (unlikely(i == sg_count)) { | 2529 | if (unlikely(i == sg_count)) { | 
| 2487 | printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, " | 2530 | printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, " | 
| 2488 | "elements %d\n", | 2531 | "elements %d\n", | 
| 2489 | __FUNCTION__, sg_len, *offset, sg_count); | 2532 | __func__, sg_len, *offset, sg_count); | 
| 2490 | WARN_ON(1); | 2533 | WARN_ON(1); | 
| 2491 | return NULL; | 2534 | return NULL; | 
| 2492 | } | 2535 | } | 
