aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-08-29 13:40:01 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-08-30 02:57:20 -0400
commit57b5918c33a0797930c3791fb602a8a9d46ef80c (patch)
tree47e3a5b503e8551f130fb722fbf1ae281e6ed292 /arch
parentd03abe5882cc4815bf98c0e01a1deafa4a5d6730 (diff)
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')
-rw-r--r--arch/s390/include/asm/pci.h4
-rw-r--r--arch/s390/kernel/suspend.c2
-rw-r--r--arch/s390/pci/pci.c15
-rw-r--r--arch/s390/pci/pci_clp.c29
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 @@
6/* must be set before including pci_clp.h */ 6/* must be set before including pci_clp.h */
7#define PCI_BAR_COUNT 6 7#define PCI_BAR_COUNT 6
8 8
9#include <linux/pci.h>
9#include <asm-generic/pci.h> 10#include <asm-generic/pci.h>
10#include <asm-generic/pci-dma-compat.h> 11#include <asm-generic/pci-dma-compat.h>
11#include <asm/pci_clp.h> 12#include <asm/pci_clp.h>
@@ -137,6 +138,7 @@ int zpci_unregister_ioat(struct zpci_dev *, u8);
137/* CLP */ 138/* CLP */
138int clp_scan_pci_devices(void); 139int clp_scan_pci_devices(void);
139int clp_rescan_pci_devices(void); 140int clp_rescan_pci_devices(void);
141int clp_rescan_pci_devices_simple(void);
140int clp_add_pci_device(u32, u32, int); 142int clp_add_pci_device(u32, u32, int);
141int clp_enable_fh(struct zpci_dev *, u8); 143int clp_enable_fh(struct zpci_dev *, u8);
142int clp_disable_fh(struct zpci_dev *); 144int clp_disable_fh(struct zpci_dev *);
@@ -145,9 +147,11 @@ int clp_disable_fh(struct zpci_dev *);
145/* Error handling and recovery */ 147/* Error handling and recovery */
146void zpci_event_error(void *); 148void zpci_event_error(void *);
147void zpci_event_availability(void *); 149void zpci_event_availability(void *);
150void zpci_rescan(void);
148#else /* CONFIG_PCI */ 151#else /* CONFIG_PCI */
149static inline void zpci_event_error(void *e) {} 152static inline void zpci_event_error(void *e) {}
150static inline void zpci_event_availability(void *e) {} 153static inline void zpci_event_availability(void *e) {}
154static inline void zpci_rescan(void) {}
151#endif /* CONFIG_PCI */ 155#endif /* CONFIG_PCI */
152 156
153#ifdef CONFIG_HOTPLUG_PCI_S390 157#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 @@
12#include <asm/ctl_reg.h> 12#include <asm/ctl_reg.h>
13#include <asm/ipl.h> 13#include <asm/ipl.h>
14#include <asm/cio.h> 14#include <asm/cio.h>
15#include <asm/pci.h>
15 16
16/* 17/*
17 * References to section boundaries 18 * References to section boundaries
@@ -219,4 +220,5 @@ void s390_early_resume(void)
219{ 220{
220 lgr_info_log(); 221 lgr_info_log();
221 channel_subsystem_reinit(); 222 channel_subsystem_reinit();
223 zpci_rescan();
222} 224}
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 @@
46 46
47/* list of all detected zpci devices */ 47/* list of all detected zpci devices */
48static LIST_HEAD(zpci_list); 48static LIST_HEAD(zpci_list);
49static DEFINE_MUTEX(zpci_list_lock); 49static DEFINE_SPINLOCK(zpci_list_lock);
50 50
51static void zpci_enable_irq(struct irq_data *data); 51static void zpci_enable_irq(struct irq_data *data);
52static void zpci_disable_irq(struct irq_data *data); 52static void zpci_disable_irq(struct irq_data *data);
@@ -88,14 +88,14 @@ struct zpci_dev *get_zdev_by_fid(u32 fid)
88{ 88{
89 struct zpci_dev *tmp, *zdev = NULL; 89 struct zpci_dev *tmp, *zdev = NULL;
90 90
91 mutex_lock(&zpci_list_lock); 91 spin_lock(&zpci_list_lock);
92 list_for_each_entry(tmp, &zpci_list, entry) { 92 list_for_each_entry(tmp, &zpci_list, entry) {
93 if (tmp->fid == fid) { 93 if (tmp->fid == fid) {
94 zdev = tmp; 94 zdev = tmp;
95 break; 95 break;
96 } 96 }
97 } 97 }
98 mutex_unlock(&zpci_list_lock); 98 spin_unlock(&zpci_list_lock);
99 return zdev; 99 return zdev;
100} 100}
101 101
@@ -821,9 +821,9 @@ int zpci_create_device(struct zpci_dev *zdev)
821 if (rc) 821 if (rc)
822 goto out_disable; 822 goto out_disable;
823 823
824 mutex_lock(&zpci_list_lock); 824 spin_lock(&zpci_list_lock);
825 list_add_tail(&zdev->entry, &zpci_list); 825 list_add_tail(&zdev->entry, &zpci_list);
826 mutex_unlock(&zpci_list_lock); 826 spin_unlock(&zpci_list_lock);
827 827
828 zpci_init_slot(zdev); 828 zpci_init_slot(zdev);
829 829
@@ -939,3 +939,8 @@ out:
939 return rc; 939 return rc;
940} 940}
941subsys_initcall_sync(pci_base_init); 941subsys_initcall_sync(pci_base_init);
942
943void zpci_rescan(void)
944{
945 clp_rescan_pci_devices_simple();
946}
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)
319 } 319 }
320} 320}
321 321
322static void __clp_update(struct clp_fh_list_entry *entry)
323{
324 struct zpci_dev *zdev;
325
326 if (!entry->vendor_id)
327 return;
328
329 zdev = get_zdev_by_fid(entry->fid);
330 if (!zdev)
331 return;
332
333 zdev->fh = entry->fh;
334}
335
322int clp_scan_pci_devices(void) 336int clp_scan_pci_devices(void)
323{ 337{
324 struct clp_req_rsp_list_pci *rrb; 338 struct clp_req_rsp_list_pci *rrb;
@@ -348,3 +362,18 @@ int clp_rescan_pci_devices(void)
348 clp_free_block(rrb); 362 clp_free_block(rrb);
349 return rc; 363 return rc;
350} 364}
365
366int clp_rescan_pci_devices_simple(void)
367{
368 struct clp_req_rsp_list_pci *rrb;
369 int rc;
370
371 rrb = clp_alloc_block(GFP_NOWAIT);
372 if (!rrb)
373 return -ENOMEM;
374
375 rc = clp_list_pci(rrb, __clp_update);
376
377 clp_free_block(rrb);
378 return rc;
379}