Re: [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
Hi Yinghai, When I was reviewing this patch, I found a little problem. Please refer to email: [PATCH 0/3] Find pci root bridges by comparing HID from acpi_device_info, not acpi_device. I could be wrong. :) If I didn't consider your idea correct, or you have a better solution, please let me know. Thanks. :) On 09/20/2012 02:54 AM, Yinghai Lu wrote: It causes confusion. We may only need acpi hp for pci host bridge. Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple. Also remove not used res_lock in the struct. -v2: put back pci_root_hp change in one patch -v3: add pcibios_resource_survey_bus() calling -v4: remove not needed code with remove_bridge -v5: put back support for acpiphp support for slots just on root bus. -v6: change some functions to *_p2p_* to make it more clean. Signed-off-by: Yinghai Lu --- drivers/acpi/Makefile |1 + drivers/acpi/pci_root_hp.c | 238 drivers/pci/hotplug/acpiphp_glue.c | 59 +++--- 3 files changed, 254 insertions(+), 44 deletions(-) create mode 100644 drivers/acpi/pci_root_hp.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2..c9abd4c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -36,6 +36,7 @@ acpi-y+= processor_core.o acpi-y+= ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y+= pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-$(CONFIG_HOTPLUG) += pci_root_hp.o acpi-y+= power.o acpi-y+= event.o acpi-y+= sysfs.o diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c new file mode 100644 index 000..e07c31b --- /dev/null +++ b/drivers/acpi/pci_root_hp.c @@ -0,0 +1,238 @@ +/* + * Separated from drivers/pci/hotplug/acpiphp_glue.c + * only support root bridge + */ + +#include +#include + +#include +#include +#include +#include +#include + +static LIST_HEAD(acpi_root_bridge_list); +struct acpi_root_bridge { + struct list_head list; + acpi_handle handle; + u32 flags; +}; + +/* bridge flags */ +#define ROOT_BRIDGE_HAS_EJ0(0x0002) +#define ROOT_BRIDGE_HAS_PS3(0x0080) + +#define ACPI_STA_FUNCTIONING (0x0008) + +static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + + list_for_each_entry(bridge,_root_bridge_list, list) + if (bridge->handle == handle) + return bridge; + + return NULL; +} + +/* allocate and initialize host bridge data structure */ +static void add_acpi_root_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + acpi_handle dummy_handle; + acpi_status status; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, "_STA",_handle); + if (ACPI_SUCCESS(status)) { + unsigned long long tmp; + + status = acpi_evaluate_integer(handle, "_STA", NULL,); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG "%s: _STA evaluation failure\n", +__func__); + return; + } + if ((tmp& ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return; + } + + bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL); + if (!bridge) + return; + + bridge->handle = handle; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0",_handle))) + bridge->flags |= ROOT_BRIDGE_HAS_EJ0; + if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3",_handle))) + bridge->flags |= ROOT_BRIDGE_HAS_PS3; + + list_add(>list,_root_bridge_list); +} + +struct acpi_root_hp_work { + struct work_struct work; + acpi_handle handle; + u32 type; + void *context; +}; + +static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type, + void *context, + void (*func)(struct work_struct *work)) +{ + struct acpi_root_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work->handle = handle; + hp_work->type = type; + hp_work->context = context; + + INIT_WORK(_work->work, func); + ret = queue_work(kacpi_hotplug_wq,_work->work); + if (!ret) + kfree(hp_work); +} + +/* Program resources in newly inserted bridge */ +static void acpi_root_configure_bridge(acpi_handle handle) +{ + struct acpi_pci_root *root = acpi_pci_find_root(handle); + +
Re: [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
Hi Yinghai, When I was reviewing this patch, I found a little problem. Please refer to email: [PATCH 0/3] Find pci root bridges by comparing HID from acpi_device_info, not acpi_device. I could be wrong. :) If I didn't consider your idea correct, or you have a better solution, please let me know. Thanks. :) On 09/20/2012 02:54 AM, Yinghai Lu wrote: It causes confusion. We may only need acpi hp for pci host bridge. Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple. Also remove not used res_lock in the struct. -v2: put back pci_root_hp change in one patch -v3: add pcibios_resource_survey_bus() calling -v4: remove not needed code with remove_bridge -v5: put back support for acpiphp support for slots just on root bus. -v6: change some functions to *_p2p_* to make it more clean. Signed-off-by: Yinghai Luying...@kernel.org --- drivers/acpi/Makefile |1 + drivers/acpi/pci_root_hp.c | 238 drivers/pci/hotplug/acpiphp_glue.c | 59 +++--- 3 files changed, 254 insertions(+), 44 deletions(-) create mode 100644 drivers/acpi/pci_root_hp.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2..c9abd4c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -36,6 +36,7 @@ acpi-y+= processor_core.o acpi-y+= ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y+= pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-$(CONFIG_HOTPLUG) += pci_root_hp.o acpi-y+= power.o acpi-y+= event.o acpi-y+= sysfs.o diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c new file mode 100644 index 000..e07c31b --- /dev/null +++ b/drivers/acpi/pci_root_hp.c @@ -0,0 +1,238 @@ +/* + * Separated from drivers/pci/hotplug/acpiphp_glue.c + * only support root bridge + */ + +#includelinux/init.h +#includelinux/module.h + +#includelinux/kernel.h +#includelinux/pci.h +#includelinux/mutex.h +#includelinux/slab.h +#includelinux/acpi.h + +static LIST_HEAD(acpi_root_bridge_list); +struct acpi_root_bridge { + struct list_head list; + acpi_handle handle; + u32 flags; +}; + +/* bridge flags */ +#define ROOT_BRIDGE_HAS_EJ0(0x0002) +#define ROOT_BRIDGE_HAS_PS3(0x0080) + +#define ACPI_STA_FUNCTIONING (0x0008) + +static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + + list_for_each_entry(bridge,acpi_root_bridge_list, list) + if (bridge-handle == handle) + return bridge; + + return NULL; +} + +/* allocate and initialize host bridge data structure */ +static void add_acpi_root_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + acpi_handle dummy_handle; + acpi_status status; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, _STA,dummy_handle); + if (ACPI_SUCCESS(status)) { + unsigned long long tmp; + + status = acpi_evaluate_integer(handle, _STA, NULL,tmp); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG %s: _STA evaluation failure\n, +__func__); + return; + } + if ((tmp ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return; + } + + bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL); + if (!bridge) + return; + + bridge-handle = handle; + + if (ACPI_SUCCESS(acpi_get_handle(handle, _EJ0,dummy_handle))) + bridge-flags |= ROOT_BRIDGE_HAS_EJ0; + if (ACPI_SUCCESS(acpi_get_handle(handle, _PS3,dummy_handle))) + bridge-flags |= ROOT_BRIDGE_HAS_PS3; + + list_add(bridge-list,acpi_root_bridge_list); +} + +struct acpi_root_hp_work { + struct work_struct work; + acpi_handle handle; + u32 type; + void *context; +}; + +static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type, + void *context, + void (*func)(struct work_struct *work)) +{ + struct acpi_root_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work-handle = handle; + hp_work-type = type; + hp_work-context = context; + + INIT_WORK(hp_work-work, func); + ret = queue_work(kacpi_hotplug_wq,hp_work-work); + if (!ret) + kfree(hp_work); +} + +/* Program resources in newly inserted bridge */ +static void
[PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
It causes confusion. We may only need acpi hp for pci host bridge. Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple. Also remove not used res_lock in the struct. -v2: put back pci_root_hp change in one patch -v3: add pcibios_resource_survey_bus() calling -v4: remove not needed code with remove_bridge -v5: put back support for acpiphp support for slots just on root bus. -v6: change some functions to *_p2p_* to make it more clean. Signed-off-by: Yinghai Lu --- drivers/acpi/Makefile |1 + drivers/acpi/pci_root_hp.c | 238 drivers/pci/hotplug/acpiphp_glue.c | 59 +++--- 3 files changed, 254 insertions(+), 44 deletions(-) create mode 100644 drivers/acpi/pci_root_hp.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2..c9abd4c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -36,6 +36,7 @@ acpi-y+= processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-$(CONFIG_HOTPLUG) += pci_root_hp.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c new file mode 100644 index 000..e07c31b --- /dev/null +++ b/drivers/acpi/pci_root_hp.c @@ -0,0 +1,238 @@ +/* + * Separated from drivers/pci/hotplug/acpiphp_glue.c + * only support root bridge + */ + +#include +#include + +#include +#include +#include +#include +#include + +static LIST_HEAD(acpi_root_bridge_list); +struct acpi_root_bridge { + struct list_head list; + acpi_handle handle; + u32 flags; +}; + +/* bridge flags */ +#define ROOT_BRIDGE_HAS_EJ0(0x0002) +#define ROOT_BRIDGE_HAS_PS3(0x0080) + +#define ACPI_STA_FUNCTIONING (0x0008) + +static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + + list_for_each_entry(bridge, _root_bridge_list, list) + if (bridge->handle == handle) + return bridge; + + return NULL; +} + +/* allocate and initialize host bridge data structure */ +static void add_acpi_root_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + acpi_handle dummy_handle; + acpi_status status; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, "_STA", _handle); + if (ACPI_SUCCESS(status)) { + unsigned long long tmp; + + status = acpi_evaluate_integer(handle, "_STA", NULL, ); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG "%s: _STA evaluation failure\n", +__func__); + return; + } + if ((tmp & ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return; + } + + bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL); + if (!bridge) + return; + + bridge->handle = handle; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", _handle))) + bridge->flags |= ROOT_BRIDGE_HAS_EJ0; + if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", _handle))) + bridge->flags |= ROOT_BRIDGE_HAS_PS3; + + list_add(>list, _root_bridge_list); +} + +struct acpi_root_hp_work { + struct work_struct work; + acpi_handle handle; + u32 type; + void *context; +}; + +static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type, + void *context, + void (*func)(struct work_struct *work)) +{ + struct acpi_root_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work->handle = handle; + hp_work->type = type; + hp_work->context = context; + + INIT_WORK(_work->work, func); + ret = queue_work(kacpi_hotplug_wq, _work->work); + if (!ret) + kfree(hp_work); +} + +/* Program resources in newly inserted bridge */ +static void acpi_root_configure_bridge(acpi_handle handle) +{ + struct acpi_pci_root *root = acpi_pci_find_root(handle); + + pcibios_resource_survey_bus(root->bus); + pci_assign_unassigned_bus_resources(root->bus); +} + +static void handle_root_bridge_insertion(acpi_handle handle) +{ + struct acpi_device *device, *pdevice; + acpi_handle phandle; + int ret_val; + + acpi_get_parent(handle, ); + if (acpi_bus_get_device(phandle, )) { + printk(KERN_DEBUG "no parent device, assuming
[PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
It causes confusion. We may only need acpi hp for pci host bridge. Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple. Also remove not used res_lock in the struct. -v2: put back pci_root_hp change in one patch -v3: add pcibios_resource_survey_bus() calling -v4: remove not needed code with remove_bridge -v5: put back support for acpiphp support for slots just on root bus. -v6: change some functions to *_p2p_* to make it more clean. Signed-off-by: Yinghai Lu ying...@kernel.org --- drivers/acpi/Makefile |1 + drivers/acpi/pci_root_hp.c | 238 drivers/pci/hotplug/acpiphp_glue.c | 59 +++--- 3 files changed, 254 insertions(+), 44 deletions(-) create mode 100644 drivers/acpi/pci_root_hp.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2..c9abd4c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -36,6 +36,7 @@ acpi-y+= processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-$(CONFIG_HOTPLUG) += pci_root_hp.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c new file mode 100644 index 000..e07c31b --- /dev/null +++ b/drivers/acpi/pci_root_hp.c @@ -0,0 +1,238 @@ +/* + * Separated from drivers/pci/hotplug/acpiphp_glue.c + * only support root bridge + */ + +#include linux/init.h +#include linux/module.h + +#include linux/kernel.h +#include linux/pci.h +#include linux/mutex.h +#include linux/slab.h +#include linux/acpi.h + +static LIST_HEAD(acpi_root_bridge_list); +struct acpi_root_bridge { + struct list_head list; + acpi_handle handle; + u32 flags; +}; + +/* bridge flags */ +#define ROOT_BRIDGE_HAS_EJ0(0x0002) +#define ROOT_BRIDGE_HAS_PS3(0x0080) + +#define ACPI_STA_FUNCTIONING (0x0008) + +static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + + list_for_each_entry(bridge, acpi_root_bridge_list, list) + if (bridge-handle == handle) + return bridge; + + return NULL; +} + +/* allocate and initialize host bridge data structure */ +static void add_acpi_root_bridge(acpi_handle handle) +{ + struct acpi_root_bridge *bridge; + acpi_handle dummy_handle; + acpi_status status; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, _STA, dummy_handle); + if (ACPI_SUCCESS(status)) { + unsigned long long tmp; + + status = acpi_evaluate_integer(handle, _STA, NULL, tmp); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG %s: _STA evaluation failure\n, +__func__); + return; + } + if ((tmp ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return; + } + + bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL); + if (!bridge) + return; + + bridge-handle = handle; + + if (ACPI_SUCCESS(acpi_get_handle(handle, _EJ0, dummy_handle))) + bridge-flags |= ROOT_BRIDGE_HAS_EJ0; + if (ACPI_SUCCESS(acpi_get_handle(handle, _PS3, dummy_handle))) + bridge-flags |= ROOT_BRIDGE_HAS_PS3; + + list_add(bridge-list, acpi_root_bridge_list); +} + +struct acpi_root_hp_work { + struct work_struct work; + acpi_handle handle; + u32 type; + void *context; +}; + +static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type, + void *context, + void (*func)(struct work_struct *work)) +{ + struct acpi_root_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work-handle = handle; + hp_work-type = type; + hp_work-context = context; + + INIT_WORK(hp_work-work, func); + ret = queue_work(kacpi_hotplug_wq, hp_work-work); + if (!ret) + kfree(hp_work); +} + +/* Program resources in newly inserted bridge */ +static void acpi_root_configure_bridge(acpi_handle handle) +{ + struct acpi_pci_root *root = acpi_pci_find_root(handle); + + pcibios_resource_survey_bus(root-bus); + pci_assign_unassigned_bus_resources(root-bus); +} + +static void handle_root_bridge_insertion(acpi_handle handle) +{ + struct acpi_device *device, *pdevice; + acpi_handle phandle; + int ret_val; + +