Merge "mmc: block: Adding device attribute for minimum sectors to start BKOPS"
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 08f7312..7dde34f 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,6 +25,15 @@
 	running parallel lmdd write and lmdd read operations and calculating
 	the max number of packed writes requests.
 
+	min_sectors_to_check_bkops_status	This attribute is used to
+	determine whether the status bit that indicates the need for BKOPS
+	should be checked. The value is stored in this attribute represents
+	the minimum number of sectors that needs to be changed in the device
+	(written or discarded) in order to require the status-bit of BKOPS
+	to be checked. The value can modified via sysfs by writing the
+	required value to:
+	/sys/block/<block_dev_name>/min_sectors_to_check_bkops_status
+
 SD and MMC Device Attributes
 ============================
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index b9cd8ec..7387d9a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -121,6 +121,7 @@
 	struct device_attribute force_ro;
 	struct device_attribute power_ro_lock;
 	struct device_attribute num_wr_reqs_to_start_packing;
+	struct device_attribute min_sectors_to_check_bkops_status;
 	int	area_type;
 };
 
@@ -306,6 +307,48 @@
 	return count;
 }
 
+static ssize_t
+min_sectors_to_check_bkops_status_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	unsigned int min_sectors_to_check_bkops_status;
+	struct mmc_card *card = md->queue.card;
+	int ret;
+
+	if (!card)
+		return -EINVAL;
+
+	min_sectors_to_check_bkops_status =
+		card->bkops_info.min_sectors_to_queue_delayed_work;
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		       min_sectors_to_check_bkops_status);
+
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t
+min_sectors_to_check_bkops_status_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int value;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+
+	if (!card)
+		return -EINVAL;
+
+	sscanf(buf, "%d", &value);
+	if (value >= 0)
+		card->bkops_info.min_sectors_to_queue_delayed_work = value;
+
+	mmc_blk_put(md);
+	return count;
+}
+
 static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 {
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -2316,6 +2359,19 @@
 	if (ret)
 		goto power_ro_lock_fail;
 
+	md->min_sectors_to_check_bkops_status.show =
+		min_sectors_to_check_bkops_status_show;
+	md->min_sectors_to_check_bkops_status.store =
+		min_sectors_to_check_bkops_status_store;
+	sysfs_attr_init(&md->min_sectors_to_check_bkops_status.attr);
+	md->min_sectors_to_check_bkops_status.attr.name =
+		"min_sectors_to_check_bkops_status";
+	md->min_sectors_to_check_bkops_status.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk),
+				 &md->min_sectors_to_check_bkops_status);
+	if (ret)
+		goto power_ro_lock_fail;
+
 	return ret;
 
 power_ro_lock_fail:
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9b9e8cc..7e03e5a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -291,7 +291,7 @@
 		return;
 
 	if (card->bkops_info.sectors_changed <
-	    BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK)
+	    card->bkops_info.min_sectors_to_queue_delayed_work)
 		return;
 
 	pr_debug("%s: %s: queueing delayed_bkops_work\n",
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 457db7f..ca8b01c 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1336,6 +1336,8 @@
 					card->bkops_info.delay_ms,
 				      card->bkops_info.host_suspend_tout_ms/2);
 
+			card->bkops_info.min_sectors_to_queue_delayed_work =
+				BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK;
 		}
 	}
 
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 257bcc0..477733c 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -248,6 +248,7 @@
 	struct delayed_work	dw;
 	unsigned int		host_suspend_tout_ms;
 	unsigned int		delay_ms;
+	unsigned int		min_sectors_to_queue_delayed_work;
 /*
  * A default time for checking the need for non urgent BKOPS once mmcqd
  * is idle.