Commit 873cc1d7775ed5de07e6722c7ff423080c2e8f71
Committed by
Tom Rini
1 parent
7c4213f6a5
Exists in
v2017.01-smarct4x
and in
30 other branches
mmc: store hwpart in the block device
This will allow us to have multiple block device structs each referring to the same eMMC device, yet different HW partitions. For now, there is still a single block device per eMMC device. As before, this block device always accesses whichever HW partition was most recently selected. Clients wishing to make use of multiple block devices referring to different HW partitions can simply take a copy of this block device once it points at the correct HW partition, and use each one as they wish. This feature will be used by the next patch. In the future, perhaps get_device() could be enhanced to return a dynamically allocated block device struct, to avoid the client needing to copy it in order to maintain multiple block devices. However, this would require all users to be updated to free those block device structs at some point, which is rather a large change. Most callers of mmc_switch_part() wish to permanently switch the default MMC block device's HW partition. Enhance mmc_switch_part() so that it does this. This removes the need for callers to do this. However, common/env_mmc.c needs to save and restore the current HW partition. Make it do this more explicitly. Replace use of mmc_switch_part() with mmc_select_hwpart() in order to remove duplicate code that skips the call if that HW partition is already selected. Signed-off-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Tom Rini <trini@konsulko.com>
Showing 7 changed files with 40 additions and 47 deletions Side-by-side Diff
common/cmd_mmc.c
... | ... | @@ -312,20 +312,14 @@ |
312 | 312 | return CMD_RET_FAILURE; |
313 | 313 | } |
314 | 314 | /* Switch to the RPMB partition */ |
315 | - original_part = mmc->part_num; | |
316 | - if (mmc->part_num != MMC_PART_RPMB) { | |
317 | - if (mmc_switch_part(curr_device, MMC_PART_RPMB) != 0) | |
318 | - return CMD_RET_FAILURE; | |
319 | - mmc->part_num = MMC_PART_RPMB; | |
320 | - } | |
315 | + original_part = mmc->block_dev.part_num; | |
316 | + if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0) | |
317 | + return CMD_RET_FAILURE; | |
321 | 318 | ret = cp->cmd(cmdtp, flag, argc, argv); |
322 | 319 | |
323 | 320 | /* Return to original partition */ |
324 | - if (mmc->part_num != original_part) { | |
325 | - if (mmc_switch_part(curr_device, original_part) != 0) | |
326 | - return CMD_RET_FAILURE; | |
327 | - mmc->part_num = original_part; | |
328 | - } | |
321 | + if (mmc_select_hwpart(curr_device, original_part) != 0) | |
322 | + return CMD_RET_FAILURE; | |
329 | 323 | return ret; |
330 | 324 | } |
331 | 325 | #endif |
... | ... | @@ -483,7 +477,7 @@ |
483 | 477 | printf("mmc%d is current device\n", curr_device); |
484 | 478 | else |
485 | 479 | printf("mmc%d(part %d) is current device\n", |
486 | - curr_device, mmc->part_num); | |
480 | + curr_device, mmc->block_dev.hwpart); | |
487 | 481 | |
488 | 482 | return CMD_RET_SUCCESS; |
489 | 483 | } |
common/env_mmc.c
... | ... | @@ -69,6 +69,8 @@ |
69 | 69 | return CONFIG_SYS_MMC_ENV_PART; |
70 | 70 | } |
71 | 71 | |
72 | +static unsigned char env_mmc_orig_hwpart; | |
73 | + | |
72 | 74 | static int mmc_set_env_part(struct mmc *mmc) |
73 | 75 | { |
74 | 76 | uint part = mmc_get_env_part(mmc); |
... | ... | @@ -79,11 +81,10 @@ |
79 | 81 | dev = 0; |
80 | 82 | #endif |
81 | 83 | |
82 | - if (part != mmc->part_num) { | |
83 | - ret = mmc_switch_part(dev, part); | |
84 | - if (ret) | |
85 | - puts("MMC partition switch failed\n"); | |
86 | - } | |
84 | + env_mmc_orig_hwpart = mmc->block_dev.hwpart; | |
85 | + ret = mmc_select_hwpart(dev, part); | |
86 | + if (ret) | |
87 | + puts("MMC partition switch failed\n"); | |
87 | 88 | |
88 | 89 | return ret; |
89 | 90 | } |
... | ... | @@ -113,8 +114,7 @@ |
113 | 114 | #ifdef CONFIG_SPL_BUILD |
114 | 115 | dev = 0; |
115 | 116 | #endif |
116 | - if (mmc_get_env_part(mmc) != mmc->part_num) | |
117 | - mmc_switch_part(dev, mmc->part_num); | |
117 | + mmc_select_hwpart(dev, env_mmc_orig_hwpart); | |
118 | 118 | #endif |
119 | 119 | } |
120 | 120 |
drivers/dfu/dfu_mmc.c
... | ... | @@ -20,23 +20,6 @@ |
20 | 20 | static long dfu_file_buf_len; |
21 | 21 | static long dfu_file_buf_filled; |
22 | 22 | |
23 | -static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part) | |
24 | -{ | |
25 | - int ret; | |
26 | - | |
27 | - if (part == mmc->part_num) | |
28 | - return 0; | |
29 | - | |
30 | - ret = mmc_switch_part(dfu->data.mmc.dev_num, part); | |
31 | - if (ret) { | |
32 | - error("Cannot switch to partition %d\n", part); | |
33 | - return ret; | |
34 | - } | |
35 | - mmc->part_num = part; | |
36 | - | |
37 | - return 0; | |
38 | -} | |
39 | - | |
40 | 23 | static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, |
41 | 24 | u64 offset, void *buf, long *len) |
42 | 25 | { |
... | ... | @@ -66,8 +49,9 @@ |
66 | 49 | } |
67 | 50 | |
68 | 51 | if (dfu->data.mmc.hw_partition >= 0) { |
69 | - part_num_bkp = mmc->part_num; | |
70 | - ret = mmc_access_part(dfu, mmc, dfu->data.mmc.hw_partition); | |
52 | + part_num_bkp = mmc->block_dev.hwpart; | |
53 | + ret = mmc_select_hwpart(dfu->data.mmc.dev_num, | |
54 | + dfu->data.mmc.hw_partition); | |
71 | 55 | if (ret) |
72 | 56 | return ret; |
73 | 57 | } |
74 | 58 | |
... | ... | @@ -91,12 +75,12 @@ |
91 | 75 | if (n != blk_count) { |
92 | 76 | error("MMC operation failed"); |
93 | 77 | if (dfu->data.mmc.hw_partition >= 0) |
94 | - mmc_access_part(dfu, mmc, part_num_bkp); | |
78 | + mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp); | |
95 | 79 | return -EIO; |
96 | 80 | } |
97 | 81 | |
98 | 82 | if (dfu->data.mmc.hw_partition >= 0) { |
99 | - ret = mmc_access_part(dfu, mmc, part_num_bkp); | |
83 | + ret = mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp); | |
100 | 84 | if (ret) |
101 | 85 | return ret; |
102 | 86 | } |
drivers/mmc/mmc.c
... | ... | @@ -238,6 +238,7 @@ |
238 | 238 | lbaint_t blkcnt, void *dst) |
239 | 239 | { |
240 | 240 | int dev_num = block_dev->dev; |
241 | + int err; | |
241 | 242 | lbaint_t cur, blocks_todo = blkcnt; |
242 | 243 | |
243 | 244 | if (blkcnt == 0) |
... | ... | @@ -247,6 +248,10 @@ |
247 | 248 | if (!mmc) |
248 | 249 | return 0; |
249 | 250 | |
251 | + err = mmc_select_hwpart(dev_num, block_dev->hwpart); | |
252 | + if (err < 0) | |
253 | + return 0; | |
254 | + | |
250 | 255 | if ((start + blkcnt) > mmc->block_dev.lba) { |
251 | 256 | #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) |
252 | 257 | printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", |
... | ... | @@ -581,7 +586,7 @@ |
581 | 586 | if (!mmc) |
582 | 587 | return -ENODEV; |
583 | 588 | |
584 | - if (mmc->part_num == hwpart) | |
589 | + if (mmc->block_dev.hwpart == hwpart) | |
585 | 590 | return 0; |
586 | 591 | |
587 | 592 | if (mmc->part_config == MMCPART_NOAVAILABLE) { |
... | ... | @@ -593,8 +598,6 @@ |
593 | 598 | if (ret) |
594 | 599 | return ret; |
595 | 600 | |
596 | - mmc->part_num = hwpart; | |
597 | - | |
598 | 601 | return 0; |
599 | 602 | } |
600 | 603 | |
601 | 604 | |
... | ... | @@ -615,8 +618,10 @@ |
615 | 618 | * Set the capacity if the switch succeeded or was intended |
616 | 619 | * to return to representing the raw device. |
617 | 620 | */ |
618 | - if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) | |
621 | + if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) { | |
619 | 622 | ret = mmc_set_capacity(mmc, part_num); |
623 | + mmc->block_dev.hwpart = part_num; | |
624 | + } | |
620 | 625 | |
621 | 626 | return ret; |
622 | 627 | } |
... | ... | @@ -1326,7 +1331,7 @@ |
1326 | 1331 | mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET]; |
1327 | 1332 | } |
1328 | 1333 | |
1329 | - err = mmc_set_capacity(mmc, mmc->part_num); | |
1334 | + err = mmc_set_capacity(mmc, mmc->block_dev.hwpart); | |
1330 | 1335 | if (err) |
1331 | 1336 | return err; |
1332 | 1337 | |
... | ... | @@ -1467,6 +1472,7 @@ |
1467 | 1472 | |
1468 | 1473 | /* fill in device description */ |
1469 | 1474 | mmc->block_dev.lun = 0; |
1475 | + mmc->block_dev.hwpart = 0; | |
1470 | 1476 | mmc->block_dev.type = 0; |
1471 | 1477 | mmc->block_dev.blksz = mmc->read_bl_len; |
1472 | 1478 | mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz); |
... | ... | @@ -1626,7 +1632,7 @@ |
1626 | 1632 | return err; |
1627 | 1633 | |
1628 | 1634 | /* The internal partition reset to user partition(0) at every CMD0*/ |
1629 | - mmc->part_num = 0; | |
1635 | + mmc->block_dev.hwpart = 0; | |
1630 | 1636 | |
1631 | 1637 | /* Test for SD version 2 */ |
1632 | 1638 | err = mmc_send_if_cond(mmc); |
drivers/mmc/mmc_write.c
... | ... | @@ -78,6 +78,10 @@ |
78 | 78 | if (!mmc) |
79 | 79 | return -1; |
80 | 80 | |
81 | + err = mmc_select_hwpart(dev_num, block_dev->hwpart); | |
82 | + if (err < 0) | |
83 | + return -1; | |
84 | + | |
81 | 85 | /* |
82 | 86 | * We want to see if the requested start or total block count are |
83 | 87 | * unaligned. We discard the whole numbers and only care about the |
84 | 88 | |
... | ... | @@ -172,9 +176,14 @@ |
172 | 176 | { |
173 | 177 | int dev_num = block_dev->dev; |
174 | 178 | lbaint_t cur, blocks_todo = blkcnt; |
179 | + int err; | |
175 | 180 | |
176 | 181 | struct mmc *mmc = find_mmc_device(dev_num); |
177 | 182 | if (!mmc) |
183 | + return 0; | |
184 | + | |
185 | + err = mmc_select_hwpart(dev_num, block_dev->hwpart); | |
186 | + if (err < 0) | |
178 | 187 | return 0; |
179 | 188 | |
180 | 189 | if (mmc_set_blocklen(mmc, mmc->write_bl_len)) |
include/mmc.h
include/part.h
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | unsigned char part_type; /* partition type */ |
19 | 19 | unsigned char target; /* target SCSI ID */ |
20 | 20 | unsigned char lun; /* target LUN */ |
21 | + unsigned char hwpart; /* HW partition, e.g. for eMMC */ | |
21 | 22 | unsigned char type; /* device type */ |
22 | 23 | unsigned char removable; /* removable device */ |
23 | 24 | #ifdef CONFIG_LBA48 |