]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
s390/pci: update function handle after resume from hibernate
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Thu, 29 Aug 2013 17:40:01 +0000 (19:40 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 30 Aug 2013 06:57:20 +0000 (08:57 +0200)
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>
arch/s390/include/asm/pci.h
arch/s390/kernel/suspend.c
arch/s390/pci/pci.c
arch/s390/pci/pci_clp.c

index 4b2bbc1fdbe01b44cd0c57ee87dfaae3caf747be..c290f13d1c47bbcc986f72f8bd715a6a7a888aee 100644 (file)
@@ -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
index eebab9f83f1d053a600b76aecb8a3090c78cb696..737bff38e3eeed4ed9d77cb87962d35205b47951 100644 (file)
@@ -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();
 }
index a7ed6685e7fb76972e06020f1b5d5be349fec6ef..f17a8343e3609d7d644b1d5896fd49bf4fca9e88 100644 (file)
@@ -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();
+}
index 3eaf63a6ecac9a9f00a7e6eb9cb6b2a7171e4046..475563c3d1e40d401417c6503946f1933457980d 100644 (file)
@@ -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;
+}