1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
7 #include <linux/pds/pds_auxbus.h>
10 * pds_client_register - Link the client to the firmware
11 * @pf: ptr to the PF driver's private data struct
12 * @devname: name that includes service into, e.g. pds_core.vDPA
14 * Return: positive client ID (ci) on success, or
17 int pds_client_register(struct pdsc
*pf
, char *devname
)
19 union pds_core_adminq_comp comp
= {};
20 union pds_core_adminq_cmd cmd
= {};
24 cmd
.client_reg
.opcode
= PDS_AQ_CMD_CLIENT_REG
;
25 strscpy(cmd
.client_reg
.devname
, devname
,
26 sizeof(cmd
.client_reg
.devname
));
28 err
= pdsc_adminq_post(pf
, &cmd
, &comp
, false);
30 dev_info(pf
->dev
, "register dev_name %s with DSC failed, status %d: %pe\n",
31 devname
, comp
.status
, ERR_PTR(err
));
35 ci
= le16_to_cpu(comp
.client_reg
.client_id
);
37 dev_err(pf
->dev
, "%s: device returned null client_id\n",
42 dev_dbg(pf
->dev
, "%s: device returned client_id %d for %s\n",
43 __func__
, ci
, devname
);
47 EXPORT_SYMBOL_GPL(pds_client_register
);
50 * pds_client_unregister - Unlink the client from the firmware
51 * @pf: ptr to the PF driver's private data struct
52 * @client_id: id returned from pds_client_register()
54 * Return: 0 on success, or
57 int pds_client_unregister(struct pdsc
*pf
, u16 client_id
)
59 union pds_core_adminq_comp comp
= {};
60 union pds_core_adminq_cmd cmd
= {};
63 cmd
.client_unreg
.opcode
= PDS_AQ_CMD_CLIENT_UNREG
;
64 cmd
.client_unreg
.client_id
= cpu_to_le16(client_id
);
66 err
= pdsc_adminq_post(pf
, &cmd
, &comp
, false);
68 dev_info(pf
->dev
, "unregister client_id %d failed, status %d: %pe\n",
69 client_id
, comp
.status
, ERR_PTR(err
));
73 EXPORT_SYMBOL_GPL(pds_client_unregister
);
76 * pds_client_adminq_cmd - Process an adminq request for the client
77 * @padev: ptr to the client device
78 * @req: ptr to buffer with request
79 * @req_len: length of actual struct used for request
80 * @resp: ptr to buffer where answer is to be copied
81 * @flags: optional flags from pds_core_adminq_flags
83 * Return: 0 on success, or
86 * Client sends pointers to request and response buffers
87 * Core copies request data into pds_core_client_request_cmd
88 * Core sets other fields as needed
89 * Core posts to AdminQ
90 * Core copies completion data into response buffer
92 int pds_client_adminq_cmd(struct pds_auxiliary_dev
*padev
,
93 union pds_core_adminq_cmd
*req
,
95 union pds_core_adminq_comp
*resp
,
98 union pds_core_adminq_cmd cmd
= {};
99 struct pci_dev
*pf_pdev
;
104 pf_pdev
= pci_physfn(padev
->vf_pdev
);
105 pf
= pci_get_drvdata(pf_pdev
);
107 dev_dbg(pf
->dev
, "%s: %s opcode %d\n",
108 __func__
, dev_name(&padev
->aux_dev
.dev
), req
->opcode
);
113 /* Wrap the client's request */
114 cmd
.client_request
.opcode
= PDS_AQ_CMD_CLIENT_CMD
;
115 cmd
.client_request
.client_id
= cpu_to_le16(padev
->client_id
);
116 cp_len
= min_t(size_t, req_len
, sizeof(cmd
.client_request
.client_cmd
));
117 memcpy(cmd
.client_request
.client_cmd
, req
, cp_len
);
119 err
= pdsc_adminq_post(pf
, &cmd
, resp
,
120 !!(flags
& PDS_AQ_FLAG_FASTPOLL
));
121 if (err
&& err
!= -EAGAIN
)
122 dev_info(pf
->dev
, "client admin cmd failed: %pe\n",
127 EXPORT_SYMBOL_GPL(pds_client_adminq_cmd
);
129 static void pdsc_auxbus_dev_release(struct device
*dev
)
131 struct pds_auxiliary_dev
*padev
=
132 container_of(dev
, struct pds_auxiliary_dev
, aux_dev
.dev
);
137 static struct pds_auxiliary_dev
*pdsc_auxbus_dev_register(struct pdsc
*cf
,
142 struct auxiliary_device
*aux_dev
;
143 struct pds_auxiliary_dev
*padev
;
146 padev
= kzalloc(sizeof(*padev
), GFP_KERNEL
);
148 return ERR_PTR(-ENOMEM
);
150 padev
->vf_pdev
= cf
->pdev
;
151 padev
->client_id
= client_id
;
153 aux_dev
= &padev
->aux_dev
;
154 aux_dev
->name
= name
;
155 aux_dev
->id
= cf
->uid
;
156 aux_dev
->dev
.parent
= cf
->dev
;
157 aux_dev
->dev
.release
= pdsc_auxbus_dev_release
;
159 err
= auxiliary_device_init(aux_dev
);
161 dev_warn(cf
->dev
, "auxiliary_device_init of %s failed: %pe\n",
167 err
= auxiliary_device_add(aux_dev
);
169 dev_warn(cf
->dev
, "auxiliary_device_add of %s failed: %pe\n",
171 auxiliary_device_uninit(aux_dev
);
178 int pdsc_auxbus_dev_del(struct pdsc
*cf
, struct pdsc
*pf
)
180 struct pds_auxiliary_dev
*padev
;
186 mutex_lock(&pf
->config_lock
);
188 padev
= pf
->vfs
[cf
->vf_id
].padev
;
190 pds_client_unregister(pf
, padev
->client_id
);
191 auxiliary_device_delete(&padev
->aux_dev
);
192 auxiliary_device_uninit(&padev
->aux_dev
);
193 padev
->client_id
= 0;
195 pf
->vfs
[cf
->vf_id
].padev
= NULL
;
197 mutex_unlock(&pf
->config_lock
);
201 int pdsc_auxbus_dev_add(struct pdsc
*cf
, struct pdsc
*pf
)
203 struct pds_auxiliary_dev
*padev
;
204 char devname
[PDS_DEVNAME_LEN
];
205 enum pds_core_vif_types vt
;
214 mutex_lock(&pf
->config_lock
);
216 mask
= BIT_ULL(PDSC_S_FW_DEAD
) |
217 BIT_ULL(PDSC_S_STOPPING_DRIVER
);
218 if (cf
->state
& mask
) {
219 dev_err(pf
->dev
, "%s: can't add dev, VF client in bad state %#lx\n",
220 __func__
, cf
->state
);
225 /* We only support vDPA so far, so it is the only one to
226 * be verified that it is available in the Core device and
227 * enabled in the devlink param. In the future this might
228 * become a loop for several VIF types.
231 /* Verify that the type is supported and enabled. It is not
232 * an error if there is no auxbus device support for this
233 * VF, it just means something else needs to happen with it.
235 vt
= PDS_DEV_TYPE_VDPA
;
236 vt_support
= !!le16_to_cpu(pf
->dev_ident
.vif_types
[vt
]);
238 pf
->viftype_status
[vt
].supported
&&
239 pf
->viftype_status
[vt
].enabled
))
242 /* Need to register with FW and get the client_id before
243 * creating the aux device so that the aux client can run
244 * adminq commands as part its probe
246 snprintf(devname
, sizeof(devname
), "%s.%s.%d",
247 PDS_CORE_DRV_NAME
, pf
->viftype_status
[vt
].name
, cf
->uid
);
248 client_id
= pds_client_register(pf
, devname
);
254 padev
= pdsc_auxbus_dev_register(cf
, pf
, client_id
,
255 pf
->viftype_status
[vt
].name
);
257 pds_client_unregister(pf
, client_id
);
258 err
= PTR_ERR(padev
);
261 pf
->vfs
[cf
->vf_id
].padev
= padev
;
264 mutex_unlock(&pf
->config_lock
);