Skip to content

Commit 4569cce

Browse files
emuslndavem330
authored andcommitted
pds_core: add auxiliary_bus devices
An auxiliary_bus device is created for each vDPA type VF at VF probe and destroyed at VF remove. The aux device name comes from the driver name + VIF type + the unique id assigned at PCI probe. The VFs are always removed on PF remove, so there should be no issues with VFs trying to access missing PF structures. The auxiliary_device names will look like "pds_core.vDPA.nn" where 'nn' is the VF's uid. Signed-off-by: Shannon Nelson <[email protected]> Acked-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f53d931 commit 4569cce

File tree

6 files changed

+171
-2
lines changed

6 files changed

+171
-2
lines changed

drivers/net/ethernet/amd/pds_core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ obj-$(CONFIG_PDS_CORE) := pds_core.o
55

66
pds_core-y := main.o \
77
devlink.o \
8+
auxbus.o \
89
dev.o \
910
adminq.o \
1011
core.o \
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright(c) 2023 Advanced Micro Devices, Inc */
3+
4+
#include <linux/pci.h>
5+
6+
#include "core.h"
7+
#include <linux/pds/pds_auxbus.h>
8+
9+
static void pdsc_auxbus_dev_release(struct device *dev)
10+
{
11+
struct pds_auxiliary_dev *padev =
12+
container_of(dev, struct pds_auxiliary_dev, aux_dev.dev);
13+
14+
kfree(padev);
15+
}
16+
17+
static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf,
18+
struct pdsc *pf,
19+
char *name)
20+
{
21+
struct auxiliary_device *aux_dev;
22+
struct pds_auxiliary_dev *padev;
23+
int err;
24+
25+
padev = kzalloc(sizeof(*padev), GFP_KERNEL);
26+
if (!padev)
27+
return ERR_PTR(-ENOMEM);
28+
29+
padev->vf_pdev = cf->pdev;
30+
31+
aux_dev = &padev->aux_dev;
32+
aux_dev->name = name;
33+
aux_dev->id = cf->uid;
34+
aux_dev->dev.parent = cf->dev;
35+
aux_dev->dev.release = pdsc_auxbus_dev_release;
36+
37+
err = auxiliary_device_init(aux_dev);
38+
if (err < 0) {
39+
dev_warn(cf->dev, "auxiliary_device_init of %s failed: %pe\n",
40+
name, ERR_PTR(err));
41+
goto err_out;
42+
}
43+
44+
err = auxiliary_device_add(aux_dev);
45+
if (err) {
46+
dev_warn(cf->dev, "auxiliary_device_add of %s failed: %pe\n",
47+
name, ERR_PTR(err));
48+
goto err_out_uninit;
49+
}
50+
51+
return padev;
52+
53+
err_out_uninit:
54+
auxiliary_device_uninit(aux_dev);
55+
err_out:
56+
kfree(padev);
57+
return ERR_PTR(err);
58+
}
59+
60+
int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf)
61+
{
62+
struct pds_auxiliary_dev *padev;
63+
int err = 0;
64+
65+
mutex_lock(&pf->config_lock);
66+
67+
padev = pf->vfs[cf->vf_id].padev;
68+
if (padev) {
69+
auxiliary_device_delete(&padev->aux_dev);
70+
auxiliary_device_uninit(&padev->aux_dev);
71+
}
72+
pf->vfs[cf->vf_id].padev = NULL;
73+
74+
mutex_unlock(&pf->config_lock);
75+
return err;
76+
}
77+
78+
int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
79+
{
80+
struct pds_auxiliary_dev *padev;
81+
enum pds_core_vif_types vt;
82+
u16 vt_support;
83+
int err = 0;
84+
85+
mutex_lock(&pf->config_lock);
86+
87+
/* We only support vDPA so far, so it is the only one to
88+
* be verified that it is available in the Core device and
89+
* enabled in the devlink param. In the future this might
90+
* become a loop for several VIF types.
91+
*/
92+
93+
/* Verify that the type is supported and enabled. It is not
94+
* an error if there is no auxbus device support for this
95+
* VF, it just means something else needs to happen with it.
96+
*/
97+
vt = PDS_DEV_TYPE_VDPA;
98+
vt_support = !!le16_to_cpu(pf->dev_ident.vif_types[vt]);
99+
if (!(vt_support &&
100+
pf->viftype_status[vt].supported &&
101+
pf->viftype_status[vt].enabled))
102+
goto out_unlock;
103+
104+
padev = pdsc_auxbus_dev_register(cf, pf,
105+
pf->viftype_status[vt].name);
106+
if (IS_ERR(padev)) {
107+
err = PTR_ERR(padev);
108+
goto out_unlock;
109+
}
110+
pf->vfs[cf->vf_id].padev = padev;
111+
112+
out_unlock:
113+
mutex_unlock(&pf->config_lock);
114+
return err;
115+
}

