Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCI: endpoint: Add support in configfs to associate two EPCs with EPF

Now that PCI endpoint core supports to add secondary endpoint controller
(EPC) with endpoint function (EPF), Add support in configfs to associate
two EPCs with EPF. This creates "primary" and "secondary" directory inside
the directory created by users for EPF device. Users have to add a symlink
of endpoint controller (pci_ep/controllers/) to "primary" or "secondary"
directory to bind EPF to primary and secondary EPF interfaces respectively.
Existing method of linking directory representing EPF device to directory
representing EPC device to associate a single EPC device with a EPF device
will continue to work.

Link: https://lore.kernel.org/r/20210201195809.7342-8-kishon@ti.com
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

authored by

Kishon Vijay Abraham I and committed by
Bjorn Helgaas
e85a2d78 63840ff5

+157
+10
Documentation/PCI/endpoint/pci-endpoint-cfs.rst
··· 68 68 ... subsys_vendor_id 69 69 ... subsys_id 70 70 ... interrupt_pin 71 + ... primary/ 72 + ... <Symlink EPC Device1>/ 73 + ... secondary/ 74 + ... <Symlink EPC Device2>/ 75 + 76 + If an EPF device has to be associated with 2 EPCs (like in the case of 77 + Non-transparent bridge), symlink of endpoint controller connected to primary 78 + interface should be added in 'primary' directory and symlink of endpoint 79 + controller connected to secondary interface should be added in 'secondary' 80 + directory. 71 81 72 82 EPC Device 73 83 ==========
+147
drivers/pci/endpoint/pci-ep-cfs.c
··· 21 21 22 22 struct pci_epf_group { 23 23 struct config_group group; 24 + struct config_group primary_epc_group; 25 + struct config_group secondary_epc_group; 26 + struct delayed_work cfs_work; 24 27 struct pci_epf *epf; 25 28 int index; 26 29 }; ··· 42 39 static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item) 43 40 { 44 41 return container_of(to_config_group(item), struct pci_epc_group, group); 42 + } 43 + 44 + static int pci_secondary_epc_epf_link(struct config_item *epf_item, 45 + struct config_item *epc_item) 46 + { 47 + int ret; 48 + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); 49 + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); 50 + struct pci_epc *epc = epc_group->epc; 51 + struct pci_epf *epf = epf_group->epf; 52 + 53 + ret = pci_epc_add_epf(epc, epf, SECONDARY_INTERFACE); 54 + if (ret) 55 + return ret; 56 + 57 + ret = pci_epf_bind(epf); 58 + if (ret) { 59 + pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE); 60 + return ret; 61 + } 62 + 63 + return 0; 64 + } 65 + 66 + static void pci_secondary_epc_epf_unlink(struct config_item *epc_item, 67 + struct config_item *epf_item) 68 + { 69 + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); 70 + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); 71 + struct pci_epc *epc; 72 + struct pci_epf *epf; 73 + 74 + WARN_ON_ONCE(epc_group->start); 75 + 76 + epc = epc_group->epc; 77 + epf = epf_group->epf; 78 + pci_epf_unbind(epf); 79 + pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE); 80 + } 81 + 82 + static struct configfs_item_operations pci_secondary_epc_item_ops = { 83 + .allow_link = pci_secondary_epc_epf_link, 84 + .drop_link = pci_secondary_epc_epf_unlink, 85 + }; 86 + 87 + static const struct config_item_type pci_secondary_epc_type = { 88 + .ct_item_ops = &pci_secondary_epc_item_ops, 89 + .ct_owner = THIS_MODULE, 90 + }; 91 + 92 + static struct config_group 93 + *pci_ep_cfs_add_secondary_group(struct pci_epf_group *epf_group) 94 + { 95 + struct config_group *secondary_epc_group; 96 + 97 + secondary_epc_group = &epf_group->secondary_epc_group; 98 + config_group_init_type_name(secondary_epc_group, "secondary", 99 + &pci_secondary_epc_type); 100 + configfs_register_group(&epf_group->group, secondary_epc_group); 101 + 102 + return secondary_epc_group; 103 + } 104 + 105 + static int pci_primary_epc_epf_link(struct config_item *epf_item, 106 + struct config_item *epc_item) 107 + { 108 + int ret; 109 + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); 110 + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); 111 + struct pci_epc *epc = epc_group->epc; 112 + struct pci_epf *epf = epf_group->epf; 113 + 114 + ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE); 115 + if (ret) 116 + return ret; 117 + 118 + ret = pci_epf_bind(epf); 119 + if (ret) { 120 + pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE); 121 + return ret; 122 + } 123 + 124 + return 0; 125 + } 126 + 127 + static void pci_primary_epc_epf_unlink(struct config_item *epc_item, 128 + struct config_item *epf_item) 129 + { 130 + struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent); 131 + struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); 132 + struct pci_epc *epc; 133 + struct pci_epf *epf; 134 + 135 + WARN_ON_ONCE(epc_group->start); 136 + 137 + epc = epc_group->epc; 138 + epf = epf_group->epf; 139 + pci_epf_unbind(epf); 140 + pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE); 141 + } 142 + 143 + static struct configfs_item_operations pci_primary_epc_item_ops = { 144 + .allow_link = pci_primary_epc_epf_link, 145 + .drop_link = pci_primary_epc_epf_unlink, 146 + }; 147 + 148 + static const struct config_item_type pci_primary_epc_type = { 149 + .ct_item_ops = &pci_primary_epc_item_ops, 150 + .ct_owner = THIS_MODULE, 151 + }; 152 + 153 + static struct config_group 154 + *pci_ep_cfs_add_primary_group(struct pci_epf_group *epf_group) 155 + { 156 + struct config_group *primary_epc_group = &epf_group->primary_epc_group; 157 + 158 + config_group_init_type_name(primary_epc_group, "primary", 159 + &pci_primary_epc_type); 160 + configfs_register_group(&epf_group->group, primary_epc_group); 161 + 162 + return primary_epc_group; 45 163 } 46 164 47 165 static ssize_t pci_epc_start_store(struct config_item *item, const char *page, ··· 496 372 .ct_owner = THIS_MODULE, 497 373 }; 498 374 375 + static void pci_epf_cfs_work(struct work_struct *work) 376 + { 377 + struct pci_epf_group *epf_group; 378 + struct config_group *group; 379 + 380 + epf_group = container_of(work, struct pci_epf_group, cfs_work.work); 381 + group = pci_ep_cfs_add_primary_group(epf_group); 382 + if (IS_ERR(group)) { 383 + pr_err("failed to create 'primary' EPC interface\n"); 384 + return; 385 + } 386 + 387 + group = pci_ep_cfs_add_secondary_group(epf_group); 388 + if (IS_ERR(group)) { 389 + pr_err("failed to create 'secondary' EPC interface\n"); 390 + return; 391 + } 392 + } 393 + 499 394 static struct config_group *pci_epf_make(struct config_group *group, 500 395 const char *name) 501 396 { ··· 556 413 epf_group->epf = epf; 557 414 558 415 kfree(epf_name); 416 + 417 + INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work); 418 + queue_delayed_work(system_wq, &epf_group->cfs_work, 419 + msecs_to_jiffies(1)); 559 420 560 421 return &epf_group->group; 561 422