2004-09-22 20:30:22

by Dave Aubin

[permalink] [raw]
Subject: Is there a user space pci rescan method?

Hi,

Is there a user space or perhaps simple kernel module way to
rescan the pci bus? I currently have a user mode program modify
the pci bus, but I can not push the user mode program to the
bios for reasons I can't get in to.
Currently I use this user mode program, then do a big hammer
approach of a reboot to get the kernel to see the pci device. Is there
a nicer way of doing this? Can someone kindly educate me.

Huge Thanks,
Dave:)


2004-09-22 20:42:45

by Richard B. Johnson

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Wed, 22 Sep 2004, Dave Aubin wrote:

> Hi,
>
> Is there a user space or perhaps simple kernel module way to
> rescan the pci bus? I currently have a user mode program modify
> the pci bus, but I can not push the user mode program to the
> bios for reasons I can't get in to.
> Currently I use this user mode program, then do a big hammer
> approach of a reboot to get the kernel to see the pci device. Is there
> a nicer way of doing this? Can someone kindly educate me.
>
> Huge Thanks,
> Dave:)
> -

Did you try `setpci` and `lspci`?
You can sometimes get things working without resorting to a boot.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips).
Note 96.31% of all statistics are fiction.

2004-09-22 21:09:21

by Alan

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Mer, 2004-09-22 at 21:30, Dave Aubin wrote:
> Hi,
>
> Is there a user space or perhaps simple kernel module way to
> rescan the pci bus? I currently have a user mode program modify
> the pci bus, but I can not push the user mode program to the
> bios for reasons I can't get in to.

Take a look at drivers/hotplug. As far as Linux is concerned you've got
a hotplug PCI slot if you have to poke at it. Alternatively if its a
general funny such as a card you have to poke to reveal devices behind
it a PCI quirk would probably do the trick.

2004-09-22 21:59:31

by Dave Aubin

[permalink] [raw]
Subject: RE: Is there a user space pci rescan method?

Lspci shows me that my new pci device is not present.
Scanpci does show the device. What I'd like to do
Is get the kernel to know about it and then be able to
See it with an lspci.

Can you tell me how with lspci or setpci?

Thanks again,
Dave:)

-----Original Message-----
From: Richard B. Johnson [mailto:[email protected]]
Sent: Wednesday, September 22, 2004 4:42 PM
To: Dave Aubin
Cc: [email protected]
Subject: Re: Is there a user space pci rescan method?

On Wed, 22 Sep 2004, Dave Aubin wrote:

> Hi,
>
> Is there a user space or perhaps simple kernel module way to rescan
> the pci bus? I currently have a user mode program modify the pci bus,

> but I can not push the user mode program to the bios for reasons I
> can't get in to.
> Currently I use this user mode program, then do a big hammer
> approach of a reboot to get the kernel to see the pci device. Is
> there a nicer way of doing this? Can someone kindly educate me.
>
> Huge Thanks,
> Dave:)
> -

Did you try `setpci` and `lspci`?
You can sometimes get things working without resorting to a boot.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips).
Note 96.31% of all statistics are fiction.

2004-09-22 22:00:59

by Dave Aubin

[permalink] [raw]
Subject: RE: Is there a user space pci rescan method?

Hi,

I know very little about hotplug, but does make sense.
How do you motivate a hotplug insertion event? Or should
I just go read the /docs on hotplugging? Any help is
Appreciated:)

Thanks,
Dave:)

-----Original Message-----
From: Alan Cox [mailto:[email protected]]
Sent: Wednesday, September 22, 2004 4:05 PM
To: Dave Aubin
Cc: Linux Kernel Mailing List
Subject: Re: Is there a user space pci rescan method?

On Mer, 2004-09-22 at 21:30, Dave Aubin wrote:
> Hi,
>
> Is there a user space or perhaps simple kernel module way to rescan
> the pci bus? I currently have a user mode program modify the pci bus,

> but I can not push the user mode program to the bios for reasons I
> can't get in to.

Take a look at drivers/hotplug. As far as Linux is concerned you've got
a hotplug PCI slot if you have to poke at it. Alternatively if its a
general funny such as a card you have to poke to reveal devices behind
it a PCI quirk would probably do the trick.

2004-09-22 23:58:47

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Dave Aubin wrote:
> Hi,
>
> I know very little about hotplug, but does make sense.
> How do you motivate a hotplug insertion event? Or should
> I just go read the /docs on hotplugging? Any help is
> Appreciated:)

There is a "fake" hotplug driver which works for normal pci. But last
time I looked at it, it did only support hot disabling, not hot enabling
- but this surely can be fixed.

Thanks,

Jan

2004-09-23 00:27:52

by Greg KH

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Thu, Sep 23, 2004 at 01:58:32AM +0200, Jan Dittmer wrote:
> Dave Aubin wrote:
> > Hi,
> >
> > I know very little about hotplug, but does make sense.
> > How do you motivate a hotplug insertion event? Or should
> > I just go read the /docs on hotplugging? Any help is
> > Appreciated:)
>
> There is a "fake" hotplug driver which works for normal pci. But last
> time I looked at it, it did only support hot disabling, not hot enabling
> - but this surely can be fixed.

Yes, hot "enabling" has been left for someone to add to the driver, if
you read the comments in it :)

Good luck,

greg k-h

2004-09-23 15:04:50

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Greg KH wrote:
> On Thu, Sep 23, 2004 at 01:58:32AM +0200, Jan Dittmer wrote:
>
>>Dave Aubin wrote:
>>
>>>Hi,
>>>
>>> I know very little about hotplug, but does make sense.
>>>How do you motivate a hotplug insertion event? Or should
>>>I just go read the /docs on hotplugging? Any help is
>>>Appreciated:)
>>
>>There is a "fake" hotplug driver which works for normal pci. But last
>>time I looked at it, it did only support hot disabling, not hot enabling
>>- but this surely can be fixed.
>
>
> Yes, hot "enabling" has been left for someone to add to the driver, if
> you read the comments in it :)
>

I read them and started playing around with this driver. So echoing 0 in
/sys/bus/pci/slots/*/power disables the pci device. The problem I see
is, that the tree with the device is disappearing. So how am I supposed
to re-enable the device. I've no real hotplug hardware to play with, so
I'm bound to reading the source code in drivers/pci/hotplug and testing
with fakephp. I found your utility pcihpview (v0.5) which searches for
/sys/bus/pci/hotplug_slots. But grepping the kernel tree doesn't show
any mentioning of it - so I suppose it is outdated.
Is there anywhere a current article (or Documentation/pci_hotplug.txt)
about the state of PCI hotplug and how this is supposed to work?

Thanks,

Jan

ps: Meanwhile I found dummyphp on the pcihpd mailinglist. This doesn't
remove the device from /sys/bus/pci/slots/*/power . Still I'd like
to know the offical way.

2004-09-23 16:45:01

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Jan Dittmer wrote:
> Greg KH wrote:
> > On Thu, Sep 23, 2004 at 01:58:32AM +0200, Jan Dittmer wrote:
> >>Dave Aubin wrote:
> >>>Hi,
> >>>
> >>> I know very little about hotplug, but does make sense.
> >>>How do you motivate a hotplug insertion event? Or should
> >>>I just go read the /docs on hotplugging? Any help is
> >>>Appreciated:)
> >>
> >>There is a "fake" hotplug driver which works for normal pci. But last
> >>time I looked at it, it did only support hot disabling, not hot enabling
> >>- but this surely can be fixed.
> >
> > Yes, hot "enabling" has been left for someone to add to the driver, if
> > you read the comments in it :)

