qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qd


From: Kevin O'Connor
Subject: Re: [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property
Date: Thu, 30 Jul 2015 14:04:29 -0400
User-agent: Mutt/1.5.23 (2014-03-12)

On Wed, Jul 29, 2015 at 10:01:03AM +0100, Stefan Hajnoczi wrote:
> On Tue, Jul 28, 2015 at 12:22:43PM -0400, Kevin O'Connor wrote:
> > Commit 19109131 disabled the sdhci-pci support because it used
> > drive_get_next().  This patch reenables sdhci-pci and changes it to
> > pass the drive via a qdev property - for example:
> >  -device sdhci-pci,drive=drive0 -drive id=drive0,if=sd,file=myimage
> > 
> > Signed-off-by: Kevin O'Connor <address@hidden>
> > ---
> > 
> > This patch only changes the SDHCI PCI code - the sysbus code continues
> > to use drive_get_next().
> > 
> > The call to blk_detach_dev() is suspicious - I added it because
> > sd.c:sd_init() calls blk_attach_dev_nofail() and that causes a crash
> > if the drive is already attached to the PCI device.  It's not clear to
> > me how this should be wired up though.
> 
> Ugly bits:
> 
> hw/core/qdev-properties-system.c:release_drive() will call
> blk_detach_dev(*ptr, dev) and assert(blk->dev == dev) will fail.

Thanks for reviewing and catching the above.

> The SD card (SDState) isn't a DeviceState, it's a plain old C struct.
> So it doesn't have the qdev machinery for its own drive property.
> 
> There is no detach call paired with sd_init() attach, so that's ugly
> too.
> 
> A solution:
> 
> Add an sd_init() flag argument that skips the attach/set_dev_ops calls.
> Make sd_cardchange() externally visible and then call blk_set_dev_ops()
> from sdhci.c instead.
> 
> That way, existing users can rely on the semi-broken but convenient
> sd_init() behavior.  sdhci can forward the .change_media_cb() to
> sd_cardchange() keep itself as the blk->dev pointer.

I can do that.  However, another solution seems to be to just change
the blk_attach_dev_nofail() call in sd.c:sd_init() to blk_attach_dev()
and ignore any errors.  (Example patch below.)

I'm confused by what blk_attach_dev() attempts to accomplish.  The
BlockBackend->dev field is only ever used as a boolean flag.  (There
are four users of it - blk_dev_has_removable_media,
drive_check_orphaned, hmp_drive_del, pci_piix3_xen_ide_unplug - the
first three use it only as a non-NULL check and the fourth only uses
it to make blk_detach_dev() succeed.)  To the SD code, it doesn't
matter if it sets the "attached flag" or if something else has already
set that flag.  (Is it even important to set the flag at all?)

Thoughts?

-Kevin


diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a1ff465..29cd22c 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -493,7 +493,7 @@ SDState *sd_init(BlockBackend *blk, bool is_spi)
     sd->blk = blk;
     sd_reset(sd);
     if (sd->blk) {
-        blk_attach_dev_nofail(sd->blk, sd);
+        blk_attach_dev(sd->blk, sd);
         blk_set_dev_ops(sd->blk, &sd_block_ops, sd);
     }
     vmstate_register(NULL, -1, &sd_vmstate, sd);
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index e63367b..6e01de7 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1142,13 +1142,9 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState 
*s)
     }
 }
 
-static void sdhci_initfn(SDHCIState *s)
+static void sdhci_initfn(SDHCIState *s, BlockBackend *blk)
 {
-    DriveInfo *di;
-
-    /* FIXME use a qdev drive property instead of drive_get_next() */
-    di = drive_get_next(IF_SD);
-    s->card = sd_init(di ? blk_by_legacy_dinfo(di) : NULL, false);
+    s->card = sd_init(blk, false);
     if (s->card == NULL) {
         exit(1);
     }
@@ -1214,7 +1210,8 @@ const VMStateDescription sdhci_vmstate = {
 
 /* Capabilities registers provide information on supported features of this
  * specific host controller implementation */
-static Property sdhci_properties[] = {
+static Property sdhci_pci_properties[] = {
+    DEFINE_BLOCK_PROPERTIES(SDHCIState, conf),
     DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
             SDHC_CAPAB_REG_DEFAULT),
     DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
@@ -1226,7 +1223,7 @@ static void sdhci_pci_realize(PCIDevice *dev, Error 
**errp)
     SDHCIState *s = PCI_SDHCI(dev);
     dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */
     dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
-    sdhci_initfn(s);
+    sdhci_initfn(s, s->conf.blk);
     s->buf_maxsz = sdhci_get_fifolen(s);
     s->fifo_buffer = g_malloc0(s->buf_maxsz);
     s->irq = pci_allocate_irq(dev);
@@ -1253,9 +1250,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void 
*data)
     k->class_id = PCI_CLASS_SYSTEM_SDHCI;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->vmsd = &sdhci_vmstate;
-    dc->props = sdhci_properties;
-    /* Reason: realize() method uses drive_get_next() */
-    dc->cannot_instantiate_with_device_add_yet = true;
+    dc->props = sdhci_pci_properties;
 }
 
 static const TypeInfo sdhci_pci_info = {
@@ -1265,10 +1260,21 @@ static const TypeInfo sdhci_pci_info = {
     .class_init = sdhci_pci_class_init,
 };
 
+static Property sdhci_sysbus_properties[] = {
+    DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
+            SDHC_CAPAB_REG_DEFAULT),
+    DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void sdhci_sysbus_init(Object *obj)
 {
     SDHCIState *s = SYSBUS_SDHCI(obj);
-    sdhci_initfn(s);
+    DriveInfo *di;
+
+    /* FIXME use a qdev drive property instead of drive_get_next() */
+    di = drive_get_next(IF_SD);
+    sdhci_initfn(s, di ? blk_by_legacy_dinfo(di) : NULL);
 }
 
 static void sdhci_sysbus_finalize(Object *obj)
@@ -1295,7 +1301,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, 
void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &sdhci_vmstate;
-    dc->props = sdhci_properties;
+    dc->props = sdhci_sysbus_properties;
     dc->realize = sdhci_sysbus_realize;
     /* Reason: instance_init() method uses drive_get_next() */
     dc->cannot_instantiate_with_device_add_yet = true;
diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci.h
index 3352d23..e2de92d 100644
--- a/hw/sd/sdhci.h
+++ b/hw/sd/sdhci.h
@@ -26,6 +26,7 @@
 #define SDHCI_H
 
 #include "qemu-common.h"
+#include "hw/block/block.h"
 #include "hw/pci/pci.h"
 #include "hw/sysbus.h"
 #include "hw/sd.h"
@@ -239,6 +240,7 @@ typedef struct SDHCIState {
     };
     SDState *card;
     MemoryRegion iomem;
+    BlockConf conf;
 
     QEMUTimer *insert_timer;       /* timer for 'changing' sd card. */
     QEMUTimer *transfer_timer;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]