From: Jan Dittmer <jdittmer@ppp0.net>
To: Greg KH <greg@kroah.com>
Cc: linux-kernel@vger.kernel.org,
Hotplug List <pcihpd-discuss@lists.sourceforge.net>
Subject: [patch 2/2] fakephp: add pci bus rescan ability
Date: Mon, 01 Nov 2004 00:59:55 +0100 [thread overview]
Message-ID: <41857C7B.3080304@ppp0.net> (raw)
In-Reply-To: <20041030041615.GH1584@kroah.com>
This adds the ability to rescan the pci bus for newly inserted,
reprogrammed or previously disabled pci devices.
To initiate a rescan you need to write '1' to any of the
/sys/bus/pci/slots/*/power control files. No known pci devices
will be touched.
Additionally this fixes a bug, when someone tries to disable
a device with subfunctions. The subfunctions will be disabled first now.
Short demo:
# modprobe fakephp
# ls /sys/bus/pci/slots | grep "0000:04"
0000:04:02.0
0000:04:02.1
0000:04:02.2
0000:04:03.0
0000:04:03.1
# echo -n 0 > /sys/bus/pci/slots/0000\:04\:02.0/power
# ls /sys/bus/pci/slots | grep "0000:04"
0000:04:03.0
0000:04:03.1
# echo -n 1 > /sys/bus/pci/slots/0000\:03\:01.0/power
# ls /sys/bus/pci/slots | grep "0000:04"
0000:04:02.0
0000:04:02.1
0000:04:02.2
0000:04:03.0
0000:04:03.1
# lspci | grep "0000:04"
0000:04:02.0 Multimedia audio controller: Creative Labs SB Audigy (rev 03)
0000:04:02.1 Input device controller: Creative Labs SB Audigy MIDI/Gameport (rev 03)
0000:04:02.2 FireWire (IEEE 1394): Creative Labs SB Audigy FireWire Port
0000:04:03.0 SCSI storage controller: Adaptec AHA-3960D / AIC-7899A U160/m (rev 01)
0000:04:03.1 SCSI storage controller: Adaptec AHA-3960D / AIC-7899A U160/m (rev 01)
Signed-off-by: Jan Dittmer <jdittmer@ppp0.net>
===== drivers/pci/hotplug/fakephp.c 1.2 vs edited =====
--- 1.2/drivers/pci/hotplug/fakephp.c 2003-08-27 16:44:50 +02:00
+++ edited/drivers/pci/hotplug/fakephp.c 2004-11-01 00:15:26 +01:00
@@ -165,14 +165,123 @@
err("Problem unregistering a slot %s\n", dslot->slot->name);
}
+/**
+ * Rescan slot.
+ * Tries hard not to re-enable already existing devices
+ * also handles scanning of subfunctions
+ *
+ * @param temp Device template. Should be set: bus and devfn.
+ */
+static void pci_rescan_slot(struct pci_dev *temp)
+{
+ struct pci_bus *bus = temp->bus;
+ struct pci_dev *dev;
+ int func;
+ u8 hdr_type;
+ if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
+ temp->hdr_type = hdr_type & 0x7f;
+ if (!pci_find_slot(bus->number, temp->devfn)) {
+ dev = pci_scan_single_device(bus, temp->devfn);
+ if (dev) {
+ dbg("New device on %s function %x:%x\n",
+ bus->name, temp->devfn >> 3,
+ temp->devfn & 7);
+ pci_bus_add_device(dev);
+ add_slot(dev);
+ }
+ }
+ /* multifunction device? */
+ if (!(hdr_type & 0x80))
+ return;
+
+ /* continue scanning for other functions */
+ for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) {
+ if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
+ continue;
+ temp->hdr_type = hdr_type & 0x7f;
+
+ if (!pci_find_slot(bus->number, temp->devfn)) {
+ dev = pci_scan_single_device(bus, temp->devfn);
+ if (dev) {
+ dbg("New device on %s function %x:%x\n",
+ bus->name, temp->devfn >> 3,
+ temp->devfn & 7);
+ pci_bus_add_device(dev);
+ add_slot(dev);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Rescan PCI bus.
+ * call pci_rescan_slot for each possible function of the bus
+ *
+ * @param bus
+ */
+static void pci_rescan_bus(const struct pci_bus *bus)
+{
+ unsigned int devfn;
+ struct pci_dev *dev;
+ dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+ if (!dev)
+ return;
+
+ memset(dev, 0, sizeof(dev));
+ dev->bus = (struct pci_bus*)bus;
+ dev->sysdata = bus->sysdata;
+ for (devfn = 0; devfn < 0x100; devfn += 8) {
+ dev->devfn = devfn;
+ pci_rescan_slot(dev);
+ }
+ kfree(dev);
+}
+
+/* recursively scan all buses */
+static void pci_rescan_buses(const struct list_head *list)
+{
+ const struct list_head *l;
+ list_for_each(l,list) {
+ const struct pci_bus *b = pci_bus_b(l);
+ pci_rescan_bus(b);
+ pci_rescan_buses(&b->children);
+ }
+}
+
+/* initiate rescan of all pci buses */
+static inline void pci_rescan(void) {
+ pci_rescan_buses(&pci_root_buses);
+}
+
+
static int enable_slot(struct hotplug_slot *hotplug_slot)
{
+ /* mis-use enable_slot for rescanning of the pci bus */
+ pci_rescan();
return -ENODEV;
}
+/* find the hotplug_slot for the pci_dev */
+static struct hotplug_slot *get_slot_from_dev(struct pci_dev *dev)
+{
+ struct dummy_slot *dslot;
+
+ list_for_each_entry(dslot, &slot_list, node) {
+ if (dslot->dev == dev)
+ return dslot->slot;
+ }
+ return NULL;
+}
+
+
static int disable_slot(struct hotplug_slot *slot)
{
struct dummy_slot *dslot;
+ struct hotplug_slot *hslot;
+ struct pci_dev *dev;
+ int func;
if (!slot)
return -ENODEV;
@@ -185,6 +294,23 @@
err("Can't remove PCI devices with other PCI devices behind it yet.\n");
return -ENODEV;
}
+ /* search for subfunctions and disable them first */
+ if (!(dslot->dev->devfn & 7)) {
+ for (func = 1; func < 8; func++) {
+ dev = pci_find_slot(dslot->dev->bus->number,
+ dslot->dev->devfn + func);
+ if (dev) {
+ hslot = get_slot_from_dev(dev);
+ if (hslot)
+ disable_slot(hslot);
+ else {
+ err("Hotplug slot not found for subfunction of PCI device\n");
+ return -ENODEV;
+ }
+ } else
+ dbg("No device in slot found\n");
+ }
+ }
/* remove the device from the pci core */
pci_remove_bus_device(dslot->dev);
@@ -227,6 +353,6 @@
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
next prev parent reply other threads:[~2004-11-01 0:01 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-09-22 22:00 Is there a user space pci rescan method? Dave Aubin
2004-09-22 23:58 ` Jan Dittmer
2004-09-23 0:26 ` Greg KH
2004-09-23 15:04 ` Jan Dittmer
2004-09-23 16:49 ` Rolf Eike Beer
2004-09-23 16:53 ` Jan Dittmer
2004-09-23 17:05 ` Rolf Eike Beer
2004-09-24 10:41 ` Rolf Eike Beer
2004-09-24 11:42 ` Jan Dittmer
2004-09-24 12:12 ` Rolf Eike Beer
2004-09-24 12:16 ` Jan Dittmer
2004-09-24 12:32 ` Rolf Eike Beer
2004-09-24 14:55 ` Greg KH
2004-09-27 9:14 ` Rolf Eike Beer
2004-10-10 0:13 ` Jan Dittmer
2004-10-10 0:59 ` Jan Dittmer
2004-10-10 13:45 ` Jan Dittmer
2004-10-30 4:16 ` Greg KH
2004-10-31 23:59 ` [patch 1/2] fakephp: introduce pci_bus_add_device Jan Dittmer
2004-11-01 9:35 ` Christoph Hellwig
2004-11-02 22:51 ` Jan Dittmer
2004-11-11 23:47 ` Greg KH
2004-11-12 0:13 ` Jan Dittmer
2004-11-12 18:59 ` Greg KH
2004-10-31 23:59 ` Jan Dittmer [this message]
2004-11-12 18:59 ` [patch 2/2] fakephp: add pci bus rescan ability Greg KH
2004-09-24 13:09 ` [Pcihpd-discuss] Re: Is there a user space pci rescan method? Matthew Wilcox
2004-09-24 13:18 ` Rolf Eike Beer
2004-09-24 12:40 ` Jan Dittmer
2004-09-24 12:59 ` Rolf Eike Beer
2004-09-23 23:31 ` Greg KH
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=41857C7B.3080304@ppp0.net \
--to=jdittmer@ppp0.net \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pcihpd-discuss@lists.sourceforge.net \
/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.