Hot enabling works for month in dummyphp...

> I read them and started playing around with this driver. So echoing 0 in
> /sys/bus/pci/slots/*/power disables the pci device. The problem I see
> is, that the tree with the device is disappearing. So how am I supposed
> to re-enable the device. I've no real hotplug hardware to play with, so
> I'm bound to reading the source code in drivers/pci/hotplug and testing
> with fakephp. I found your utility pcihpview (v0.5) which searches for
> /sys/bus/pci/hotplug_slots. But grepping the kernel tree doesn't show
> any mentioning of it - so I suppose it is outdated.
> Is there anywhere a current article (or Documentation/pci_hotplug.txt)
> about the state of PCI hotplug and how this is supposed to work?

Just search the archive of [email protected] for dummyphp,
this is the version that works. I'll rediff it soon and hope Greg will accept
it this time.

Message-Id to search for: <[email protected]>

Eike

2004-09-23 17:05:17

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Jan Dittmer wrote:
> Rolf Eike Beer wrote:
> > Just search the archive of [email protected] for
> > dummyphp, this is the version that works. I'll rediff it soon and hope
> > Greg will accept it this time.
> >
> > Message-Id to search for: <[email protected]>
>
> You didn't read my p.s. ... I found it and it's working quite nice. Already

Ehm, yes. Sorry, around 1900 local time and no real breakfast until now.

> discovered a bug in dv1394. Just one thing: Can you strip DUMMY- from the
> name in /sys/bus/pci/slots/ ? It's really ugly and you can't mix different
> hotplug drivers anyway.

Sounds reasonable.

Eike

2004-09-23 16:58:42

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Rolf Eike Beer wrote:
> Just search the archive of [email protected] for dummyphp,
> this is the version that works. I'll rediff it soon and hope Greg will accept
> it this time.
>
> Message-Id to search for: <[email protected]>

You didn't read my p.s. ... I found it and it's working quite nice. Already
discovered a bug in dv1394. Just one thing: Can you strip DUMMY- from the
name in /sys/bus/pci/slots/ ? It's really ugly and you can't mix different
hotplug drivers anyway.

Thanks,

Jan

2004-09-24 00:08:05

by Greg KH

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Thu, Sep 23, 2004 at 05:04:38PM +0200, Jan Dittmer wrote:
> Greg KH wrote:
> > On Thu, Sep 23, 2004 at 01:58:32AM +0200, Jan Dittmer wrote:
> >
> >>Dave Aubin wrote:
> >>
> >>>Hi,
> >>>
> >>> I know very little about hotplug, but does make sense.
> >>>How do you motivate a hotplug insertion event? Or should
> >>>I just go read the /docs on hotplugging? Any help is
> >>>Appreciated:)
> >>
> >>There is a "fake" hotplug driver which works for normal pci. But last
> >>time I looked at it, it did only support hot disabling, not hot enabling
> >>- but this surely can be fixed.
> >
> >
> > Yes, hot "enabling" has been left for someone to add to the driver, if
> > you read the comments in it :)
> >
>
> I read them and started playing around with this driver. So echoing 0 in
> /sys/bus/pci/slots/*/power disables the pci device. The problem I see
> is, that the tree with the device is disappearing. So how am I supposed
> to re-enable the device.

You need to add another sysfs file called "rescan" or something.
Writing to that file will cause the kernel to rescan pci space, and add
any devices it finds that are not already present. The code to do that
can be taken from the pci startup code in the kernel today.

> I've no real hotplug hardware to play with, so I'm bound to reading
> the source code in drivers/pci/hotplug and testing with fakephp.

That's fine. You don't need real hotplug pci hardware to use fakephp,
that's what the driver is for :)

> I found your utility pcihpview (v0.5) which searches for
> /sys/bus/pci/hotplug_slots. But grepping the kernel tree doesn't show
> any mentioning of it - so I suppose it is outdated.

That's a 2.4 interface. I need to get a new version of that program out
there that works for 2.6 one of these days (the bk version of the
program has this support already in it, if you want to mess with
that...)

> Is there anywhere a current article (or Documentation/pci_hotplug.txt)
> about the state of PCI hotplug and how this is supposed to work?

Not really, sorry.

