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>
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index a7ed668..f17a834 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 *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 @@
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 @@
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 3eaf63a..475563c 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -319,6 +319,20 @@
}
}
+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 @@
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;
+}