Skip to content

Commit 70b3740

Browse files
damien-lemoalbjorn-helgaas
authored andcommitted
PCI: endpoint: Automatically create a function specific attributes group
A PCI endpoint function driver can define function specific attributes under its function configfs directory using the add_cfs() endpoint driver operation. This is done by tying up the mkdir operation for the function configfs directory to a call to the add_cfs() operation. However, there are no checks preventing the user from repeatedly creating function specific attribute directories with different names, resulting in the same endpoint specific attributes group being added multiple times, which also result in an invalid reference counting for the attribute groups. E.g., using the pci-epf-ntb function driver as an example, the user creates the function as follows: $ modprobe pci-epf-ntb $ cd /sys/kernel/config/pci_ep/functions/pci_epf_ntb $ mkdir func0 $ tree func0 func0/ |-- baseclass_code |-- cache_line_size |-- ... `-- vendorid $ mkdir func0/attrs $ tree func0 func0/ |-- attrs | |-- db_count | |-- mw1 | |-- mw2 | |-- mw3 | |-- mw4 | |-- num_mws | `-- spad_count |-- baseclass_code |-- cache_line_size |-- ... `-- vendorid At this point, the function can be started by linking the EP controller. However, if the user mistakenly creates again a directory: $ mkdir func0/attrs2 $ tree func0 func0/ |-- attrs | |-- db_count | |-- mw1 | |-- mw2 | |-- mw3 | |-- mw4 | |-- num_mws | `-- spad_count |-- attrs2 | |-- db_count | |-- mw1 | |-- mw2 | |-- mw3 | |-- mw4 | |-- num_mws | `-- spad_count |-- baseclass_code |-- cache_line_size |-- ... `-- vendorid The endpoint function specific attributes are duplicated and cause a crash when the endpoint function device is torn down: refcount_t: addition on 0; use-after-free. WARNING: CPU: 2 PID: 834 at lib/refcount.c:25 refcount_warn_saturate+0xc8/0x144 CPU: 2 PID: 834 Comm: rmdir Not tainted 6.3.0-rc1 #1 Hardware name: Pine64 RockPro64 v2.1 (DT) pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) ... Call trace: refcount_warn_saturate+0xc8/0x144 config_item_get+0x7c/0x80 configfs_rmdir+0x17c/0x30c vfs_rmdir+0x8c/0x204 do_rmdir+0x158/0x184 __arm64_sys_unlinkat+0x64/0x80 invoke_syscall+0x48/0x114 ... Fix this by modifying pci_epf_cfs_work() to execute the new function pci_ep_cfs_add_type_group() which itself calls pci_epf_type_add_cfs() to obtain the function specific attribute group and the group name (directory name) from the endpoint function driver. If the function driver defines an attribute group, pci_ep_cfs_add_type_group() then proceeds to register this group using configfs_register_group(), thus automatically exposing the function type specific configfs attributes to the user. E.g.: $ modprobe pci-epf-ntb $ cd /sys/kernel/config/pci_ep/functions/pci_epf_ntb $ mkdir func0 $ tree func0 func0/ |-- baseclass_code |-- cache_line_size |-- ... |-- pci_epf_ntb.0 | |-- db_count | |-- mw1 | |-- mw2 | |-- mw3 | |-- mw4 | |-- num_mws | `-- spad_count |-- primary |-- ... `-- vendorid With this change, there is no need for the user to create or delete directories in the endpoint function attributes directory. The pci_epf_type_group_ops group operations are thus removed. Also update the documentation for the pci-epf-ntb and pci-epf-vntb function drivers to reflect this change, removing the explanations showing the need to manually create the sub-directory for the function specific attributes. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Damien Le Moal <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]>
1 parent 3758767 commit 70b3740

File tree

3 files changed

+29
-37
lines changed

3 files changed

+29
-37
lines changed

Documentation/PCI/endpoint/pci-ntb-howto.rst

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,10 @@ commands can be used::
8888
# echo 0x104c > functions/pci_epf_ntb/func1/vendorid
8989
# echo 0xb00d > functions/pci_epf_ntb/func1/deviceid
9090

