aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2010-09-10 14:50:10 -0400
committerJens Axboe <axboe@carl.home.kernel.dk>2010-09-10 14:50:10 -0400
commit13f05c8d8e98bbdce89158bfdb2e380940695a88 (patch)
tree055215e7e2b1bdc684ead64daa61b30b35eaa3c5 /include
parentc8bf1336824ebd698d37b71763e1c43190f2229a (diff)
block/scsi: Provide a limit on the number of integrity segments
Some controllers have a hardware limit on the number of protection information scatter-gather list segments they can handle. Introduce a max_integrity_segments limit in the block layer and provide a new scsi_host_template setting that allows HBA drivers to provide a value suitable for the hardware. Add support for honoring the integrity segment limit when merging both bios and requests. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <axboe@carl.home.kernel.dk>
Diffstat (limited to 'include')
-rw-r--r--include/linux/bio.h4
-rw-r--r--include/linux/blkdev.h33
-rw-r--r--include/scsi/scsi.h6
-rw-r--r--include/scsi/scsi_host.h7
4 files changed, 46 insertions, 4 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 5274103434a..2c3fd742160 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -496,6 +496,10 @@ static inline struct bio *bio_list_get(struct bio_list *bl)
496#define bip_for_each_vec(bvl, bip, i) \ 496#define bip_for_each_vec(bvl, bip, i) \
497 __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx) 497 __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
498 498
499#define bio_for_each_integrity_vec(_bvl, _bio, _iter) \
500 for_each_bio(_bio) \
501 bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
502
499#define bio_integrity(bio) (bio->bi_integrity != NULL) 503#define bio_integrity(bio) (bio->bi_integrity != NULL)
500 504
501extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); 505extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2c54906f678..7e661106270 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -124,6 +124,9 @@ struct request {
124 * physical address coalescing is performed. 124 * physical address coalescing is performed.
125 */ 125 */
126 unsigned short nr_phys_segments; 126 unsigned short nr_phys_segments;
127#if defined(CONFIG_BLK_DEV_INTEGRITY)
128 unsigned short nr_integrity_segments;
129#endif
127 130
128 unsigned short ioprio; 131 unsigned short ioprio;
129 132
@@ -243,6 +246,7 @@ struct queue_limits {
243 246
244 unsigned short logical_block_size; 247 unsigned short logical_block_size;
245 unsigned short max_segments; 248 unsigned short max_segments;
249 unsigned short max_integrity_segments;
246 250
247 unsigned char misaligned; 251 unsigned char misaligned;
248 unsigned char discard_misaligned; 252 unsigned char discard_misaligned;
@@ -1213,8 +1217,13 @@ struct blk_integrity {
1213extern int blk_integrity_register(struct gendisk *, struct blk_integrity *); 1217extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
1214extern void blk_integrity_unregister(struct gendisk *); 1218extern void blk_integrity_unregister(struct gendisk *);
1215extern int blk_integrity_compare(struct gendisk *, struct gendisk *); 1219extern int blk_integrity_compare(struct gendisk *, struct gendisk *);
1216extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); 1220extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
1217extern int blk_rq_count_integrity_sg(struct request *); 1221 struct scatterlist *);
1222extern int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
1223extern int blk_integrity_merge_rq(struct request_queue *, struct request *,
1224 struct request *);
1225extern int blk_integrity_merge_bio(struct request_queue *, struct request *,
1226 struct bio *);
1218 1227
1219static inline 1228static inline
1220struct blk_integrity *bdev_get_integrity(struct block_device *bdev) 1229struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
@@ -1235,16 +1244,32 @@ static inline int blk_integrity_rq(struct request *rq)
1235 return bio_integrity(rq->bio); 1244 return bio_integrity(rq->bio);
1236} 1245}
1237 1246
1247static inline void blk_queue_max_integrity_segments(struct request_queue *q,
1248 unsigned int segs)
1249{
1250 q->limits.max_integrity_segments = segs;
1251}
1252
1253static inline unsigned short
1254queue_max_integrity_segments(struct request_queue *q)
1255{
1256 return q->limits.max_integrity_segments;
1257}
1258
1238#else /* CONFIG_BLK_DEV_INTEGRITY */ 1259#else /* CONFIG_BLK_DEV_INTEGRITY */
1239 1260
1240#define blk_integrity_rq(rq) (0) 1261#define blk_integrity_rq(rq) (0)
1241#define blk_rq_count_integrity_sg(a) (0) 1262#define blk_rq_count_integrity_sg(a, b) (0)
1242#define blk_rq_map_integrity_sg(a, b) (0) 1263#define blk_rq_map_integrity_sg(a, b, c) (0)
1243#define bdev_get_integrity(a) (0) 1264#define bdev_get_integrity(a) (0)
1244#define blk_get_integrity(a) (0) 1265#define blk_get_integrity(a) (0)
1245#define blk_integrity_compare(a, b) (0) 1266#define blk_integrity_compare(a, b) (0)
1246#define blk_integrity_register(a, b) (0) 1267#define blk_integrity_register(a, b) (0)
1247#define blk_integrity_unregister(a) do { } while (0); 1268#define blk_integrity_unregister(a) do { } while (0);
1269#define blk_queue_max_integrity_segments(a, b) do { } while (0);
1270#define queue_max_integrity_segments(a) (0)
1271#define blk_integrity_merge_rq(a, b, c) (0)
1272#define blk_integrity_merge_bio(a, b, c) (0)
1248 1273
1249#endif /* CONFIG_BLK_DEV_INTEGRITY */ 1274#endif /* CONFIG_BLK_DEV_INTEGRITY */
1250 1275
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8fcb6e0e9e7..d63533a4a59 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@ struct scsi_cmnd;
32#endif 32#endif
33 33
34/* 34/*
35 * DIX-capable adapters effectively support infinite chaining for the
36 * protection information scatterlist
37 */
38#define SCSI_MAX_PROT_SG_SEGMENTS 0xFFFF
39
40/*
35 * Special value for scanning to specify scanning or rescanning of all 41 * Special value for scanning to specify scanning or rescanning of all
36 * possible channels, (target) ids, or luns on a given shost. 42 * possible channels, (target) ids, or luns on a given shost.
37 */ 43 */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index b7bdecb7b76..d0a6a845f20 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -388,6 +388,7 @@ struct scsi_host_template {
388 * of scatter-gather. 388 * of scatter-gather.
389 */ 389 */
390 unsigned short sg_tablesize; 390 unsigned short sg_tablesize;
391 unsigned short sg_prot_tablesize;
391 392
392 /* 393 /*
393 * Set this if the host adapter has limitations beside segment count. 394 * Set this if the host adapter has limitations beside segment count.
@@ -599,6 +600,7 @@ struct Scsi_Host {
599 int can_queue; 600 int can_queue;
600 short cmd_per_lun; 601 short cmd_per_lun;
601 short unsigned int sg_tablesize; 602 short unsigned int sg_tablesize;
603 short unsigned int sg_prot_tablesize;
602 short unsigned int max_sectors; 604 short unsigned int max_sectors;
603 unsigned long dma_boundary; 605 unsigned long dma_boundary;
604 /* 606 /*
@@ -823,6 +825,11 @@ static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost)
823 return shost->prot_capabilities; 825 return shost->prot_capabilities;
824} 826}
825 827
828static inline int scsi_host_prot_dma(struct Scsi_Host *shost)
829{
830 return shost->prot_capabilities >= SHOST_DIX_TYPE0_PROTECTION;
831}
832
826static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type) 833static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
827{ 834{
828 static unsigned char cap[] = { 0, 835 static unsigned char cap[] = { 0,