From: Chris Wright <chrisw@sous-sol.org>
To: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Chris Wright <chrisw@sous-sol.org>, Greg KH <greg@kroah.com>,
Mark McLoughlin <markmc@redhat.com>, kvm <kvm@vger.kernel.org>,
"linux-pci@vger.kernel.org" <linux-pci@vger.kernel.org>,
Chris Wright <chrisw@redhat.com>,
"Dugger, Donald D" <donald.d.dugger@intel.com>,
"Kay, Allen M" <allen.m.kay@intel.com>
Subject: [PATCH 2/2] PCI: add remove_id sysfs entry
Date: Mon, 23 Feb 2009 18:18:29 -0800 [thread overview]
Message-ID: <20090224021829.GC7436@sequoia.sous-sol.org> (raw)
In-Reply-To: <20090224021725.GB7436@sequoia.sous-sol.org>
This adds a remove_id sysfs entry to allow users of new_id to later
remove the added dynid. One use case is management tools that want to
dynamically bind/unbind devices to pci-stub driver while devices are
assigned to KVM guests. Rather than having to track which driver was
originally bound to the driver, a mangement tool can simply:
# echo "8086 10f5" > /sys/bus/pci/drivers/pci-stub/new_id
# echo -n 0000:00:19.0 > /sys/bus/pci/devices/0000:00:19.0/driver/unbind
# echo -n 0000:00:19.0 > /sys/bus/pci/drivers/pci-stub/bind
Guest uses device
# echo "8086 10f5" > /sys/bus/pci/drivers/pci-stub/remove_id
# echo 0000:00:19.0 > /sys/bus/pci/drivers_probe
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
---
Documentation/ABI/testing/sysfs-bus-pci | 16 ++++++
drivers/pci/pci-driver.c | 80 +++++++++++++++++++++++++++++++-
2 files changed, 94 insertions(+), 2 deletions(-)
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -99,6 +99,52 @@ store_new_id(struct device_driver *drive
}
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+/**
+ * store_remove_id - remove a PCI device ID from this driver
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
+ *
+ * Removes a dynamic pci device ID to this driver.
+ */
+static ssize_t
+store_remove_id(struct device_driver *driver, const char *buf, size_t count)
+{
+ struct pci_dynid *dynid, *n;
+ struct pci_driver *pdrv = to_pci_driver(driver);
+ __u32 vendor, device, subvendor = PCI_ANY_ID,
+ subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
+ int fields = 0;
+ int retval = -ENODEV;
+
+ fields = sscanf(buf, "%x %x %x %x %x %x",
+ &vendor, &device, &subvendor, &subdevice,
+ &class, &class_mask);
+ if (fields < 2)
+ return -EINVAL;
+
+ spin_lock(&pdrv->dynids.lock);
+ list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) {
+ struct pci_device_id *id = &dynid->id;
+ if ((id->vendor == vendor) &&
+ (id->device == device) &&
+ (subvendor == PCI_ANY_ID || id->subvendor == subvendor) &&
+ (subdevice == PCI_ANY_ID || id->subdevice == subdevice) &&
+ !((id->class ^ class) & class_mask)) {
+ list_del(&dynid->node);
+ kfree(dynid);
+ retval = 0;
+ break;
+ }
+ }
+ spin_unlock(&pdrv->dynids.lock);
+
+ if (retval)
+ return retval;
+ return count;
+}
+static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
+
static void
pci_free_dynids(struct pci_driver *drv)
{
@@ -125,6 +171,20 @@ static void pci_remove_newid_file(struct
{
driver_remove_file(&drv->driver, &driver_attr_new_id);
}
+
+static int
+pci_create_removeid_file(struct pci_driver *drv)
+{
+ int error = 0;
+ if (drv->probe != NULL)
+ error = driver_create_file(&drv->driver,&driver_attr_remove_id);
+ return error;
+}
+
+static void pci_remove_removeid_file(struct pci_driver *drv)
+{
+ driver_remove_file(&drv->driver, &driver_attr_remove_id);
+}
#else /* !CONFIG_HOTPLUG */
static inline void pci_free_dynids(struct pci_driver *drv) {}
static inline int pci_create_newid_file(struct pci_driver *drv)
@@ -132,6 +192,11 @@ static inline int pci_create_newid_file(
return 0;
}
static inline void pci_remove_newid_file(struct pci_driver *drv) {}
+static inline int pci_create_removeid_file(struct pci_driver *drv)
+{
+ return 0;
+}
+static inline void pci_remove_removeid_file(struct pci_driver *drv) {}
#endif
/**
@@ -852,13 +917,23 @@ int __pci_register_driver(struct pci_dri
/* register with core */
error = driver_register(&drv->driver);
if (error)
- return error;
+ goto out;
error = pci_create_newid_file(drv);
if (error)
- driver_unregister(&drv->driver);
+ goto out_newid;
+ error = pci_create_removeid_file(drv);
+ if (error)
+ goto out_removeid;
+out:
return error;
+
+out_removeid:
+ pci_remove_newid_file(drv);
+out_newid:
+ driver_unregister(&drv->driver);
+ goto out;
}
/**
@@ -874,6 +949,7 @@ int __pci_register_driver(struct pci_dri
void
pci_unregister_driver(struct pci_driver *drv)
{
+ pci_remove_removeid_file(drv);
pci_remove_newid_file(drv);
driver_unregister(&drv->driver);
pci_free_dynids(drv);
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -39,6 +39,22 @@ Description:
for the device and attempt to bind to it. For example:
# echo 8086 10f5 > /sys/bus/pci/drivers/foo/new_id
+What: /sys/bus/pci/drivers/.../remove_id
+Date: February 2009
+Contact: Chris Wright <chrisw@sous-sol.org>
+Description:
+ Writing a device ID to this file will remove an ID
+ that was dynamically added via the new_id sysfs entry.
+ The format for the device ID is:
+ VVVV DDDD SVVV SDDD CCCC MMMM. That is Vendor ID, Device
+ ID, Subsystem Vendor ID, Subsystem Device ID, Class,
+ and Class Mask. The Vendor ID and Device ID fields are
+ required, the rest are optional. After successfully
+ removing an ID, the driver will no longer support the
+ device. This is useful to ensure auto probing won't
+ match the driver to the device. For example:
+ # echo 8086 10f5 > /sys/bus/pci/drivers/foo/remove_id
+
What: /sys/bus/pci/devices/.../vpd
Date: February 2008
Contact: Ben Hutchings <bhutchings@solarflare.com>
next prev parent reply other threads:[~2009-02-24 2:18 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-13 16:32 KVM PCI device assignment issues Mark McLoughlin
2009-02-13 16:56 ` Greg KH
2009-02-13 17:06 ` Mark McLoughlin
2009-02-13 17:36 ` Matthew Wilcox
2009-02-13 18:22 ` Chris Wright
2009-02-13 19:47 ` Chris Wright
2009-02-24 9:20 ` Zhao, Yu
2009-02-14 2:12 ` [PATCH] pci: add remove_id sysfs entry Chris Wright
2009-02-14 3:33 ` Greg KH
2009-02-24 1:26 ` Chris Wright
2009-02-24 2:17 ` [PATCH 1/2] PCI: add some sysfs ABI docs Chris Wright
2009-02-24 2:18 ` Chris Wright [this message]
2009-02-24 3:47 ` [PATCH 2/2] PCI: add remove_id sysfs entry Greg KH
2009-02-24 5:33 ` Chris Wright
2009-02-24 5:43 ` Greg KH
2009-02-24 3:47 ` [PATCH 1/2] PCI: add some sysfs ABI docs Greg KH
2009-02-24 5:08 ` Chris Wright
2009-02-24 5:50 ` [PATCH 1/2 v2] " Chris Wright
2009-02-24 5:52 ` [PATCH 2/2 v2] PCI: add remove_id sysfs entry Chris Wright
2009-02-26 5:37 ` Han, Weidong
2009-02-27 0:27 ` Chris Wright
2009-03-20 0:35 ` Jesse Barnes
2009-02-24 17:37 ` [PATCH 1/2 v2] PCI: add some sysfs ABI docs Jesse Barnes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090224021829.GC7436@sequoia.sous-sol.org \
--to=chrisw@sous-sol.org \
--cc=allen.m.kay@intel.com \
--cc=chrisw@redhat.com \
--cc=donald.d.dugger@intel.com \
--cc=greg@kroah.com \
--cc=jbarnes@virtuousgeek.org \
--cc=kvm@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=markmc@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.