162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * blk-integrity.c - Block layer data integrity extensions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007, 2008 Oracle Corporation 662306a36Sopenharmony_ci * Written by: Martin K. Petersen <martin.petersen@oracle.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/blk-integrity.h> 1062306a36Sopenharmony_ci#include <linux/backing-dev.h> 1162306a36Sopenharmony_ci#include <linux/mempool.h> 1262306a36Sopenharmony_ci#include <linux/bio.h> 1362306a36Sopenharmony_ci#include <linux/scatterlist.h> 1462306a36Sopenharmony_ci#include <linux/export.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "blk.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/** 2062306a36Sopenharmony_ci * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements 2162306a36Sopenharmony_ci * @q: request queue 2262306a36Sopenharmony_ci * @bio: bio with integrity metadata attached 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Description: Returns the number of elements required in a 2562306a36Sopenharmony_ci * scatterlist corresponding to the integrity metadata in a bio. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ciint blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct bio_vec iv, ivprv = { NULL }; 3062306a36Sopenharmony_ci unsigned int segments = 0; 3162306a36Sopenharmony_ci unsigned int seg_size = 0; 3262306a36Sopenharmony_ci struct bvec_iter iter; 3362306a36Sopenharmony_ci int prev = 0; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci bio_for_each_integrity_vec(iv, bio, iter) { 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (prev) { 3862306a36Sopenharmony_ci if (!biovec_phys_mergeable(q, &ivprv, &iv)) 3962306a36Sopenharmony_ci goto new_segment; 4062306a36Sopenharmony_ci if (seg_size + iv.bv_len > queue_max_segment_size(q)) 4162306a36Sopenharmony_ci goto new_segment; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci seg_size += iv.bv_len; 4462306a36Sopenharmony_ci } else { 4562306a36Sopenharmony_cinew_segment: 4662306a36Sopenharmony_ci segments++; 4762306a36Sopenharmony_ci seg_size = iv.bv_len; 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci prev = 1; 5162306a36Sopenharmony_ci ivprv = iv; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return segments; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ciEXPORT_SYMBOL(blk_rq_count_integrity_sg); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/** 5962306a36Sopenharmony_ci * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist 6062306a36Sopenharmony_ci * @q: request queue 6162306a36Sopenharmony_ci * @bio: bio with integrity metadata attached 6262306a36Sopenharmony_ci * @sglist: target scatterlist 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * Description: Map the integrity vectors in request into a 6562306a36Sopenharmony_ci * scatterlist. The scatterlist must be big enough to hold all 6662306a36Sopenharmony_ci * elements. I.e. sized using blk_rq_count_integrity_sg(). 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ciint blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio, 6962306a36Sopenharmony_ci struct scatterlist *sglist) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct bio_vec iv, ivprv = { NULL }; 7262306a36Sopenharmony_ci struct scatterlist *sg = NULL; 7362306a36Sopenharmony_ci unsigned int segments = 0; 7462306a36Sopenharmony_ci struct bvec_iter iter; 7562306a36Sopenharmony_ci int prev = 0; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci bio_for_each_integrity_vec(iv, bio, iter) { 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (prev) { 8062306a36Sopenharmony_ci if (!biovec_phys_mergeable(q, &ivprv, &iv)) 8162306a36Sopenharmony_ci goto new_segment; 8262306a36Sopenharmony_ci if (sg->length + iv.bv_len > queue_max_segment_size(q)) 8362306a36Sopenharmony_ci goto new_segment; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci sg->length += iv.bv_len; 8662306a36Sopenharmony_ci } else { 8762306a36Sopenharmony_cinew_segment: 8862306a36Sopenharmony_ci if (!sg) 8962306a36Sopenharmony_ci sg = sglist; 9062306a36Sopenharmony_ci else { 9162306a36Sopenharmony_ci sg_unmark_end(sg); 9262306a36Sopenharmony_ci sg = sg_next(sg); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset); 9662306a36Sopenharmony_ci segments++; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci prev = 1; 10062306a36Sopenharmony_ci ivprv = iv; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (sg) 10462306a36Sopenharmony_ci sg_mark_end(sg); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return segments; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ciEXPORT_SYMBOL(blk_rq_map_integrity_sg); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/** 11162306a36Sopenharmony_ci * blk_integrity_compare - Compare integrity profile of two disks 11262306a36Sopenharmony_ci * @gd1: Disk to compare 11362306a36Sopenharmony_ci * @gd2: Disk to compare 11462306a36Sopenharmony_ci * 11562306a36Sopenharmony_ci * Description: Meta-devices like DM and MD need to verify that all 11662306a36Sopenharmony_ci * sub-devices use the same integrity format before advertising to 11762306a36Sopenharmony_ci * upper layers that they can send/receive integrity metadata. This 11862306a36Sopenharmony_ci * function can be used to check whether two gendisk devices have 11962306a36Sopenharmony_ci * compatible integrity formats. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ciint blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct blk_integrity *b1 = &gd1->queue->integrity; 12462306a36Sopenharmony_ci struct blk_integrity *b2 = &gd2->queue->integrity; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (!b1->profile && !b2->profile) 12762306a36Sopenharmony_ci return 0; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (!b1->profile || !b2->profile) 13062306a36Sopenharmony_ci return -1; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (b1->interval_exp != b2->interval_exp) { 13362306a36Sopenharmony_ci pr_err("%s: %s/%s protection interval %u != %u\n", 13462306a36Sopenharmony_ci __func__, gd1->disk_name, gd2->disk_name, 13562306a36Sopenharmony_ci 1 << b1->interval_exp, 1 << b2->interval_exp); 13662306a36Sopenharmony_ci return -1; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (b1->tuple_size != b2->tuple_size) { 14062306a36Sopenharmony_ci pr_err("%s: %s/%s tuple sz %u != %u\n", __func__, 14162306a36Sopenharmony_ci gd1->disk_name, gd2->disk_name, 14262306a36Sopenharmony_ci b1->tuple_size, b2->tuple_size); 14362306a36Sopenharmony_ci return -1; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { 14762306a36Sopenharmony_ci pr_err("%s: %s/%s tag sz %u != %u\n", __func__, 14862306a36Sopenharmony_ci gd1->disk_name, gd2->disk_name, 14962306a36Sopenharmony_ci b1->tag_size, b2->tag_size); 15062306a36Sopenharmony_ci return -1; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (b1->profile != b2->profile) { 15462306a36Sopenharmony_ci pr_err("%s: %s/%s type %s != %s\n", __func__, 15562306a36Sopenharmony_ci gd1->disk_name, gd2->disk_name, 15662306a36Sopenharmony_ci b1->profile->name, b2->profile->name); 15762306a36Sopenharmony_ci return -1; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ciEXPORT_SYMBOL(blk_integrity_compare); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cibool blk_integrity_merge_rq(struct request_queue *q, struct request *req, 16562306a36Sopenharmony_ci struct request *next) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0) 16862306a36Sopenharmony_ci return true; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0) 17162306a36Sopenharmony_ci return false; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (bio_integrity(req->bio)->bip_flags != 17462306a36Sopenharmony_ci bio_integrity(next->bio)->bip_flags) 17562306a36Sopenharmony_ci return false; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (req->nr_integrity_segments + next->nr_integrity_segments > 17862306a36Sopenharmony_ci q->limits.max_integrity_segments) 17962306a36Sopenharmony_ci return false; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci if (integrity_req_gap_back_merge(req, next->bio)) 18262306a36Sopenharmony_ci return false; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return true; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cibool blk_integrity_merge_bio(struct request_queue *q, struct request *req, 18862306a36Sopenharmony_ci struct bio *bio) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci int nr_integrity_segs; 19162306a36Sopenharmony_ci struct bio *next = bio->bi_next; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL) 19462306a36Sopenharmony_ci return true; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL) 19762306a36Sopenharmony_ci return false; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags) 20062306a36Sopenharmony_ci return false; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci bio->bi_next = NULL; 20362306a36Sopenharmony_ci nr_integrity_segs = blk_rq_count_integrity_sg(q, bio); 20462306a36Sopenharmony_ci bio->bi_next = next; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (req->nr_integrity_segments + nr_integrity_segs > 20762306a36Sopenharmony_ci q->limits.max_integrity_segments) 20862306a36Sopenharmony_ci return false; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci req->nr_integrity_segments += nr_integrity_segs; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return true; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic inline struct blk_integrity *dev_to_bi(struct device *dev) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci return &dev_to_disk(dev)->queue->integrity; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic ssize_t format_show(struct device *dev, struct device_attribute *attr, 22162306a36Sopenharmony_ci char *page) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (bi->profile && bi->profile->name) 22662306a36Sopenharmony_ci return sysfs_emit(page, "%s\n", bi->profile->name); 22762306a36Sopenharmony_ci return sysfs_emit(page, "none\n"); 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic ssize_t tag_size_show(struct device *dev, struct device_attribute *attr, 23162306a36Sopenharmony_ci char *page) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return sysfs_emit(page, "%u\n", bi->tag_size); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic ssize_t protection_interval_bytes_show(struct device *dev, 23962306a36Sopenharmony_ci struct device_attribute *attr, 24062306a36Sopenharmony_ci char *page) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return sysfs_emit(page, "%u\n", 24562306a36Sopenharmony_ci bi->interval_exp ? 1 << bi->interval_exp : 0); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic ssize_t read_verify_store(struct device *dev, 24962306a36Sopenharmony_ci struct device_attribute *attr, 25062306a36Sopenharmony_ci const char *page, size_t count) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 25362306a36Sopenharmony_ci char *p = (char *) page; 25462306a36Sopenharmony_ci unsigned long val = simple_strtoul(p, &p, 10); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (val) 25762306a36Sopenharmony_ci bi->flags |= BLK_INTEGRITY_VERIFY; 25862306a36Sopenharmony_ci else 25962306a36Sopenharmony_ci bi->flags &= ~BLK_INTEGRITY_VERIFY; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return count; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic ssize_t read_verify_show(struct device *dev, 26562306a36Sopenharmony_ci struct device_attribute *attr, char *page) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return sysfs_emit(page, "%d\n", !!(bi->flags & BLK_INTEGRITY_VERIFY)); 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic ssize_t write_generate_store(struct device *dev, 27362306a36Sopenharmony_ci struct device_attribute *attr, 27462306a36Sopenharmony_ci const char *page, size_t count) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci char *p = (char *) page; 27962306a36Sopenharmony_ci unsigned long val = simple_strtoul(p, &p, 10); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (val) 28262306a36Sopenharmony_ci bi->flags |= BLK_INTEGRITY_GENERATE; 28362306a36Sopenharmony_ci else 28462306a36Sopenharmony_ci bi->flags &= ~BLK_INTEGRITY_GENERATE; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return count; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic ssize_t write_generate_show(struct device *dev, 29062306a36Sopenharmony_ci struct device_attribute *attr, char *page) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return sysfs_emit(page, "%d\n", !!(bi->flags & BLK_INTEGRITY_GENERATE)); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic ssize_t device_is_integrity_capable_show(struct device *dev, 29862306a36Sopenharmony_ci struct device_attribute *attr, 29962306a36Sopenharmony_ci char *page) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct blk_integrity *bi = dev_to_bi(dev); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return sysfs_emit(page, "%u\n", 30462306a36Sopenharmony_ci !!(bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE)); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(format); 30862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(tag_size); 30962306a36Sopenharmony_cistatic DEVICE_ATTR_RO(protection_interval_bytes); 31062306a36Sopenharmony_cistatic DEVICE_ATTR_RW(read_verify); 31162306a36Sopenharmony_cistatic DEVICE_ATTR_RW(write_generate); 31262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(device_is_integrity_capable); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic struct attribute *integrity_attrs[] = { 31562306a36Sopenharmony_ci &dev_attr_format.attr, 31662306a36Sopenharmony_ci &dev_attr_tag_size.attr, 31762306a36Sopenharmony_ci &dev_attr_protection_interval_bytes.attr, 31862306a36Sopenharmony_ci &dev_attr_read_verify.attr, 31962306a36Sopenharmony_ci &dev_attr_write_generate.attr, 32062306a36Sopenharmony_ci &dev_attr_device_is_integrity_capable.attr, 32162306a36Sopenharmony_ci NULL 32262306a36Sopenharmony_ci}; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ciconst struct attribute_group blk_integrity_attr_group = { 32562306a36Sopenharmony_ci .name = "integrity", 32662306a36Sopenharmony_ci .attrs = integrity_attrs, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic blk_status_t blk_integrity_nop_fn(struct blk_integrity_iter *iter) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci return BLK_STS_OK; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void blk_integrity_nop_prepare(struct request *rq) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void blk_integrity_nop_complete(struct request *rq, 33962306a36Sopenharmony_ci unsigned int nr_bytes) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic const struct blk_integrity_profile nop_profile = { 34462306a36Sopenharmony_ci .name = "nop", 34562306a36Sopenharmony_ci .generate_fn = blk_integrity_nop_fn, 34662306a36Sopenharmony_ci .verify_fn = blk_integrity_nop_fn, 34762306a36Sopenharmony_ci .prepare_fn = blk_integrity_nop_prepare, 34862306a36Sopenharmony_ci .complete_fn = blk_integrity_nop_complete, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/** 35262306a36Sopenharmony_ci * blk_integrity_register - Register a gendisk as being integrity-capable 35362306a36Sopenharmony_ci * @disk: struct gendisk pointer to make integrity-aware 35462306a36Sopenharmony_ci * @template: block integrity profile to register 35562306a36Sopenharmony_ci * 35662306a36Sopenharmony_ci * Description: When a device needs to advertise itself as being able to 35762306a36Sopenharmony_ci * send/receive integrity metadata it must use this function to register 35862306a36Sopenharmony_ci * the capability with the block layer. The template is a blk_integrity 35962306a36Sopenharmony_ci * struct with values appropriate for the underlying hardware. See 36062306a36Sopenharmony_ci * Documentation/block/data-integrity.rst. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_civoid blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci struct blk_integrity *bi = &disk->queue->integrity; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | 36762306a36Sopenharmony_ci template->flags; 36862306a36Sopenharmony_ci bi->interval_exp = template->interval_exp ? : 36962306a36Sopenharmony_ci ilog2(queue_logical_block_size(disk->queue)); 37062306a36Sopenharmony_ci bi->profile = template->profile ? template->profile : &nop_profile; 37162306a36Sopenharmony_ci bi->tuple_size = template->tuple_size; 37262306a36Sopenharmony_ci bi->tag_size = template->tag_size; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci#ifdef CONFIG_BLK_INLINE_ENCRYPTION 37762306a36Sopenharmony_ci if (disk->queue->crypto_profile) { 37862306a36Sopenharmony_ci pr_warn("blk-integrity: Integrity and hardware inline encryption are not supported together. Disabling hardware inline encryption.\n"); 37962306a36Sopenharmony_ci disk->queue->crypto_profile = NULL; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci#endif 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ciEXPORT_SYMBOL(blk_integrity_register); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/** 38662306a36Sopenharmony_ci * blk_integrity_unregister - Unregister block integrity profile 38762306a36Sopenharmony_ci * @disk: disk whose integrity profile to unregister 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * Description: This function unregisters the integrity capability from 39062306a36Sopenharmony_ci * a block device. 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_civoid blk_integrity_unregister(struct gendisk *disk) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct blk_integrity *bi = &disk->queue->integrity; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci if (!bi->profile) 39762306a36Sopenharmony_ci return; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* ensure all bios are off the integrity workqueue */ 40062306a36Sopenharmony_ci blk_flush_integrity(); 40162306a36Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, disk->queue); 40262306a36Sopenharmony_ci memset(bi, 0, sizeof(*bi)); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ciEXPORT_SYMBOL(blk_integrity_unregister); 405