> ps: Meanwhile I found dummyphp on the pcihpd mailinglist. This doesn't
> remove the device from /sys/bus/pci/slots/*/power . Still I'd like
> to know the offical way.

That's the driver that I based fakephp on. It's a good starting point
for what it sounds like you want to do.

Hope this helps,

greg k-h

2004-09-24 10:34:57

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Am Donnerstag, 23. September 2004 19:05 schrieb Rolf Eike Beer:
> Jan Dittmer wrote:
> > Rolf Eike Beer wrote:
> > > Just search the archive of [email protected] for
> > > dummyphp, this is the version that works. I'll rediff it soon and hope
> > > Greg will accept it this time.
> > >
> > > Message-Id to search for:
> > > <[email protected]>
> >
> > You didn't read my p.s. ... I found it and it's working quite nice.
> > Already
>
> Ehm, yes. Sorry, around 1900 local time and no real breakfast until now.
>
> > discovered a bug in dv1394. Just one thing: Can you strip DUMMY- from the
> > name in /sys/bus/pci/slots/ ? It's really ugly and you can't mix
> > different hotplug drivers anyway.
>
> Sounds reasonable.

Ok, here we go. This is my current diff that I use for my tests at home. It adds
dummyphp and cleans up fakephp a lot (read: kills it). Changes from last version:

-removed some dead comments
-removed some unused instructions
-reordered allocation in add_slot to do less memory allocations if there is
no device in slot
-changed param "usedonly" to "showunused" so it behaves like fakephp at the
first look: if you load dummyphp without parameters there are only slots with
devices in it.
-removed "DUMMY-" prefix to entries in /sys/bus/pci/slots/

Please send comments so I can send it for inclusion soon.

Eike

diff -x '*.o' -x '.tmp*' -Naur linux-2.6.8/drivers/pci/hotplug/Kconfig linux-2.6.9-rc2-bk/drivers/pci/hotplug/Kconfig
--- linux-2.6.8/drivers/pci/hotplug/Kconfig 2004-09-23 21:16:49.000000000 +0200
+++ linux-2.6.9-rc2-bk/drivers/pci/hotplug/Kconfig 2004-09-23 21:58:35.000000000 +0200
@@ -19,26 +19,29 @@

When in doubt, say N.

-config HOTPLUG_PCI_FAKE
- tristate "Fake PCI Hotplug driver"
+config HOTPLUG_PCI_DUMMY
+ tristate "Dummy PCI Hotplug driver"
depends on HOTPLUG_PCI
help
- Say Y here if you want to use the fake PCI hotplug driver. It can
- be used to simulate PCI hotplug events if even if your system is
- not PCI hotplug capable.
+ Say Y here if you want to use the dummy PCI hotplug driver. It can
+ be used to simulate PCI hotplug events even if your system is not
+ PCI hotplug capable.

This driver will "emulate" removing PCI devices from the system.
If the "power" file is written to with "0" then the specified PCI
- device will be completely removed from the kernel.
+ device will be completely removed from the kernel. Writing "1" to
+ the power file will bring the device back.
+
+ Be careful: it claims all PCI slots in the system with a device in it.
+ There will be side effects on other hotplug drivers, so do NOT use
+ another hotplug driver at the same time.

WARNING, this does NOT turn off the power to the PCI device.
This is a "logical" removal, not a physical or electrical
removal.

- Use this module at your own risk. You have been warned!
-
- To compile this driver as a module, choose M here: the
- module will be called fakephp.
+ To compile this driver as a module, choose M here: the module
+ will be called dummyphp.

When in doubt, say N.

diff -x '*.o' -x '.tmp*' -Naur linux-2.6.8/drivers/pci/hotplug/Makefile linux-2.6.9-rc2-bk/drivers/pci/hotplug/Makefile
--- linux-2.6.8/drivers/pci/hotplug/Makefile 2004-09-23 21:16:49.000000000 +0200
+++ linux-2.6.9-rc2-bk/drivers/pci/hotplug/Makefile 2004-09-17 16:30:26.000000000 +0200
@@ -3,7 +3,7 @@
#

obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
+obj-$(CONFIG_HOTPLUG_PCI_DUMMY) += dummyphp.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
diff -x '*.o' -x '.tmp*' -Naur linux-2.6.8/drivers/pci/hotplug/dummyphp.c linux-2.6.9-rc2-bk/drivers/pci/hotplug/dummyphp.c
--- linux-2.6.8/drivers/pci/hotplug/dummyphp.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-rc2-bk/drivers/pci/hotplug/dummyphp.c 2004-09-23 23:11:23.000000000 +0200
@@ -0,0 +1,386 @@
+/*
+ * Dummy PCI Hot Plug Controller Driver
+ *
+ * Copyright (c) 2003 Rolf Eike Beer <[email protected]>
+ *
+ * Based on code from:
+ * Vladimir Kondratiev <[email protected]>
+ * Greg Kroah-Hartman <[email protected]>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * Send feedback to <[email protected]>
+ */
+
+/*
+ *
+ * This driver will "emulate" removing PCI devices from the system. If
+ * the "power" file is written to with "0" then the specified PCI device
+ * will be completely removed from the kernel.
+ *
+ * WARNING, this does NOT turn off the power to the PCI device. This is
+ * a "logical" removal, not a physical or electrical removal.
+ *
+ * Use this module at your own risk, you have been warned!
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci_hotplug.h"
+#include "../pci.h"
+
+#define MY_NAME "dummyphp"
+
+#define dbg(format, arg...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "%s: " format, \
+ MY_NAME , ## arg); \
+ } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+
+/* name size which is used for entries in pcihpfs */
+#define SLOT_NAME_SIZE 14 /* {DOMAIN}-{BUS}:{DEV} */
+
+struct dummy_slot {
+ struct list_head node;
+ struct hotplug_slot *slot;
+ struct pci_dev *dev;
+ struct pci_bus *bus;
+ int devfn;
+};
+
+#define DRIVER_DESC "Dummy PCI Hot Plug Controller Driver"
+
+static int debug;
+static int showunused;
+static LIST_HEAD(slot_list);
+
+MODULE_AUTHOR("Rolf Eike Beer <[email protected]>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+module_param(debug, bool, 644);
+MODULE_PARM_DESC(showunused, "Show slots even if there is no device in it");
+module_param(showunused, bool, 644);
+
+static int enable_slot(struct hotplug_slot *slot);
+static int disable_slot(struct hotplug_slot *slot);
+static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value);
+
+static struct hotplug_slot_ops dummy_hotplug_slot_ops = {
+ .owner = THIS_MODULE,
+ .enable_slot = enable_slot,
+ .disable_slot = disable_slot,
+ .get_adapter_status = get_adapter_status
+};
+
+/**
+ * dummy_release - free the memory of a slot
+ * @slot: slot pointer to remove
+ */
+static void dummy_release(struct hotplug_slot *slot)
+{
+ struct dummy_slot *dslot = slot->private;
+
+ list_del(&dslot->node);
+ kfree(dslot->slot->name);
+ kfree(dslot->slot->info);
+ kfree(dslot->slot);
+ if (dslot->dev)
+ pci_dev_put(dslot->dev);
+ kfree(dslot);
+}
+
+/**
+ * get_adapter_status - look if adapter is present in slot
+ * @hotplug_slot: slot to test value
+ * @value: status of the adapter
+ */
+static int get_adapter_status(struct hotplug_slot *slot, u8 *value)
+{
+ struct dummy_slot *dslot;
+
+ dslot = slot->private;
+
+ *value = pci_scan_slot(dslot->bus, dslot->devfn);
+ slot->info->adapter_status = *value;
+
+ return 0;
+}
+
+/**
+ * add_slot - add a new "hotplug" slot
+ * @dev: a struct pci_dev describing this slot (regardless if
+ * there is actually a device in this slot or not)
+ */
+static inline int
+add_slot(const struct pci_dev *dev)
+{
+ struct dummy_slot *dslot;
+ struct hotplug_slot *slot;
+ int retval = -ENOMEM;
+
+ dslot = kmalloc(sizeof(*dslot), GFP_KERNEL);
+ if (!dslot)
+ goto error;
+
+ dslot->bus = dev->bus;
+ dslot->devfn = dev->devfn;
+
+ dslot->dev = pci_get_slot(dslot->bus, dslot->devfn);
+
+ if (showunused || dslot->dev) {
+ retval = 0;
+ goto error_dslot;
+ }
+
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
+ goto error_dslot;
+
+ memset(slot, 0, sizeof(*slot));
+
+ slot->info = kmalloc(sizeof(*(slot->info)), GFP_KERNEL);
+ if (!slot->info)
+ goto error_slot;
+
+ memset(slot->info, 0, sizeof(struct hotplug_slot_info));
+
+ slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
+ slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
+
+ slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+ if (!slot->name)
+ goto error_info;
+ slot->info->power_status = (dslot->dev != NULL);
+ slot->info->adapter_status = slot->info->power_status;
+
+ slot->ops = &dummy_hotplug_slot_ops;
+ slot->release = &dummy_release;
+ slot->private = dslot;
+
+ snprintf(slot->name, SLOT_NAME_SIZE, "%04x:%02x:%02x",
+ pci_domain_nr(dev->bus), dslot->bus->number,
+ PCI_SLOT(dslot->devfn));
+
+ retval = pci_hp_register(slot);
+ if (retval) {
+ err("pci_hp_register failed with error %d\n", retval);
+ goto error_name;
+ }
+
+ dslot->slot = slot;
+ list_add(&dslot->node, &slot_list);
+
+ return retval;
+
+error_name:
+ kfree(slot->name);
+error_info:
+ kfree(slot->info);
+error_slot:
+ kfree(slot);
+error_dslot:
+ pci_dev_put(dslot->dev);
+ kfree(dslot);
+error:
+ return retval;
+}
+
+/**
+ * scan_pci_bus - add an entry for every slot on this bus
+ * @bus: bus to scan
+ */
+static inline int
+scan_pci_bus(struct pci_bus *bus)
+{
+ int retval;
+ struct pci_dev dev;
+
+ memset(&dev, 0, sizeof(dev));
+ dev.bus = bus;
+ for (dev.devfn = 0; dev.devfn < 0x100; dev.devfn += 8) {
+ retval = add_slot(&dev);
+ if (retval)
+ break;
+ }
+ return retval;
+}
+
+/**
+ * pci_scan_buses - scan this bus and all child buses for slots
+ * @list: list of buses to scan
+ */
+static int
+pci_scan_buses(struct list_head *list)
+{
+ int retval = 0;
+ const struct list_head *l;
+
+ list_for_each(l, list) {
+ struct list_head *tmp;
+ struct list_head *next;
+ struct pci_bus *b = pci_bus_b(l);
+ int i = 0;
+
+ /* scan the list of slots to see if we have already
+ * a slot on the new bus registered */
+ list_for_each_safe(tmp, next, &slot_list) {
+ if ((list_entry(tmp, struct dummy_slot, node))->bus == b) {
+ i = 1;
+ break;
+ }
+ }
+ if (i)
+ continue;
+
+ retval = scan_pci_bus(b);
+ if (retval)
+ break;
+ retval = pci_scan_buses(&b->children);
+ if (retval)
+ break;
+ }
+ return retval;
+}
+
+/**
+ * enable_slot - power on and enable a slot
+ * @hotplug_slot: slot to enable
+ */
+static int
+enable_slot(struct hotplug_slot *hotplug_slot)
+{
+ struct dummy_slot *dslot = hotplug_slot->private;
+ int num, result = -ENODEV;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+ /* exit if device in slot is already active */
+ if (dslot->dev != NULL)
+ return 0;
+
+ dslot->dev = pci_get_slot(dslot->bus, dslot->devfn);
+
+ /* No pci device, we need to create it then */
+ if (dslot->dev == NULL) {
+ num = pci_scan_slot(dslot->bus, dslot->devfn);
+ if (!num) {
+ dbg("INFO: enable_slot called on empty slot\n");
+ return result;
+ }
+
+ pci_bus_add_devices(dslot->bus);
+
+ dslot->dev = pci_get_slot(dslot->bus, dslot->devfn);
+ /* pci_get_slot fails but we have found devices in this slot before? */
+ WARN_ON(dslot->dev == NULL);
+ }
+
+ if (dslot->dev->subordinate)
+ result = pci_scan_buses(&(dslot->dev->subordinate->node));
+ else
+ result = 0;
+
+ return result;
+}
+
+/**
+ * disable_subordinate - remove hotplug slot entry of device on this bus
+ * @bus: PCI bus to remove (including all children)
+ */
+static void
+disable_subordinate(struct pci_bus *bus)
+{
+ struct list_head *tmp;
+ struct list_head *next;
+ struct dummy_slot *dslot;
+
+ list_for_each_safe(tmp, next, &slot_list) {
+ dslot = list_entry(tmp, struct dummy_slot, node);
+ if (dslot->bus == bus) {
+ if (dslot->dev != NULL)
+ if (dslot->dev->subordinate)
+ /* FIXME: look if this bus can be reached through a
+ different bridge. If yes, don't disable it */
+ disable_subordinate(dslot->dev->subordinate);
+ /* no need to disable the devices itself, this will be
+ done by pci_remove_bus_device */
+ pci_hp_deregister(dslot->slot);
+ }
+ }
+}
+
+/**
+ * disable_slot - disable any adapter in this slot
+ * @slot: slot to disable
+ */
+static int
+disable_slot(struct hotplug_slot *slot)
+{
+ struct dummy_slot *dslot = slot->private;
+ struct pci_dev *dev = dslot->dev;
+ int i;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name);
+
+ if (!dev) {
+ dbg("No device in slot, exiting");
+ return -ENODEV;
+ }
+
+ /* check if this is a PCI bridge and remove devices on
+ sub-buses first */
+ if (dev->subordinate)
+ disable_subordinate(dev->subordinate);
+
+ dslot->dev = NULL;
+ pci_dev_put(dev);
+
+ /* remove the device from the pci core */
+ info("Slot %s removed\n", pci_name(dev));
+
+ for (i = 0; i < 8; i++) {
+ dev = pci_get_slot(dslot->bus, dslot->devfn + i);
+ if (dev)
+ pci_remove_bus_device(dev);
+ }
+
+ slot->info->power_status = 0;
+
+ return 0;
+}
+
+static int __init
+dummyphp_init(void)
+{
+ info(DRIVER_DESC "\n");
+
+ return pci_scan_buses(&pci_root_buses);
+}
+
+static void __exit
+dummyphp_exit(void)
+{
+ struct list_head *tmp;
+ struct list_head *next;
+ struct dummy_slot *dslot;
+
+ list_for_each_safe(tmp, next, &slot_list) {
+ dslot = list_entry(tmp, struct dummy_slot, node);
+ pci_hp_deregister(dslot->slot);
+ }
+}
+
+module_init(dummyphp_init);
+module_exit(dummyphp_exit);
diff -x '*.o' -x '.tmp*' -Naur linux-2.6.8/drivers/pci/hotplug/fakephp.c linux-2.6.9-rc2-bk/drivers/pci/hotplug/fakephp.c
--- linux-2.6.8/drivers/pci/hotplug/fakephp.c 2004-08-14 07:37:25.000000000 +0200
+++ linux-2.6.9-rc2-bk/drivers/pci/hotplug/fakephp.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,232 +0,0 @@
-/*
- * Fake PCI Hot Plug Controller Driver
- *
- * Copyright (C) 2003 Greg Kroah-Hartman <[email protected]>
- * Copyright (C) 2003 IBM Corp.
- * Copyright (C) 2003 Rolf Eike Beer <[email protected]>
- *
- * Based on ideas and code from:
- * Vladimir Kondratiev <[email protected]>
- * Rolf Eike Beer <[email protected]>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * Send feedback to <[email protected]>
- */
-
-/*
- *
- * This driver will "emulate" removing PCI devices from the system. If
- * the "power" file is written to with "0" then the specified PCI device
- * will be completely removed from the kernel.
- *
- * WARNING, this does NOT turn off the power to the PCI device. This is
- * a "logical" removal, not a physical or electrical removal.
- *
- * Use this module at your own risk, you have been warned!
- *
- * Enabling PCI devices is left as an exercise for the reader...
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci_hotplug.h"
-#include "../pci.h"
-
-#if !defined(CONFIG_HOTPLUG_PCI_FAKE_MODULE)
- #define MY_NAME "fakephp"
-#else
- #define MY_NAME THIS_MODULE->name
-#endif
-
-#define dbg(format, arg...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG "%s: " format, \
- MY_NAME , ## arg); \
- } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
-
-#define DRIVER_AUTHOR "Greg Kroah-Hartman <[email protected]>"
-#define DRIVER_DESC "Fake PCI Hot Plug Controller Driver"
-
-struct dummy_slot {
- struct list_head node;
- struct hotplug_slot *slot;
- struct pci_dev *dev;
-};
-
-static int debug;
-static LIST_HEAD(slot_list);
-
-static int enable_slot (struct hotplug_slot *slot);
-static int disable_slot (struct hotplug_slot *slot);
-
-static struct hotplug_slot_ops dummy_hotplug_slot_ops = {
- .owner = THIS_MODULE,
- .enable_slot = enable_slot,
- .disable_slot = disable_slot,
-};
-
-static void dummy_release(struct hotplug_slot *slot)
-{
- struct dummy_slot *dslot = slot->private;
-
- list_del(&dslot->node);
- kfree(dslot->slot->info);
- kfree(dslot->slot);
- pci_dev_put(dslot->dev);
- kfree(dslot);
-}
-
-static int add_slot(struct pci_dev *dev)
-{
- struct dummy_slot *dslot;
- struct hotplug_slot *slot;
- int retval = -ENOMEM;
-
- slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
- if (!slot)
- goto error;
- memset(slot, 0, sizeof(*slot));
-
- slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
- if (!slot->info)
- goto error_slot;
- memset(slot->info, 0, sizeof(struct hotplug_slot_info));
-
- slot->info->power_status = 1;
- slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
- slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
-
- slot->name = &dev->dev.bus_id[0];
- dbg("slot->name = %s\n", slot->name);
-
- dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
- if (!dslot)
- goto error_info;
-
- slot->ops = &dummy_hotplug_slot_ops;
- slot->release = &dummy_release;
- slot->private = dslot;
-
- retval = pci_hp_register(slot);
- if (retval) {
- err("pci_hp_register failed with error %d\n", retval);
- goto error_dslot;
- }
-
- dslot->slot = slot;
- dslot->dev = pci_dev_get(dev);
- list_add (&dslot->node, &slot_list);
- return retval;
-
-error_dslot:
- kfree(dslot);
-error_info:
- kfree(slot->info);
-error_slot:
- kfree(slot);
-error:
- return retval;
-}
-
-static int __init pci_scan_buses(void)
-{
- struct pci_dev *dev = NULL;
- int retval = 0;
-
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- retval = add_slot(dev);
- if (retval) {
- pci_dev_put(dev);
- break;
- }
- }
-
- return retval;
-}
-
-static void remove_slot(struct dummy_slot *dslot)
-{
- int retval;
-
- dbg("removing slot %s\n", dslot->slot->name);
- retval = pci_hp_deregister(dslot->slot);
- if (retval)
- err("Problem unregistering a slot %s\n", dslot->slot->name);
-}
-
-static int enable_slot(struct hotplug_slot *hotplug_slot)
-{
- return -ENODEV;
-}
-
-static int disable_slot(struct hotplug_slot *slot)
-{
- struct dummy_slot *dslot;
-
- if (!slot)
- return -ENODEV;
- dslot = slot->private;
-
- dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name);
-
- /* don't disable bridged devices just yet, we can't handle them easily... */
- if (dslot->dev->subordinate) {
- err("Can't remove PCI devices with other PCI devices behind it yet.\n");
- return -ENODEV;
- }
-
- /* remove the device from the pci core */
- pci_remove_bus_device(dslot->dev);
-
- /* blow away this sysfs entry and other parts. */
- remove_slot(dslot);
-
- return 0;
-}
-
-static void cleanup_slots (void)
-{
- struct list_head *tmp;
- struct list_head *next;
- struct dummy_slot *dslot;
-
- list_for_each_safe (tmp, next, &slot_list) {
- dslot = list_entry (tmp, struct dummy_slot, node);
- remove_slot(dslot);
- }
-
-}
-
-static int __init dummyphp_init(void)
-{
- info(DRIVER_DESC "\n");
-
- return pci_scan_buses();
-}
-
-
-static void __exit dummyphp_exit(void)
-{
- cleanup_slots();
-}
-
-module_init(dummyphp_init);
-module_exit(dummyphp_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-

2004-09-24 11:43:22

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Rolf Eike Beer wrote:
> Ok, here we go. This is my current diff that I use for my tests at home. It adds
> dummyphp and cleans up fakephp a lot (read: kills it). Changes from last version:
>
> -removed some dead comments
> -removed some unused instructions
> -reordered allocation in add_slot to do less memory allocations if there is
> no device in slot
> -changed param "usedonly" to "showunused" so it behaves like fakephp at the
> first look: if you load dummyphp without parameters there are only slots with
> devices in it.
> -removed "DUMMY-" prefix to entries in /sys/bus/pci/slots/
>
> Please send comments so I can send it for inclusion soon.

Well, first of all I think you should just submit a patch to add dummyphp and not
removing fakephp in the same step. Also you somehow mis-copied the patch to
your mail app - most (not all) tabs are converted to one space (or is it just
thunderbird displaying the mail?). Can you resend it? Then I'll give it a try.
Greg wrote in another mail that the 'proper' way of 'powering up' device slots should
be to rescan the entire bus. I don't know, your approach certainly seems easier, but you
are bound to either display all pci slots which may come to live or just the ones
in the system already, which means you cannot rescan slots which weren't equipped
on boot up. So perhaps adding a rescan method to fakephp is indeed cleaner.

Jan

2004-09-24 12:05:44

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Am Freitag, 24. September 2004 13:42 schrieben Sie:
> Rolf Eike Beer wrote:
> > Ok, here we go. This is my current diff that I use for my tests at home.
> > It adds dummyphp and cleans up fakephp a lot (read: kills it). Changes
> > from last version:
> >
> > -removed some dead comments
> > -removed some unused instructions
> > -reordered allocation in add_slot to do less memory allocations if there
> > is no device in slot
> > -changed param "usedonly" to "showunused" so it behaves like fakephp at
> > the first look: if you load dummyphp without parameters there are only
> > slots with devices in it.
> > -removed "DUMMY-" prefix to entries in /sys/bus/pci/slots/
> >
> > Please send comments so I can send it for inclusion soon.
>
> Well, first of all I think you should just submit a patch to add dummyphp
> and not removing fakephp in the same step. Also you somehow mis-copied the

I said it's my test diff and that I'll redo it for submission ;)

