All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wright <chrisw@sous-sol.org>
To: Mark McLoughlin <markmc@redhat.com>
Cc: 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] pci: add remove_id sysfs entry
Date: Fri, 13 Feb 2009 18:12:44 -0800	[thread overview]
Message-ID: <20090214021244.GW27684@sequoia.sous-sol.org> (raw)
In-Reply-To: <1234542767.23746.81.camel@blaa>

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>
---
 drivers/pci/pci-driver.c |   80 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 93eac14..87a5ddb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -99,6 +99,52 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
 }
 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 pci_driver *drv)
 {
 	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(struct pci_driver *drv)
 	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_driver *drv, struct module *owner,
 	/* 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_driver *drv, struct module *owner,
 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);

  parent reply	other threads:[~2009-02-14  2:13 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 ` Chris Wright [this message]
2009-02-14  3:33   ` [PATCH] pci: add remove_id sysfs entry 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         ` [PATCH 2/2] PCI: add remove_id sysfs entry Chris Wright
2009-02-24  3:47           ` 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=20090214021244.GW27684@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=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.