mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 17:24:17 +08:00
PCI: endpoint: Assign function number for each PF in EPC core
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>
This commit is contained in:
parent
07301c9826
commit
2499ee84e0
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user