> patch to your mail app - most (not all) tabs are converted to one space (or
> is it just thunderbird displaying the mail?). Can you resend it? Then I'll

Yes, looks like KMail has eaten it. Hey KDE guys, is this intentional or was
this my fault?

You can get it from http://opensource.sf-tec.de/kernel/fake_vs_dummy.diff

> give it a try. Greg wrote in another mail that the 'proper' way of
> 'powering up' device slots should be to rescan the entire bus. I don't
> know, your approach certainly seems easier, but you are bound to either
> display all pci slots which may come to live or just the ones in the system
> already, which means you cannot rescan slots which weren't equipped on boot
> up. So perhaps adding a rescan method to fakephp is indeed cleaner.

This is for simulating hotplug events. I don't know how there could be a slot
where you put in a device that has not been there on system bootup. Ok, you
can trigger such a case by disabling a slot, rmmod dummyphp, modprobe
dummyphp again. Greg didn't like dummyphp to display all logical slots even
if there is no device in them - which I can understand, under normal
circumstances you will never have a use for this extra slots. If you want
them just do "modprobe dummyphp showunused=1" and you'll get them all.

Normally you will just remove and bring back one or two cards in the system
(e.g. your NIC or sound card, depending on xmms or irc being on top of your
priority list *g*). So from my point of view it's a good idea to keep the
slot dirs on remove so you can just go back in your command history and
replace 0 with 1 to get the device back. I don't see why bus structure or
whatever may ever change so rescanning the whole bus is IMHO a bit overkill.