drivers/net/ethernet/amd/pds_core/core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ struct pdsc_dev_bar {
3030
int res_index;
3131
};
3232

33+
struct pdsc;
34+
3335
struct pdsc_vf {
3436
struct pds_auxiliary_dev *padev;
37+
struct pdsc *vf;
3538
u16 index;
3639
__le16 vif_types[PDS_DEV_TYPE_MAX];
3740
};
@@ -287,6 +290,9 @@ int pdsc_start(struct pdsc *pdsc);
287290
void pdsc_stop(struct pdsc *pdsc);
288291
void pdsc_health_thread(struct work_struct *work);
289292

293+
int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf);
294+
int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf);
295+
290296
void pdsc_process_adminq(struct pdsc_qcq *qcq);
291297
void pdsc_work_thread(struct work_struct *work);
292298
irqreturn_t pdsc_adminq_isr(int irq, void *data);

drivers/net/ethernet/amd/pds_core/main.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ static int pdsc_sriov_configure(struct pci_dev *pdev, int num_vfs)
169169
static int pdsc_init_vf(struct pdsc *vf)
170170
{
171171
struct devlink *dl;
172+
struct pdsc *pf;
173+
int err;
174+
175+
pf = pdsc_get_pf_struct(vf->pdev);
176+
if (IS_ERR_OR_NULL(pf))
177+
return PTR_ERR(pf) ?: -1;
172178

173179
vf->vf_id = pci_iov_vf_id(vf->pdev);
174180

@@ -177,7 +183,15 @@ static int pdsc_init_vf(struct pdsc *vf)
177183
devl_register(dl);
178184
devl_unlock(dl);
179185

180-
return 0;
186+
pf->vfs[vf->vf_id].vf = vf;
187+
err = pdsc_auxbus_dev_add(vf, pf);
188+
if (err) {
189+
devl_lock(dl);
190+
devl_unregister(dl);
191+
devl_unlock(dl);
192+
}
193+
194+
return err;
181195
}
182196

183197
static const struct devlink_health_reporter_ops pdsc_fw_reporter_ops = {
@@ -365,7 +379,19 @@ static void pdsc_remove(struct pci_dev *pdev)
365379
}
366380
devl_unlock(dl);
367381

368-
if (!pdev->is_virtfn) {
382+
if (pdev->is_virtfn) {
383+
struct pdsc *pf;
384+
385+
pf = pdsc_get_pf_struct(pdsc->pdev);
386+
if (!IS_ERR(pf)) {
387+
pdsc_auxbus_dev_del(pdsc, pf);
388+
pf->vfs[pdsc->vf_id].vf = NULL;
389+
}
390+
} else {
391+
/* Remove the VFs and their aux_bus connections before other
392+
* cleanup so that the clients can use the AdminQ to cleanly
393+
* shut themselves down.
394+
*/
369395
pdsc_sriov_configure(pdev, 0);
370396

371397
del_timer_sync(&pdsc->wdtimer);
@@ -402,6 +428,12 @@ static struct pci_driver pdsc_driver = {
402428
.sriov_configure = pdsc_sriov_configure,
403429
};
404430

431+
void *pdsc_get_pf_struct(struct pci_dev *vf_pdev)
432+
{
433+
return pci_iov_get_pf_drvdata(vf_pdev, &pdsc_driver);
434+
}
435+
EXPORT_SYMBOL_GPL(pdsc_get_pf_struct);
436+
405437
static int __init pdsc_init_module(void)
406438
{
407439
if (strcmp(KBUILD_MODNAME, PDS_CORE_DRV_NAME))

include/linux/pds/pds_auxbus.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright(c) 2023 Advanced Micro Devices, Inc */
3+
4+
#ifndef _PDSC_AUXBUS_H_
5+
#define _PDSC_AUXBUS_H_
6+
7+
#include <linux/auxiliary_bus.h>
8+
9+
struct pds_auxiliary_dev {
10+
struct auxiliary_device aux_dev;
11+
struct pci_dev *vf_pdev;
12+
u16 client_id;
13+
};
14+
#endif /* _PDSC_AUXBUS_H_ */

include/linux/pds/pds_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,5 @@ enum pds_core_logical_qtype {
6060
PDS_CORE_QTYPE_MAX = 16 /* don't change - used in struct size */
6161
};
6262

63+
void *pdsc_get_pf_struct(struct pci_dev *vf_pdev);
6364
#endif /* _PDS_COMMON_H_ */

0 commit comments

Comments
 (0)