From 320f929d8c790eb5336b3847d45538fd8b7201a2 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Wed, 31 Aug 2016 14:40:06 +0200 Subject: [PATCH] sd: Fix rw_max for devices that report an optimal xfer size backported from upstream kernel --- Makefile | 2 ++ sd-fix-rw_max.patch | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 sd-fix-rw_max.patch diff --git a/Makefile b/Makefile index e281e7a..8c724fe 100644 --- a/Makefile +++ b/Makefile @@ -266,6 +266,8 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR} cd ${KERNEL_SRC}; patch -p1 < ../watchdog_implement-mei-iamt-driver.patch cd ${KERNEL_SRC}; patch -p1 < ../mei_drop-watchdog-code.patch cd ${KERNEL_SRC}; patch -p1 < ../mei_bus-whitelist-watchdog-client.patch + #sd: Fix rw_max for devices that report an optimal xfer size + cd ${KERNEL_SRC}; patch -p1 < ../sd-fix-rw_max.patch sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' touch $@ diff --git a/sd-fix-rw_max.patch b/sd-fix-rw_max.patch new file mode 100644 index 0000000..e0752ee --- /dev/null +++ b/sd-fix-rw_max.patch @@ -0,0 +1,60 @@ +From 6b7e9cde49691e04314342b7dce90c67ad567fcc Mon Sep 17 00:00:00 2001 +From: "Martin K. Petersen" +Date: Thu, 12 May 2016 22:17:34 -0400 +Subject: sd: Fix rw_max for devices that report an optimal xfer size + +For historic reasons, io_opt is in bytes and max_sectors in block layer +sectors. This interface inconsistency is error prone and should be +fixed. But for 4.4--4.7 let's make the unit difference explicit via a +wrapper function. + +Fixes: d0eb20a863ba ("sd: Optimal I/O size is in bytes, not sectors") +Cc: stable@vger.kernel.org # 4.4+ +Reported-by: Fam Zheng +Reviewed-by: Bart Van Assche +Reviewed-by: Christoph Hellwig +Tested-by: Andrew Patterson +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/sd.c | 8 ++++---- + drivers/scsi/sd.h | 5 +++++ + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index f459dff..60bff78 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2867,10 +2867,10 @@ static int sd_revalidate_disk(struct gendisk *disk) + if (sdkp->opt_xfer_blocks && + sdkp->opt_xfer_blocks <= dev_max && + sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS && +- sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE) +- rw_max = q->limits.io_opt = +- sdkp->opt_xfer_blocks * sdp->sector_size; +- else ++ logical_to_bytes(sdp, sdkp->opt_xfer_blocks) >= PAGE_SIZE) { ++ q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); ++ rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); ++ } else + rw_max = BLK_DEF_MAX_SECTORS; + + /* Combine with controller limits */ +diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h +index 654630b..765a6f1 100644 +--- a/drivers/scsi/sd.h ++++ b/drivers/scsi/sd.h +@@ -151,6 +151,11 @@ static inline sector_t logical_to_sectors(struct scsi_device *sdev, sector_t blo + return blocks << (ilog2(sdev->sector_size) - 9); + } + ++static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t blocks) ++{ ++ return blocks * sdev->sector_size; ++} ++ + /* + * A DIF-capable target device can be formatted with different + * protection schemes. Currently 0 through 3 are defined: +-- +cgit v0.12 + -- 2.39.2