Skip to content

Commit 1065903

Browse files
emuslndavem330
authored andcommitted
pds_core: add the aux client API
Add the client API operations for running adminq commands. The core registers the client with the FW, then the client has a context for requesting adminq services. We expect to add additional operations for other clients, including requesting additional private adminqs and IRQs, but don't have the need yet. Signed-off-by: Shannon Nelson <[email protected]> Acked-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 40ced89 commit 1065903

File tree

3 files changed

+158
-1
lines changed

3 files changed

+158
-1
lines changed

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

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,136 @@
66
#include "core.h"
77
#include <linux/pds/pds_auxbus.h>
88

9+
/**
10+
* pds_client_register - Link the client to the firmware
11+
* @pf_pdev: ptr to the PF driver struct
12+
* @devname: name that includes service into, e.g. pds_core.vDPA
13+
*
14+
* Return: 0 on success, or
15+
* negative for error
16+
*/
17+
int pds_client_register(struct pci_dev *pf_pdev, char *devname)
18+
{
19+
union pds_core_adminq_comp comp = {};
20+
union pds_core_adminq_cmd cmd = {};
21+
struct pdsc *pf;
22+
int err;
23+
u16 ci;
24+
25+
pf = pci_get_drvdata(pf_pdev);
26+
if (pf->state)
27+
return -ENXIO;
28+
29+
cmd.client_reg.opcode = PDS_AQ_CMD_CLIENT_REG;
30+
strscpy(cmd.client_reg.devname, devname,
31+
sizeof(cmd.client_reg.devname));
32+
33+
err = pdsc_adminq_post(pf, &cmd, &comp, false);
34+
if (err) {
35+
dev_info(pf->dev, "register dev_name %s with DSC failed, status %d: %pe\n",
36+
devname, comp.status, ERR_PTR(err));
37+
return err;
38+
}
39+
40+
ci = le16_to_cpu(comp.client_reg.client_id);
41+
if (!ci) {
42+
dev_err(pf->dev, "%s: device returned null client_id\n",
43+
__func__);
44+
return -EIO;
45+
}
46+
47+
dev_dbg(pf->dev, "%s: device returned client_id %d for %s\n",
48+
__func__, ci, devname);
49+
50+
return ci;
51+
}
52+
EXPORT_SYMBOL_GPL(pds_client_register);
53+
54+
/**
55+
* pds_client_unregister - Unlink the client from the firmware
56+
* @pf_pdev: ptr to the PF driver struct
57+
* @client_id: id returned from pds_client_register()
58+
*
59+
* Return: 0 on success, or
60+
* negative for error
61+
*/
62+
int pds_client_unregister(struct pci_dev *pf_pdev, u16 client_id)
63+
{
64+
union pds_core_adminq_comp comp = {};
65+
union pds_core_adminq_cmd cmd = {};
66+
struct pdsc *pf;
67+
int err;
68+
69+
pf = pci_get_drvdata(pf_pdev);
70+
if (pf->state)
71+
return -ENXIO;
72+
73+
cmd.client_unreg.opcode = PDS_AQ_CMD_CLIENT_UNREG;
74+
cmd.client_unreg.client_id = cpu_to_le16(client_id);
75+
76+
err = pdsc_adminq_post(pf, &cmd, &comp, false);
77+
if (err)
78+
dev_info(pf->dev, "unregister client_id %d failed, status %d: %pe\n",
79+
client_id, comp.status, ERR_PTR(err));
80+
81+
return err;
82+
}
83+
EXPORT_SYMBOL_GPL(pds_client_unregister);
84+
85+
/**
86+
* pds_client_adminq_cmd - Process an adminq request for the client
87+
* @padev: ptr to the client device
88+
* @req: ptr to buffer with request
89+
* @req_len: length of actual struct used for request
90+
* @resp: ptr to buffer where answer is to be copied
91+
* @flags: optional flags from pds_core_adminq_flags
92+
*
93+
* Return: 0 on success, or
94+
* negative for error
95+
*
96+
* Client sends pointers to request and response buffers
97+
* Core copies request data into pds_core_client_request_cmd
98+
* Core sets other fields as needed
99+
* Core posts to AdminQ
100+
* Core copies completion data into response buffer
101+
*/
102+
int pds_client_adminq_cmd(struct pds_auxiliary_dev *padev,
103+
union pds_core_adminq_cmd *req,
104+
size_t req_len,
105+
union pds_core_adminq_comp *resp,
106+
u64 flags)
107+
{
108+
union pds_core_adminq_cmd cmd = {};
109+
struct pci_dev *pf_pdev;
110+
struct pdsc *pf;
111+
size_t cp_len;
112+
int err;
113+
114+
pf_pdev = pci_physfn(padev->vf_pdev);
115+
pf = pci_get_drvdata(pf_pdev);
116+
117+
dev_dbg(pf->dev, "%s: %s opcode %d\n",
118+
__func__, dev_name(&padev->aux_dev.dev), req->opcode);
119+
120+
if (pf->state)
121+
return -ENXIO;
122+
123+
/* Wrap the client's request */
124+
cmd.client_request.opcode = PDS_AQ_CMD_CLIENT_CMD;
125+
cmd.client_request.client_id = cpu_to_le16(padev->client_id);
126+
cp_len = min_t(size_t, req_len, sizeof(cmd.client_request.client_cmd));
127+
memcpy(cmd.client_request.client_cmd, req, cp_len);
128+
129+
err = pdsc_adminq_post(pf, &cmd, resp,
130+
!!(flags & PDS_AQ_FLAG_FASTPOLL));
131+
if (err && err != -EAGAIN)
132+
dev_info(pf->dev, "client admin cmd failed: %pe\n",
133+
ERR_PTR(err));
134+
135+
return err;
136+
}
137+
EXPORT_SYMBOL_GPL(pds_client_adminq_cmd);
138+
9139
static void pdsc_auxbus_dev_release(struct device *dev)
10140
{
11141
struct pds_auxiliary_dev *padev =
@@ -16,6 +146,7 @@ static void pdsc_auxbus_dev_release(struct device *dev)
16146

17147
static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf,
18148
struct pdsc *pf,
149+
u16 client_id,
19150
char *name)
20151
{
21152
struct auxiliary_device *aux_dev;
@@ -27,6 +158,7 @@ static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf,
27158
return ERR_PTR(-ENOMEM);
28159

29160
padev->vf_pdev = cf->pdev;
161+
padev->client_id = client_id;
30162

31163
aux_dev = &padev->aux_dev;
32164
aux_dev->name = name;
@@ -66,8 +198,10 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf)
66198