Adding a rescan file is also extra work, the power file is there
automagically ;)

Eike

2004-09-24 12:16:51

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Rolf Eike Beer wrote:
> Normally you will just remove and bring back one or two cards in the system
> (e.g. your NIC or sound card, depending on xmms or irc being on top of your
> priority list *g*). So from my point of view it's a good idea to keep the
> slot dirs on remove so you can just go back in your command history and
> replace 0 with 1 to get the device back. I don't see why bus structure or
> whatever may ever change so rescanning the whole bus is IMHO a bit overkill.

My point was, I load dummyphp with showunused=0 and only get dirs for the
slots with devices in them. Now I decide to put a network card (or whatever
I have to spare) in an empty slot, hope that the system doesn't reboot
immediately, and voila I don't have any /sys/bus/pci/slots dir to enable
the slot and have to reboot nevertheless. Or does the pci system a rescan
if I reinsert the module?

Thanks,

Jan

2004-09-24 12:25:03

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Am Freitag, 24. September 2004 14:16 schrieben Sie:
> Rolf Eike Beer wrote:
> > Normally you will just remove and bring back one or two cards in the
> > system (e.g. your NIC or sound card, depending on xmms or irc being on
> > top of your priority list *g*). So from my point of view it's a good idea
> > to keep the slot dirs on remove so you can just go back in your command
> > history and replace 0 with 1 to get the device back. I don't see why bus
> > structure or whatever may ever change so rescanning the whole bus is IMHO
> > a bit overkill.
>
> My point was, I load dummyphp with showunused=0 and only get dirs for the
> slots with devices in them. Now I decide to put a network card (or whatever
> I have to spare) in an empty slot, hope that the system doesn't reboot
> immediately, and voila I don't have any /sys/bus/pci/slots dir to enable
> the slot and have to reboot nevertheless. Or does the pci system a rescan
> if I reinsert the module?

