aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorJohan Rudholm <johan.rudholm@stericsson.com>2011-12-02 02:51:06 -0500
committerChris Ball <cjb@laptop.org>2012-01-11 23:58:43 -0500
commitadd710eaa88606de8ba98a014d37178579e6dbaf (patch)
tree2d719508cabd213d5923cef95fdd3d6c9c40d977 /drivers/mmc/card
parent92df954df3422a7dcf99eea34cf4cb68bb06ea08 (diff)
mmc: boot partition ro lock support
Enable boot partitions to be read-only locked until next power on via a sysfs entry. There will be one sysfs entry for each boot partition: /sys/block/mmcblkXbootY/ro_lock_until_next_power_on Each boot partition is locked by writing 1 to its file. Signed-off-by: Johan Rudholm <johan.rudholm@stericsson.com> Signed-off-by: John Beckett <john.beckett@stericsson.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c121
1 files changed, 113 insertions, 8 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index ad0fb8d74dda..0c959c96005e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -107,6 +107,8 @@ struct mmc_blk_data {
107 */ 107 */
108 unsigned int part_curr; 108 unsigned int part_curr;
109 struct device_attribute force_ro; 109 struct device_attribute force_ro;
110 struct device_attribute power_ro_lock;
111 int area_type;
110}; 112};
111 113
112static DEFINE_MUTEX(open_lock); 114static DEFINE_MUTEX(open_lock);
@@ -165,6 +167,70 @@ static void mmc_blk_put(struct mmc_blk_data *md)
165 mutex_unlock(&open_lock); 167 mutex_unlock(&open_lock);
166} 168}
167 169
170static ssize_t power_ro_lock_show(struct device *dev,
171 struct device_attribute *attr, char *buf)
172{
173 int ret;
174 struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
175 struct mmc_card *card = md->queue.card;
176 int locked = 0;
177
178 if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
179 locked = 2;
180 else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
181 locked = 1;
182
183 ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
184
185 return ret;
186}
187
188static ssize_t power_ro_lock_store(struct device *dev,
189 struct device_attribute *attr, const char *buf, size_t count)
190{
191 int ret;
192 struct mmc_blk_data *md, *part_md;
193 struct mmc_card *card;
194 unsigned long set;
195
196 if (kstrtoul(buf, 0, &set))
197 return -EINVAL;
198
199 if (set != 1)
200 return count;
201
202 md = mmc_blk_get(dev_to_disk(dev));
203 card = md->queue.card;
204
205 mmc_claim_host(card->host);
206
207 ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
208 card->ext_csd.boot_ro_lock |
209 EXT_CSD_BOOT_WP_B_PWR_WP_EN,
210 card->ext_csd.part_time);
211 if (ret)
212 pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
213 else
214 card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
215
216 mmc_release_host(card->host);
217
218 if (!ret) {
219 pr_info("%s: Locking boot partition ro until next power on\n",
220 md->disk->disk_name);
221 set_disk_ro(md->disk, 1);
222
223 list_for_each_entry(part_md, &md->part, part)
224 if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
225 pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
226 set_disk_ro(part_md->disk, 1);
227 }
228 }
229
230 mmc_blk_put(md);
231 return count;
232}
233
168static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, 234static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
169 char *buf) 235 char *buf)
170{ 236{
@@ -1347,7 +1413,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
1347 struct device *parent, 1413 struct device *parent,
1348 sector_t size, 1414 sector_t size,
1349 bool default_ro, 1415 bool default_ro,
1350 const char *subname) 1416 const char *subname,
1417 int area_type)
1351{ 1418{
1352 struct mmc_blk_data *md; 1419 struct mmc_blk_data *md;
1353 int devidx, ret; 1420 int devidx, ret;
@@ -1372,11 +1439,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
1372 if (!subname) { 1439 if (!subname) {
1373 md->name_idx = find_first_zero_bit(name_use, max_devices); 1440 md->name_idx = find_first_zero_bit(name_use, max_devices);
1374 __set_bit(md->name_idx, name_use); 1441 __set_bit(md->name_idx, name_use);
1375 } 1442 } else
1376 else
1377 md->name_idx = ((struct mmc_blk_data *) 1443 md->name_idx = ((struct mmc_blk_data *)
1378 dev_to_disk(parent)->private_data)->name_idx; 1444 dev_to_disk(parent)->private_data)->name_idx;
1379 1445
1446 md->area_type = area_type;
1447
1380 /* 1448 /*
1381 * Set the read-only status based on the supported commands 1449 * Set the read-only status based on the supported commands
1382 * and the write protect switch. 1450 * and the write protect switch.
@@ -1470,7 +1538,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
1470 size = card->csd.capacity << (card->csd.read_blkbits - 9); 1538 size = card->csd.capacity << (card->csd.read_blkbits - 9);
1471 } 1539 }
1472 1540
1473 md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL); 1541 md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
1542 MMC_BLK_DATA_AREA_MAIN);
1474 return md; 1543 return md;
1475} 1544}
1476 1545
@@ -1479,13 +1548,14 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
1479 unsigned int part_type, 1548 unsigned int part_type,
1480 sector_t size, 1549 sector_t size,
1481 bool default_ro, 1550 bool default_ro,
1482 const char *subname) 1551 const char *subname,
1552 int area_type)
1483{ 1553{
1484 char cap_str[10]; 1554 char cap_str[10];
1485 struct mmc_blk_data *part_md; 1555 struct mmc_blk_data *part_md;
1486 1556
1487 part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, 1557 part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
1488 subname); 1558 subname, area_type);
1489 if (IS_ERR(part_md)) 1559 if (IS_ERR(part_md))
1490 return PTR_ERR(part_md); 1560 return PTR_ERR(part_md);
1491 part_md->part_type = part_type; 1561 part_md->part_type = part_type;
@@ -1518,7 +1588,8 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
1518 card->part[idx].part_cfg, 1588 card->part[idx].part_cfg,
1519 card->part[idx].size >> 9, 1589 card->part[idx].size >> 9,
1520 card->part[idx].force_ro, 1590 card->part[idx].force_ro,
1521 card->part[idx].name); 1591 card->part[idx].name,
1592 card->part[idx].area_type);
1522 if (ret) 1593 if (ret)
1523 return ret; 1594 return ret;
1524 } 1595 }
@@ -1547,9 +1618,16 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
1547 1618
1548static void mmc_blk_remove_req(struct mmc_blk_data *md) 1619static void mmc_blk_remove_req(struct mmc_blk_data *md)
1549{ 1620{
1621 struct mmc_card *card;
1622
1550 if (md) { 1623 if (md) {
1624 card = md->queue.card;
1551 if (md->disk->flags & GENHD_FL_UP) { 1625 if (md->disk->flags & GENHD_FL_UP) {
1552 device_remove_file(disk_to_dev(md->disk), &md->force_ro); 1626 device_remove_file(disk_to_dev(md->disk), &md->force_ro);
1627 if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
1628 card->ext_csd.boot_ro_lockable)
1629 device_remove_file(disk_to_dev(md->disk),
1630 &md->power_ro_lock);
1553 1631
1554 /* Stop new requests from getting into the queue */ 1632 /* Stop new requests from getting into the queue */
1555 del_gendisk(md->disk); 1633 del_gendisk(md->disk);
@@ -1578,6 +1656,7 @@ static void mmc_blk_remove_parts(struct mmc_card *card,
1578static int mmc_add_disk(struct mmc_blk_data *md) 1656static int mmc_add_disk(struct mmc_blk_data *md)
1579{ 1657{
1580 int ret; 1658 int ret;
1659 struct mmc_card *card = md->queue.card;
1581 1660
1582 add_disk(md->disk); 1661 add_disk(md->disk);
1583 md->force_ro.show = force_ro_show; 1662 md->force_ro.show = force_ro_show;
@@ -1587,7 +1666,33 @@ static int mmc_add_disk(struct mmc_blk_data *md)
1587 md->force_ro.attr.mode = S_IRUGO | S_IWUSR; 1666 md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
1588 ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); 1667 ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
1589 if (ret) 1668 if (ret)
1590 del_gendisk(md->disk); 1669 goto force_ro_fail;
1670
1671 if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
1672 card->ext_csd.boot_ro_lockable) {
1673 mode_t mode;
1674
1675 if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
1676 mode = S_IRUGO;
1677 else
1678 mode = S_IRUGO | S_IWUSR;
1679
1680 md->power_ro_lock.show = power_ro_lock_show;
1681 md->power_ro_lock.store = power_ro_lock_store;
1682 md->power_ro_lock.attr.mode = mode;
1683 md->power_ro_lock.attr.name =
1684 "ro_lock_until_next_power_on";
1685 ret = device_create_file(disk_to_dev(md->disk),
1686 &md->power_ro_lock);
1687 if (ret)
1688 goto power_ro_lock_fail;
1689 }
1690 return ret;
1691
1692power_ro_lock_fail:
1693 device_remove_file(disk_to_dev(md->disk), &md->force_ro);
1694force_ro_fail:
1695 del_gendisk(md->disk);
1591 1696
1592 return ret; 1697 return ret;
1593} 1698}