PCI: endpoint: Assign function number for each PF in EPC core
authorKishon Vijay Abraham I <kishon@ti.com>
Mon, 24 Feb 2020 09:53:38 +0000 (15:23 +0530)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Mon, 24 Feb 2020 10:15:45 +0000 (10:15 +0000)
The PCIe endpoint core relies on the drivers that invoke the
pci_epc_add_epf() API to allocate and assign a function number
to each physical function (PF). Since endpoint function device can
be created by multiple mechanisms (configfs, devicetree, etc..),
allowing each of these mechanisms to assign a function number
would result in mutliple endpoint function devices having the
same function number. In order to avoid this, let EPC core assign
a function number to the endpoint device.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
drivers/pci/endpoint/pci-ep-cfs.c
drivers/pci/endpoint/pci-epc-core.c
include/linux/pci-epc.h

index d1288a0..e7e8367 100644 (file)
@@ -29,7 +29,6 @@ struct pci_epc_group {
        struct config_group group;
        struct pci_epc *epc;
        bool start;
-       unsigned long function_num_map;
 };
 
 static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
@@ -89,37 +88,22 @@ static int pci_epc_epf_link(struct config_item *epc_item,
                            struct config_item *epf_item)
 {
        int ret;
-       u32 func_no = 0;
        struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
        struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
        struct pci_epc *epc = epc_group->epc;
        struct pci_epf *epf = epf_group->epf;
 
-       func_no = find_first_zero_bit(&epc_group->function_num_map,
-                                     BITS_PER_LONG);
-       if (func_no >= BITS_PER_LONG)
-               return -EINVAL;
-
-       set_bit(func_no, &epc_group->function_num_map);
-       epf->func_no = func_no;
-
        ret = pci_epc_add_epf(epc, epf);
        if (ret)
-               goto err_add_epf;
+               return ret;
 
        ret = pci_epf_bind(epf);
-       if (ret)
-               goto err_epf_bind;
+       if (ret) {
+               pci_epc_remove_epf(epc, epf);
+               return ret;
+       }
 
        return 0;
-
-err_epf_bind:
-       pci_epc_remove_epf(epc, epf);
-
-err_add_epf:
-       clear_bit(func_no, &epc_group->function_num_map);
-
-       return ret;
 }
 
 static void pci_epc_epf_unlink(struct config_item *epc_item,
@@ -134,7 +118,6 @@ static void pci_epc_epf_unlink(struct config_item *epc_item,
 
        epc = epc_group->epc;
        epf = epf_group->epf;
-       clear_bit(epf->func_no, &epc_group->function_num_map);
        pci_epf_unbind(epf);
        pci_epc_remove_epf(epc, epf);
 }
index e51a12e..dc1c673 100644 (file)
@@ -471,22 +471,39 @@ EXPORT_SYMBOL_GPL(pci_epc_write_header);
  */
 int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf)
 {
+       u32 func_no;
+       int ret = 0;
+
        if (epf->epc)
                return -EBUSY;
 
        if (IS_ERR(epc))
                return -EINVAL;
 
-       if (epf->func_no > epc->max_functions - 1)
-               return -EINVAL;
+       mutex_lock(&epc->lock);
+       func_no = find_first_zero_bit(&epc->function_num_map,
+                                     BITS_PER_LONG);
+       if (func_no >= BITS_PER_LONG) {
+               ret = -EINVAL;
+               goto ret;
+       }
+
+       if (func_no > epc->max_functions - 1) {
+               dev_err(&epc->dev, "Exceeding max supported Function Number\n");
+               ret = -EINVAL;
+               goto ret;
+       }
 
+       set_bit(func_no, &epc->function_num_map);
+       epf->func_no = func_no;
        epf->epc = epc;
 
-       mutex_lock(&epc->lock);
        list_add_tail(&epf->list, &epc->pci_epf);
+
+ret:
        mutex_unlock(&epc->lock);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(pci_epc_add_epf);
 
@@ -503,6 +520,7 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf)
                return;
 
        mutex_lock(&epc->lock);
+       clear_bit(epf->func_no, &epc->function_num_map);
        list_del(&epf->list);
        epf->epc = NULL;
        mutex_unlock(&epc->lock);
index 4e3e527..ccaf6e3 100644 (file)
@@ -92,6 +92,7 @@ struct pci_epc_mem {
  * @max_functions: max number of functions that can be configured in this EPC
  * @group: configfs group representing the PCI EPC device
  * @lock: mutex to protect pci_epc ops
+ * @function_num_map: bitmap to manage physical function number
  * @notifier: used to notify EPF of any EPC events (like linkup)
  */
 struct pci_epc {
@@ -103,6 +104,7 @@ struct pci_epc {
        struct config_group             *group;
        /* mutex to protect against concurrent access of EP controller */
        struct mutex                    lock;
+       unsigned long                   function_num_map;
        struct atomic_notifier_head     notifier;
 };