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

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 <shannon.nelson@amd.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Shannon Nelson and committed by
David S. Miller
10659034 40ced894

+158 -1
+150 -1
drivers/net/ethernet/amd/pds_core/auxbus.c
··· 6 6 #include "core.h" 7 7 #include <linux/pds/pds_auxbus.h> 8 8 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 + 9 139 static void pdsc_auxbus_dev_release(struct device *dev) 10 140 { 11 141 struct pds_auxiliary_dev *padev = ··· 146 16 147 17 static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf, 148 18 struct pdsc *pf, 19 + u16 client_id, 149 20 char *name) 150 21 { 151 22 struct auxiliary_device *aux_dev; ··· 158 27 return ERR_PTR(-ENOMEM); 159 28 160 29 padev->vf_pdev = cf->pdev; 30 + padev->client_id = client_id; 161 31 162 32 aux_dev = &padev->aux_dev; 163 33 aux_dev->name = name; ··· 198 66 199 67 padev = pf->vfs[cf->vf_id].padev; 200 68 if (padev) { 69 + pds_client_unregister(pf->pdev, padev->client_id); 201 70 auxiliary_device_delete(&padev->aux_dev); 202 71 auxiliary_device_uninit(&padev->aux_dev); 72 + padev->client_id = 0; 203 73 } 204 74 pf->vfs[cf->vf_id].padev = NULL; 205 75 ··· 213 79 { 214 80 struct pds_auxiliary_dev *padev; 215 81 enum pds_core_vif_types vt; 82 + char devname[PDS_DEVNAME_LEN]; 216 83 u16 vt_support; 84 + int client_id; 217 85 int err = 0; 218 86 219 87 mutex_lock(&pf->config_lock); ··· 237 101 pf->viftype_status[vt].enabled)) 238 102 goto out_unlock; 239 103 240 - padev = pdsc_auxbus_dev_register(cf, pf, 104 + /* Need to register with FW and get the client_id before 105 + * creating the aux device so that the aux client can run 106 + * adminq commands as part its probe 107 + */ 108 + snprintf(devname, sizeof(devname), "%s.%s.%d", 109 + PDS_CORE_DRV_NAME, pf->viftype_status[vt].name, cf->uid); 110 + client_id = pds_client_register(pf->pdev, devname); 111 + if (client_id < 0) { 112 + err = client_id; 113 + goto out_unlock; 114 + } 115 + 116 + padev = pdsc_auxbus_dev_register(cf, pf, client_id, 241 117 pf->viftype_status[vt].name); 242 118 if (IS_ERR(padev)) { 119 + pds_client_unregister(pf->pdev, client_id); 243 120 err = PTR_ERR(padev); 244 121 goto out_unlock; 245 122 }
+6
include/linux/pds/pds_auxbus.h
··· 11 11 struct pci_dev *vf_pdev; 12 12 u16 client_id; 13 13 }; 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); 14 20 #endif /* _PDSC_AUXBUS_H_ */
+2
include/linux/pds/pds_common.h
··· 61 61 }; 62 62 63 63 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); 64 66 #endif /* _PDS_COMMON_H_ */