[PULL 2/2] hw/sd: Add SDHC support for SD card SPI-mode

2022-01-08 Thread Philippe Mathieu-Daudé
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

2022-01-08 Thread Philippe Mathieu-Daudé
'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

2022-01-08 Thread Philippe Mathieu-Daudé
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

2022-01-08 Thread Peter Lieven
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.
>> + */
>> +