In this case you have to "rmmod dummyphp; modprobe dummyphp showunused=1" to
get all slots and try to enable the device. We have tested it once with a
special PCI debugging board where we can electrically disable the PCI bus so
we don't kill our hardware. The problem was that on reenabling a interrupt
storm killed the machine, I don't remember the exact problem. IIRC it looked
like the kernel found the device but the PCI bridge got confused by the new
device (or something like this). I don't know if there is a way to survive
this situation as the bridges in "normal" hardware are not hotplug aware.
Greg?

If there is a way I will try to impleement it, but for now this is beyound my
knowledge.

Eike

2004-09-24 12:40:54

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Rolf Eike Beer wrote:
> -changed param "usedonly" to "showunused" so it behaves like fakephp at the
> first look: if you load dummyphp without parameters there are only slots with
> devices in it.

Well, know I get only entries for all devices I don't have!

> + dslot->dev = pci_get_slot(dslot->bus, dslot->devfn);
> +
> + if (showunused || dslot->dev) {
> + retval = 0;
> + goto error_dslot;
> + }

This should probably be !showunused || !dslot->dev ?

Jan

2004-09-24 12:52:45

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Am Freitag, 24. September 2004 14:40 schrieben Sie:
> Rolf Eike Beer wrote:
> > -changed param "usedonly" to "showunused" so it behaves like fakephp at
> > the first look: if you load dummyphp without parameters there are only
> > slots with devices in it.
>
> Well, know I get only entries for all devices I don't have!

There was a device mask but I decided this was too ugly and ripped it out.
Maybe it would make sense to have a parameter with an array of buses you want
to see completely or something like this.

> > + dslot->dev = pci_get_slot(dslot->bus, dslot->devfn);
> > +
> > + if (showunused || dslot->dev) {
> > + retval = 0;
> > + goto error_dslot;
> > + }
>
> This should probably be !showunused || !dslot->dev ?

Yes. Error in boolean simplification.

Eike

2004-09-24 13:09:57

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [Pcihpd-discuss] Re: Is there a user space pci rescan method?

On Fri, Sep 24, 2004 at 02:16:09PM +0200, Jan Dittmer wrote:
> My point was, I load dummyphp with showunused=0 and only get dirs for the
> slots with devices in them. Now I decide to put a network card (or whatever
> I have to spare) in an empty slot, hope that the system doesn't reboot
> immediately, and voila I don't have any /sys/bus/pci/slots dir to enable
> the slot and have to reboot nevertheless. Or does the pci system a rescan
> if I reinsert the module?

That is DANGEROUS and WILL DESTROY YOUR SYSTEM. Under no circumstances
should we be encouraging people to do that.

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-24 13:11:56

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: [Pcihpd-discuss] Re: Is there a user space pci rescan method?

Am Freitag, 24. September 2004 15:09 schrieb Matthew Wilcox:
> On Fri, Sep 24, 2004 at 02:16:09PM +0200, Jan Dittmer wrote:
> > My point was, I load dummyphp with showunused=0 and only get dirs for the
> > slots with devices in them. Now I decide to put a network card (or
> > whatever I have to spare) in an empty slot, hope that the system doesn't
> > reboot immediately, and voila I don't have any /sys/bus/pci/slots dir to
> > enable the slot and have to reboot nevertheless. Or does the pci system a
> > rescan if I reinsert the module?
>
> That is DANGEROUS and WILL DESTROY YOUR SYSTEM. Under no circumstances
> should we be encouraging people to do that.

Yes, and that's why there a big comments as well in the Kconfig help as well
as in the source of both dummyphp and fakephp.

Eike

2004-09-24 15:16:51

by Greg KH

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Fri, Sep 24, 2004 at 02:32:06PM +0200, Rolf Eike Beer wrote:
> Am Freitag, 24. September 2004 14:16 schrieben Sie:
> > Rolf Eike Beer wrote:
> > > Normally you will just remove and bring back one or two cards in the
> > > system (e.g. your NIC or sound card, depending on xmms or irc being on
> > > top of your priority list *g*). So from my point of view it's a good idea
> > > to keep the slot dirs on remove so you can just go back in your command
> > > history and replace 0 with 1 to get the device back. I don't see why bus
> > > structure or whatever may ever change so rescanning the whole bus is IMHO
> > > a bit overkill.
> >
> > My point was, I load dummyphp with showunused=0 and only get dirs for the
> > slots with devices in them. Now I decide to put a network card (or whatever
> > I have to spare) in an empty slot, hope that the system doesn't reboot
> > immediately, and voila I don't have any /sys/bus/pci/slots dir to enable
> > the slot and have to reboot nevertheless. Or does the pci system a rescan
> > if I reinsert the module?
>
> In this case you have to "rmmod dummyphp; modprobe dummyphp showunused=1" to
> get all slots and try to enable the device. We have tested it once with a
> special PCI debugging board where we can electrically disable the PCI bus so
> we don't kill our hardware. The problem was that on reenabling a interrupt
> storm killed the machine, I don't remember the exact problem. IIRC it looked
> like the kernel found the device but the PCI bridge got confused by the new
> device (or something like this). I don't know if there is a way to survive
> this situation as the bridges in "normal" hardware are not hotplug aware.
> Greg?

Hm, don't know, but that's the whole reason people want this, so it
should work :)

The main reason I don't like showing _all_ possible pci devices like
dummyphp does is that it doesn't handle adding a new device (like you
just said), and the fact that you forgot to handle pci domains. If you
add support for PCI domains, then the list of files in that directory
will pretty much be unusable.

Please just add the "rescan" support to fakephp, and everyone will be
happy...

thanks,

greg k-h

2004-09-27 09:07:49

by Rolf Eike Beer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

> > to get all slots and try to enable the device. We have tested it once
> > with a special PCI debugging board where we can electrically disable the
> > PCI bus so we don't kill our hardware. The problem was that on reenabling
> > a interrupt storm killed the machine, I don't remember the exact problem.
> > IIRC it looked like the kernel found the device but the PCI bridge got
> > confused by the new device (or something like this). I don't know if
> > there is a way to survive this situation as the bridges in "normal"
> > hardware are not hotplug aware. Greg?
>
> Hm, don't know, but that's the whole reason people want this, so it
> should work :)

IMHO they want it for testing logical removal, hot removal without hardware
support is just too dangerous to test with dummyphp. Or what am I missing?

> The main reason I don't like showing _all_ possible pci devices like
> dummyphp does is that it doesn't handle adding a new device (like you
> just said), and the fact that you forgot to handle pci domains. If you
> add support for PCI domains, then the list of files in that directory
> will pretty much be unusable.

Ehm? Did you read the code? I use the PCI domains of the slots and buses. And
by default there are only slots with devices in it shown now.

> Please just add the "rescan" support to fakephp, and everyone will be
> happy...

That can't be. I hate fakephp ;)

Eike

2004-10-10 00:14:30

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

ifneq ($(KERNELRELEASE),)

obj-m := pcirescan.o

else