91-
In order to configure NTB specific attributes, a new sub-directory to func1
92-
should be created::
93-
94-
# mkdir functions/pci_epf_ntb/func1/pci_epf_ntb.0/
95-
96-
The NTB function driver will populate this directory with various attributes
97-
that can be configured by the user::
91+
The PCI endpoint framework also automatically creates a sub-directory in the
92+
function attribute directory. This sub-directory has the same name as the name
93+
of the function device and is populated with the following NTB specific
94+
attributes that can be configured by the user::
9895

9996
# ls functions/pci_epf_ntb/func1/pci_epf_ntb.0/
10097
db_count mw1 mw2 mw3 mw4 num_mws

Documentation/PCI/endpoint/pci-vntb-howto.rst

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,10 @@ commands can be used::
8484
# echo 0x1957 > functions/pci_epf_vntb/func1/vendorid
8585
# echo 0x0809 > functions/pci_epf_vntb/func1/deviceid
8686

87-
In order to configure NTB specific attributes, a new sub-directory to func1
88-
should be created::
89-
90-
# mkdir functions/pci_epf_vntb/func1/pci_epf_vntb.0/
91-
92-
The NTB function driver will populate this directory with various attributes
93-
that can be configured by the user::
87+
The PCI endpoint framework also automatically creates a sub-directory in the
88+
function attribute directory. This sub-directory has the same name as the name
89+
of the function device and is populated with the following NTB specific
90+
attributes that can be configured by the user::
9491

9592
# ls functions/pci_epf_vntb/func1/pci_epf_vntb.0/
9693
db_count mw1 mw2 mw3 mw4 num_mws
@@ -103,7 +100,7 @@ A sample configuration for NTB function is given below::
103100
# echo 1 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/num_mws
104101
# echo 0x100000 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/mw1
105102

106-
A sample configuration for virtual NTB driver for virutal PCI bus::
103+
A sample configuration for virtual NTB driver for virtual PCI bus::
107104

108105
# echo 0x1957 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_vid
109106
# echo 0x080A > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_pid

drivers/pci/endpoint/pci-ep-cfs.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct pci_epf_group {
2323
struct config_group group;
2424
struct config_group primary_epc_group;
2525
struct config_group secondary_epc_group;
26+
struct config_group *type_group;
2627
struct delayed_work cfs_work;
2728
struct pci_epf *epf;
2829
int index;
@@ -502,34 +503,29 @@ static struct configfs_item_operations pci_epf_ops = {
502503
.release = pci_epf_release,
503504
};
504505

505-
static struct config_group *pci_epf_type_make(struct config_group *group,
506-
const char *name)
507-
{
508-
struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item);
509-
struct config_group *epf_type_group;
510-
511-
epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group);
512-
return epf_type_group;
513-
}
514-
515-
static void pci_epf_type_drop(struct config_group *group,
516-
struct config_item *item)
517-
{
518-
config_item_put(item);
519-
}
520-
521-
static struct configfs_group_operations pci_epf_type_group_ops = {
522-
.make_group = &pci_epf_type_make,
523-
.drop_item = &pci_epf_type_drop,
524-
};
525-
526506
static const struct config_item_type pci_epf_type = {
527-
.ct_group_ops = &pci_epf_type_group_ops,
528507
.ct_item_ops = &pci_epf_ops,
529508
.ct_attrs = pci_epf_attrs,
530509
.ct_owner = THIS_MODULE,
531510
};
532511

512+
static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
513+
{
514+
struct config_group *group;
515+
516+
group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group);
517+
if (!group)
518+
return;
519+
520+
if (IS_ERR(group)) {
521+
dev_err(&epf_group->epf->dev,
522+
"failed to create epf type specific attributes\n");
523+
return;
524+
}
525+
526+
configfs_register_group(&epf_group->group, group);
527+
}
528+
533529
static void pci_epf_cfs_work(struct work_struct *work)
534530
{
535531
struct pci_epf_group *epf_group;
@@ -547,6 +543,8 @@ static void pci_epf_cfs_work(struct work_struct *work)
547543
pr_err("failed to create 'secondary' EPC interface\n");
548544
return;
549545
}
546+
547+
pci_ep_cfs_add_type_group(epf_group);
550548
}
551549

552550
static struct config_group *pci_epf_make(struct config_group *group,

0 commit comments

Comments
 (0)