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 88d1b5f44e5..ff5d56b3ee4 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 | } |