sandbox: pci: Remember the device being emulated
authorSimon Glass <sjg@chromium.org>
Sat, 21 Sep 2019 20:32:41 +0000 (14:32 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 11 Oct 2019 09:37:15 +0000 (17:37 +0800)
Add a field to the PCI emulator per-device data which records which device
is being emulated. This is useful when the emulator needs to check the
device for something.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
[bmeng: rebase the patch against u-boot-x86/master to get it applied cleanly]
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
drivers/pci/pci-emul-uclass.c
include/pci.h

index 0dcf937d9a67bc28a562e6496d3c5cbb68935416..0f63e491a79645614641e5c273e8f9f5a9a78e60 100644 (file)
@@ -18,6 +18,7 @@ struct sandbox_pci_emul_priv {
 int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn,
                         struct udevice **containerp, struct udevice **emulp)
 {
+       struct pci_emul_uc_priv *upriv;
        struct udevice *dev;
        int ret;
 
@@ -30,16 +31,32 @@ int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn,
        }
        *containerp = dev;
 
-       /*
-        * See commit 4345998ae9df,
-        * "pci: sandbox: Support dynamically binding device driver"
-        */
        ret = uclass_get_device_by_phandle(UCLASS_PCI_EMUL, dev, "sandbox,emul",
                                           emulp);
-       if (ret && device_get_uclass_id(dev) != UCLASS_PCI_GENERIC)
+       if (!ret) {
+               upriv = dev_get_uclass_priv(*emulp);
+
+               upriv->client = dev;
+       } else if (device_get_uclass_id(dev) != UCLASS_PCI_GENERIC) {
+               /*
+                * See commit 4345998ae9df,
+                * "pci: sandbox: Support dynamically binding device driver"
+                */
                *emulp = dev;
+       }
+
+       return 0;
+}
 
-       return *emulp ? 0 : -ENODEV;
+int sandbox_pci_get_client(struct udevice *emul, struct udevice **devp)
+{
+       struct pci_emul_uc_priv *upriv = dev_get_uclass_priv(emul);
+
+       if (!upriv->client)
+               return -ENOENT;
+       *devp = upriv->client;
+
+       return 0;
 }
 
 uint sandbox_pci_read_bar(u32 barval, int type, uint size)
@@ -88,6 +105,7 @@ UCLASS_DRIVER(pci_emul) = {
        .post_probe     = sandbox_pci_emul_post_probe,
        .pre_remove     = sandbox_pci_emul_pre_remove,
        .priv_auto_alloc_size   = sizeof(struct sandbox_pci_emul_priv),
+       .per_device_auto_alloc_size     = sizeof(struct pci_emul_uc_priv),
 };
 
 /*
index 8aa6636cfbf85441376dfc2c5ae2dbb1651cbc54..ff59ac0e69553584b83ec44d6d7657807a4836bf 100644 (file)
@@ -1490,6 +1490,17 @@ int dm_pci_find_device(unsigned int vendor, unsigned int device, int index,
  */
 int dm_pci_find_class(uint find_class, int index, struct udevice **devp);
 
+/**
+ * struct pci_emul_uc_priv - holds info about an emulator device
+ *
+ * There is always at most one emulator per client
+ *
+ * @client: Client device if any, else NULL
+ */
+struct pci_emul_uc_priv {
+       struct udevice *client;
+};
+
 /**
  * struct dm_pci_emul_ops - PCI device emulator operations
  */
@@ -1592,6 +1603,15 @@ struct dm_pci_emul_ops {
 int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn,
                         struct udevice **containerp, struct udevice **emulp);
 
+/**
+ * sandbox_pci_get_client() - Find the client for an emulation device
+ *
+ * @emul:      Emulation device to check
+ * @devp:      Returns the client device emulated by this device
+ * @return 0 if OK, -ENOENT if the device has no client yet
+ */
+int sandbox_pci_get_client(struct udevice *emul, struct udevice **devp);
+
 /**
  * pci_get_devfn() - Extract the devfn from fdt_pci_addr of the device
  *