67199
padev = pf->vfs[cf->vf_id].padev;
68200
if (padev) {
201+
pds_client_unregister(pf->pdev, padev->client_id);
69202
auxiliary_device_delete(&padev->aux_dev);
70203
auxiliary_device_uninit(&padev->aux_dev);
204+
padev->client_id = 0;
71205
}
72206
pf->vfs[cf->vf_id].padev = NULL;
73207

@@ -79,7 +213,9 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
79213
{
80214
struct pds_auxiliary_dev *padev;
81215
enum pds_core_vif_types vt;
216+
char devname[PDS_DEVNAME_LEN];
82217
u16 vt_support;
218+
int client_id;
83219
int err = 0;
84220

85221
mutex_lock(&pf->config_lock);
@@ -101,9 +237,22 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
101237
pf->viftype_status[vt].enabled))
102238
goto out_unlock;
103239

104-
padev = pdsc_auxbus_dev_register(cf, pf,
240+
/* Need to register with FW and get the client_id before
241+
* creating the aux device so that the aux client can run
242+
* adminq commands as part its probe
243+
*/
244+
snprintf(devname, sizeof(devname), "%s.%s.%d",
245+
PDS_CORE_DRV_NAME, pf->viftype_status[vt].name, cf->uid);
246+
client_id = pds_client_register(pf->pdev, devname);
247+
if (client_id < 0) {
248+
err = client_id;
249+
goto out_unlock;
250+
}
251+
252+
padev = pdsc_auxbus_dev_register(cf, pf, client_id,
105253
pf->viftype_status[vt].name);
106254
if (IS_ERR(padev)) {
255+
pds_client_unregister(pf->pdev, client_id);
107256
err = PTR_ERR(padev);
108257
goto out_unlock;
109258
}

include/linux/pds/pds_auxbus.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ struct pds_auxiliary_dev {
1111
struct pci_dev *vf_pdev;
1212
u16 client_id;
1313
};
14+
15+
int pds_client_adminq_cmd(struct pds_auxiliary_dev *padev,
16+
union pds_core_adminq_cmd *req,
17+
size_t req_len,
18+
union pds_core_adminq_comp *resp,
19+
u64 flags);
1420
#endif /* _PDSC_AUXBUS_H_ */

include/linux/pds/pds_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ enum pds_core_logical_qtype {
6161
};
6262

6363
void *pdsc_get_pf_struct(struct pci_dev *vf_pdev);
64+
int pds_client_register(struct pci_dev *pf_pdev, char *devname);
65+
int pds_client_unregister(struct pci_dev *pf_pdev, u16 client_id);
6466
#endif /* _PDS_COMMON_H_ */

0 commit comments

Comments
 (0)