diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-18 14:53:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-18 14:53:51 -0400 |
commit | d3dc366bbaf07c125561e90d6da4bb147741101a (patch) | |
tree | 6eb7e79a8ec9df1fa705393c6d15ccea3d104661 /drivers/scsi | |
parent | 511c41d9e6665a07aca94eb00983cf6d77dd87ff (diff) | |
parent | e19a8a0ad2d255316830ead05b59c5a704434cbb (diff) |
Merge branch 'for-3.18/core' of git://git.kernel.dk/linux-block
Pull core block layer changes from Jens Axboe:
"This is the core block IO pull request for 3.18. Apart from the new
and improved flush machinery for blk-mq, this is all mostly bug fixes
and cleanups.
- blk-mq timeout updates and fixes from Christoph.
- Removal of REQ_END, also from Christoph. We pass it through the
->queue_rq() hook for blk-mq instead, freeing up one of the request
bits. The space was overly tight on 32-bit, so Martin also killed
REQ_KERNEL since it's no longer used.
- blk integrity updates and fixes from Martin and Gu Zheng.
- Update to the flush machinery for blk-mq from Ming Lei. Now we
have a per hardware context flush request, which both cleans up the
code should scale better for flush intensive workloads on blk-mq.
- Improve the error printing, from Rob Elliott.
- Backing device improvements and cleanups from Tejun.
- Fixup of a misplaced rq_complete() tracepoint from Hannes.
- Make blk_get_request() return error pointers, fixing up issues
where we NULL deref when a device goes bad or missing. From Joe
Lawrence.
- Prep work for drastically reducing the memory consumption of dm
devices from Junichi Nomura. This allows creating clone bio sets
without preallocating a lot of memory.
- Fix a blk-mq hang on certain combinations of queue depths and
hardware queues from me.
- Limit memory consumption for blk-mq devices for crash dump
scenarios and drivers that use crazy high depths (certain SCSI
shared tag setups). We now just use a single queue and limited
depth for that"
* 'for-3.18/core' of git://git.kernel.dk/linux-block: (58 commits)
block: Remove REQ_KERNEL
blk-mq: allocate cpumask on the home node
bio-integrity: remove the needless fail handle of bip_slab creating
block: include func name in __get_request prints
block: make blk_update_request print prefix match ratelimited prefix
blk-merge: don't compute bi_phys_segments from bi_vcnt for cloned bio
block: fix alignment_offset math that assumes io_min is a power-of-2
blk-mq: Make bt_clear_tag() easier to read
blk-mq: fix potential hang if rolling wakeup depth is too high
block: add bioset_create_nobvec()
block: use bio_clone_fast() in blk_rq_prep_clone()
block: misplaced rq_complete tracepoint
sd: Honor block layer integrity handling flags
block: Replace strnicmp with strncasecmp
block: Add T10 Protection Information functions
block: Don't merge requests if integrity flags differ
block: Integrity checksum flag
block: Relocate bio integrity flags
block: Add a disk flag to block integrity profile
block: Add prefix to block integrity profile flags
...
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 2 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_emc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_hp_sw.c | 4 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_rdac.c | 2 | ||||
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 4 | ||||
-rw-r--r-- | drivers/scsi/osst.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_error.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 24 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 73 | ||||
-rw-r--r-- | drivers/scsi/sd.h | 66 | ||||
-rw-r--r-- | drivers/scsi/sd_dif.c | 353 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 4 | ||||
-rw-r--r-- | drivers/scsi/st.c | 2 |
14 files changed, 187 insertions, 354 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 296619b7426c..3a820f61ce65 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -73,7 +73,6 @@ comment "SCSI support type (disk, tape, CD-ROM)" | |||
73 | config BLK_DEV_SD | 73 | config BLK_DEV_SD |
74 | tristate "SCSI disk support" | 74 | tristate "SCSI disk support" |
75 | depends on SCSI | 75 | depends on SCSI |
76 | select CRC_T10DIF if BLK_DEV_INTEGRITY | ||
77 | ---help--- | 76 | ---help--- |
78 | If you want to use SCSI hard disks, Fibre Channel disks, | 77 | If you want to use SCSI hard disks, Fibre Channel disks, |
79 | Serial ATA (SATA) or Parallel ATA (PATA) hard disks, | 78 | Serial ATA (SATA) or Parallel ATA (PATA) hard disks, |
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 7bcf67eec921..e99507ed0e3c 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -115,7 +115,7 @@ static struct request *get_alua_req(struct scsi_device *sdev, | |||
115 | 115 | ||
116 | rq = blk_get_request(q, rw, GFP_NOIO); | 116 | rq = blk_get_request(q, rw, GFP_NOIO); |
117 | 117 | ||
118 | if (!rq) { | 118 | if (IS_ERR(rq)) { |
119 | sdev_printk(KERN_INFO, sdev, | 119 | sdev_printk(KERN_INFO, sdev, |
120 | "%s: blk_get_request failed\n", __func__); | 120 | "%s: blk_get_request failed\n", __func__); |
121 | return NULL; | 121 | return NULL; |
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6f07f7fe3aa1..84765384c47c 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |||
@@ -275,7 +275,7 @@ static struct request *get_req(struct scsi_device *sdev, int cmd, | |||
275 | 275 | ||
276 | rq = blk_get_request(sdev->request_queue, | 276 | rq = blk_get_request(sdev->request_queue, |
277 | (cmd != INQUIRY) ? WRITE : READ, GFP_NOIO); | 277 | (cmd != INQUIRY) ? WRITE : READ, GFP_NOIO); |
278 | if (!rq) { | 278 | if (IS_ERR(rq)) { |
279 | sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed"); | 279 | sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed"); |
280 | return NULL; | 280 | return NULL; |
281 | } | 281 | } |
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index e9d9fea9e272..4ee2759f5299 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
@@ -117,7 +117,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
117 | 117 | ||
118 | retry: | 118 | retry: |
119 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); | 119 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); |
120 | if (!req) | 120 | if (IS_ERR(req)) |
121 | return SCSI_DH_RES_TEMP_UNAVAIL; | 121 | return SCSI_DH_RES_TEMP_UNAVAIL; |
122 | 122 | ||
123 | blk_rq_set_block_pc(req); | 123 | blk_rq_set_block_pc(req); |
@@ -247,7 +247,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h) | |||
247 | struct request *req; | 247 | struct request *req; |
248 | 248 | ||
249 | req = blk_get_request(h->sdev->request_queue, WRITE, GFP_ATOMIC); | 249 | req = blk_get_request(h->sdev->request_queue, WRITE, GFP_ATOMIC); |
250 | if (!req) | 250 | if (IS_ERR(req)) |
251 | return SCSI_DH_RES_TEMP_UNAVAIL; | 251 | return SCSI_DH_RES_TEMP_UNAVAIL; |
252 | 252 | ||
253 | blk_rq_set_block_pc(req); | 253 | blk_rq_set_block_pc(req); |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 826069db9848..1b5bc9293e37 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -274,7 +274,7 @@ static struct request *get_rdac_req(struct scsi_device *sdev, | |||
274 | 274 | ||
275 | rq = blk_get_request(q, rw, GFP_NOIO); | 275 | rq = blk_get_request(q, rw, GFP_NOIO); |
276 | 276 | ||
277 | if (!rq) { | 277 | if (IS_ERR(rq)) { |
278 | sdev_printk(KERN_INFO, sdev, | 278 | sdev_printk(KERN_INFO, sdev, |
279 | "get_rdac_req: blk_get_request failed.\n"); | 279 | "get_rdac_req: blk_get_request failed.\n"); |
280 | return NULL; | 280 | return NULL; |
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 5f4cbf0c4759..fd19fd8468ac 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
@@ -1567,8 +1567,8 @@ static struct request *_make_request(struct request_queue *q, bool has_write, | |||
1567 | struct request *req; | 1567 | struct request *req; |
1568 | 1568 | ||
1569 | req = blk_get_request(q, has_write ? WRITE : READ, flags); | 1569 | req = blk_get_request(q, has_write ? WRITE : READ, flags); |
1570 | if (unlikely(!req)) | 1570 | if (IS_ERR(req)) |
1571 | return ERR_PTR(-ENOMEM); | 1571 | return req; |
1572 | 1572 | ||
1573 | blk_rq_set_block_pc(req); | 1573 | blk_rq_set_block_pc(req); |
1574 | return req; | 1574 | return req; |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 0727ea7cc387..dff37a250d79 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -362,7 +362,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd, | |||
362 | int write = (data_direction == DMA_TO_DEVICE); | 362 | int write = (data_direction == DMA_TO_DEVICE); |
363 | 363 | ||
364 | req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL); | 364 | req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL); |
365 | if (!req) | 365 | if (IS_ERR(req)) |
366 | return DRIVER_ERROR << 24; | 366 | return DRIVER_ERROR << 24; |
367 | 367 | ||
368 | blk_rq_set_block_pc(req); | 368 | blk_rq_set_block_pc(req); |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 6b20ef3fee54..9a6f8468225f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1961,6 +1961,8 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) | |||
1961 | * request becomes available | 1961 | * request becomes available |
1962 | */ | 1962 | */ |
1963 | req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL); | 1963 | req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL); |
1964 | if (IS_ERR(req)) | ||
1965 | return; | ||
1964 | 1966 | ||
1965 | blk_rq_set_block_pc(req); | 1967 | blk_rq_set_block_pc(req); |
1966 | 1968 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index db8c449282f9..9eff8a375132 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -221,7 +221,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
221 | int ret = DRIVER_ERROR << 24; | 221 | int ret = DRIVER_ERROR << 24; |
222 | 222 | ||
223 | req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); | 223 | req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); |
224 | if (!req) | 224 | if (IS_ERR(req)) |
225 | return ret; | 225 | return ret; |
226 | blk_rq_set_block_pc(req); | 226 | blk_rq_set_block_pc(req); |
227 | 227 | ||
@@ -715,7 +715,7 @@ static bool scsi_end_request(struct request *req, int error, | |||
715 | 715 | ||
716 | if (req->mq_ctx) { | 716 | if (req->mq_ctx) { |
717 | /* | 717 | /* |
718 | * In the MQ case the command gets freed by __blk_mq_end_io, | 718 | * In the MQ case the command gets freed by __blk_mq_end_request, |
719 | * so we have to do all cleanup that depends on it earlier. | 719 | * so we have to do all cleanup that depends on it earlier. |
720 | * | 720 | * |
721 | * We also can't kick the queues from irq context, so we | 721 | * We also can't kick the queues from irq context, so we |
@@ -723,7 +723,7 @@ static bool scsi_end_request(struct request *req, int error, | |||
723 | */ | 723 | */ |
724 | scsi_mq_uninit_cmd(cmd); | 724 | scsi_mq_uninit_cmd(cmd); |
725 | 725 | ||
726 | __blk_mq_end_io(req, error); | 726 | __blk_mq_end_request(req, error); |
727 | 727 | ||
728 | if (scsi_target(sdev)->single_lun || | 728 | if (scsi_target(sdev)->single_lun || |
729 | !list_empty(&sdev->host->starved_list)) | 729 | !list_empty(&sdev->host->starved_list)) |
@@ -1847,6 +1847,8 @@ static int scsi_mq_prep_fn(struct request *req) | |||
1847 | next_rq->special = bidi_sdb; | 1847 | next_rq->special = bidi_sdb; |
1848 | } | 1848 | } |
1849 | 1849 | ||
1850 | blk_mq_start_request(req); | ||
1851 | |||
1850 | return scsi_setup_cmnd(sdev, req); | 1852 | return scsi_setup_cmnd(sdev, req); |
1851 | } | 1853 | } |
1852 | 1854 | ||
@@ -1856,7 +1858,8 @@ static void scsi_mq_done(struct scsi_cmnd *cmd) | |||
1856 | blk_mq_complete_request(cmd->request); | 1858 | blk_mq_complete_request(cmd->request); |
1857 | } | 1859 | } |
1858 | 1860 | ||
1859 | static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) | 1861 | static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, |
1862 | bool last) | ||
1860 | { | 1863 | { |
1861 | struct request_queue *q = req->q; | 1864 | struct request_queue *q = req->q; |
1862 | struct scsi_device *sdev = q->queuedata; | 1865 | struct scsi_device *sdev = q->queuedata; |
@@ -1880,11 +1883,14 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) | |||
1880 | if (!scsi_host_queue_ready(q, shost, sdev)) | 1883 | if (!scsi_host_queue_ready(q, shost, sdev)) |
1881 | goto out_dec_target_busy; | 1884 | goto out_dec_target_busy; |
1882 | 1885 | ||
1886 | |||
1883 | if (!(req->cmd_flags & REQ_DONTPREP)) { | 1887 | if (!(req->cmd_flags & REQ_DONTPREP)) { |
1884 | ret = prep_to_mq(scsi_mq_prep_fn(req)); | 1888 | ret = prep_to_mq(scsi_mq_prep_fn(req)); |
1885 | if (ret) | 1889 | if (ret) |
1886 | goto out_dec_host_busy; | 1890 | goto out_dec_host_busy; |
1887 | req->cmd_flags |= REQ_DONTPREP; | 1891 | req->cmd_flags |= REQ_DONTPREP; |
1892 | } else { | ||
1893 | blk_mq_start_request(req); | ||
1888 | } | 1894 | } |
1889 | 1895 | ||
1890 | scsi_init_cmd_errh(cmd); | 1896 | scsi_init_cmd_errh(cmd); |
@@ -1931,6 +1937,14 @@ out: | |||
1931 | return ret; | 1937 | return ret; |
1932 | } | 1938 | } |
1933 | 1939 | ||
1940 | static enum blk_eh_timer_return scsi_timeout(struct request *req, | ||
1941 | bool reserved) | ||
1942 | { | ||
1943 | if (reserved) | ||
1944 | return BLK_EH_RESET_TIMER; | ||
1945 | return scsi_times_out(req); | ||
1946 | } | ||
1947 | |||
1934 | static int scsi_init_request(void *data, struct request *rq, | 1948 | static int scsi_init_request(void *data, struct request *rq, |
1935 | unsigned int hctx_idx, unsigned int request_idx, | 1949 | unsigned int hctx_idx, unsigned int request_idx, |
1936 | unsigned int numa_node) | 1950 | unsigned int numa_node) |
@@ -2042,7 +2056,7 @@ static struct blk_mq_ops scsi_mq_ops = { | |||
2042 | .map_queue = blk_mq_map_queue, | 2056 | .map_queue = blk_mq_map_queue, |
2043 | .queue_rq = scsi_queue_rq, | 2057 | .queue_rq = scsi_queue_rq, |
2044 | .complete = scsi_softirq_done, | 2058 | .complete = scsi_softirq_done, |
2045 | .timeout = scsi_times_out, | 2059 | .timeout = scsi_timeout, |
2046 | .init_request = scsi_init_request, | 2060 | .init_request = scsi_init_request, |
2047 | .exit_request = scsi_exit_request, | 2061 | .exit_request = scsi_exit_request, |
2048 | }; | 2062 | }; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0cb5c9f0c743..7ee86028a535 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -610,29 +610,44 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
610 | mutex_unlock(&sd_ref_mutex); | 610 | mutex_unlock(&sd_ref_mutex); |
611 | } | 611 | } |
612 | 612 | ||
613 | static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) | 613 | |
614 | { | 614 | |
615 | unsigned int prot_op = SCSI_PROT_NORMAL; | 615 | static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, |
616 | unsigned int dix = scsi_prot_sg_count(scmd); | 616 | unsigned int dix, unsigned int dif) |
617 | 617 | { | |
618 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) { | 618 | struct bio *bio = scmd->request->bio; |
619 | if (dif && dix) | 619 | unsigned int prot_op = sd_prot_op(rq_data_dir(scmd->request), dix, dif); |
620 | prot_op = SCSI_PROT_READ_PASS; | 620 | unsigned int protect = 0; |
621 | else if (dif && !dix) | 621 | |
622 | prot_op = SCSI_PROT_READ_STRIP; | 622 | if (dix) { /* DIX Type 0, 1, 2, 3 */ |
623 | else if (!dif && dix) | 623 | if (bio_integrity_flagged(bio, BIP_IP_CHECKSUM)) |
624 | prot_op = SCSI_PROT_READ_INSERT; | 624 | scmd->prot_flags |= SCSI_PROT_IP_CHECKSUM; |
625 | } else { | 625 | |
626 | if (dif && dix) | 626 | if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) |
627 | prot_op = SCSI_PROT_WRITE_PASS; | 627 | scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; |
628 | else if (dif && !dix) | 628 | } |
629 | prot_op = SCSI_PROT_WRITE_INSERT; | 629 | |
630 | else if (!dif && dix) | 630 | if (dif != SD_DIF_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ |
631 | prot_op = SCSI_PROT_WRITE_STRIP; | 631 | scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; |
632 | |||
633 | if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) | ||
634 | scmd->prot_flags |= SCSI_PROT_REF_CHECK; | ||
635 | } | ||
636 | |||
637 | if (dif) { /* DIX/DIF Type 1, 2, 3 */ | ||
638 | scmd->prot_flags |= SCSI_PROT_TRANSFER_PI; | ||
639 | |||
640 | if (bio_integrity_flagged(bio, BIP_DISK_NOCHECK)) | ||
641 | protect = 3 << 5; /* Disable target PI checking */ | ||
642 | else | ||
643 | protect = 1 << 5; /* Enable target PI checking */ | ||
632 | } | 644 | } |
633 | 645 | ||
634 | scsi_set_prot_op(scmd, prot_op); | 646 | scsi_set_prot_op(scmd, prot_op); |
635 | scsi_set_prot_type(scmd, dif); | 647 | scsi_set_prot_type(scmd, dif); |
648 | scmd->prot_flags &= sd_prot_flag_mask(prot_op); | ||
649 | |||
650 | return protect; | ||
636 | } | 651 | } |
637 | 652 | ||
638 | static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | 653 | static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) |
@@ -893,7 +908,8 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
893 | sector_t block = blk_rq_pos(rq); | 908 | sector_t block = blk_rq_pos(rq); |
894 | sector_t threshold; | 909 | sector_t threshold; |
895 | unsigned int this_count = blk_rq_sectors(rq); | 910 | unsigned int this_count = blk_rq_sectors(rq); |
896 | int ret, host_dif; | 911 | unsigned int dif, dix; |
912 | int ret; | ||
897 | unsigned char protect; | 913 | unsigned char protect; |
898 | 914 | ||
899 | ret = scsi_init_io(SCpnt, GFP_ATOMIC); | 915 | ret = scsi_init_io(SCpnt, GFP_ATOMIC); |
@@ -995,7 +1011,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
995 | SCpnt->cmnd[0] = WRITE_6; | 1011 | SCpnt->cmnd[0] = WRITE_6; |
996 | 1012 | ||
997 | if (blk_integrity_rq(rq)) | 1013 | if (blk_integrity_rq(rq)) |
998 | sd_dif_prepare(rq, block, sdp->sector_size); | 1014 | sd_dif_prepare(SCpnt); |
999 | 1015 | ||
1000 | } else if (rq_data_dir(rq) == READ) { | 1016 | } else if (rq_data_dir(rq) == READ) { |
1001 | SCpnt->cmnd[0] = READ_6; | 1017 | SCpnt->cmnd[0] = READ_6; |
@@ -1010,14 +1026,15 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
1010 | "writing" : "reading", this_count, | 1026 | "writing" : "reading", this_count, |
1011 | blk_rq_sectors(rq))); | 1027 | blk_rq_sectors(rq))); |
1012 | 1028 | ||
1013 | /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ | 1029 | dix = scsi_prot_sg_count(SCpnt); |
1014 | host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); | 1030 | dif = scsi_host_dif_capable(SCpnt->device->host, sdkp->protection_type); |
1015 | if (host_dif) | 1031 | |
1016 | protect = 1 << 5; | 1032 | if (dif || dix) |
1033 | protect = sd_setup_protect_cmnd(SCpnt, dix, dif); | ||
1017 | else | 1034 | else |
1018 | protect = 0; | 1035 | protect = 0; |
1019 | 1036 | ||
1020 | if (host_dif == SD_DIF_TYPE2_PROTECTION) { | 1037 | if (protect && sdkp->protection_type == SD_DIF_TYPE2_PROTECTION) { |
1021 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); | 1038 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); |
1022 | 1039 | ||
1023 | if (unlikely(SCpnt->cmnd == NULL)) { | 1040 | if (unlikely(SCpnt->cmnd == NULL)) { |
@@ -1102,10 +1119,6 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
1102 | } | 1119 | } |
1103 | SCpnt->sdb.length = this_count * sdp->sector_size; | 1120 | SCpnt->sdb.length = this_count * sdp->sector_size; |
1104 | 1121 | ||
1105 | /* If DIF or DIX is enabled, tell HBA how to handle request */ | ||
1106 | if (host_dif || scsi_prot_sg_count(SCpnt)) | ||
1107 | sd_prot_op(SCpnt, host_dif); | ||
1108 | |||
1109 | /* | 1122 | /* |
1110 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 1123 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
1111 | * host adapter, it's safe to assume that we can at least transfer | 1124 | * host adapter, it's safe to assume that we can at least transfer |
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 4c3ab8377fd3..467377884b63 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
@@ -167,6 +167,68 @@ enum sd_dif_target_protection_types { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | /* | 169 | /* |
170 | * Look up the DIX operation based on whether the command is read or | ||
171 | * write and whether dix and dif are enabled. | ||
172 | */ | ||
173 | static inline unsigned int sd_prot_op(bool write, bool dix, bool dif) | ||
174 | { | ||
175 | /* Lookup table: bit 2 (write), bit 1 (dix), bit 0 (dif) */ | ||
176 | const unsigned int ops[] = { /* wrt dix dif */ | ||
177 | SCSI_PROT_NORMAL, /* 0 0 0 */ | ||
178 | SCSI_PROT_READ_STRIP, /* 0 0 1 */ | ||
179 | SCSI_PROT_READ_INSERT, /* 0 1 0 */ | ||
180 | SCSI_PROT_READ_PASS, /* 0 1 1 */ | ||
181 | SCSI_PROT_NORMAL, /* 1 0 0 */ | ||
182 | SCSI_PROT_WRITE_INSERT, /* 1 0 1 */ | ||
183 | SCSI_PROT_WRITE_STRIP, /* 1 1 0 */ | ||
184 | SCSI_PROT_WRITE_PASS, /* 1 1 1 */ | ||
185 | }; | ||
186 | |||
187 | return ops[write << 2 | dix << 1 | dif]; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Returns a mask of the protection flags that are valid for a given DIX | ||
192 | * operation. | ||
193 | */ | ||
194 | static inline unsigned int sd_prot_flag_mask(unsigned int prot_op) | ||
195 | { | ||
196 | const unsigned int flag_mask[] = { | ||
197 | [SCSI_PROT_NORMAL] = 0, | ||
198 | |||
199 | [SCSI_PROT_READ_STRIP] = SCSI_PROT_TRANSFER_PI | | ||
200 | SCSI_PROT_GUARD_CHECK | | ||
201 | SCSI_PROT_REF_CHECK | | ||
202 | SCSI_PROT_REF_INCREMENT, | ||
203 | |||
204 | [SCSI_PROT_READ_INSERT] = SCSI_PROT_REF_INCREMENT | | ||
205 | SCSI_PROT_IP_CHECKSUM, | ||
206 | |||
207 | [SCSI_PROT_READ_PASS] = SCSI_PROT_TRANSFER_PI | | ||
208 | SCSI_PROT_GUARD_CHECK | | ||
209 | SCSI_PROT_REF_CHECK | | ||
210 | SCSI_PROT_REF_INCREMENT | | ||
211 | SCSI_PROT_IP_CHECKSUM, | ||
212 | |||
213 | [SCSI_PROT_WRITE_INSERT] = SCSI_PROT_TRANSFER_PI | | ||
214 | SCSI_PROT_REF_INCREMENT, | ||
215 | |||
216 | [SCSI_PROT_WRITE_STRIP] = SCSI_PROT_GUARD_CHECK | | ||
217 | SCSI_PROT_REF_CHECK | | ||
218 | SCSI_PROT_REF_INCREMENT | | ||
219 | SCSI_PROT_IP_CHECKSUM, | ||
220 | |||
221 | [SCSI_PROT_WRITE_PASS] = SCSI_PROT_TRANSFER_PI | | ||
222 | SCSI_PROT_GUARD_CHECK | | ||
223 | SCSI_PROT_REF_CHECK | | ||
224 | SCSI_PROT_REF_INCREMENT | | ||
225 | SCSI_PROT_IP_CHECKSUM, | ||
226 | }; | ||
227 | |||
228 | return flag_mask[prot_op]; | ||
229 | } | ||
230 | |||
231 | /* | ||
170 | * Data Integrity Field tuple. | 232 | * Data Integrity Field tuple. |
171 | */ | 233 | */ |
172 | struct sd_dif_tuple { | 234 | struct sd_dif_tuple { |
@@ -178,7 +240,7 @@ struct sd_dif_tuple { | |||
178 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 240 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
179 | 241 | ||
180 | extern void sd_dif_config_host(struct scsi_disk *); | 242 | extern void sd_dif_config_host(struct scsi_disk *); |
181 | extern void sd_dif_prepare(struct request *rq, sector_t, unsigned int); | 243 | extern void sd_dif_prepare(struct scsi_cmnd *scmd); |
182 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); | 244 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); |
183 | 245 | ||
184 | #else /* CONFIG_BLK_DEV_INTEGRITY */ | 246 | #else /* CONFIG_BLK_DEV_INTEGRITY */ |
@@ -186,7 +248,7 @@ extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); | |||
186 | static inline void sd_dif_config_host(struct scsi_disk *disk) | 248 | static inline void sd_dif_config_host(struct scsi_disk *disk) |
187 | { | 249 | { |
188 | } | 250 | } |
189 | static inline int sd_dif_prepare(struct request *rq, sector_t s, unsigned int a) | 251 | static inline int sd_dif_prepare(struct scsi_cmnd *scmd) |
190 | { | 252 | { |
191 | return 0; | 253 | return 0; |
192 | } | 254 | } |
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index a7a691d0af7d..14c7d42a11c2 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/blkdev.h> | 23 | #include <linux/blkdev.h> |
24 | #include <linux/crc-t10dif.h> | 24 | #include <linux/t10-pi.h> |
25 | 25 | ||
26 | #include <scsi/scsi.h> | 26 | #include <scsi/scsi.h> |
27 | #include <scsi/scsi_cmnd.h> | 27 | #include <scsi/scsi_cmnd.h> |
@@ -33,268 +33,8 @@ | |||
33 | #include <scsi/scsi_ioctl.h> | 33 | #include <scsi/scsi_ioctl.h> |
34 | #include <scsi/scsicam.h> | 34 | #include <scsi/scsicam.h> |
35 | 35 | ||
36 | #include <net/checksum.h> | ||
37 | |||
38 | #include "sd.h" | 36 | #include "sd.h" |
39 | 37 | ||
40 | typedef __u16 (csum_fn) (void *, unsigned int); | ||
41 | |||
42 | static __u16 sd_dif_crc_fn(void *data, unsigned int len) | ||
43 | { | ||
44 | return cpu_to_be16(crc_t10dif(data, len)); | ||
45 | } | ||
46 | |||
47 | static __u16 sd_dif_ip_fn(void *data, unsigned int len) | ||
48 | { | ||
49 | return ip_compute_csum(data, len); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Type 1 and Type 2 protection use the same format: 16 bit guard tag, | ||
54 | * 16 bit app tag, 32 bit reference tag. | ||
55 | */ | ||
56 | static void sd_dif_type1_generate(struct blk_integrity_exchg *bix, csum_fn *fn) | ||
57 | { | ||
58 | void *buf = bix->data_buf; | ||
59 | struct sd_dif_tuple *sdt = bix->prot_buf; | ||
60 | sector_t sector = bix->sector; | ||
61 | unsigned int i; | ||
62 | |||
63 | for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) { | ||
64 | sdt->guard_tag = fn(buf, bix->sector_size); | ||
65 | sdt->ref_tag = cpu_to_be32(sector & 0xffffffff); | ||
66 | sdt->app_tag = 0; | ||
67 | |||
68 | buf += bix->sector_size; | ||
69 | sector++; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void sd_dif_type1_generate_crc(struct blk_integrity_exchg *bix) | ||
74 | { | ||
75 | sd_dif_type1_generate(bix, sd_dif_crc_fn); | ||
76 | } | ||
77 | |||
78 | static void sd_dif_type1_generate_ip(struct blk_integrity_exchg *bix) | ||
79 | { | ||
80 | sd_dif_type1_generate(bix, sd_dif_ip_fn); | ||
81 | } | ||
82 | |||
83 | static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn) | ||
84 | { | ||
85 | void *buf = bix->data_buf; | ||
86 | struct sd_dif_tuple *sdt = bix->prot_buf; | ||
87 | sector_t sector = bix->sector; | ||
88 | unsigned int i; | ||
89 | __u16 csum; | ||
90 | |||
91 | for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) { | ||
92 | /* Unwritten sectors */ | ||
93 | if (sdt->app_tag == 0xffff) | ||
94 | return 0; | ||
95 | |||
96 | if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { | ||
97 | printk(KERN_ERR | ||
98 | "%s: ref tag error on sector %lu (rcvd %u)\n", | ||
99 | bix->disk_name, (unsigned long)sector, | ||
100 | be32_to_cpu(sdt->ref_tag)); | ||
101 | return -EIO; | ||
102 | } | ||
103 | |||
104 | csum = fn(buf, bix->sector_size); | ||
105 | |||
106 | if (sdt->guard_tag != csum) { | ||
107 | printk(KERN_ERR "%s: guard tag error on sector %lu " \ | ||
108 | "(rcvd %04x, data %04x)\n", bix->disk_name, | ||
109 | (unsigned long)sector, | ||
110 | be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); | ||
111 | return -EIO; | ||
112 | } | ||
113 | |||
114 | buf += bix->sector_size; | ||
115 | sector++; | ||
116 | } | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int sd_dif_type1_verify_crc(struct blk_integrity_exchg *bix) | ||
122 | { | ||
123 | return sd_dif_type1_verify(bix, sd_dif_crc_fn); | ||
124 | } | ||
125 | |||
126 | static int sd_dif_type1_verify_ip(struct blk_integrity_exchg *bix) | ||
127 | { | ||
128 | return sd_dif_type1_verify(bix, sd_dif_ip_fn); | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * Functions for interleaving and deinterleaving application tags | ||
133 | */ | ||
134 | static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors) | ||
135 | { | ||
136 | struct sd_dif_tuple *sdt = prot; | ||
137 | u8 *tag = tag_buf; | ||
138 | unsigned int i, j; | ||
139 | |||
140 | for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) { | ||
141 | sdt->app_tag = tag[j] << 8 | tag[j+1]; | ||
142 | BUG_ON(sdt->app_tag == 0xffff); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void sd_dif_type1_get_tag(void *prot, void *tag_buf, unsigned int sectors) | ||
147 | { | ||
148 | struct sd_dif_tuple *sdt = prot; | ||
149 | u8 *tag = tag_buf; | ||
150 | unsigned int i, j; | ||
151 | |||
152 | for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) { | ||
153 | tag[j] = (sdt->app_tag & 0xff00) >> 8; | ||
154 | tag[j+1] = sdt->app_tag & 0xff; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static struct blk_integrity dif_type1_integrity_crc = { | ||
159 | .name = "T10-DIF-TYPE1-CRC", | ||
160 | .generate_fn = sd_dif_type1_generate_crc, | ||
161 | .verify_fn = sd_dif_type1_verify_crc, | ||
162 | .get_tag_fn = sd_dif_type1_get_tag, | ||
163 | .set_tag_fn = sd_dif_type1_set_tag, | ||
164 | .tuple_size = sizeof(struct sd_dif_tuple), | ||
165 | .tag_size = 0, | ||
166 | }; | ||
167 | |||
168 | static struct blk_integrity dif_type1_integrity_ip = { | ||
169 | .name = "T10-DIF-TYPE1-IP", | ||
170 | .generate_fn = sd_dif_type1_generate_ip, | ||
171 | .verify_fn = sd_dif_type1_verify_ip, | ||
172 | .get_tag_fn = sd_dif_type1_get_tag, | ||
173 | .set_tag_fn = sd_dif_type1_set_tag, | ||
174 | .tuple_size = sizeof(struct sd_dif_tuple), | ||
175 | .tag_size = 0, | ||
176 | }; | ||
177 | |||
178 | |||
179 | /* | ||
180 | * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque | ||
181 | * tag space. | ||
182 | */ | ||
183 | static void sd_dif_type3_generate(struct blk_integrity_exchg *bix, csum_fn *fn) | ||
184 | { | ||
185 | void *buf = bix->data_buf; | ||
186 | struct sd_dif_tuple *sdt = bix->prot_buf; | ||
187 | unsigned int i; | ||
188 | |||
189 | for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) { | ||
190 | sdt->guard_tag = fn(buf, bix->sector_size); | ||
191 | sdt->ref_tag = 0; | ||
192 | sdt->app_tag = 0; | ||
193 | |||
194 | buf += bix->sector_size; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | static void sd_dif_type3_generate_crc(struct blk_integrity_exchg *bix) | ||
199 | { | ||
200 | sd_dif_type3_generate(bix, sd_dif_crc_fn); | ||
201 | } | ||
202 | |||
203 | static void sd_dif_type3_generate_ip(struct blk_integrity_exchg *bix) | ||
204 | { | ||
205 | sd_dif_type3_generate(bix, sd_dif_ip_fn); | ||
206 | } | ||
207 | |||
208 | static int sd_dif_type3_verify(struct blk_integrity_exchg *bix, csum_fn *fn) | ||
209 | { | ||
210 | void *buf = bix->data_buf; | ||
211 | struct sd_dif_tuple *sdt = bix->prot_buf; | ||
212 | sector_t sector = bix->sector; | ||
213 | unsigned int i; | ||
214 | __u16 csum; | ||
215 | |||
216 | for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) { | ||
217 | /* Unwritten sectors */ | ||
218 | if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff) | ||
219 | return 0; | ||
220 | |||
221 | csum = fn(buf, bix->sector_size); | ||
222 | |||
223 | if (sdt->guard_tag != csum) { | ||
224 | printk(KERN_ERR "%s: guard tag error on sector %lu " \ | ||
225 | "(rcvd %04x, data %04x)\n", bix->disk_name, | ||
226 | (unsigned long)sector, | ||
227 | be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); | ||
228 | return -EIO; | ||
229 | } | ||
230 | |||
231 | buf += bix->sector_size; | ||
232 | sector++; | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int sd_dif_type3_verify_crc(struct blk_integrity_exchg *bix) | ||
239 | { | ||
240 | return sd_dif_type3_verify(bix, sd_dif_crc_fn); | ||
241 | } | ||
242 | |||
243 | static int sd_dif_type3_verify_ip(struct blk_integrity_exchg *bix) | ||
244 | { | ||
245 | return sd_dif_type3_verify(bix, sd_dif_ip_fn); | ||
246 | } | ||
247 | |||
248 | static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors) | ||
249 | { | ||
250 | struct sd_dif_tuple *sdt = prot; | ||
251 | u8 *tag = tag_buf; | ||
252 | unsigned int i, j; | ||
253 | |||
254 | for (i = 0, j = 0 ; i < sectors ; i++, j += 6, sdt++) { | ||
255 | sdt->app_tag = tag[j] << 8 | tag[j+1]; | ||
256 | sdt->ref_tag = tag[j+2] << 24 | tag[j+3] << 16 | | ||
257 | tag[j+4] << 8 | tag[j+5]; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static void sd_dif_type3_get_tag(void *prot, void *tag_buf, unsigned int sectors) | ||
262 | { | ||
263 | struct sd_dif_tuple *sdt = prot; | ||
264 | u8 *tag = tag_buf; | ||
265 | unsigned int i, j; | ||
266 | |||
267 | for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) { | ||
268 | tag[j] = (sdt->app_tag & 0xff00) >> 8; | ||
269 | tag[j+1] = sdt->app_tag & 0xff; | ||
270 | tag[j+2] = (sdt->ref_tag & 0xff000000) >> 24; | ||
271 | tag[j+3] = (sdt->ref_tag & 0xff0000) >> 16; | ||
272 | tag[j+4] = (sdt->ref_tag & 0xff00) >> 8; | ||
273 | tag[j+5] = sdt->ref_tag & 0xff; | ||
274 | BUG_ON(sdt->app_tag == 0xffff || sdt->ref_tag == 0xffffffff); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static struct blk_integrity dif_type3_integrity_crc = { | ||
279 | .name = "T10-DIF-TYPE3-CRC", | ||
280 | .generate_fn = sd_dif_type3_generate_crc, | ||
281 | .verify_fn = sd_dif_type3_verify_crc, | ||
282 | .get_tag_fn = sd_dif_type3_get_tag, | ||
283 | .set_tag_fn = sd_dif_type3_set_tag, | ||
284 | .tuple_size = sizeof(struct sd_dif_tuple), | ||
285 | .tag_size = 0, | ||
286 | }; | ||
287 | |||
288 | static struct blk_integrity dif_type3_integrity_ip = { | ||
289 | .name = "T10-DIF-TYPE3-IP", | ||
290 | .generate_fn = sd_dif_type3_generate_ip, | ||
291 | .verify_fn = sd_dif_type3_verify_ip, | ||
292 | .get_tag_fn = sd_dif_type3_get_tag, | ||
293 | .set_tag_fn = sd_dif_type3_set_tag, | ||
294 | .tuple_size = sizeof(struct sd_dif_tuple), | ||
295 | .tag_size = 0, | ||
296 | }; | ||
297 | |||
298 | /* | 38 | /* |
299 | * Configure exchange of protection information between OS and HBA. | 39 | * Configure exchange of protection information between OS and HBA. |
300 | */ | 40 | */ |
@@ -316,22 +56,30 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
316 | return; | 56 | return; |
317 | 57 | ||
318 | /* Enable DMA of protection information */ | 58 | /* Enable DMA of protection information */ |
319 | if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) | 59 | if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { |
320 | if (type == SD_DIF_TYPE3_PROTECTION) | 60 | if (type == SD_DIF_TYPE3_PROTECTION) |
321 | blk_integrity_register(disk, &dif_type3_integrity_ip); | 61 | blk_integrity_register(disk, &t10_pi_type3_ip); |
322 | else | 62 | else |
323 | blk_integrity_register(disk, &dif_type1_integrity_ip); | 63 | blk_integrity_register(disk, &t10_pi_type1_ip); |
324 | else | 64 | |
65 | disk->integrity->flags |= BLK_INTEGRITY_IP_CHECKSUM; | ||
66 | } else | ||
325 | if (type == SD_DIF_TYPE3_PROTECTION) | 67 | if (type == SD_DIF_TYPE3_PROTECTION) |
326 | blk_integrity_register(disk, &dif_type3_integrity_crc); | 68 | blk_integrity_register(disk, &t10_pi_type3_crc); |
327 | else | 69 | else |
328 | blk_integrity_register(disk, &dif_type1_integrity_crc); | 70 | blk_integrity_register(disk, &t10_pi_type1_crc); |
329 | 71 | ||
330 | sd_printk(KERN_NOTICE, sdkp, | 72 | sd_printk(KERN_NOTICE, sdkp, |
331 | "Enabling DIX %s protection\n", disk->integrity->name); | 73 | "Enabling DIX %s protection\n", disk->integrity->name); |
332 | 74 | ||
333 | /* Signal to block layer that we support sector tagging */ | 75 | /* Signal to block layer that we support sector tagging */ |
334 | if (dif && type && sdkp->ATO) { | 76 | if (dif && type) { |
77 | |||
78 | disk->integrity->flags |= BLK_INTEGRITY_DEVICE_CAPABLE; | ||
79 | |||
80 | if (!sdkp) | ||
81 | return; | ||
82 | |||
335 | if (type == SD_DIF_TYPE3_PROTECTION) | 83 | if (type == SD_DIF_TYPE3_PROTECTION) |
336 | disk->integrity->tag_size = sizeof(u16) + sizeof(u32); | 84 | disk->integrity->tag_size = sizeof(u16) + sizeof(u32); |
337 | else | 85 | else |
@@ -358,50 +106,49 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
358 | * | 106 | * |
359 | * Type 3 does not have a reference tag so no remapping is required. | 107 | * Type 3 does not have a reference tag so no remapping is required. |
360 | */ | 108 | */ |
361 | void sd_dif_prepare(struct request *rq, sector_t hw_sector, | 109 | void sd_dif_prepare(struct scsi_cmnd *scmd) |
362 | unsigned int sector_sz) | ||
363 | { | 110 | { |
364 | const int tuple_sz = sizeof(struct sd_dif_tuple); | 111 | const int tuple_sz = sizeof(struct t10_pi_tuple); |
365 | struct bio *bio; | 112 | struct bio *bio; |
366 | struct scsi_disk *sdkp; | 113 | struct scsi_disk *sdkp; |
367 | struct sd_dif_tuple *sdt; | 114 | struct t10_pi_tuple *pi; |
368 | u32 phys, virt; | 115 | u32 phys, virt; |
369 | 116 | ||
370 | sdkp = rq->bio->bi_bdev->bd_disk->private_data; | 117 | sdkp = scsi_disk(scmd->request->rq_disk); |
371 | 118 | ||
372 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION) | 119 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION) |
373 | return; | 120 | return; |
374 | 121 | ||
375 | phys = hw_sector & 0xffffffff; | 122 | phys = scsi_prot_ref_tag(scmd); |
376 | 123 | ||
377 | __rq_for_each_bio(bio, rq) { | 124 | __rq_for_each_bio(bio, scmd->request) { |
125 | struct bio_integrity_payload *bip = bio_integrity(bio); | ||
378 | struct bio_vec iv; | 126 | struct bio_vec iv; |
379 | struct bvec_iter iter; | 127 | struct bvec_iter iter; |
380 | unsigned int j; | 128 | unsigned int j; |
381 | 129 | ||
382 | /* Already remapped? */ | 130 | /* Already remapped? */ |
383 | if (bio_flagged(bio, BIO_MAPPED_INTEGRITY)) | 131 | if (bip->bip_flags & BIP_MAPPED_INTEGRITY) |
384 | break; | 132 | break; |
385 | 133 | ||
386 | virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff; | 134 | virt = bip_get_seed(bip) & 0xffffffff; |
387 | 135 | ||
388 | bip_for_each_vec(iv, bio->bi_integrity, iter) { | 136 | bip_for_each_vec(iv, bip, iter) { |
389 | sdt = kmap_atomic(iv.bv_page) | 137 | pi = kmap_atomic(iv.bv_page) + iv.bv_offset; |
390 | + iv.bv_offset; | ||
391 | 138 | ||
392 | for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { | 139 | for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { |
393 | 140 | ||
394 | if (be32_to_cpu(sdt->ref_tag) == virt) | 141 | if (be32_to_cpu(pi->ref_tag) == virt) |
395 | sdt->ref_tag = cpu_to_be32(phys); | 142 | pi->ref_tag = cpu_to_be32(phys); |
396 | 143 | ||
397 | virt++; | 144 | virt++; |
398 | phys++; | 145 | phys++; |
399 | } | 146 | } |
400 | 147 | ||
401 | kunmap_atomic(sdt); | 148 | kunmap_atomic(pi); |
402 | } | 149 | } |
403 | 150 | ||
404 | bio->bi_flags |= (1 << BIO_MAPPED_INTEGRITY); | 151 | bip->bip_flags |= BIP_MAPPED_INTEGRITY; |
405 | } | 152 | } |
406 | } | 153 | } |
407 | 154 | ||
@@ -411,11 +158,11 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector, | |||
411 | */ | 158 | */ |
412 | void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) | 159 | void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) |
413 | { | 160 | { |
414 | const int tuple_sz = sizeof(struct sd_dif_tuple); | 161 | const int tuple_sz = sizeof(struct t10_pi_tuple); |
415 | struct scsi_disk *sdkp; | 162 | struct scsi_disk *sdkp; |
416 | struct bio *bio; | 163 | struct bio *bio; |
417 | struct sd_dif_tuple *sdt; | 164 | struct t10_pi_tuple *pi; |
418 | unsigned int j, sectors, sector_sz; | 165 | unsigned int j, intervals; |
419 | u32 phys, virt; | 166 | u32 phys, virt; |
420 | 167 | ||
421 | sdkp = scsi_disk(scmd->request->rq_disk); | 168 | sdkp = scsi_disk(scmd->request->rq_disk); |
@@ -423,39 +170,35 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) | |||
423 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0) | 170 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0) |
424 | return; | 171 | return; |
425 | 172 | ||
426 | sector_sz = scmd->device->sector_size; | 173 | intervals = good_bytes / scsi_prot_interval(scmd); |
427 | sectors = good_bytes / sector_sz; | 174 | phys = scsi_prot_ref_tag(scmd); |
428 | |||
429 | phys = blk_rq_pos(scmd->request) & 0xffffffff; | ||
430 | if (sector_sz == 4096) | ||
431 | phys >>= 3; | ||
432 | 175 | ||
433 | __rq_for_each_bio(bio, scmd->request) { | 176 | __rq_for_each_bio(bio, scmd->request) { |
177 | struct bio_integrity_payload *bip = bio_integrity(bio); | ||
434 | struct bio_vec iv; | 178 | struct bio_vec iv; |
435 | struct bvec_iter iter; | 179 | struct bvec_iter iter; |
436 | 180 | ||
437 | virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff; | 181 | virt = bip_get_seed(bip) & 0xffffffff; |
438 | 182 | ||
439 | bip_for_each_vec(iv, bio->bi_integrity, iter) { | 183 | bip_for_each_vec(iv, bip, iter) { |
440 | sdt = kmap_atomic(iv.bv_page) | 184 | pi = kmap_atomic(iv.bv_page) + iv.bv_offset; |
441 | + iv.bv_offset; | ||
442 | 185 | ||
443 | for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { | 186 | for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { |
444 | 187 | ||
445 | if (sectors == 0) { | 188 | if (intervals == 0) { |
446 | kunmap_atomic(sdt); | 189 | kunmap_atomic(pi); |
447 | return; | 190 | return; |
448 | } | 191 | } |
449 | 192 | ||
450 | if (be32_to_cpu(sdt->ref_tag) == phys) | 193 | if (be32_to_cpu(pi->ref_tag) == phys) |
451 | sdt->ref_tag = cpu_to_be32(virt); | 194 | pi->ref_tag = cpu_to_be32(virt); |
452 | 195 | ||
453 | virt++; | 196 | virt++; |
454 | phys++; | 197 | phys++; |
455 | sectors--; | 198 | intervals--; |
456 | } | 199 | } |
457 | 200 | ||
458 | kunmap_atomic(sdt); | 201 | kunmap_atomic(pi); |
459 | } | 202 | } |
460 | } | 203 | } |
461 | } | 204 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 01cf88888797..60354449d9ed 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1711,9 +1711,9 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
1711 | } | 1711 | } |
1712 | 1712 | ||
1713 | rq = blk_get_request(q, rw, GFP_ATOMIC); | 1713 | rq = blk_get_request(q, rw, GFP_ATOMIC); |
1714 | if (!rq) { | 1714 | if (IS_ERR(rq)) { |
1715 | kfree(long_cmdp); | 1715 | kfree(long_cmdp); |
1716 | return -ENOMEM; | 1716 | return PTR_ERR(rq); |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | blk_rq_set_block_pc(rq); | 1719 | blk_rq_set_block_pc(rq); |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index d3fd6e8fb378..4daa372ed381 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -490,7 +490,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, | |||
490 | 490 | ||
491 | req = blk_get_request(SRpnt->stp->device->request_queue, write, | 491 | req = blk_get_request(SRpnt->stp->device->request_queue, write, |
492 | GFP_KERNEL); | 492 | GFP_KERNEL); |
493 | if (!req) | 493 | if (IS_ERR(req)) |
494 | return DRIVER_ERROR << 24; | 494 | return DRIVER_ERROR << 24; |
495 | 495 | ||
496 | blk_rq_set_block_pc(req); | 496 | blk_rq_set_block_pc(req); |