lkml.org 
[lkml]   [2020]   [Feb]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 5/5] PCI: endpoint: Assign function number for each PF in EPC core
    Date
    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>
    ---
    drivers/pci/endpoint/pci-ep-cfs.c | 27 +++++----------------------
    drivers/pci/endpoint/pci-epc-core.c | 26 ++++++++++++++++++++++----
    include/linux/pci-epc.h | 2 ++
    3 files changed, 29 insertions(+), 26 deletions(-)

    diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
    index d1288a0bd530..e7e8367eead1 100644
    --- a/drivers/pci/endpoint/pci-ep-cfs.c
    +++ b/drivers/pci/endpoint/pci-ep-cfs.c
    @@ -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);
    }
    diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
    index e51a12ed85bb..dc1c673534e0 100644
    --- a/drivers/pci/endpoint/pci-epc-core.c
    +++ b/drivers/pci/endpoint/pci-epc-core.c
    @@ -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);
    diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
    index 4e3e527c49d1..ccaf6e3fa931 100644
    --- a/include/linux/pci-epc.h
    +++ b/include/linux/pci-epc.h
    @@ -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;
    };

    --
    2.17.1
    \
     
     \ /
      Last update: 2020-02-12 12:22    [W:2.639 / U:0.296 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site