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 =
@@ -16,6 +146,7 @@ static void pdsc_auxbus_dev_release(struct device *dev)
16
146
17
147
static struct pds_auxiliary_dev * pdsc_auxbus_dev_register (struct pdsc * cf ,
18
148
struct pdsc * pf ,
149
+ u16 client_id ,
19
150
char * name )
20
151
{
21
152
struct auxiliary_device * aux_dev ;
@@ -27,6 +158,7 @@ static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf,
27
158
return ERR_PTR (- ENOMEM );
28
159
29
160
padev -> vf_pdev = cf -> pdev ;
161
+ padev -> client_id = client_id ;
30
162
31
163
aux_dev = & padev -> aux_dev ;
32
164
aux_dev -> name = name ;
@@ -66,8 +198,10 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf)
66
198
67
199
padev = pf -> vfs [cf -> vf_id ].padev ;
68
200
if (padev ) {
201
+ pds_client_unregister (pf -> pdev , padev -> client_id );
69
202
auxiliary_device_delete (& padev -> aux_dev );
70
203
auxiliary_device_uninit (& padev -> aux_dev );
204
+ padev -> client_id = 0 ;
71
205
}
72
206
pf -> vfs [cf -> vf_id ].padev = NULL ;
73
207
@@ -79,7 +213,9 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
79
213
{
80
214
struct pds_auxiliary_dev * padev ;
81
215
enum pds_core_vif_types vt ;
216
+ char devname [PDS_DEVNAME_LEN ];
82
217
u16 vt_support ;
218
+ int client_id ;
83
219
int err = 0 ;
84
220
85
221
mutex_lock (& pf -> config_lock );
@@ -101,9 +237,22 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
101
237
pf -> viftype_status [vt ].enabled ))
102
238
goto out_unlock ;
103
239
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 ,
105
253
pf -> viftype_status [vt ].name );
106
254
if (IS_ERR (padev )) {
255
+ pds_client_unregister (pf -> pdev , client_id );
107
256
err = PTR_ERR (padev );
108
257
goto out_unlock ;
109
258
}
0 commit comments