KDIR := /lib/modules/$(shell uname -r)/build
# KDIR := ../pcirescan
PWD := $(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif


Attachments:
pci_bus_add_device.patch (1.65 kB)
Makefile (202.00 B)
pcirescan.c (3.10 kB)
Download all attachments

2004-10-10 01:00:29

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Jan Dittmer wrote:
> Greg KH wrote:
>
>>Please just add the "rescan" support to fakephp, and everyone will be
>>happy...
>
>
> Well, I started to work on this for fun. What I currently have is a
> stand-alone module which rescans the pci bus on insert and enables
> previously disabled devices. This works (at least with my ieee1394 port).
> Problem is, that fakephp does not get notified about this new pci device
> and no new file is created in /sys/bus/pci/slots. So I'm going to add
> this rescan functionality directly to fakephp.
> Question is: where? My current idea is a fake hotplug slot "rescan" in
> /sys/bus/pci/slots , where you can write "1" into the "power" attribute.
> FWIW I've attached the standalone module and a kernel patch which rips
> out the pci_bus_add_device functionality from pci_bus_add_devices.

Well, here is a quick & dirty hack, which adds this function to
enable_slot in fakephp. So if you write "1" in the power attribute of
any slot, the whole bus gets rescanned (you still need the
pci_bus_add_device.patch from the previous mail).

Thanks,

Jan


Attachments:
fakephp-rescan-on-enable.patch (3.17 kB)

2004-10-10 13:47:18

by Jan Dittmer

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

Jan Dittmer wrote:
> Jan Dittmer wrote:
>
>>Greg KH wrote:
>>
>>
>>>Please just add the "rescan" support to fakephp, and everyone will be
>>>happy...
>>
>>
>>Well, I started to work on this for fun. What I currently have is a
>>stand-alone module which rescans the pci bus on insert and enables
>>previously disabled devices. This works (at least with my ieee1394 port).
>>Problem is, that fakephp does not get notified about this new pci device
>>and no new file is created in /sys/bus/pci/slots. So I'm going to add
>>this rescan functionality directly to fakephp.
>>Question is: where? My current idea is a fake hotplug slot "rescan" in
>>/sys/bus/pci/slots , where you can write "1" into the "power" attribute.
>>FWIW I've attached the standalone module and a kernel patch which rips
>>out the pci_bus_add_device functionality from pci_bus_add_devices.
>
>
> Well, here is a quick & dirty hack, which adds this function to
> enable_slot in fakephp. So if you write "1" in the power attribute of
> any slot, the whole bus gets rescanned (you still need the
> pci_bus_add_device.patch from the previous mail).

Well one last update. This version also handles deactivation of
subfunctions correctly, ie. when the parent should be disabled, all
subfunctions will be disabled first.

Small 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/Game
port (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)

Sound plays fine afterwards.
Actually this only works only once or twice. At some point the removal
command will hang (but I suppose this is a problem with either
snd-emu10k1 or ieee1394).

Jan



Attachments:
fakephp-rescan-on-enable-3.patch (4.17 kB)
pci_bus_add_device.patch (1.65 kB)
Download all attachments

2004-10-30 16:18:34

by Greg KH

[permalink] [raw]
Subject: Re: Is there a user space pci rescan method?

On Sun, Oct 10, 2004 at 03:45:29PM +0200, Jan Dittmer wrote:
> Jan Dittmer wrote:
> > Jan Dittmer wrote:
> >
> >>Greg KH wrote:
> >>
> >>
> >>>Please just add the "rescan" support to fakephp, and everyone will be
> >>>happy...
> >>
> >>
> >>Well, I started to work on this for fun. What I currently have is a
> >>stand-alone module which rescans the pci bus on insert and enables
> >>previously disabled devices. This works (at least with my ieee1394 port).
> >>Problem is, that fakephp does not get notified about this new pci device
> >>and no new file is created in /sys/bus/pci/slots. So I'm going to add
> >>this rescan functionality directly to fakephp.
> >>Question is: where? My current idea is a fake hotplug slot "rescan" in
> >>/sys/bus/pci/slots , where you can write "1" into the "power" attribute.
> >>FWIW I've attached the standalone module and a kernel patch which rips
> >>out the pci_bus_add_device functionality from pci_bus_add_devices.
> >
> >
> > Well, here is a quick & dirty hack, which adds this function to
> > enable_slot in fakephp. So if you write "1" in the power attribute of
> > any slot, the whole bus gets rescanned (you still need the
> > pci_bus_add_device.patch from the previous mail).
>
> Well one last update. This version also handles deactivation of
> subfunctions correctly, ie. when the parent should be disabled, all
> subfunctions will be disabled first.

Nice, I like it. Care to resend this in 2 different emails, with a good
description in the subject line, and in the body of the email, and a
"Signed-off-by:" line in it too (as per the
Documentation/SubmittingPatches file) so I can apply these to the tree?

thanks,

greg k-h

2004-11-01 00:01:06

by Jan Dittmer

[permalink] [raw]
Subject: [patch 2/2] fakephp: add pci bus rescan ability

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 <[email protected]>

===== 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");


2004-11-01 00:01:22

by Jan Dittmer

[permalink] [raw]
Subject: [patch 1/2] fakephp: introduce pci_bus_add_device

fakephp needs to add newly discovered devices to the global pci list.
Therefore seperate out the appropriate chunk from pci_bus_add_devices
to pci_bus_add_device to add a single device to sysfs, procfs
and the global device list.

Signed-off-by: Jan Dittmer <[email protected]>

===== drivers/pci/bus.c 1.9 vs edited =====
--- 1.9/drivers/pci/bus.c 2004-04-11 00:27:59 +02:00
+++ edited/drivers/pci/bus.c 2004-10-31 23:24:10 +01:00
@@ -69,6 +69,24 @@
}

/**
+ * add a single device
+ * @dev: device to add
+ *
+ * This adds a single pci device to the global
+ * device list and adds sysfs and procfs entries for it
+ */
+void __devinit pci_bus_add_device(struct pci_dev *dev) {
+ device_add(&dev->dev);
+
+ spin_lock(&pci_bus_lock);
+ list_add_tail(&dev->global_list, &pci_devices);
+ spin_unlock(&pci_bus_lock);
+
+ pci_proc_attach_device(dev);
+ pci_create_sysfs_dev_files(dev);
+}
+
+/**
* pci_bus_add_devices - insert newly discovered PCI devices
* @bus: bus to check for new devices
*
@@ -91,16 +109,7 @@
*/
if (!list_empty(&dev->global_list))
continue;
-
- device_add(&dev->dev);
-
- spin_lock(&pci_bus_lock);
- list_add_tail(&dev->global_list, &pci_devices);
- spin_unlock(&pci_bus_lock);
-
- pci_proc_attach_device(dev);
- pci_create_sysfs_dev_files(dev);
-
+ pci_bus_add_device(dev);
}

list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -136,5 +145,6 @@
}

EXPORT_SYMBOL(pci_bus_alloc_resource);
+EXPORT_SYMBOL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices);
EXPORT_SYMBOL(pci_enable_bridges);
===== include/linux/pci.h 1.139 vs edited =====
--- 1.139/include/linux/pci.h 2004-10-06 00:56:26 +02:00
+++ edited/include/linux/pci.h 2004-10-31 23:10:04 +01:00
@@ -713,6 +713,7 @@
int pci_scan_slot(struct pci_bus *bus, int devfn);
struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
unsigned int pci_scan_child_bus(struct pci_bus *bus);
+void pci_bus_add_device(struct pci_dev *dev);
void pci_bus_add_devices(struct pci_bus *bus);
void pci_name_device(struct pci_dev *dev);
char *pci_class_name(u32 class);

2004-11-01 09:35:38

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [patch 1/2] fakephp: introduce pci_bus_add_device

