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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox