diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-08-29 19:40:01 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-08-30 08:57:20 +0200 |
commit | 57b5918c33a0797930c3791fb602a8a9d46ef80c (patch) | |
tree | 47e3a5b503e8551f130fb722fbf1ae281e6ed292 /arch/s390 | |
parent | d03abe5882cc4815bf98c0e01a1deafa4a5d6730 (diff) | |
download | linux-57b5918c33a0797930c3791fb602a8a9d46ef80c.tar.bz2 |
s390/pci: update function handle after resume from hibernate
Function handles may change while the system was in hibernation
use list pci functions and update the function handles.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/pci.h | 4 | ||||
-rw-r--r-- | arch/s390/kernel/suspend.c | 2 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 15 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 29 |
4 files changed, 45 insertions, 5 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 4b2bbc1fdbe0..c290f13d1c47 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -6,6 +6,7 @@ /* must be set before including pci_clp.h */ #define PCI_BAR_COUNT 6 +#include <linux/pci.h> #include <asm-generic/pci.h> #include <asm-generic/pci-dma-compat.h> #include <asm/pci_clp.h> @@ -137,6 +138,7 @@ int zpci_unregister_ioat(struct zpci_dev *, u8); /* CLP */ int clp_scan_pci_devices(void); int clp_rescan_pci_devices(void); +int clp_rescan_pci_devices_simple(void); int clp_add_pci_device(u32, u32, int); int clp_enable_fh(struct zpci_dev *, u8); int clp_disable_fh(struct zpci_dev *); @@ -145,9 +147,11 @@ int clp_disable_fh(struct zpci_dev *); /* Error handling and recovery */ void zpci_event_error(void *); void zpci_event_availability(void *); +void zpci_rescan(void); #else /* CONFIG_PCI */ static inline void zpci_event_error(void *e) {} static inline void zpci_event_availability(void *e) {} +static inline void zpci_rescan(void) {} #endif /* CONFIG_PCI */ #ifdef CONFIG_HOTPLUG_PCI_S390 diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c index eebab9f83f1d..737bff38e3ee 100644 --- a/arch/s390/kernel/suspend.c +++ b/arch/s390/kernel/suspend.c @@ -12,6 +12,7 @@ #include <asm/ctl_reg.h> #include <asm/ipl.h> #include <asm/cio.h> +#include <asm/pci.h> /* * References to section boundaries @@ -219,4 +220,5 @@ void s390_early_resume(void) { lgr_info_log(); channel_subsystem_reinit(); + zpci_rescan(); } diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index a7ed6685e7fb..f17a8343e360 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -46,7 +46,7 @@ /* list of all detected zpci devices */ static LIST_HEAD(zpci_list); -static DEFINE_MUTEX(zpci_list_lock); +static DEFINE_SPINLOCK(zpci_list_lock); static void zpci_enable_irq(struct irq_data *data); static void zpci_disable_irq(struct irq_data *data); @@ -88,14 +88,14 @@ struct zpci_dev *get_zdev_by_fid(u32 fid) { struct zpci_dev *tmp, *zdev = NULL; - mutex_lock(&zpci_list_lock); + spin_lock(&zpci_list_lock); list_for_each_entry(tmp, &zpci_list, entry) { if (tmp->fid == fid) { zdev = tmp; break; } } - mutex_unlock(&zpci_list_lock); + spin_unlock(&zpci_list_lock); return zdev; } @@ -821,9 +821,9 @@ int zpci_create_device(struct zpci_dev *zdev) if (rc) goto out_disable; - mutex_lock(&zpci_list_lock); + spin_lock(&zpci_list_lock); list_add_tail(&zdev->entry, &zpci_list); - mutex_unlock(&zpci_list_lock); + spin_unlock(&zpci_list_lock); zpci_init_slot(zdev); @@ -939,3 +939,8 @@ out: return rc; } subsys_initcall_sync(pci_base_init); + +void zpci_rescan(void) +{ + clp_rescan_pci_devices_simple(); +} diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 3eaf63a6ecac..475563c3d1e4 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -319,6 +319,20 @@ static void __clp_rescan(struct clp_fh_list_entry *entry) } } +static void __clp_update(struct clp_fh_list_entry *entry) +{ + struct zpci_dev *zdev; + + if (!entry->vendor_id) + return; + + zdev = get_zdev_by_fid(entry->fid); + if (!zdev) + return; + + zdev->fh = entry->fh; +} + int clp_scan_pci_devices(void) { struct clp_req_rsp_list_pci *rrb; @@ -348,3 +362,18 @@ int clp_rescan_pci_devices(void) clp_free_block(rrb); return rc; } + +int clp_rescan_pci_devices_simple(void) +{ + struct clp_req_rsp_list_pci *rrb; + int rc; + + rrb = clp_alloc_block(GFP_NOWAIT); + if (!rrb) + return -ENOMEM; + + rc = clp_list_pci(rrb, __clp_update); + + clp_free_block(rrb); + return rc; +} |