qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property
@ 2015-07-28 16:22 Kevin O'Connor
  2015-07-29  9:01 ` Stefan Hajnoczi
  0 siblings, 1 reply; 4+ messages in thread
From: Kevin O'Connor @ 2015-07-28 16:22 UTC (permalink / raw)
  To: qemu-devel, Markus Armbruster, Paolo Bonzini, Stefan Hajnoczi

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 <kevin@koconnor.net>
---

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.

---
 hw/sd/sdhci.c | 34 +++++++++++++++++++++-------------
 hw/sd/sdhci.h |  2 ++
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index e63367b..296bf2a 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,9 @@ 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);
+    if (s->conf.blk)
+        blk_detach_dev(s->conf.blk, dev);
+    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 +1252,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 +1262,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 +1303,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;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property
  2015-07-28 16:22 [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property Kevin O'Connor
@ 2015-07-29  9:01 ` Stefan Hajnoczi
  2015-07-30 18:04   ` Kevin O'Connor
  0 siblings, 1 reply; 4+ messages in thread
From: Stefan Hajnoczi @ 2015-07-29  9:01 UTC (permalink / raw)
  To: Kevin O'Connor; +Cc: Paolo Bonzini, qemu-devel, Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 1493 bytes --]

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 <kevin@koconnor.net>
> ---
> 
> 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.

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.

[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property
  2015-07-29  9:01 ` Stefan Hajnoczi
@ 2015-07-30 18:04   ` Kevin O'Connor
  2015-07-31  8:29     ` Stefan Hajnoczi
  0 siblings, 1 reply; 4+ messages in thread
From: Kevin O'Connor @ 2015-07-30 18:04 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: Paolo Bonzini, qemu-devel, Markus Armbruster

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 <kevin@koconnor.net>
> > ---
> > 
> > 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;

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property
  2015-07-30 18:04   ` Kevin O'Connor
@ 2015-07-31  8:29     ` Stefan Hajnoczi
  0 siblings, 0 replies; 4+ messages in thread
From: Stefan Hajnoczi @ 2015-07-31  8:29 UTC (permalink / raw)
  To: Kevin O'Connor; +Cc: Paolo Bonzini, qemu-devel, Markus Armbruster

On Thu, Jul 30, 2015 at 7:04 PM, Kevin O'Connor <kevin@koconnor.net> wrote:
> 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 <kevin@koconnor.net>
>> > ---
>> >
>> > 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?

That looks good.  I suggest adding a comment to let the reader know
that blk_attach_dev() is anticipated to silently fail if the storage
controller is using a drive property.

Stefan

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-07-31  8:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-28 16:22 [Qemu-devel] [PATCH] sdhci: Pass drive parameter to sdhci-pci via qdev property Kevin O'Connor
2015-07-29  9:01 ` Stefan Hajnoczi
2015-07-30 18:04   ` Kevin O'Connor
2015-07-31  8:29     ` Stefan Hajnoczi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).