net/ngbe: support flow control
[dpdk.git] / drivers / net / ngbe / base / ngbe_mbx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include "ngbe_type.h"
7
8 #include "ngbe_mbx.h"
9
10 /**
11  *  ngbe_read_mbx - Reads a message from the mailbox
12  *  @hw: pointer to the HW structure
13  *  @msg: The message buffer
14  *  @size: Length of buffer
15  *  @mbx_id: id of mailbox to read
16  *
17  *  returns 0 if it successfully read message from buffer
18  **/
19 s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
20 {
21         struct ngbe_mbx_info *mbx = &hw->mbx;
22         s32 ret_val = NGBE_ERR_MBX;
23
24         DEBUGFUNC("ngbe_read_mbx");
25
26         /* limit read to size of mailbox */
27         if (size > mbx->size)
28                 size = mbx->size;
29
30         if (mbx->read)
31                 ret_val = mbx->read(hw, msg, size, mbx_id);
32
33         return ret_val;
34 }
35
36 /**
37  *  ngbe_write_mbx - Write a message to the mailbox
38  *  @hw: pointer to the HW structure
39  *  @msg: The message buffer
40  *  @size: Length of buffer
41  *  @mbx_id: id of mailbox to write
42  *
43  *  returns 0 if it successfully copied message into the buffer
44  **/
45 s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
46 {
47         struct ngbe_mbx_info *mbx = &hw->mbx;
48         s32 ret_val = 0;
49
50         DEBUGFUNC("ngbe_write_mbx");
51
52         if (size > mbx->size) {
53                 ret_val = NGBE_ERR_MBX;
54                 DEBUGOUT("Invalid mailbox message size %d", size);
55         } else if (mbx->write) {
56                 ret_val = mbx->write(hw, msg, size, mbx_id);
57         }
58
59         return ret_val;
60 }
61
62 /**
63  *  ngbe_check_for_msg - checks to see if someone sent us mail
64  *  @hw: pointer to the HW structure
65  *  @mbx_id: id of mailbox to check
66  *
67  *  returns 0 if the Status bit was found or else ERR_MBX
68  **/
69 s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id)
70 {
71         struct ngbe_mbx_info *mbx = &hw->mbx;
72         s32 ret_val = NGBE_ERR_MBX;
73
74         DEBUGFUNC("ngbe_check_for_msg");
75
76         if (mbx->check_for_msg)
77                 ret_val = mbx->check_for_msg(hw, mbx_id);
78
79         return ret_val;
80 }
81
82 /**
83  *  ngbe_check_for_ack - checks to see if someone sent us ACK
84  *  @hw: pointer to the HW structure
85  *  @mbx_id: id of mailbox to check
86  *
87  *  returns 0 if the Status bit was found or else ERR_MBX
88  **/
89 s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id)
90 {
91         struct ngbe_mbx_info *mbx = &hw->mbx;
92         s32 ret_val = NGBE_ERR_MBX;
93
94         DEBUGFUNC("ngbe_check_for_ack");
95
96         if (mbx->check_for_ack)
97                 ret_val = mbx->check_for_ack(hw, mbx_id);
98
99         return ret_val;
100 }
101
102 /**
103  *  ngbe_check_for_rst - checks to see if other side has reset
104  *  @hw: pointer to the HW structure
105  *  @mbx_id: id of mailbox to check
106  *
107  *  returns 0 if the Status bit was found or else ERR_MBX
108  **/
109 s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id)
110 {
111         struct ngbe_mbx_info *mbx = &hw->mbx;
112         s32 ret_val = NGBE_ERR_MBX;
113
114         DEBUGFUNC("ngbe_check_for_rst");
115
116         if (mbx->check_for_rst)
117                 ret_val = mbx->check_for_rst(hw, mbx_id);
118
119         return ret_val;
120 }
121
122 STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask)
123 {
124         u32 mbvficr = rd32(hw, NGBE_MBVFICR);
125         s32 ret_val = NGBE_ERR_MBX;
126
127         if (mbvficr & mask) {
128                 ret_val = 0;
129                 wr32(hw, NGBE_MBVFICR, mask);
130         }
131
132         return ret_val;
133 }
134
135 /**
136  *  ngbe_check_for_msg_pf - checks to see if the VF has sent mail
137  *  @hw: pointer to the HW structure
138  *  @vf_number: the VF index
139  *
140  *  returns 0 if the VF has set the Status bit or else ERR_MBX
141  **/
142 s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number)
143 {
144         s32 ret_val = NGBE_ERR_MBX;
145         u32 vf_bit = vf_number;
146
147         DEBUGFUNC("ngbe_check_for_msg_pf");
148
149         if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) {
150                 ret_val = 0;
151                 hw->mbx.stats.reqs++;
152         }
153
154         return ret_val;
155 }
156
157 /**
158  *  ngbe_check_for_ack_pf - checks to see if the VF has ACKed
159  *  @hw: pointer to the HW structure
160  *  @vf_number: the VF index
161  *
162  *  returns 0 if the VF has set the Status bit or else ERR_MBX
163  **/
164 s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number)
165 {
166         s32 ret_val = NGBE_ERR_MBX;
167         u32 vf_bit = vf_number;
168
169         DEBUGFUNC("ngbe_check_for_ack_pf");
170
171         if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) {
172                 ret_val = 0;
173                 hw->mbx.stats.acks++;
174         }
175
176         return ret_val;
177 }
178
179 /**
180  *  ngbe_check_for_rst_pf - checks to see if the VF has reset
181  *  @hw: pointer to the HW structure
182  *  @vf_number: the VF index
183  *
184  *  returns 0 if the VF has set the Status bit or else ERR_MBX
185  **/
186 s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number)
187 {
188         u32 vflre = 0;
189         s32 ret_val = NGBE_ERR_MBX;
190
191         DEBUGFUNC("ngbe_check_for_rst_pf");
192
193         vflre = rd32(hw, NGBE_FLRVFE);
194         if (vflre & (1 << vf_number)) {
195                 ret_val = 0;
196                 wr32(hw, NGBE_FLRVFEC, (1 << vf_number));
197                 hw->mbx.stats.rsts++;
198         }
199
200         return ret_val;
201 }
202
203 /**
204  *  ngbe_obtain_mbx_lock_pf - obtain mailbox lock
205  *  @hw: pointer to the HW structure
206  *  @vf_number: the VF index
207  *
208  *  return 0 if we obtained the mailbox lock
209  **/
210 STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number)
211 {
212         s32 ret_val = NGBE_ERR_MBX;
213         u32 p2v_mailbox;
214
215         DEBUGFUNC("ngbe_obtain_mbx_lock_pf");
216
217         /* Take ownership of the buffer */
218         wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU);
219
220         /* reserve mailbox for vf use */
221         p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number));
222         if (p2v_mailbox & NGBE_MBCTL_PFU)
223                 ret_val = 0;
224         else
225                 DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number);
226
227
228         return ret_val;
229 }
230
231 /**
232  *  ngbe_write_mbx_pf - Places a message in the mailbox
233  *  @hw: pointer to the HW structure
234  *  @msg: The message buffer
235  *  @size: Length of buffer
236  *  @vf_number: the VF index
237  *
238  *  returns 0 if it successfully copied message into the buffer
239  **/
240 s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
241 {
242         s32 ret_val;
243         u16 i;
244
245         DEBUGFUNC("ngbe_write_mbx_pf");
246
247         /* lock the mailbox to prevent pf/vf race condition */
248         ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
249         if (ret_val)
250                 goto out_no_write;
251
252         /* flush msg and acks as we are overwriting the message buffer */
253         ngbe_check_for_msg_pf(hw, vf_number);
254         ngbe_check_for_ack_pf(hw, vf_number);
255
256         /* copy the caller specified message to the mailbox memory buffer */
257         for (i = 0; i < size; i++)
258                 wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]);
259
260         /* Interrupt VF to tell it a message has been sent and release buffer*/
261         wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS);
262
263         /* update stats */
264         hw->mbx.stats.msgs_tx++;
265
266 out_no_write:
267         return ret_val;
268 }
269
270 /**
271  *  ngbe_read_mbx_pf - Read a message from the mailbox
272  *  @hw: pointer to the HW structure
273  *  @msg: The message buffer
274  *  @size: Length of buffer
275  *  @vf_number: the VF index
276  *
277  *  This function copies a message from the mailbox buffer to the caller's
278  *  memory buffer.  The presumption is that the caller knows that there was
279  *  a message due to a VF request so no polling for message is needed.
280  **/
281 s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
282 {
283         s32 ret_val;
284         u16 i;
285
286         DEBUGFUNC("ngbe_read_mbx_pf");
287
288         /* lock the mailbox to prevent pf/vf race condition */
289         ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
290         if (ret_val)
291                 goto out_no_read;
292
293         /* copy the message to the mailbox memory buffer */
294         for (i = 0; i < size; i++)
295                 msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i);
296
297         /* Acknowledge the message and release buffer */
298         wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK);
299
300         /* update stats */
301         hw->mbx.stats.msgs_rx++;
302
303 out_no_read:
304         return ret_val;
305 }
306
307 /**
308  *  ngbe_init_mbx_params_pf - set initial values for pf mailbox
309  *  @hw: pointer to the HW structure
310  *
311  *  Initializes the hw->mbx struct to correct values for pf mailbox
312  */
313 void ngbe_init_mbx_params_pf(struct ngbe_hw *hw)
314 {
315         struct ngbe_mbx_info *mbx = &hw->mbx;
316
317         mbx->timeout = 0;
318         mbx->usec_delay = 0;
319
320         mbx->size = NGBE_P2VMBX_SIZE;
321
322         mbx->stats.msgs_tx = 0;
323         mbx->stats.msgs_rx = 0;
324         mbx->stats.reqs = 0;
325         mbx->stats.acks = 0;
326         mbx->stats.rsts = 0;
327 }