[PULL 2/2] hw/sd: Add SDHC support for SD card SPI-mode
From: Frank Chang In SPI-mode, SD card's OCR register: Card Capacity Status (CCS) bit is not set to 1 correclty when the assigned SD image size is larger than 2GB (SDHC). This will cause the SD card to be indentified as SDSC incorrectly. CCS bit should be set to 1 if we are using SDHC. Also, as there's no power up emulation in SPI-mode. The OCR register: Card power up status bit bit (busy) should also be set to 1 when reset. (busy bit is set to LOW if the card has not finished the power up routine.) Signed-off-by: Frank Chang Reviewed-by: Jim Shu Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228125719.14712-1-frank.ch...@sifive.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/sd/sd.c | 24 +--- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index c10a1e469b7..cd67a7bac8e 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -290,12 +290,6 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) | R_OCR_CARD_CAPACITY_MASK \ | R_OCR_CARD_POWER_UP_MASK) -static void sd_set_ocr(SDState *sd) -{ -/* All voltages OK */ -sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; -} - static void sd_ocr_powerup(void *opaque) { SDState *sd = opaque; @@ -311,6 +305,22 @@ static void sd_ocr_powerup(void *opaque) } } +static void sd_set_ocr(SDState *sd) +{ +/* All voltages OK */ +sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; + +if (sd->spi) { +/* + * We don't need to emulate power up sequence in SPI-mode. + * Thus, the card's power up status bit should be set to 1 when reset. + * The card's capacity status bit should also be set if SD card size + * is larger than 2GB for SDHC support. + */ +sd_ocr_powerup(sd); +} +} + static void sd_set_scr(SDState *sd) { sd->scr[0] = 0 << 4;/* SCR structure version 1.0 */ @@ -560,6 +570,7 @@ static void sd_reset(DeviceState *dev) sd->state = sd_idle_state; sd->rca = 0x; +sd->size = size; sd_set_ocr(sd); sd_set_scr(sd); sd_set_cid(sd); @@ -574,7 +585,6 @@ static void sd_reset(DeviceState *dev) memset(sd->function_group, 0, sizeof(sd->function_group)); sd->erase_start = INVALID_ADDRESS; sd->erase_end = INVALID_ADDRESS; -sd->size = size; sd->blk_len = 0x200; sd->pwd_len = 0; sd->expecting_acmd = false; -- 2.33.1
[PULL 1/2] hw/sd/sdcard: Rename Write Protect Group variables
'wp_groups' holds a bitmap, rename it as 'wp_group_bmap'. 'wpgrps_size' is the bitmap size (in bits), rename it as 'wp_group_bits'. Patch created mechanically using: $ sed -i -e s/wp_groups/wp_group_bmap/ \ -e s/wpgrps_size/wp_group_bits/ hw/sd/sd.c Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210728181728.2012952-4-f4...@amsat.org> Reviewed-by: Alexander Bulekov --- hw/sd/sd.c | 28 ++-- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index bb5dbff68c0..c10a1e469b7 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -116,8 +116,8 @@ struct SDState { int32_t state;/* current card state, one of SDCardStates */ uint32_t vhs; bool wp_switch; -unsigned long *wp_groups; -int32_t wpgrps_size; +unsigned long *wp_group_bmap; +int32_t wp_group_bits; uint64_t size; uint32_t blk_len; uint32_t multi_blk_cnt; @@ -567,10 +567,10 @@ static void sd_reset(DeviceState *dev) sd_set_cardstatus(sd); sd_set_sdstatus(sd); -g_free(sd->wp_groups); +g_free(sd->wp_group_bmap); sd->wp_switch = sd->blk ? !blk_is_writable(sd->blk) : false; -sd->wpgrps_size = sect; -sd->wp_groups = bitmap_new(sd->wpgrps_size); +sd->wp_group_bits = sect; +sd->wp_group_bmap = bitmap_new(sd->wp_group_bits); memset(sd->function_group, 0, sizeof(sd->function_group)); sd->erase_start = INVALID_ADDRESS; sd->erase_end = INVALID_ADDRESS; @@ -673,7 +673,7 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT32(card_status, SDState), VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1), VMSTATE_UINT32(vhs, SDState), -VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size), +VMSTATE_BITMAP(wp_group_bmap, SDState, 0, wp_group_bits), VMSTATE_UINT32(blk_len, SDState), VMSTATE_UINT32(multi_blk_cnt, SDState), VMSTATE_UINT32(erase_start, SDState), @@ -803,8 +803,8 @@ static void sd_erase(SDState *sd) if (sdsc) { /* Only SDSC cards support write protect groups */ wpnum = sd_addr_to_wpnum(erase_addr); -assert(wpnum < sd->wpgrps_size); -if (test_bit(wpnum, sd->wp_groups)) { +assert(wpnum < sd->wp_group_bits); +if (test_bit(wpnum, sd->wp_group_bmap)) { sd->card_status |= WP_ERASE_SKIP; continue; } @@ -828,8 +828,8 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) */ continue; } -assert(wpnum < sd->wpgrps_size); -if (test_bit(wpnum, sd->wp_groups)) { +assert(wpnum < sd->wp_group_bits); +if (test_bit(wpnum, sd->wp_group_bmap)) { ret |= (1 << i); } } @@ -869,7 +869,7 @@ static void sd_function_switch(SDState *sd, uint32_t arg) static inline bool sd_wp_addr(SDState *sd, uint64_t addr) { -return test_bit(sd_addr_to_wpnum(addr), sd->wp_groups); +return test_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); } static void sd_lock_command(SDState *sd) @@ -897,7 +897,7 @@ static void sd_lock_command(SDState *sd) sd->card_status |= LOCK_UNLOCK_FAILED; return; } -bitmap_zero(sd->wp_groups, sd->wpgrps_size); +bitmap_zero(sd->wp_group_bmap, sd->wp_group_bits); sd->csd[14] &= ~0x10; sd->card_status &= ~CARD_IS_LOCKED; sd->pwd_len = 0; @@ -1348,7 +1348,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } sd->state = sd_programming_state; -set_bit(sd_addr_to_wpnum(addr), sd->wp_groups); +set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); /* Bzzztt Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; @@ -1370,7 +1370,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } sd->state = sd_programming_state; -clear_bit(sd_addr_to_wpnum(addr), sd->wp_groups); +clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); /* Bzzztt Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; -- 2.33.1
[PULL 0/2] SD/MMC patches for 2022-01-08
Hi Richard, This is the SD/MMC PR that ought to be sent previously. The following changes since commit b5a3d8bc9146ba22a25116cb748c97341bf99737: Merge tag 'pull-misc-20220103' of https://gitlab.com/rth7680/qemu into staging (2022-01-03 09:34:41 -0800) are available in the Git repository at: https://github.com/philmd/qemu.git tags/sdmmc-20220108 for you to fetch changes up to b66f73a0cb312c81470433dfd5275d2824bb89de: hw/sd: Add SDHC support for SD card SPI-mode (2022-01-04 08:50:28 +0100) SD/MMC patches queue - Add SDHC support for SD card SPI-mode (Frank Chang) Frank Chang (1): hw/sd: Add SDHC support for SD card SPI-mode Philippe Mathieu-Daudé (1): hw/sd/sdcard: Rename Write Protect Group variables hw/sd/sd.c | 52 +++- 1 file changed, 31 insertions(+), 21 deletions(-) -- 2.33.1
Re: [PATCH V3] block/rbd: implement bdrv_co_block_status
Am 06.01.22 um 17:01 schrieb Ilya Dryomov: > On Thu, Jan 6, 2022 at 4:27 PM Peter Lieven wrote: >> Am 05.10.21 um 10:36 schrieb Ilya Dryomov: >>> On Tue, Oct 5, 2021 at 10:19 AM Peter Lieven wrote: Am 05.10.21 um 09:54 schrieb Ilya Dryomov: > On Thu, Sep 16, 2021 at 2:21 PM Peter Lieven wrote: >> the qemu rbd driver currently lacks support for bdrv_co_block_status. >> This results mainly in incorrect progress during block operations (e.g. >> qemu-img convert with an rbd image as source). >> >> This patch utilizes the rbd_diff_iterate2 call from librbd to detect >> allocated and unallocated (all zero areas). >> >> To avoid querying the ceph OSDs for the answer this is only done if >> the image has the fast-diff feature which depends on the object-map and >> exclusive-lock features. In this case it is guaranteed that the >> information >> is present in memory in the librbd client and thus very fast. >> >> If fast-diff is not available all areas are reported to be allocated >> which is the current behaviour if bdrv_co_block_status is not >> implemented. >> >> Signed-off-by: Peter Lieven >> --- >> V2->V3: >> - check rbd_flags every time (they can change during runtime) [Ilya] >> - also check for fast-diff invalid flag [Ilya] >> - *map and *file cant be NULL [Ilya] >> - set ret = BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID in case of an >> unallocated area [Ilya] >> - typo: catched -> caught [Ilya] >> - changed wording about fast-diff, object-map and exclusive lock in >> commit msg [Ilya] >> >> V1->V2: >> - add commit comment [Stefano] >> - use failed_post_open [Stefano] >> - remove redundant assert [Stefano] >> - add macro+comment for the magic -9000 value [Stefano] >> - always set *file if its non NULL [Stefano] >> >>block/rbd.c | 126 >>1 file changed, 126 insertions(+) >> >> diff --git a/block/rbd.c b/block/rbd.c >> index dcf82b15b8..3cb24f9981 100644 >> --- a/block/rbd.c >> +++ b/block/rbd.c >> @@ -1259,6 +1259,131 @@ static ImageInfoSpecific >> *qemu_rbd_get_specific_info(BlockDriverState *bs, >>return spec_info; >>} >> >> +typedef struct rbd_diff_req { >> +uint64_t offs; >> +uint64_t bytes; >> +int exists; > Hi Peter, > > Nit: make exists a bool. The one in the callback has to be an int > because of the callback signature but let's not spread that. > >> +} rbd_diff_req; >> + >> +/* >> + * rbd_diff_iterate2 allows to interrupt the exection by returning a >> negative >> + * value in the callback routine. Choose a value that does not conflict >> with >> + * an existing exitcode and return it if we want to prematurely stop the >> + * execution because we detected a change in the allocation status. >> + */ >> +#define QEMU_RBD_EXIT_DIFF_ITERATE2 -9000 >> + >> +static int qemu_rbd_co_block_status_cb(uint64_t offs, size_t len, >> + int exists, void *opaque) >> +{ >> +struct rbd_diff_req *req = opaque; >> + >> +assert(req->offs + req->bytes <= offs); >> + >> +if (req->exists && offs > req->offs + req->bytes) { >> +/* >> + * we started in an allocated area and jumped over an >> unallocated area, >> + * req->bytes contains the length of the allocated area before >> the >> + * unallocated area. stop further processing. >> + */ >> +return QEMU_RBD_EXIT_DIFF_ITERATE2; >> +} >> +if (req->exists && !exists) { >> +/* >> + * we started in an allocated area and reached a hole. >> req->bytes >> + * contains the length of the allocated area before the hole. >> + * stop further processing. >> + */ >> +return QEMU_RBD_EXIT_DIFF_ITERATE2; > Do you have a test case for when this branch is taken? That would happen if you diff from a snapshot, the question is if it can also happen if the image is a clone from a snapshot? >> +} >> +if (!req->exists && exists && offs > req->offs) { >> +/* >> + * we started in an unallocated area and hit the first allocated >> + * block. req->bytes must be set to the length of the >> unallocated area >> + * before the allocated area. stop further processing. >> + */ >> +req->bytes = offs - req->offs; >> +return QEMU_RBD_EXIT_DIFF_ITERATE2; >> +} >> + >> +/* >> + * assert that we caught all cases above and allocation state has >> not >> + * changed during callbacks. >> + */ >> +