s390/pci: split lpf
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Thu, 29 Aug 2013 17:37:28 +0000 (19:37 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 30 Aug 2013 06:57:17 +0000 (08:57 +0200)
List pci functions is used to query and iterate over pci functions.
This function currently has 2 users - initial device discovery and
rescan after a machine check. Instead of having a multipurpose
function pass a callback which gets called for each pci function.

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/pci/pci.c
arch/s390/pci/pci_clp.c
arch/s390/pci/pci_event.c

index 64081f8..4b2bbc1 100644 (file)
@@ -135,7 +135,8 @@ int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
 int zpci_unregister_ioat(struct zpci_dev *, u8);
 
 /* CLP */
-int clp_find_pci_devices(void);
+int clp_scan_pci_devices(void);
+int clp_rescan_pci_devices(void);
 int clp_add_pci_device(u32, u32, int);
 int clp_enable_fh(struct zpci_dev *, u8);
 int clp_disable_fh(struct zpci_dev *);
@@ -163,7 +164,6 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {}
 /* Helpers */
 struct zpci_dev *get_zdev(struct pci_dev *);
 struct zpci_dev *get_zdev_by_fid(u32);
-bool zpci_fid_present(u32);
 
 /* sysfs */
 int zpci_sysfs_add_device(struct device *);
index b0ccd42..a7ed668 100644 (file)
@@ -99,11 +99,6 @@ struct zpci_dev *get_zdev_by_fid(u32 fid)
        return zdev;
 }
 
-bool zpci_fid_present(u32 fid)
-{
-       return (get_zdev_by_fid(fid) != NULL) ? true : false;
-}
-
 static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
 {
        return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
@@ -926,7 +921,7 @@ static int __init pci_base_init(void)
        if (rc)
                goto out_dma;
 
-       rc = clp_find_pci_devices();
+       rc = clp_scan_pci_devices();
        if (rc)
                goto out_find;
 
index 2e95396..70db060 100644 (file)
@@ -36,9 +36,9 @@ static inline u8 clp_instr(void *data)
        return cc;
 }
 
-static void *clp_alloc_block(void)
+static void *clp_alloc_block(gfp_t gfp_mask)
 {
-       return (void *) __get_free_pages(GFP_KERNEL, get_order(CLP_BLK_SIZE));
+       return (void *) __get_free_pages(gfp_mask, get_order(CLP_BLK_SIZE));
 }
 
 static void clp_free_block(void *ptr)
@@ -70,7 +70,7 @@ static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
        struct clp_req_rsp_query_pci_grp *rrb;
        int rc;
 
-       rrb = clp_alloc_block();
+       rrb = clp_alloc_block(GFP_KERNEL);
        if (!rrb)
                return -ENOMEM;
 
@@ -113,7 +113,7 @@ static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
        struct clp_req_rsp_query_pci *rrb;
        int rc;
 
-       rrb = clp_alloc_block();
+       rrb = clp_alloc_block(GFP_KERNEL);
        if (!rrb)
                return -ENOMEM;
 
@@ -181,7 +181,7 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
        struct clp_req_rsp_set_pci *rrb;
        int rc, retries = 1000;
 
-       rrb = clp_alloc_block();
+       rrb = clp_alloc_block(GFP_KERNEL);
        if (!rrb)
                return -ENOMEM;
 
@@ -245,49 +245,12 @@ int clp_disable_fh(struct zpci_dev *zdev)
        return rc;
 }
 
-static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry)
+static int clp_list_pci(struct clp_req_rsp_list_pci *rrb,
+                       void (*cb)(struct clp_fh_list_entry *entry))
 {
-       int present, rc;
-
-       if (!entry->vendor_id)
-               return;
-
-       /* TODO: be a little bit more scalable */
-       present = zpci_fid_present(entry->fid);
-
-       if (present)
-               pr_debug("%s: device %x already present\n", __func__, entry->fid);
-
-       /* skip already used functions */
-       if (present && entry->config_state)
-               return;
-
-       /* aev 306: function moved to stand-by state */
-       if (present && !entry->config_state) {
-               /*
-                * The handle is already disabled, that means no iota/irq freeing via
-                * the firmware interfaces anymore. Need to free resources manually
-                * (DMA memory, debug, sysfs)...
-                */
-               zpci_stop_device(get_zdev_by_fid(entry->fid));
-               return;
-       }
-
-       rc = clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
-       if (rc)
-               pr_err("Failed to add fid: 0x%x\n", entry->fid);
-}
-
-int clp_find_pci_devices(void)
-{
-       struct clp_req_rsp_list_pci *rrb;
        u64 resume_token = 0;
        int entries, i, rc;
 
-       rrb = clp_alloc_block();
-       if (!rrb)
-               return -ENOMEM;
-
        do {
                memset(rrb, 0, sizeof(*rrb));
                rrb->request.hdr.len = sizeof(rrb->request);
@@ -316,12 +279,72 @@ int clp_find_pci_devices(void)
                resume_token = rrb->response.resume_token;
 
                for (i = 0; i < entries; i++)
-                       clp_check_pcifn_entry(&rrb->response.fh_list[i]);
+                       cb(&rrb->response.fh_list[i]);
        } while (resume_token);
 
        pr_debug("Maximum number of supported PCI functions: %u\n",
                rrb->response.max_fn);
 out:
+       return rc;
+}
+
+static void __clp_add(struct clp_fh_list_entry *entry)
+{
+       if (!entry->vendor_id)
+               return;
+
+       clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
+}
+
+static void __clp_rescan(struct clp_fh_list_entry *entry)
+{
+       struct zpci_dev *zdev;
+
+       if (!entry->vendor_id)
+               return;
+
+       zdev = get_zdev_by_fid(entry->fid);
+       if (!zdev) {
+               clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
+               return;
+       }
+
+       if (!entry->config_state) {
+               /*
+                * The handle is already disabled, that means no iota/irq freeing via
+                * the firmware interfaces anymore. Need to free resources manually
+                * (DMA memory, debug, sysfs)...
+                */
+               zpci_stop_device(zdev);
+       }
+}
+
+int clp_scan_pci_devices(void)
+{
+       struct clp_req_rsp_list_pci *rrb;
+       int rc;
+
+       rrb = clp_alloc_block(GFP_KERNEL);
+       if (!rrb)
+               return -ENOMEM;
+
+       rc = clp_list_pci(rrb, __clp_add);
+
+       clp_free_block(rrb);
+       return rc;
+}
+
+int clp_rescan_pci_devices(void)
+{
+       struct clp_req_rsp_list_pci *rrb;
+       int rc;
+
+       rrb = clp_alloc_block(GFP_KERNEL);
+       if (!rrb)
+               return -ENOMEM;
+
+       rc = clp_list_pci(rrb, __clp_rescan);
+
        clp_free_block(rrb);
        return rc;
 }
index ec62e3a..0aecaf9 100644 (file)
@@ -69,7 +69,7 @@ static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
                clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
                break;
        case 0x0306:
-               clp_find_pci_devices();
+               clp_rescan_pci_devices();
                break;
        default:
                break;