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+
9139static 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
17147static 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 }
0 commit comments