This is a preparation patchset for introducing PCI bus lock mechanisms
to protect PCI subsystem from concurrent hotplug operations.
Patch 1:
Introduce pci_bus_{get|put}() to manage PCI bus reference count
Patch 2-3:
pci_alloc_dev() patchset from Gu Zheng
Patch 8:
Make PCI bus creating/destroying logic symmetric
Other:
Minor code improvements/cleanups
Gu Zheng (2):
PCI: Introduce pci_alloc_dev(struct pci_bus*) to replace
alloc_pci_dev()
PCI: Convert alloc_pci_dev(void) to pci_alloc_dev(bus) instead
Jiang Liu (7):
PCI: introduce pci_bus_{get|put}() to manage PCI bus reference count
PCI: mark pci_scan_bus_parented() as __deprecated
ACPI, PCI: remove unused global list acpi_pci_roots in pci_root.c
ACPI, pci_root: use acpi_handle_print() and pr_xxx() to print messages
PCI, IA64: minor code clean up
PCI: make PCI host bridge/bus creating and destroying logic symmetric
PCI, unicore, m68k: remove redundant call of pci_bus_add_devices()
arch/ia64/sn/kernel/io_init.c | 11 +---
arch/m68k/platform/coldfire/pci.c | 2 +-
arch/powerpc/kernel/pci_of_scan.c | 3 +-
arch/sparc/kernel/pci.c | 3 +-
arch/tile/kernel/pci.c | 3 --
arch/unicore32/kernel/pci.c | 5 --
drivers/acpi/pci_root.c | 96 +++++++++++++----------------------
drivers/char/agp/alpha-agp.c | 2 +-
drivers/char/agp/parisc-agp.c | 2 +-
drivers/pci/bus.c | 15 ++++++
drivers/pci/iov.c | 8 +--
drivers/pci/probe.c | 102 ++++++++++++++++++--------------------
drivers/pci/remove.c | 3 +-
drivers/scsi/megaraid.c | 2 +-
include/acpi/acpi_bus.h | 1 -
include/linux/pci.h | 9 ++--
16 files changed, 119 insertions(+), 148 deletions(-)
--
1.8.1.2
Introduce helper functions pci_bus_{get|put}() to manage PCI bus
reference count.
Signed-off-by: Jiang Liu <[email protected]>
Signed-off-by: Yijing Wang <[email protected]>
Signed-off-by: Gu Zheng <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
drivers/pci/bus.c | 15 +++++++++++++++
include/linux/pci.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 748f8f3..f7e1f76 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -282,6 +282,21 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
}
EXPORT_SYMBOL_GPL(pci_walk_bus);
+struct pci_bus *pci_bus_get(struct pci_bus *bus)
+{
+ if (bus)
+ get_device(&bus->dev);
+ return bus;
+}
+EXPORT_SYMBOL(pci_bus_get);
+
+void pci_bus_put(struct pci_bus *bus)
+{
+ if (bus)
+ put_device(&bus->dev);
+}
+EXPORT_SYMBOL(pci_bus_put);
+
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e19d864..f5e13f0 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1017,6 +1017,8 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
void pci_release_selected_regions(struct pci_dev *, int);
/* drivers/pci/bus.c */
+struct pci_bus *pci_bus_get(struct pci_bus *bus);
+void pci_bus_put(struct pci_bus *bus);
void pci_add_resource(struct list_head *resources, struct resource *res);
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset);
--
1.8.1.2
From: Gu Zheng <[email protected]>
<marker to prevent gmail from removing below "From:">
From: Gu Zheng <[email protected]>
Now here we introduce a new interface to replace alloc_pci_dev():
struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
It take a "struct pci_bus *" argument, so we can alloc a pci device
on a target pci bus, and it acquire the reference of the pci_bus.
We use pci_alloc_dev(NULL) to simplify the old alloc_pci_dev(),
and keep it for a while but mark it as __deprecated.
Jiang Liu <[email protected]>
Minor code tweaks and change
__deprecated struct pci_dev * alloc_pci_dev(void);
to
struct pci_dev * __deprecated alloc_pci_dev(void);
This enhancement makes it safe to reference pci_dev->bus when holding
a reference on a pci_dev.
Signed-off-by: Gu Zheng <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
drivers/pci/probe.c | 16 +++++++++++-----
include/linux/pci.h | 3 ++-
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 43ece5d..4f0bc0a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1201,18 +1201,24 @@ static void pci_release_bus_bridge_dev(struct device *dev)
kfree(bridge);
}
-struct pci_dev *alloc_pci_dev(void)
+struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
{
struct pci_dev *dev;
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- INIT_LIST_HEAD(&dev->bus_list);
+ if (dev) {
+ INIT_LIST_HEAD(&dev->bus_list);
+ dev->bus = pci_bus_get(bus);
+ }
return dev;
}
+EXPORT_SYMBOL(pci_alloc_dev);
+
+struct pci_dev *alloc_pci_dev(void)
+{
+ return pci_alloc_dev(NULL);
+}
EXPORT_SYMBOL(alloc_pci_dev);
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f5e13f0..68beb11 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -364,7 +364,8 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
return dev;
}
-struct pci_dev *alloc_pci_dev(void);
+struct pci_dev *pci_alloc_dev(struct pci_bus *bus);
+struct pci_dev * __deprecated alloc_pci_dev(void);
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
--
1.8.1.2
From: Gu Zheng <[email protected]>
<marker to prevent gmail from removing below "From:">
From: Gu Zheng <[email protected]>
Use the new pci_alloc_dev(bus) to replace the existing using of
alloc_pci_dev(void).
v2:
Follow Bjorn's correction to move pci_bus_put() to
pci_release_dev() instead.
Signed-off-by: Gu Zheng <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: David Airlie <[email protected]>
Cc: Neela Syam Kolli <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Jiang Liu <[email protected]>
---
arch/powerpc/kernel/pci_of_scan.c | 3 +--
arch/sparc/kernel/pci.c | 3 +--
drivers/char/agp/alpha-agp.c | 2 +-
drivers/char/agp/parisc-agp.c | 2 +-
drivers/pci/iov.c | 8 +++++---
drivers/pci/probe.c | 4 ++--
drivers/scsi/megaraid.c | 2 +-
7 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 2a67e9b..24d01c4 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -128,7 +128,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
const char *type;
struct pci_slot *slot;
- dev = alloc_pci_dev();
+ dev = pci_alloc_dev(bus);
if (!dev)
return NULL;
type = of_get_property(node, "device_type", NULL);
@@ -137,7 +137,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
pr_debug(" create device, devfn: %x, type: %s\n", devfn, type);
- dev->bus = bus;
dev->dev.of_node = of_node_get(node);
dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index baf4366..e5871fb 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -254,7 +254,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
const char *type;
u32 class;
- dev = alloc_pci_dev();
+ dev = pci_alloc_dev(bus);
if (!dev)
return NULL;
@@ -281,7 +281,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
printk(" create device, devfn: %x, type: %s\n",
devfn, type);
- dev->bus = bus;
dev->sysdata = node;
dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type;
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index dd84af4..199b8e9 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -174,7 +174,7 @@ alpha_core_agp_setup(void)
/*
* Build a fake pci_dev struct
*/
- pdev = alloc_pci_dev();
+ pdev = pci_alloc_dev(NULL);
if (!pdev)
return -ENOMEM;
pdev->vendor = 0xffff;
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index 94821ab..bf5d247 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -333,7 +333,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa)
struct agp_bridge_data *bridge;
int error = 0;
- fake_bridge_dev = alloc_pci_dev();
+ fake_bridge_dev = pci_alloc_dev(NULL);
if (!fake_bridge_dev) {
error = -ENOMEM;
goto fail;
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index ee599f2..24134cd 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -75,18 +75,20 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
struct pci_dev *virtfn;
struct resource *res;
struct pci_sriov *iov = dev->sriov;
+ struct pci_bus *bus;
- virtfn = alloc_pci_dev();
+ virtfn = pci_alloc_dev(NULL);
if (!virtfn)
return -ENOMEM;
mutex_lock(&iov->dev->sriov->lock);
- virtfn->bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id));
- if (!virtfn->bus) {
+ bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id));
+ if (!bus) {
kfree(virtfn);
mutex_unlock(&iov->dev->sriov->lock);
return -ENOMEM;
}
+ virtfn->bus = pci_bus_get(bus);
virtfn->devfn = virtfn_devfn(dev, id);
virtfn->vendor = dev->vendor;
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 4f0bc0a..bc075a3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1131,6 +1131,7 @@ static void pci_release_dev(struct device *dev)
struct pci_dev *pci_dev;
pci_dev = to_pci_dev(dev);
+ pci_bus_put(pci_dev->bus);
pci_release_capabilities(pci_dev);
pci_release_of_node(pci_dev);
kfree(pci_dev);
@@ -1269,11 +1270,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
return NULL;
- dev = alloc_pci_dev();
+ dev = pci_alloc_dev(bus);
if (!dev)
return NULL;
- dev->bus = bus;
dev->devfn = devfn;
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 9504ec0..e1660ca 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -2025,7 +2025,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
static inline int
make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
{
- *pdev = alloc_pci_dev();
+ *pdev = pci_alloc_dev(NULL);
if( *pdev == NULL ) return -1;
--
1.8.1.2
Now the global list acpi_pci_roots pci_root.c is useless, remove it.
Signed-off-by: Jiang Liu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
drivers/acpi/pci_root.c | 25 +++----------------------
include/acpi/acpi_bus.h | 1 -
2 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index b80e06e..91ddfd6 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -65,10 +65,6 @@ static struct acpi_scan_handler pci_root_handler = {
.detach = acpi_pci_root_remove,
};
-/* Lock to protect both acpi_pci_roots lists */
-static DEFINE_MUTEX(acpi_pci_root_lock);
-static LIST_HEAD(acpi_pci_roots);
-
static DEFINE_MUTEX(osc_lock);
/**
@@ -423,7 +419,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
}
}
- INIT_LIST_HEAD(&root->node);
root->device = device;
root->segment = segment & 0xFFFF;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
@@ -501,10 +496,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
- mutex_lock(&acpi_pci_root_lock);
- list_add_tail(&root->node, &acpi_pci_roots);
- mutex_unlock(&acpi_pci_root_lock);
-
/*
* Scan the Root Bridge
* --------------------
@@ -518,7 +509,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
- goto out_del_root;
+ goto end;
}
/* ASPM setting */
@@ -538,20 +529,13 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (system_state != SYSTEM_BOOTING) {
pcibios_resource_survey_bus(root->bus);
pci_assign_unassigned_bus_resources(root->bus);
- }
-
- /* need to after hot-added ioapic is registered */
- if (system_state != SYSTEM_BOOTING)
+ /* need to after hot-added ioapic is registered */
pci_enable_bridges(root->bus);
+ }
pci_bus_add_devices(root->bus);
return 1;
-out_del_root:
- mutex_lock(&acpi_pci_root_lock);
- list_del(&root->node);
- mutex_unlock(&acpi_pci_root_lock);
-
end:
kfree(root);
return result;
@@ -568,9 +552,6 @@ static void acpi_pci_root_remove(struct acpi_device *device)
pci_remove_root_bus(root->bus);
- mutex_lock(&acpi_pci_root_lock);
- list_del(&root->node);
- mutex_unlock(&acpi_pci_root_lock);
kfree(root);
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 22ba56e..4eb9a88 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -447,7 +447,6 @@ int register_acpi_bus_type(struct acpi_bus_type *);
int unregister_acpi_bus_type(struct acpi_bus_type *);
struct acpi_pci_root {
- struct list_head node;
struct acpi_device * device;
struct pci_bus *bus;
u16 segment;
--
1.8.1.2
pci_scan_root_bus() already set bus->sysdata, so no need to explicitly
set it again in function sn_pci_controller_fixup();
Signed-off-by: Jiang Liu <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
arch/ia64/sn/kernel/io_init.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 238e2c5..e2c7733 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -326,16 +326,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
&resources);
if (bus == NULL)
- goto error_return; /* error, or bus already scanned */
-
- bus->sysdata = controller;
-
- return;
-
-error_return:
-
- kfree(controller);
- return;
+ kfree(controller);
}
/*
--
1.8.1.2
Use acpi_handle_print() and pr_xxx() to print messages in pci_root.c.
Signed-off-by: Jiang Liu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
drivers/acpi/pci_root.c | 71 ++++++++++++++++++++++---------------------------
1 file changed, 32 insertions(+), 39 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 91ddfd6..9ced5c3 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -379,23 +379,23 @@ static int acpi_pci_root_add(struct acpi_device *device,
struct acpi_pci_root *root;
u32 flags, base_flags;
bool is_osc_granted = false;
+ acpi_handle hdl = device->handle;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
return -ENOMEM;
segment = 0;
- status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
- &segment);
+ status = acpi_evaluate_integer(hdl, METHOD_NAME__SEG, NULL, &segment);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
+ acpi_handle_err(hdl, "can't evaluate _SEG\n");
result = -ENODEV;
goto end;
}
/* Check _CRS first, then _BBN. If no _BBN, default to zero. */
root->secondary.flags = IORESOURCE_BUS;
- status = try_get_root_bridge_busnr(device->handle, &root->secondary);
+ status = try_get_root_bridge_busnr(hdl, &root->secondary);
if (ACPI_FAILURE(status)) {
/*
* We need both the start and end of the downstream bus range
@@ -404,16 +404,16 @@ static int acpi_pci_root_add(struct acpi_device *device,
* can do is assume [_BBN-0xFF] or [0-0xFF].
*/
root->secondary.end = 0xFF;
- printk(KERN_WARNING FW_BUG PREFIX
- "no secondary bus range in _CRS\n");
- status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
+ acpi_handle_warn(hdl,
+ FW_BUG "no secondary bus range in _CRS\n");
+ status = acpi_evaluate_integer(hdl, METHOD_NAME__BBN,
NULL, &bus);
if (ACPI_SUCCESS(status))
root->secondary.start = bus;
else if (status == AE_NOT_FOUND)
root->secondary.start = 0;
else {
- printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
+ acpi_handle_err(hdl, "can't evaluate _BBN\n");
result = -ENODEV;
goto end;
}
@@ -425,11 +425,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
- printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
+ pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
- root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(hdl);
/*
* All supported architectures that use ACPI have support for
@@ -473,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
dev_info(&device->dev,
"Requesting ACPI _OSC control (0x%02x)\n", flags);
- status = acpi_pci_osc_control_set(device->handle, &flags,
+ status = acpi_pci_osc_control_set(hdl, &flags,
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_SUCCESS(status)) {
is_osc_granted = true;
@@ -505,9 +505,9 @@ static int acpi_pci_root_add(struct acpi_device *device,
*/
root->bus = pci_acpi_scan_root(root);
if (!root->bus) {
- printk(KERN_ERR PREFIX
- "Bus %04x:%02x not present in PCI namespace\n",
- root->segment, (unsigned int)root->secondary.start);
+ acpi_handle_err(hdl,
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
goto end;
}
@@ -517,8 +517,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
pcie_clear_aspm(root->bus);
} else {
- pr_info("ACPI _OSC control for PCIe not granted, "
- "disabling ASPM\n");
+ acpi_handle_info(hdl,
+ "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
pcie_no_aspm();
}
@@ -571,12 +571,13 @@ static void handle_root_bridge_insertion(acpi_handle handle)
struct acpi_device *device;
if (!acpi_bus_get_device(handle, &device)) {
- printk(KERN_DEBUG "acpi device exists...\n");
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "acpi device exists...\n");
return;
}
if (acpi_bus_scan(handle))
- printk(KERN_ERR "cannot add bridge to acpi list\n");
+ acpi_handle_err(handle, "cannot add bridge to acpi list\n");
}
static void handle_root_bridge_removal(struct acpi_device *device)
@@ -602,7 +603,6 @@ static void handle_root_bridge_removal(struct acpi_device *device)
static void _handle_hotplug_event_root(struct work_struct *work)
{
struct acpi_pci_root *root;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
@@ -613,13 +613,11 @@ static void _handle_hotplug_event_root(struct work_struct *work)
root = acpi_pci_find_root(handle);
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus enumerate */
- printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Bus check notify on %s\n", __func__);
if (!root)
handle_root_bridge_insertion(handle);
@@ -627,27 +625,26 @@ static void _handle_hotplug_event_root(struct work_struct *work)
case ACPI_NOTIFY_DEVICE_CHECK:
/* device check */
- printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Device check notify on %s\n", __func__);
if (!root)
handle_root_bridge_insertion(handle);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
- printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Device eject notify on %s\n", __func__);
if (root)
handle_root_bridge_removal(root->device);
break;
default:
- printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
- type, (char *)buffer.pointer);
+ acpi_handle_warn(handle,
+ "notify_handler: unknown event type 0x%xn", type);
break;
}
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
- kfree(buffer.pointer);
}
static void handle_hotplug_event_root(acpi_handle handle, u32 type,
@@ -661,9 +658,6 @@ static acpi_status __init
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- char objname[64];
- struct acpi_buffer buffer = { .length = sizeof(objname),
- .pointer = objname };
int *count = (int *)context;
if (!acpi_is_root_bridge(handle))
@@ -671,16 +665,15 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
(*count)++;
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_root, NULL);
if (ACPI_FAILURE(status))
- printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
- objname, (unsigned int)status);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "notify handler is not installed, exit status: %u\n",
+ (unsigned int)status);
else
- printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
- objname);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "notify handler is installed\n");
return AE_OK;
}
--
1.8.1.2
pci_scan_bus() and pci_scan_root_bus() has called pci_bus_add_devices()
once, so remove the redundant call of pci_bus_add_devices().
On the other handle, subsys_init() callbacks will be invoked before
device_init() callbacks, so it should be safe to remove the redundant
calls.
Signed-off-by: Jiang Liu <[email protected]>
---
arch/m68k/platform/coldfire/pci.c | 2 +-
arch/unicore32/kernel/pci.c | 5 -----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c
index 8572246..2345972 100644
--- a/arch/m68k/platform/coldfire/pci.c
+++ b/arch/m68k/platform/coldfire/pci.c
@@ -320,7 +320,7 @@ static int __init mcf_pci_init(void)
pci_bus_size_bridges(rootbus);
pci_bus_assign_resources(rootbus);
pci_enable_bridges(rootbus);
- pci_bus_add_devices(rootbus);
+
return 0;
}
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index ef69c0c..374a055 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -277,11 +277,6 @@ static int __init pci_common_init(void)
pci_bus_assign_resources(puv3_bus);
}
- /*
- * Tell drivers about devices found.
- */
- pci_bus_add_devices(puv3_bus);
-
return 0;
}
subsys_initcall(pci_common_init);
--
1.8.1.2
This patch makes PCI host bridge/bus creating and destroying logic
symmetric by using device_initialize()/device_add()/device_del()/put_device()
pairs as discussed in thread at:
http://comments.gmane.org/gmane.linux.kernel.pci/22073
It also fixes a bug in error recovery path in pci_create_root_bus()
which may kfree() an in-use host bridge object.
Signed-off-by: Jiang Liu <[email protected]>
Cc: Yinghai Lu <[email protected]>
---
drivers/pci/probe.c | 84 +++++++++++++++++++++++-----------------------------
drivers/pci/remove.c | 3 +-
2 files changed, 39 insertions(+), 48 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bc075a3..a2617c2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -451,7 +451,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
}
}
-static struct pci_bus * pci_alloc_bus(void)
+static struct pci_bus *pci_alloc_bus(struct pci_ops *ops, void *sd, int bus)
{
struct pci_bus *b;
@@ -464,10 +464,32 @@ static struct pci_bus * pci_alloc_bus(void)
INIT_LIST_HEAD(&b->resources);
b->max_bus_speed = PCI_SPEED_UNKNOWN;
b->cur_bus_speed = PCI_SPEED_UNKNOWN;
+ b->sysdata = sd;
+ b->ops = ops;
+ b->number = bus;
+ b->busn_res.start = bus;
+ b->busn_res.end = 0xff;
+ b->busn_res.flags = IORESOURCE_BUS;
+ b->dev.class = &pcibus_class;
+ dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+ device_initialize(&b->dev);
}
+
return b;
}
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+ struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+ if (bridge->release_fn)
+ bridge->release_fn(bridge);
+
+ pci_free_resource_list(&bridge->windows);
+
+ kfree(bridge);
+}
+
static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
{
struct pci_host_bridge *bridge;
@@ -476,6 +498,10 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
if (bridge) {
INIT_LIST_HEAD(&bridge->windows);
bridge->bus = b;
+ bridge->dev.release = pci_release_host_bridge_dev;
+ dev_set_name(&bridge->dev, "pci%04x:%02x",
+ pci_domain_nr(b), b->number);
+ device_initialize(&bridge->dev);
}
return bridge;
@@ -628,28 +654,13 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
/*
* Allocate a new bus, and inherit stuff from the parent..
*/
- child = pci_alloc_bus();
+ child = pci_alloc_bus(parent->ops, parent->sysdata, busnr);
if (!child)
return NULL;
child->parent = parent;
- child->ops = parent->ops;
- child->sysdata = parent->sysdata;
child->bus_flags = parent->bus_flags;
-
- /* initialize some portions of the bus device, but don't register it
- * now as the parent is not properly set up yet.
- */
- child->dev.class = &pcibus_class;
- dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
-
- /*
- * Set up the primary, secondary and subordinate
- * bus numbers.
- */
- child->number = child->busn_res.start = busnr;
child->primary = parent->busn_res.start;
- child->busn_res.end = 0xff;
if (!bridge) {
child->dev.parent = parent->bridge;
@@ -670,7 +681,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
bridge->subordinate = child;
add_dev:
- ret = device_register(&child->dev);
+ ret = device_add(&child->dev);
WARN_ON(ret < 0);
pcibios_add_bus(child);
@@ -1190,18 +1201,6 @@ int pci_cfg_space_size(struct pci_dev *dev)
return PCI_CFG_SPACE_SIZE;
}
-static void pci_release_bus_bridge_dev(struct device *dev)
-{
- struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
-
- if (bridge->release_fn)
- bridge->release_fn(bridge);
-
- pci_free_resource_list(&bridge->windows);
-
- kfree(bridge);
-}
-
struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -1688,13 +1687,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
char bus_addr[64];
char *fmt;
- b = pci_alloc_bus();
+ b = pci_alloc_bus(ops, sysdata, bus);
if (!b)
return NULL;
- b->sysdata = sysdata;
- b->ops = ops;
- b->number = b->busn_res.start = bus;
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1706,27 +1702,22 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
if (!bridge)
goto err_out;
- bridge->dev.parent = parent;
- bridge->dev.release = pci_release_bus_bridge_dev;
- dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
error = pcibios_root_bridge_prepare(bridge);
if (error)
goto bridge_dev_reg_err;
- error = device_register(&bridge->dev);
+ bridge->dev.parent = parent;
+ error = device_add(&bridge->dev);
if (error)
goto bridge_dev_reg_err;
+
b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);
-
if (!parent)
set_dev_node(b->bridge, pcibus_to_node(b));
-
- b->dev.class = &pcibus_class;
b->dev.parent = b->bridge;
- dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
- error = device_register(&b->dev);
+ error = device_add(&b->dev);
if (error)
goto class_dev_reg_err;
@@ -1769,12 +1760,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
return b;
class_dev_reg_err:
- put_device(&bridge->dev);
- device_unregister(&bridge->dev);
+ device_del(&bridge->dev);
bridge_dev_reg_err:
- kfree(bridge);
+ put_device(&bridge->dev);
err_out:
- kfree(b);
+ put_device(&b->dev);
return NULL;
}
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 8fc54b7..b0ce875 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -52,7 +52,8 @@ void pci_remove_bus(struct pci_bus *bus)
up_write(&pci_bus_sem);
pci_remove_legacy_files(bus);
pcibios_remove_bus(bus);
- device_unregister(&bus->dev);
+ device_del(&bus->dev);
+ put_device(&bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
--
1.8.1.2
Mark pci_scan_bus_parented() as __deprecated and clean up outdated
comments.
Signed-off-by: Jiang Liu <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Thierry Reding <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
arch/tile/kernel/pci.c | 3 ---
include/linux/pci.h | 4 ++--
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 67237d3..936e087 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -309,9 +309,6 @@ int __init pcibios_init(void)
*
* It reads the PCI tree for this bus into the Linux
* data structures.
- *
- * This is inlined in linux/pci.h and calls into
- * pci_scan_bus_parented() in probe.c.
*/
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 68beb11..cc4ce27 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -720,8 +720,8 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
void pcibios_scan_specific_bus(int busn);
struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
-struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata);
+struct pci_bus * __deprecated pci_scan_bus_parented(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
--
1.8.1.2
On Mon, May 13, 2013 at 9:08 AM, Jiang Liu <[email protected]> wrote:
> From: Gu Zheng <[email protected]>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 4f0bc0a..bc075a3 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1131,6 +1131,7 @@ static void pci_release_dev(struct device *dev)
> struct pci_dev *pci_dev;
>
> pci_dev = to_pci_dev(dev);
> + pci_bus_put(pci_dev->bus);
> pci_release_capabilities(pci_dev);
> pci_release_of_node(pci_dev);
> kfree(pci_dev);
> @@ -1269,11 +1270,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
> if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
> return NULL;
>
> - dev = alloc_pci_dev();
> + dev = pci_alloc_dev(bus);
> if (!dev)
> return NULL;
>
> - dev->bus = bus;
> dev->devfn = devfn;
> dev->vendor = l & 0xffff;
> dev->device = (l >> 16) & 0xffff;
in pci_setup_device() fail path, it release the ref to that bus.
Yinghai
On Tuesday, May 14, 2013 12:08:30 AM Jiang Liu wrote:
> Use acpi_handle_print() and pr_xxx() to print messages in pci_root.c.
>
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: Len Brown <[email protected]>
> Cc: "Rafael J. Wysocki" <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> drivers/acpi/pci_root.c | 71 ++++++++++++++++++++++---------------------------
> 1 file changed, 32 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 91ddfd6..9ced5c3 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -379,23 +379,23 @@ static int acpi_pci_root_add(struct acpi_device *device,
> struct acpi_pci_root *root;
> u32 flags, base_flags;
> bool is_osc_granted = false;
> + acpi_handle hdl = device->handle;
The usual way is to call it 'handle'. Any reason why not to do it here too?
> root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
> if (!root)
> return -ENOMEM;
>
> segment = 0;
> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
> - &segment);
> + status = acpi_evaluate_integer(hdl, METHOD_NAME__SEG, NULL, &segment);
> if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
> - printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
> + acpi_handle_err(hdl, "can't evaluate _SEG\n");
> result = -ENODEV;
> goto end;
> }
>
> /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
> root->secondary.flags = IORESOURCE_BUS;
> - status = try_get_root_bridge_busnr(device->handle, &root->secondary);
> + status = try_get_root_bridge_busnr(hdl, &root->secondary);
> if (ACPI_FAILURE(status)) {
> /*
> * We need both the start and end of the downstream bus range
> @@ -404,16 +404,16 @@ static int acpi_pci_root_add(struct acpi_device *device,
> * can do is assume [_BBN-0xFF] or [0-0xFF].
> */
> root->secondary.end = 0xFF;
> - printk(KERN_WARNING FW_BUG PREFIX
> - "no secondary bus range in _CRS\n");
> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
> + acpi_handle_warn(hdl,
> + FW_BUG "no secondary bus range in _CRS\n");
> + status = acpi_evaluate_integer(hdl, METHOD_NAME__BBN,
> NULL, &bus);
> if (ACPI_SUCCESS(status))
> root->secondary.start = bus;
> else if (status == AE_NOT_FOUND)
> root->secondary.start = 0;
> else {
> - printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
> + acpi_handle_err(hdl, "can't evaluate _BBN\n");
> result = -ENODEV;
> goto end;
> }
> @@ -425,11 +425,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
> strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
> device->driver_data = root;
>
> - printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
> + pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
> acpi_device_name(device), acpi_device_bid(device),
> root->segment, &root->secondary);
>
> - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
> + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(hdl);
>
> /*
> * All supported architectures that use ACPI have support for
> @@ -473,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
> dev_info(&device->dev,
> "Requesting ACPI _OSC control (0x%02x)\n", flags);
>
> - status = acpi_pci_osc_control_set(device->handle, &flags,
> + status = acpi_pci_osc_control_set(hdl, &flags,
> OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
> if (ACPI_SUCCESS(status)) {
> is_osc_granted = true;
> @@ -505,9 +505,9 @@ static int acpi_pci_root_add(struct acpi_device *device,
> */
> root->bus = pci_acpi_scan_root(root);
> if (!root->bus) {
> - printk(KERN_ERR PREFIX
> - "Bus %04x:%02x not present in PCI namespace\n",
> - root->segment, (unsigned int)root->secondary.start);
> + acpi_handle_err(hdl,
> + "Bus %04x:%02x not present in PCI namespace\n",
> + root->segment, (unsigned int)root->secondary.start);
> result = -ENODEV;
> goto end;
> }
> @@ -517,8 +517,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
> if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
> pcie_clear_aspm(root->bus);
> } else {
> - pr_info("ACPI _OSC control for PCIe not granted, "
> - "disabling ASPM\n");
> + acpi_handle_info(hdl,
> + "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
> pcie_no_aspm();
> }
>
> @@ -571,12 +571,13 @@ static void handle_root_bridge_insertion(acpi_handle handle)
> struct acpi_device *device;
>
> if (!acpi_bus_get_device(handle, &device)) {
> - printk(KERN_DEBUG "acpi device exists...\n");
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "acpi device exists...\n");
Do we have acpi_handle_dbg()? If so, why don't you use it here? (And below.)
If not, why don't you add it and use it here (and below)?
> return;
> }
>
> if (acpi_bus_scan(handle))
> - printk(KERN_ERR "cannot add bridge to acpi list\n");
> + acpi_handle_err(handle, "cannot add bridge to acpi list\n");
> }
>
> static void handle_root_bridge_removal(struct acpi_device *device)
> @@ -602,7 +603,6 @@ static void handle_root_bridge_removal(struct acpi_device *device)
> static void _handle_hotplug_event_root(struct work_struct *work)
> {
> struct acpi_pci_root *root;
> - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
> struct acpi_hp_work *hp_work;
> acpi_handle handle;
> u32 type;
> @@ -613,13 +613,11 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>
> root = acpi_pci_find_root(handle);
>
> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
> -
> switch (type) {
> case ACPI_NOTIFY_BUS_CHECK:
> /* bus enumerate */
> - printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Bus check notify on %s\n", __func__);
> if (!root)
> handle_root_bridge_insertion(handle);
>
> @@ -627,27 +625,26 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>
> case ACPI_NOTIFY_DEVICE_CHECK:
> /* device check */
> - printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Device check notify on %s\n", __func__);
> if (!root)
> handle_root_bridge_insertion(handle);
> break;
>
> case ACPI_NOTIFY_EJECT_REQUEST:
> /* request device eject */
> - printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Device eject notify on %s\n", __func__);
> if (root)
> handle_root_bridge_removal(root->device);
> break;
> default:
> - printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
> - type, (char *)buffer.pointer);
> + acpi_handle_warn(handle,
> + "notify_handler: unknown event type 0x%xn", type);
> break;
> }
>
> kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
> - kfree(buffer.pointer);
> }
>
> static void handle_hotplug_event_root(acpi_handle handle, u32 type,
> @@ -661,9 +658,6 @@ static acpi_status __init
> find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> {
> acpi_status status;
> - char objname[64];
> - struct acpi_buffer buffer = { .length = sizeof(objname),
> - .pointer = objname };
> int *count = (int *)context;
>
> if (!acpi_is_root_bridge(handle))
> @@ -671,16 +665,15 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
>
> (*count)++;
>
> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
> -
> status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> handle_hotplug_event_root, NULL);
> if (ACPI_FAILURE(status))
> - printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
> - objname, (unsigned int)status);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "notify handler is not installed, exit status: %u\n",
> + (unsigned int)status);
> else
> - printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
> - objname);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "notify handler is installed\n");
>
> return AE_OK;
> }
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
On Tuesday, May 14, 2013 12:08:29 AM Jiang Liu wrote:
> Now the global list acpi_pci_roots pci_root.c is useless, remove it.
Well, are patches [1-4/9] needed for that or does it apply without them?
Rafael
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: Len Brown <[email protected]>
> Cc: "Rafael J. Wysocki" <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> drivers/acpi/pci_root.c | 25 +++----------------------
> include/acpi/acpi_bus.h | 1 -
> 2 files changed, 3 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index b80e06e..91ddfd6 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -65,10 +65,6 @@ static struct acpi_scan_handler pci_root_handler = {
> .detach = acpi_pci_root_remove,
> };
>
> -/* Lock to protect both acpi_pci_roots lists */
> -static DEFINE_MUTEX(acpi_pci_root_lock);
> -static LIST_HEAD(acpi_pci_roots);
> -
> static DEFINE_MUTEX(osc_lock);
>
> /**
> @@ -423,7 +419,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
> }
> }
>
> - INIT_LIST_HEAD(&root->node);
> root->device = device;
> root->segment = segment & 0xFFFF;
> strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
> @@ -501,10 +496,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
> * TBD: Need PCI interface for enumeration/configuration of roots.
> */
>
> - mutex_lock(&acpi_pci_root_lock);
> - list_add_tail(&root->node, &acpi_pci_roots);
> - mutex_unlock(&acpi_pci_root_lock);
> -
> /*
> * Scan the Root Bridge
> * --------------------
> @@ -518,7 +509,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
> "Bus %04x:%02x not present in PCI namespace\n",
> root->segment, (unsigned int)root->secondary.start);
> result = -ENODEV;
> - goto out_del_root;
> + goto end;
> }
>
> /* ASPM setting */
> @@ -538,20 +529,13 @@ static int acpi_pci_root_add(struct acpi_device *device,
> if (system_state != SYSTEM_BOOTING) {
> pcibios_resource_survey_bus(root->bus);
> pci_assign_unassigned_bus_resources(root->bus);
> - }
> -
> - /* need to after hot-added ioapic is registered */
> - if (system_state != SYSTEM_BOOTING)
> + /* need to after hot-added ioapic is registered */
> pci_enable_bridges(root->bus);
> + }
>
> pci_bus_add_devices(root->bus);
> return 1;
>
> -out_del_root:
> - mutex_lock(&acpi_pci_root_lock);
> - list_del(&root->node);
> - mutex_unlock(&acpi_pci_root_lock);
> -
> end:
> kfree(root);
> return result;
> @@ -568,9 +552,6 @@ static void acpi_pci_root_remove(struct acpi_device *device)
>
> pci_remove_root_bus(root->bus);
>
> - mutex_lock(&acpi_pci_root_lock);
> - list_del(&root->node);
> - mutex_unlock(&acpi_pci_root_lock);
> kfree(root);
> }
>
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 22ba56e..4eb9a88 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -447,7 +447,6 @@ int register_acpi_bus_type(struct acpi_bus_type *);
> int unregister_acpi_bus_type(struct acpi_bus_type *);
>
> struct acpi_pci_root {
> - struct list_head node;
> struct acpi_device * device;
> struct pci_bus *bus;
> u16 segment;
>
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
On 05/14/2013 01:23 AM, Yinghai Lu wrote:
> On Mon, May 13, 2013 at 9:08 AM, Jiang Liu <[email protected]> wrote:
>> From: Gu Zheng <[email protected]>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 4f0bc0a..bc075a3 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -1131,6 +1131,7 @@ static void pci_release_dev(struct device *dev)
>> struct pci_dev *pci_dev;
>>
>> pci_dev = to_pci_dev(dev);
>> + pci_bus_put(pci_dev->bus);
>> pci_release_capabilities(pci_dev);
>> pci_release_of_node(pci_dev);
>> kfree(pci_dev);
>> @@ -1269,11 +1270,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
>> if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
>> return NULL;
>>
>> - dev = alloc_pci_dev();
>> + dev = pci_alloc_dev(bus);
>> if (!dev)
>> return NULL;
>>
>> - dev->bus = bus;
>> dev->devfn = devfn;
>> dev->vendor = l & 0xffff;
>> dev->device = (l >> 16) & 0xffff;
>
> in pci_setup_device() fail path, it release the ref to that bus.
Yes, you're right, we need to release the bus' ref if pci_setup_device() failed.
Thanks for your correction.:)
Best regards,
Gu
>
> Yinghai
>
On 05/14/2013 12:08 AM, Jiang Liu wrote:
> Use acpi_handle_print() and pr_xxx() to print messages in pci_root.c.
>
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: Len Brown <[email protected]>
> Cc: "Rafael J. Wysocki" <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> drivers/acpi/pci_root.c | 71 ++++++++++++++++++++++---------------------------
> 1 file changed, 32 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 91ddfd6..9ced5c3 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -379,23 +379,23 @@ static int acpi_pci_root_add(struct acpi_device *device,
> struct acpi_pci_root *root;
> u32 flags, base_flags;
> bool is_osc_granted = false;
> + acpi_handle hdl = device->handle;
>
> root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
> if (!root)
> return -ENOMEM;
>
> segment = 0;
> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
> - &segment);
> + status = acpi_evaluate_integer(hdl, METHOD_NAME__SEG, NULL, &segment);
> if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
> - printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
> + acpi_handle_err(hdl, "can't evaluate _SEG\n");
> result = -ENODEV;
> goto end;
> }
>
> /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
> root->secondary.flags = IORESOURCE_BUS;
> - status = try_get_root_bridge_busnr(device->handle, &root->secondary);
> + status = try_get_root_bridge_busnr(hdl, &root->secondary);
> if (ACPI_FAILURE(status)) {
> /*
> * We need both the start and end of the downstream bus range
> @@ -404,16 +404,16 @@ static int acpi_pci_root_add(struct acpi_device *device,
> * can do is assume [_BBN-0xFF] or [0-0xFF].
> */
> root->secondary.end = 0xFF;
> - printk(KERN_WARNING FW_BUG PREFIX
> - "no secondary bus range in _CRS\n");
> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
> + acpi_handle_warn(hdl,
> + FW_BUG "no secondary bus range in _CRS\n");
> + status = acpi_evaluate_integer(hdl, METHOD_NAME__BBN,
> NULL, &bus);
> if (ACPI_SUCCESS(status))
> root->secondary.start = bus;
> else if (status == AE_NOT_FOUND)
> root->secondary.start = 0;
> else {
> - printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
> + acpi_handle_err(hdl, "can't evaluate _BBN\n");
> result = -ENODEV;
> goto end;
> }
> @@ -425,11 +425,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
> strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
> device->driver_data = root;
>
> - printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
> + pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
> acpi_device_name(device), acpi_device_bid(device),
> root->segment, &root->secondary);
>
> - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
> + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(hdl);
>
> /*
> * All supported architectures that use ACPI have support for
> @@ -473,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
> dev_info(&device->dev,
> "Requesting ACPI _OSC control (0x%02x)\n", flags);
>
> - status = acpi_pci_osc_control_set(device->handle, &flags,
> + status = acpi_pci_osc_control_set(hdl, &flags,
> OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
> if (ACPI_SUCCESS(status)) {
> is_osc_granted = true;
> @@ -505,9 +505,9 @@ static int acpi_pci_root_add(struct acpi_device *device,
> */
> root->bus = pci_acpi_scan_root(root);
> if (!root->bus) {
> - printk(KERN_ERR PREFIX
> - "Bus %04x:%02x not present in PCI namespace\n",
> - root->segment, (unsigned int)root->secondary.start);
> + acpi_handle_err(hdl,
> + "Bus %04x:%02x not present in PCI namespace\n",
> + root->segment, (unsigned int)root->secondary.start);
> result = -ENODEV;
> goto end;
> }
> @@ -517,8 +517,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
> if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
> pcie_clear_aspm(root->bus);
> } else {
> - pr_info("ACPI _OSC control for PCIe not granted, "
> - "disabling ASPM\n");
> + acpi_handle_info(hdl,
> + "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
> pcie_no_aspm();
> }
>
> @@ -571,12 +571,13 @@ static void handle_root_bridge_insertion(acpi_handle handle)
> struct acpi_device *device;
>
> if (!acpi_bus_get_device(handle, &device)) {
> - printk(KERN_DEBUG "acpi device exists...\n");
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "acpi device exists...\n");
> return;
> }
>
> if (acpi_bus_scan(handle))
> - printk(KERN_ERR "cannot add bridge to acpi list\n");
> + acpi_handle_err(handle, "cannot add bridge to acpi list\n");
> }
>
> static void handle_root_bridge_removal(struct acpi_device *device)
> @@ -602,7 +603,6 @@ static void handle_root_bridge_removal(struct acpi_device *device)
> static void _handle_hotplug_event_root(struct work_struct *work)
> {
> struct acpi_pci_root *root;
> - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
> struct acpi_hp_work *hp_work;
> acpi_handle handle;
> u32 type;
> @@ -613,13 +613,11 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>
> root = acpi_pci_find_root(handle);
>
> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
> -
> switch (type) {
> case ACPI_NOTIFY_BUS_CHECK:
> /* bus enumerate */
> - printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Bus check notify on %s\n", __func__);
> if (!root)
> handle_root_bridge_insertion(handle);
>
> @@ -627,27 +625,26 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>
> case ACPI_NOTIFY_DEVICE_CHECK:
> /* device check */
> - printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Device check notify on %s\n", __func__);
> if (!root)
> handle_root_bridge_insertion(handle);
> break;
>
> case ACPI_NOTIFY_EJECT_REQUEST:
> /* request device eject */
> - printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
> - (char *)buffer.pointer);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "Device eject notify on %s\n", __func__);
> if (root)
> handle_root_bridge_removal(root->device);
> break;
> default:
> - printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
> - type, (char *)buffer.pointer);
> + acpi_handle_warn(handle,
> + "notify_handler: unknown event type 0x%xn", type);
Here may be "0x%x\n".
A better way I think is that we can change the format string of printk in acpi_handle_printk()
from "%sACPI: %s: %pV" to "%sACPI: %s: %pV \n", so that there is no need to append the '\n' in the
format string when we call acpi_handle_printk().
Thanks,
Gu
> break;
> }
>
> kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
> - kfree(buffer.pointer);
> }
>
> static void handle_hotplug_event_root(acpi_handle handle, u32 type,
> @@ -661,9 +658,6 @@ static acpi_status __init
> find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> {
> acpi_status status;
> - char objname[64];
> - struct acpi_buffer buffer = { .length = sizeof(objname),
> - .pointer = objname };
> int *count = (int *)context;
>
> if (!acpi_is_root_bridge(handle))
> @@ -671,16 +665,15 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
>
> (*count)++;
>
> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
> -
> status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> handle_hotplug_event_root, NULL);
> if (ACPI_FAILURE(status))
> - printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
> - objname, (unsigned int)status);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "notify handler is not installed, exit status: %u\n",
> + (unsigned int)status);
> else
> - printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
> - objname);
> + acpi_handle_printk(KERN_DEBUG, handle,
> + "notify handler is installed\n");
>
> return AE_OK;
> }
On Tue 14 May 2013 07:28:45 AM CST, Rafael J. Wysocki wrote:
> On Tuesday, May 14, 2013 12:08:29 AM Jiang Liu wrote:
>> Now the global list acpi_pci_roots pci_root.c is useless, remove it.
>
> Well, are patches [1-4/9] needed for that or does it apply without them?
Hi Rafael,
This two patches have no dependency on others.
Thanks!
>
> Rafael
>
>
On 05/14/2013 07:27 AM, Rafael J. Wysocki wrote:
> On Tuesday, May 14, 2013 12:08:30 AM Jiang Liu wrote:
>> Use acpi_handle_print() and pr_xxx() to print messages in pci_root.c.
>>
>> Signed-off-by: Jiang Liu <[email protected]>
>> Cc: Len Brown <[email protected]>
>> Cc: "Rafael J. Wysocki" <[email protected]>
>> Cc: [email protected]
>> Cc: [email protected]
>> ---
>> drivers/acpi/pci_root.c | 71 ++++++++++++++++++++++---------------------------
>> 1 file changed, 32 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index 91ddfd6..9ced5c3 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -379,23 +379,23 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> struct acpi_pci_root *root;
>> u32 flags, base_flags;
>> bool is_osc_granted = false;
>> + acpi_handle hdl = device->handle;
> The usual way is to call it 'handle'. Any reason why not to do it here
Hi Rafael,
Just to avoid splitting some code into two lines, I could to use
"handle"
if preferred.
>> root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
>> if (!root)
>> return -ENOMEM;
>>
>> segment = 0;
>> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
>> - &segment);
>> + status = acpi_evaluate_integer(hdl, METHOD_NAME__SEG, NULL, &segment);
>> if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
>> - printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
>> + acpi_handle_err(hdl, "can't evaluate _SEG\n");
>> result = -ENODEV;
>> goto end;
>> }
>>
>> /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
>> root->secondary.flags = IORESOURCE_BUS;
>> - status = try_get_root_bridge_busnr(device->handle, &root->secondary);
>> + status = try_get_root_bridge_busnr(hdl, &root->secondary);
>> if (ACPI_FAILURE(status)) {
>> /*
>> * We need both the start and end of the downstream bus range
>> @@ -404,16 +404,16 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> * can do is assume [_BBN-0xFF] or [0-0xFF].
>> */
>> root->secondary.end = 0xFF;
>> - printk(KERN_WARNING FW_BUG PREFIX
>> - "no secondary bus range in _CRS\n");
>> - status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
>> + acpi_handle_warn(hdl,
>> + FW_BUG "no secondary bus range in _CRS\n");
>> + status = acpi_evaluate_integer(hdl, METHOD_NAME__BBN,
>> NULL, &bus);
>> if (ACPI_SUCCESS(status))
>> root->secondary.start = bus;
>> else if (status == AE_NOT_FOUND)
>> root->secondary.start = 0;
>> else {
>> - printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
>> + acpi_handle_err(hdl, "can't evaluate _BBN\n");
>> result = -ENODEV;
>> goto end;
>> }
>> @@ -425,11 +425,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
>> device->driver_data = root;
>>
>> - printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
>> + pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
>> acpi_device_name(device), acpi_device_bid(device),
>> root->segment, &root->secondary);
>>
>> - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
>> + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(hdl);
>>
>> /*
>> * All supported architectures that use ACPI have support for
>> @@ -473,7 +473,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> dev_info(&device->dev,
>> "Requesting ACPI _OSC control (0x%02x)\n", flags);
>>
>> - status = acpi_pci_osc_control_set(device->handle, &flags,
>> + status = acpi_pci_osc_control_set(hdl, &flags,
>> OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
>> if (ACPI_SUCCESS(status)) {
>> is_osc_granted = true;
>> @@ -505,9 +505,9 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> */
>> root->bus = pci_acpi_scan_root(root);
>> if (!root->bus) {
>> - printk(KERN_ERR PREFIX
>> - "Bus %04x:%02x not present in PCI namespace\n",
>> - root->segment, (unsigned int)root->secondary.start);
>> + acpi_handle_err(hdl,
>> + "Bus %04x:%02x not present in PCI namespace\n",
>> + root->segment, (unsigned int)root->secondary.start);
>> result = -ENODEV;
>> goto end;
>> }
>> @@ -517,8 +517,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
>> if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
>> pcie_clear_aspm(root->bus);
>> } else {
>> - pr_info("ACPI _OSC control for PCIe not granted, "
>> - "disabling ASPM\n");
>> + acpi_handle_info(hdl,
>> + "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
>> pcie_no_aspm();
>> }
>>
>> @@ -571,12 +571,13 @@ static void handle_root_bridge_insertion(acpi_handle handle)
>> struct acpi_device *device;
>>
>> if (!acpi_bus_get_device(handle, &device)) {
>> - printk(KERN_DEBUG "acpi device exists...\n");
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "acpi device exists...\n");
> Do we have acpi_handle_dbg()? If so, why don't you use it here? (And below.)
> If not, why don't you add it and use it here (and below)?
acpi_handle_dbg() only generates message if CONFIG_DEBUG is enabled,
so use pci_handle_printk(KERN_DEBUG, xxx) to keep original behavior.
Thanks,
Gerry
>
>> return;
>> }
>>
>> if (acpi_bus_scan(handle))
>> - printk(KERN_ERR "cannot add bridge to acpi list\n");
>> + acpi_handle_err(handle, "cannot add bridge to acpi list\n");
>> }
>>
>> static void handle_root_bridge_removal(struct acpi_device *device)
>> @@ -602,7 +603,6 @@ static void handle_root_bridge_removal(struct acpi_device *device)
>> static void _handle_hotplug_event_root(struct work_struct *work)
>> {
>> struct acpi_pci_root *root;
>> - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
>> struct acpi_hp_work *hp_work;
>> acpi_handle handle;
>> u32 type;
>> @@ -613,13 +613,11 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>>
>> root = acpi_pci_find_root(handle);
>>
>> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
>> -
>> switch (type) {
>> case ACPI_NOTIFY_BUS_CHECK:
>> /* bus enumerate */
>> - printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
>> - (char *)buffer.pointer);
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "Bus check notify on %s\n", __func__);
>> if (!root)
>> handle_root_bridge_insertion(handle);
>>
>> @@ -627,27 +625,26 @@ static void _handle_hotplug_event_root(struct work_struct *work)
>>
>> case ACPI_NOTIFY_DEVICE_CHECK:
>> /* device check */
>> - printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
>> - (char *)buffer.pointer);
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "Device check notify on %s\n", __func__);
>> if (!root)
>> handle_root_bridge_insertion(handle);
>> break;
>>
>> case ACPI_NOTIFY_EJECT_REQUEST:
>> /* request device eject */
>> - printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
>> - (char *)buffer.pointer);
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "Device eject notify on %s\n", __func__);
>> if (root)
>> handle_root_bridge_removal(root->device);
>> break;
>> default:
>> - printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
>> - type, (char *)buffer.pointer);
>> + acpi_handle_warn(handle,
>> + "notify_handler: unknown event type 0x%xn", type);
>> break;
>> }
>>
>> kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
>> - kfree(buffer.pointer);
>> }
>>
>> static void handle_hotplug_event_root(acpi_handle handle, u32 type,
>> @@ -661,9 +658,6 @@ static acpi_status __init
>> find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
>> {
>> acpi_status status;
>> - char objname[64];
>> - struct acpi_buffer buffer = { .length = sizeof(objname),
>> - .pointer = objname };
>> int *count = (int *)context;
>>
>> if (!acpi_is_root_bridge(handle))
>> @@ -671,16 +665,15 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
>>
>> (*count)++;
>>
>> - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
>> -
>> status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
>> handle_hotplug_event_root, NULL);
>> if (ACPI_FAILURE(status))
>> - printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
>> - objname, (unsigned int)status);
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "notify handler is not installed, exit status: %u\n",
>> + (unsigned int)status);
>> else
>> - printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
>> - objname);
>> + acpi_handle_printk(KERN_DEBUG, handle,
>> + "notify handler is installed\n");
>>
>> return AE_OK;
>> }
> Thanks,
> Rafael
>
>
On Tuesday, May 14, 2013 08:41:56 PM Liu Jiang wrote:
> On Tue 14 May 2013 07:28:45 AM CST, Rafael J. Wysocki wrote:
> > On Tuesday, May 14, 2013 12:08:29 AM Jiang Liu wrote:
> >> Now the global list acpi_pci_roots pci_root.c is useless, remove it.
> >
> > Well, are patches [1-4/9] needed for that or does it apply without them?
> Hi Rafael,
> This two patches have no dependency on others.
Can you please submit them separately, then?
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
On 05/14/2013 04:26 PM, Gu Zheng wrote:
> On 05/14/2013 01:23 AM, Yinghai Lu wrote:
>
>> On Mon, May 13, 2013 at 9:08 AM, Jiang Liu <[email protected]> wrote:
>>> From: Gu Zheng <[email protected]>
>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>> index 4f0bc0a..bc075a3 100644
>>> --- a/drivers/pci/probe.c
>>> +++ b/drivers/pci/probe.c
>>> @@ -1131,6 +1131,7 @@ static void pci_release_dev(struct device *dev)
>>> struct pci_dev *pci_dev;
>>>
>>> pci_dev = to_pci_dev(dev);
>>> + pci_bus_put(pci_dev->bus);
>>> pci_release_capabilities(pci_dev);
>>> pci_release_of_node(pci_dev);
>>> kfree(pci_dev);
>>> @@ -1269,11 +1270,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
>>> if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
>>> return NULL;
>>>
>>> - dev = alloc_pci_dev();
>>> + dev = pci_alloc_dev(bus);
>>> if (!dev)
>>> return NULL;
>>>
>>> - dev->bus = bus;
>>> dev->devfn = devfn;
>>> dev->vendor = l & 0xffff;
>>> dev->device = (l >> 16) & 0xffff;
>> in pci_setup_device() fail path, it release the ref to that bus.
> Yes, you're right, we need to release the bus' ref if pci_setup_device() failed.
Hi Zheng,
I suggest to use pci_release_dev() instead because it also needs to
release OF related resources.
I will update it in next version.
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bc075a3..2ac6338 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct
pci_bus *bus
pci_set_of_node(dev);
if (pci_setup_device(dev)) {
- kfree(dev);
+ pci_release_dev(&dev->dev);
return NULL;
}
> hanks for your correction.:)
>
> Best regards,
> Gu
>
>> Yinghai
>>
>
On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
> On 05/14/2013 04:26 PM, Gu Zheng wrote:
> I suggest to use pci_release_dev() instead because it also needs to
> release OF related resources.
> I will update it in next version.
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index bc075a3..2ac6338 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus
> *bus
> pci_set_of_node(dev);
>
> if (pci_setup_device(dev)) {
> - kfree(dev);
> + pci_release_dev(&dev->dev);
> return NULL;
no, should move pci_set_of_node calling into pci_setup_device.
Yinghai
On Tue 14 May 2013 11:10:33 PM CST, Yinghai Lu wrote:
> On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
>> On 05/14/2013 04:26 PM, Gu Zheng wrote:
>> I suggest to use pci_release_dev() instead because it also needs to
>> release OF related resources.
>> I will update it in next version.
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index bc075a3..2ac6338 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus
>> *bus
>> pci_set_of_node(dev);
>>
>> if (pci_setup_device(dev)) {
>> - kfree(dev);
>> + pci_release_dev(&dev->dev);
>> return NULL;
>
> no, should move pci_set_of_node calling into pci_setup_device.
>
> Yinghai
I'm not sure whether we should call pci_set_of_node() for SR-IOV
devices too,
any suggestions here?
On Tue, May 14, 2013 at 9:57 AM, Liu Jiang <[email protected]> wrote:
> On Tue 14 May 2013 11:10:33 PM CST, Yinghai Lu wrote:
>>
>> On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
>>>
>>> On 05/14/2013 04:26 PM, Gu Zheng wrote:
>>> I suggest to use pci_release_dev() instead because it also needs to
>>> release OF related resources.
>>> I will update it in next version.
>>>
>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>> index bc075a3..2ac6338 100644
>>> --- a/drivers/pci/probe.c
>>> +++ b/drivers/pci/probe.c
>>> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct
>>> pci_bus
>>> *bus
>>> pci_set_of_node(dev);
>>>
>>> if (pci_setup_device(dev)) {
>>> - kfree(dev);
>>> + pci_release_dev(&dev->dev);
>>> return NULL;
>>
>>
>> no, should move pci_set_of_node calling into pci_setup_device.
>>
>> Yinghai
>
>
> I'm not sure whether we should call pci_set_of_node() for SR-IOV devices
> too,
> any suggestions here?
or just move down pci_set_of_node after pci_setup_device?
anyway that is another bug.
Yinghai
On Wed 15 May 2013 02:52:51 AM CST, Yinghai Lu wrote:
> On Tue, May 14, 2013 at 9:57 AM, Liu Jiang <[email protected]> wrote:
>> On Tue 14 May 2013 11:10:33 PM CST, Yinghai Lu wrote:
>>>
>>> On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
>>>>
>>>> On 05/14/2013 04:26 PM, Gu Zheng wrote:
>>>> I suggest to use pci_release_dev() instead because it also needs to
>>>> release OF related resources.
>>>> I will update it in next version.
>>>>
>>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>>> index bc075a3..2ac6338 100644
>>>> --- a/drivers/pci/probe.c
>>>> +++ b/drivers/pci/probe.c
>>>> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct
>>>> pci_bus
>>>> *bus
>>>> pci_set_of_node(dev);
>>>>
>>>> if (pci_setup_device(dev)) {
>>>> - kfree(dev);
>>>> + pci_release_dev(&dev->dev);
>>>> return NULL;
>>>
>>>
>>> no, should move pci_set_of_node calling into pci_setup_device.
>>>
>>> Yinghai
>>
>>
>> I'm not sure whether we should call pci_set_of_node() for SR-IOV devices
>> too,
>> any suggestions here?
>
> or just move down pci_set_of_node after pci_setup_device?
>
> anyway that is another bug.
>
> Yinghai
I'm not familiar with the OF logic and can't make sure whether
pci_setup_device()
has dependency on dev->of_node. Feel it's more safe to call
pci_release_of_node()
on failing path instead of tuning call-site of pci_set_of_node().
On Wed, May 15, 2013 at 7:39 AM, Liu Jiang <[email protected]> wrote:
> On Wed 15 May 2013 02:52:51 AM CST, Yinghai Lu wrote:
>>
>> On Tue, May 14, 2013 at 9:57 AM, Liu Jiang <[email protected]> wrote:
>>>
>>> On Tue 14 May 2013 11:10:33 PM CST, Yinghai Lu wrote:
>>>>
>>>>
>>>> On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
>>>>>
>>>>>
>>>>> On 05/14/2013 04:26 PM, Gu Zheng wrote:
>>>>> I suggest to use pci_release_dev() instead because it also needs
>>>>> to
>>>>> release OF related resources.
>>>>> I will update it in next version.
>>>>>
>>>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>>>> index bc075a3..2ac6338 100644
>>>>> --- a/drivers/pci/probe.c
>>>>> +++ b/drivers/pci/probe.c
>>>>> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct
>>>>> pci_bus
>>>>> *bus
>>>>> pci_set_of_node(dev);
>>>>>
>>>>> if (pci_setup_device(dev)) {
>>>>> - kfree(dev);
>>>>> + pci_release_dev(&dev->dev);
>>>>> return NULL;
>>>>
>>>>
>>>>
>>>> no, should move pci_set_of_node calling into pci_setup_device.
>>>>
>>>> Yinghai
>>>
>>>
>>>
>>> I'm not sure whether we should call pci_set_of_node() for SR-IOV devices
>>> too,
>>> any suggestions here?
>>
>>
>> or just move down pci_set_of_node after pci_setup_device?
>>
>> anyway that is another bug.
> I'm not familiar with the OF logic and can't make sure whether
> pci_setup_device()
> has dependency on dev->of_node. Feel it's more safe to call
> pci_release_of_node()
> on failing path instead of tuning call-site of pci_set_of_node().
that is another bug, let of guy handle it.
Yinghai
On Wed 15 May 2013 10:43:02 PM CST, Yinghai Lu wrote:
> On Wed, May 15, 2013 at 7:39 AM, Liu Jiang <[email protected]> wrote:
>> On Wed 15 May 2013 02:52:51 AM CST, Yinghai Lu wrote:
>>>
>>> On Tue, May 14, 2013 at 9:57 AM, Liu Jiang <[email protected]> wrote:
>>>>
>>>> On Tue 14 May 2013 11:10:33 PM CST, Yinghai Lu wrote:
>>>>>
>>>>>
>>>>> On Tue, May 14, 2013 at 7:59 AM, Liu Jiang <[email protected]> wrote:
>>>>>>
>>>>>>
>>>>>> On 05/14/2013 04:26 PM, Gu Zheng wrote:
>>>>>> I suggest to use pci_release_dev() instead because it also needs
>>>>>> to
>>>>>> release OF related resources.
>>>>>> I will update it in next version.
>>>>>>
>>>>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>>>>> index bc075a3..2ac6338 100644
>>>>>> --- a/drivers/pci/probe.c
>>>>>> +++ b/drivers/pci/probe.c
>>>>>> @@ -1281,7 +1281,7 @@ static struct pci_dev *pci_scan_device(struct
>>>>>> pci_bus
>>>>>> *bus
>>>>>> pci_set_of_node(dev);
>>>>>>
>>>>>> if (pci_setup_device(dev)) {
>>>>>> - kfree(dev);
>>>>>> + pci_release_dev(&dev->dev);
>>>>>> return NULL;
>>>>>
>>>>>
>>>>>
>>>>> no, should move pci_set_of_node calling into pci_setup_device.
>>>>>
>>>>> Yinghai
>>>>
>>>>
>>>>
>>>> I'm not sure whether we should call pci_set_of_node() for SR-IOV devices
>>>> too,
>>>> any suggestions here?
>>>
>>>
>>> or just move down pci_set_of_node after pci_setup_device?
>>>
>>> anyway that is another bug.
>
>> I'm not familiar with the OF logic and can't make sure whether
>> pci_setup_device()
>> has dependency on dev->of_node. Feel it's more safe to call
>> pci_release_of_node()
>> on failing path instead of tuning call-site of pci_set_of_node().
>
> that is another bug, let of guy handle it.
>
> Yinghai
Hi Yinghai,
I don't know any OF exports, could you please help to CC
some OF experts?
Thanks,
Gerry
On Wed, May 15, 2013 at 7:46 AM, Liu Jiang <[email protected]> wrote:
> On Wed 15 May 2013 10:43:02 PM CST, Yinghai Lu wrote:
>>
>
>> that is another bug, let of guy handle it.
>>
>> Yinghai
>
> Hi Yinghai,
> I don't know any OF exports, could you please help to CC
> some OF experts?
powerpc and sparc are using that.
Ben,
in drivers/pci/probe.c::pci_scan_device() there is
pci_set_of_node(dev);
if (pci_setup_device(dev)) {
kfree(dev);
return NULL;
}
so if pci_setup_device fails, there is one dev reference is not release.
please check you can just move down pci_set_of_node down after that
failing path, like
if (pci_setup_device(dev)) {
kfree(dev);
return NULL;
}
pci_set_of_node(dev);
Yinghai
On Wed, 2013-05-15 at 22:46 +0800, Liu Jiang wrote:
> I don't know any OF exports, could you please help to CC
> some OF experts?
I wrote that code I think. Sorry, I've missed the beginning of the
thread, what is the problem ?
Cheers,
Ben.
On Wed, 2013-05-15 at 07:58 -0700, Yinghai Lu wrote:
> Ben,
>
> in drivers/pci/probe.c::pci_scan_device() there is
>
> pci_set_of_node(dev);
>
> if (pci_setup_device(dev)) {
> kfree(dev);
> return NULL;
> }
>
> so if pci_setup_device fails, there is one dev reference is not release.
>
> please check you can just move down pci_set_of_node down after that
> failing path, like
>
>
> if (pci_setup_device(dev)) {
> kfree(dev);
> return NULL;
> }
>
> pci_set_of_node(dev);
No, we want the OF node set when we run the quirks, we intentionally do
that early, the right thing to do is to to call pci_release_of_node()
in the error path (it's safe to call even if the node is NULL).
Cheers,
Ben.
On Wed, May 15, 2013 at 2:32 PM, Benjamin Herrenschmidt
<[email protected]> wrote:
> On Wed, 2013-05-15 at 07:58 -0700, Yinghai Lu wrote:
>
>> Ben,
>>
>> in drivers/pci/probe.c::pci_scan_device() there is
>>
>> pci_set_of_node(dev);
>>
>> if (pci_setup_device(dev)) {
>> kfree(dev);
>> return NULL;
>> }
>>
>> so if pci_setup_device fails, there is one dev reference is not release.
>>
>> please check you can just move down pci_set_of_node down after that
>> failing path, like
>>
>>
>> if (pci_setup_device(dev)) {
>> kfree(dev);
>> return NULL;
>> }
>>
>> pci_set_of_node(dev);
>
> No, we want the OF node set when we run the quirks, we intentionally do
> that early, the right thing to do is to to call pci_release_of_node()
> in the error path (it's safe to call even if the node is NULL).
>
Good.
We have two options.
1. can you please submit one complete patch, and get it merged into v3.10.
2. put it together with pci_alloc_dev patchset towards to v3.11?
Thanks
Yinghai
On Thu 16 May 2013 05:29:31 AM CST, Benjamin Herrenschmidt wrote:
> On Wed, 2013-05-15 at 22:46 +0800, Liu Jiang wrote:
>> I don't know any OF exports, could you please help to CC
>> some OF experts?
>
> I wrote that code I think. Sorry, I've missed the beginning of the
> thread, what is the problem ?
>
> Cheers,
> Ben.
>
>
Hi,
Just found a little memory leak issue that we should call
pci_release_of_node()
on error recovery path in function pci_scan_device().
pci_set_of_node(dev);
if (pci_setup_device(dev)) {
kfree(dev);
return NULL;
}
Regards!
Gerry
On 05/14/2013 12:08 AM, Jiang Liu wrote:
> This patch makes PCI host bridge/bus creating and destroying logic
> symmetric by using device_initialize()/device_add()/device_del()/put_device()
> pairs as discussed in thread at:
> http://comments.gmane.org/gmane.linux.kernel.pci/22073
>
> It also fixes a bug in error recovery path in pci_create_root_bus()
> which may kfree() an in-use host bridge object.
>
> Signed-off-by: Jiang Liu <[email protected]>
> Cc: Yinghai Lu <[email protected]>
> ---
> drivers/pci/probe.c | 84 +++++++++++++++++++++++-----------------------------
> drivers/pci/remove.c | 3 +-
> 2 files changed, 39 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index bc075a3..a2617c2 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -451,7 +451,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
> }
> }
>
> -static struct pci_bus * pci_alloc_bus(void)
> +static struct pci_bus *pci_alloc_bus(struct pci_ops *ops, void *sd, int bus)
> {
> struct pci_bus *b;
>
> @@ -464,10 +464,32 @@ static struct pci_bus * pci_alloc_bus(void)
> INIT_LIST_HEAD(&b->resources);
> b->max_bus_speed = PCI_SPEED_UNKNOWN;
> b->cur_bus_speed = PCI_SPEED_UNKNOWN;
> + b->sysdata = sd;
> + b->ops = ops;
> + b->number = bus;
> + b->busn_res.start = bus;
> + b->busn_res.end = 0xff;
> + b->busn_res.flags = IORESOURCE_BUS;
> + b->dev.class = &pcibus_class;
> + dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
> + device_initialize(&b->dev);
> }
> +
> return b;
> }
>
> +static void pci_release_host_bridge_dev(struct device *dev)
> +{
> + struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
> +
> + if (bridge->release_fn)
> + bridge->release_fn(bridge);
> +
> + pci_free_resource_list(&bridge->windows);
> +
> + kfree(bridge);
> +}
> +
> static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
> {
> struct pci_host_bridge *bridge;
> @@ -476,6 +498,10 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
> if (bridge) {
> INIT_LIST_HEAD(&bridge->windows);
> bridge->bus = b;
> + bridge->dev.release = pci_release_host_bridge_dev;
> + dev_set_name(&bridge->dev, "pci%04x:%02x",
> + pci_domain_nr(b), b->number);
> + device_initialize(&bridge->dev);
> }
>
> return bridge;
> @@ -628,28 +654,13 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
> /*
> * Allocate a new bus, and inherit stuff from the parent..
> */
> - child = pci_alloc_bus();
> + child = pci_alloc_bus(parent->ops, parent->sysdata, busnr);
> if (!child)
> return NULL;
>
> child->parent = parent;
> - child->ops = parent->ops;
> - child->sysdata = parent->sysdata;
> child->bus_flags = parent->bus_flags;
> -
> - /* initialize some portions of the bus device, but don't register it
> - * now as the parent is not properly set up yet.
> - */
> - child->dev.class = &pcibus_class;
> - dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
> -
> - /*
> - * Set up the primary, secondary and subordinate
> - * bus numbers.
> - */
> - child->number = child->busn_res.start = busnr;
> child->primary = parent->busn_res.start;
> - child->busn_res.end = 0xff;
>
> if (!bridge) {
> child->dev.parent = parent->bridge;
> @@ -670,7 +681,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
> bridge->subordinate = child;
>
> add_dev:
> - ret = device_register(&child->dev);
> + ret = device_add(&child->dev);
> WARN_ON(ret < 0);
>
> pcibios_add_bus(child);
> @@ -1190,18 +1201,6 @@ int pci_cfg_space_size(struct pci_dev *dev)
> return PCI_CFG_SPACE_SIZE;
> }
>
> -static void pci_release_bus_bridge_dev(struct device *dev)
> -{
> - struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
> -
> - if (bridge->release_fn)
> - bridge->release_fn(bridge);
> -
> - pci_free_resource_list(&bridge->windows);
> -
> - kfree(bridge);
> -}
> -
> struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
> {
> struct pci_dev *dev;
> @@ -1688,13 +1687,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> char bus_addr[64];
> char *fmt;
>
> - b = pci_alloc_bus();
> + b = pci_alloc_bus(ops, sysdata, bus);
> if (!b)
> return NULL;
>
> - b->sysdata = sysdata;
> - b->ops = ops;
> - b->number = b->busn_res.start = bus;
> b2 = pci_find_bus(pci_domain_nr(b), bus);
> if (b2) {
> /* If we already got to this bus through a different bridge, ignore it */
> @@ -1706,27 +1702,22 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> if (!bridge)
> goto err_out;
>
> - bridge->dev.parent = parent;
> - bridge->dev.release = pci_release_bus_bridge_dev;
> - dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> error = pcibios_root_bridge_prepare(bridge);
> if (error)
> goto bridge_dev_reg_err;
>
> - error = device_register(&bridge->dev);
> + bridge->dev.parent = parent;
> + error = device_add(&bridge->dev);
> if (error)
> goto bridge_dev_reg_err;
> +
> b->bridge = get_device(&bridge->dev);
> device_enable_async_suspend(b->bridge);
> pci_set_bus_of_node(b);
> -
> if (!parent)
> set_dev_node(b->bridge, pcibus_to_node(b));
> -
> - b->dev.class = &pcibus_class;
> b->dev.parent = b->bridge;
> - dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
> - error = device_register(&b->dev);
> + error = device_add(&b->dev);
> if (error)
> goto class_dev_reg_err;
>
> @@ -1769,12 +1760,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> return b;
>
> class_dev_reg_err:
> - put_device(&bridge->dev);
> - device_unregister(&bridge->dev);
> + device_del(&bridge->dev);
> bridge_dev_reg_err:
> - kfree(bridge);
> + put_device(&bridge->dev);
> err_out:
> - kfree(b);
> + put_device(&b->dev);
> return NULL;
> }
Hi Jiang,
I think the changes here may lead to memleak, doesn't it?
Best regards,
Gu
>
> diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
> index 8fc54b7..b0ce875 100644
> --- a/drivers/pci/remove.c
> +++ b/drivers/pci/remove.c
> @@ -52,7 +52,8 @@ void pci_remove_bus(struct pci_bus *bus)
> up_write(&pci_bus_sem);
> pci_remove_legacy_files(bus);
> pcibios_remove_bus(bus);
> - device_unregister(&bus->dev);
> + device_del(&bus->dev);
> + put_device(&bus->dev);
> }
> EXPORT_SYMBOL(pci_remove_bus);
>
On Mon 20 May 2013 02:35:31 PM CST, Gu Zheng wrote:
>
> On 05/14/2013 12:08 AM, Jiang Liu wrote:
>
>> This patch makes PCI host bridge/bus creating and destroying logic
>> symmetric by using device_initialize()/device_add()/device_del()/put_device()
>> pairs as discussed in thread at:
>> http://comments.gmane.org/gmane.linux.kernel.pci/22073
>>
>> It also fixes a bug in error recovery path in pci_create_root_bus()
>> which may kfree() an in-use host bridge object.
>>
>> Signed-off-by: Jiang Liu <[email protected]>
>> Cc: Yinghai Lu <[email protected]>
>> ---
>> drivers/pci/probe.c | 84 +++++++++++++++++++++++-----------------------------
>> drivers/pci/remove.c | 3 +-
>> 2 files changed, 39 insertions(+), 48 deletions(-)
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index bc075a3..a2617c2 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -451,7 +451,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
>> }
>> }
>>
>> -static struct pci_bus * pci_alloc_bus(void)
>> +static struct pci_bus *pci_alloc_bus(struct pci_ops *ops, void *sd, int bus)
>> {
>> struct pci_bus *b;
>>
>> @@ -464,10 +464,32 @@ static struct pci_bus * pci_alloc_bus(void)
>> INIT_LIST_HEAD(&b->resources);
>> b->max_bus_speed = PCI_SPEED_UNKNOWN;
>> b->cur_bus_speed = PCI_SPEED_UNKNOWN;
>> + b->sysdata = sd;
>> + b->ops = ops;
>> + b->number = bus;
>> + b->busn_res.start = bus;
>> + b->busn_res.end = 0xff;
>> + b->busn_res.flags = IORESOURCE_BUS;
>> + b->dev.class = &pcibus_class;
>> + dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
>> + device_initialize(&b->dev);
>> }
>> +
>> return b;
>> }
>>
>> +static void pci_release_host_bridge_dev(struct device *dev)
>> +{
>> + struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
>> +
>> + if (bridge->release_fn)
>> + bridge->release_fn(bridge);
>> +
>> + pci_free_resource_list(&bridge->windows);
>> +
>> + kfree(bridge);
>> +}
>> +
>> static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
>> {
>> struct pci_host_bridge *bridge;
>> @@ -476,6 +498,10 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
>> if (bridge) {
>> INIT_LIST_HEAD(&bridge->windows);
>> bridge->bus = b;
>> + bridge->dev.release = pci_release_host_bridge_dev;
>> + dev_set_name(&bridge->dev, "pci%04x:%02x",
>> + pci_domain_nr(b), b->number);
>> + device_initialize(&bridge->dev);
>> }
>>
>> return bridge;
>> @@ -628,28 +654,13 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
>> /*
>> * Allocate a new bus, and inherit stuff from the parent..
>> */
>> - child = pci_alloc_bus();
>> + child = pci_alloc_bus(parent->ops, parent->sysdata, busnr);
>> if (!child)
>> return NULL;
>>
>> child->parent = parent;
>> - child->ops = parent->ops;
>> - child->sysdata = parent->sysdata;
>> child->bus_flags = parent->bus_flags;
>> -
>> - /* initialize some portions of the bus device, but don't register it
>> - * now as the parent is not properly set up yet.
>> - */
>> - child->dev.class = &pcibus_class;
>> - dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
>> -
>> - /*
>> - * Set up the primary, secondary and subordinate
>> - * bus numbers.
>> - */
>> - child->number = child->busn_res.start = busnr;
>> child->primary = parent->busn_res.start;
>> - child->busn_res.end = 0xff;
>>
>> if (!bridge) {
>> child->dev.parent = parent->bridge;
>> @@ -670,7 +681,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
>> bridge->subordinate = child;
>>
>> add_dev:
>> - ret = device_register(&child->dev);
>> + ret = device_add(&child->dev);
>> WARN_ON(ret < 0);
>>
>> pcibios_add_bus(child);
>> @@ -1190,18 +1201,6 @@ int pci_cfg_space_size(struct pci_dev *dev)
>> return PCI_CFG_SPACE_SIZE;
>> }
>>
>> -static void pci_release_bus_bridge_dev(struct device *dev)
>> -{
>> - struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
>> -
>> - if (bridge->release_fn)
>> - bridge->release_fn(bridge);
>> -
>> - pci_free_resource_list(&bridge->windows);
>> -
>> - kfree(bridge);
>> -}
>> -
>> struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
>> {
>> struct pci_dev *dev;
>> @@ -1688,13 +1687,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>> char bus_addr[64];
>> char *fmt;
>>
>> - b = pci_alloc_bus();
>> + b = pci_alloc_bus(ops, sysdata, bus);
>> if (!b)
>> return NULL;
>>
>> - b->sysdata = sysdata;
>> - b->ops = ops;
>> - b->number = b->busn_res.start = bus;
>> b2 = pci_find_bus(pci_domain_nr(b), bus);
>> if (b2) {
>> /* If we already got to this bus through a different bridge, ignore it */
>> @@ -1706,27 +1702,22 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>> if (!bridge)
>> goto err_out;
>>
>> - bridge->dev.parent = parent;
>> - bridge->dev.release = pci_release_bus_bridge_dev;
>> - dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>> error = pcibios_root_bridge_prepare(bridge);
>> if (error)
>> goto bridge_dev_reg_err;
>>
>> - error = device_register(&bridge->dev);
>> + bridge->dev.parent = parent;
>> + error = device_add(&bridge->dev);
>> if (error)
>> goto bridge_dev_reg_err;
>> +
>> b->bridge = get_device(&bridge->dev);
>> device_enable_async_suspend(b->bridge);
>> pci_set_bus_of_node(b);
>> -
>> if (!parent)
>> set_dev_node(b->bridge, pcibus_to_node(b));
>> -
>> - b->dev.class = &pcibus_class;
>> b->dev.parent = b->bridge;
>> - dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
>> - error = device_register(&b->dev);
>> + error = device_add(&b->dev);
>> if (error)
>> goto class_dev_reg_err;
>>
>> @@ -1769,12 +1760,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>> return b;
>>
>> class_dev_reg_err:
>> - put_device(&bridge->dev);
>> - device_unregister(&bridge->dev);
>> + device_del(&bridge->dev);
>> bridge_dev_reg_err:
>> - kfree(bridge);
>> + put_device(&bridge->dev);
>> err_out:
>> - kfree(b);
>> + put_device(&b->dev);
>> return NULL;
>> }
>
> Hi Jiang,
> I think the changes here may lead to memleak, doesn't it?
>
> Best regards,
> Gu
Hi Gu Zheng,
I have checked to code again and didn't find the memory leakage
issue.
Could you please help to give more hints about the leakage?
Thanks!
Gerry
>
>>
>> diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
>> index 8fc54b7..b0ce875 100644
>> --- a/drivers/pci/remove.c
>> +++ b/drivers/pci/remove.c
>> @@ -52,7 +52,8 @@ void pci_remove_bus(struct pci_bus *bus)
>> up_write(&pci_bus_sem);
>> pci_remove_legacy_files(bus);
>> pcibios_remove_bus(bus);
>> - device_unregister(&bus->dev);
>> + device_del(&bus->dev);
>> + put_device(&bus->dev);
>> }
>> EXPORT_SYMBOL(pci_remove_bus);
>>
>
>