On Mon, Nov 01, 2004 at 12:59:54AM +0100, Jan Dittmer wrote:
> fakephp needs to add newly discovered devices to the global pci list.
> Therefore seperate out the appropriate chunk from pci_bus_add_devices
> to pci_bus_add_device to add a single device to sysfs, procfs
> and the global device list.
>
> Signed-off-by: Jan Dittmer <[email protected]>
>
> ===== drivers/pci/bus.c 1.9 vs edited =====
> --- 1.9/drivers/pci/bus.c 2004-04-11 00:27:59 +02:00
> +++ edited/drivers/pci/bus.c 2004-10-31 23:24:10 +01:00
> @@ -69,6 +69,24 @@
> }
>
> /**
> + * add a single device
> + * @dev: device to add
> + *
> + * This adds a single pci device to the global
> + * device list and adds sysfs and procfs entries for it
> + */
> +void __devinit pci_bus_add_device(struct pci_dev *dev) {

the brace should go to a line of it's own

2004-11-02 22:56:39

by Jan Dittmer

[permalink] [raw]
Subject: Re: [patch 1/2] fakephp: introduce pci_bus_add_device

Christoph Hellwig wrote:
> On Mon, Nov 01, 2004 at 12:59:54AM +0100, Jan Dittmer wrote:
>
>>fakephp needs to add newly discovered devices to the global pci list.
>>Therefore seperate out the appropriate chunk from pci_bus_add_devices
>>to pci_bus_add_device to add a single device to sysfs, procfs
>>and the global device list.
>>
>>Signed-off-by: Jan Dittmer <[email protected]>

> the brace should go to a line of it's own

Sorry about that, updated patch follows:

--- 1.9/drivers/pci/bus.c 2004-04-11 00:27:59 +02:00
+++ edited/drivers/pci/bus.c 2004-11-01 10:41:27 +01:00
@@ -69,6 +69,25 @@
}

/**
+ * add a single device
+ * @dev: device to add
+ *
+ * This adds a single pci device to the global
+ * device list and adds sysfs and procfs entries
+ */
+void __devinit pci_bus_add_device(struct pci_dev *dev)
+{
+ device_add(&dev->dev);
+
+ spin_lock(&pci_bus_lock);
+ list_add_tail(&dev->global_list, &pci_devices);
+ spin_unlock(&pci_bus_lock);
+
+ pci_proc_attach_device(dev);
+ pci_create_sysfs_dev_files(dev);
+}
+
+/**
* pci_bus_add_devices - insert newly discovered PCI devices
* @bus: bus to check for new devices
*
@@ -91,16 +110,7 @@
*/
if (!list_empty(&dev->global_list))
continue;
-
- device_add(&dev->dev);
-
- spin_lock(&pci_bus_lock);
- list_add_tail(&dev->global_list, &pci_devices);
- spin_unlock(&pci_bus_lock);
-
- pci_proc_attach_device(dev);
- pci_create_sysfs_dev_files(dev);
-
+ pci_bus_add_device(dev);
}

list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -136,5 +146,6 @@
}

EXPORT_SYMBOL(pci_bus_alloc_resource);
+EXPORT_SYMBOL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices);
EXPORT_SYMBOL(pci_enable_bridges);
--- 1.139/include/linux/pci.h 2004-10-06 00:56:26 +02:00
+++ edited/include/linux/pci.h 2004-10-31 23:10:04 +01:00
@@ -713,6 +713,7 @@
int pci_scan_slot(struct pci_bus *bus, int devfn);
struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
unsigned int pci_scan_child_bus(struct pci_bus *bus);
+void pci_bus_add_device(struct pci_dev *dev);
void pci_bus_add_devices(struct pci_bus *bus);
void pci_name_device(struct pci_dev *dev);
char *pci_class_name(u32 class);


2004-11-11 23:51:03

by Greg KH

[permalink] [raw]
Subject: Re: [patch 1/2] fakephp: introduce pci_bus_add_device

On Tue, Nov 02, 2004 at 11:51:15PM +0100, Jan Dittmer wrote:
> Christoph Hellwig wrote:
> > On Mon, Nov 01, 2004 at 12:59:54AM +0100, Jan Dittmer wrote:
> >
> >>fakephp needs to add newly discovered devices to the global pci list.
> >>Therefore seperate out the appropriate chunk from pci_bus_add_devices
> >>to pci_bus_add_device to add a single device to sysfs, procfs
> >>and the global device list.
> >>
> >>Signed-off-by: Jan Dittmer <[email protected]>
>
> > the brace should go to a line of it's own
>
> Sorry about that, updated patch follows:

Ugh, your email client ate all of the tabs and spit them out as spaces
for this patch :(

Care to try it again?

thanks,

greg k-h

2004-11-12 00:21:07

by Jan Dittmer

[permalink] [raw]
Subject: Re: [patch 1/2] fakephp: introduce pci_bus_add_device

Greg KH wrote:
> On Tue, Nov 02, 2004 at 11:51:15PM +0100, Jan Dittmer wrote:
>
>>Christoph Hellwig wrote:
>>
>>>On Mon, Nov 01, 2004 at 12:59:54AM +0100, Jan Dittmer wrote:
>>>
>>>
>>>>fakephp needs to add newly discovered devices to the global pci list.
>>>>Therefore seperate out the appropriate chunk from pci_bus_add_devices
>>>>to pci_bus_add_device to add a single device to sysfs, procfs
>>>>and the global device list.
>>>>
>>>>Signed-off-by: Jan Dittmer <[email protected]>
>>
>>>the brace should go to a line of it's own
>>
>>Sorry about that, updated patch follows:
>
>
> Ugh, your email client ate all of the tabs and spit them out as spaces
> for this patch :(
>
> Care to try it again?

Well, I still don't know how to do this with Thunderbird as
non attachment. So here it goes as attachment.

Jan


Attachments:
pci_bus_add_device-2.patch (1.76 kB)

2004-11-12 19:14:58

by Greg KH

[permalink] [raw]
Subject: Re: [patch 1/2] fakephp: introduce pci_bus_add_device

On Fri, Nov 12, 2004 at 01:13:13AM +0100, Jan Dittmer wrote:
> Greg KH wrote:
> > On Tue, Nov 02, 2004 at 11:51:15PM +0100, Jan Dittmer wrote:
> >
> >>Christoph Hellwig wrote:
> >>
> >>>On Mon, Nov 01, 2004 at 12:59:54AM +0100, Jan Dittmer wrote:
> >>>
> >>>
> >>>>fakephp needs to add newly discovered devices to the global pci list.
> >>>>Therefore seperate out the appropriate chunk from pci_bus_add_devices
> >>>>to pci_bus_add_device to add a single device to sysfs, procfs
> >>>>and the global device list.
> >>>>
> >>>>Signed-off-by: Jan Dittmer <[email protected]>
> >>
> >>>the brace should go to a line of it's own
> >>
> >>Sorry about that, updated patch follows:
> >
> >
> > Ugh, your email client ate all of the tabs and spit them out as spaces
> > for this patch :(
> >
> > Care to try it again?
>
> Well, I still don't know how to do this with Thunderbird as
> non attachment. So here it goes as attachment.

I'll live with that :)

Applied, thanks,

greg k-h

2004-11-12 19:16:49

by Greg KH

[permalink] [raw]
Subject: Re: [patch 2/2] fakephp: add pci bus rescan ability

On Mon, Nov 01, 2004 at 12:59:55AM +0100, Jan Dittmer wrote:
> 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.

Very nice, thanks for doing this work.

Applied, thanks.

greg k-h