FILE
wx_mbx.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/wangxun/libwx/wx_mbx.c
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */ 3 4#include <linux/pci.h> 5#include "wx_type.h" 6#include "wx_mbx.h" 7 8/** 9 * wx_obtain_mbx_lock_pf - obtain mailbox lock 10 * @wx: pointer to the HW structure 11 * @vf: the VF index 12 * 13 * Return: return 0 on success and -EBUSY on failure 14 **/ 15static int wx_obtain_mbx_lock_pf(struct wx *wx, u16 vf) 16{ 17 int count = 5; 18 u32 mailbox; 19 20 while (count--) { 21 /* Take ownership of the buffer */ 22 wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_PFU); 23 24 /* reserve mailbox for vf use */ 25 mailbox = rd32(wx, WX_PXMAILBOX(vf)); 26 if (mailbox & WX_PXMAILBOX_PFU) 27 return 0; 28 else if (count) 29 udelay(10); 30 } 31 wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf); 32 33 return -EBUSY; 34} 35 36static int wx_check_for_bit_pf(struct wx *wx, u32 mask, int index) 37{ 38 u32 mbvficr = rd32(wx, WX_MBVFICR(index)); 39 40 if (!(mbvficr & mask)) 41 return -EBUSY; 42 wr32(wx, WX_MBVFICR(index), mask); 43 44 return 0; 45} 46 47/** 48 * wx_check_for_ack_pf - checks to see if the VF has acked 49 * @wx: pointer to the HW structure 50 * @vf: the VF index 51 * 52 * Return: return 0 if the VF has set the status bit or else -EBUSY 53 **/ 54int wx_check_for_ack_pf(struct wx *wx, u16 vf) 55{ 56 u32 index = vf / 16, vf_bit = vf % 16; 57 58 return wx_check_for_bit_pf(wx, 59 FIELD_PREP(WX_MBVFICR_VFACK_MASK, 60 BIT(vf_bit)), 61 index); 62} 63 64/** 65 * wx_check_for_msg_pf - checks to see if the VF has sent mail 66 * @wx: pointer to the HW structure 67 * @vf: the VF index 68 * 69 * Return: return 0 if the VF has got req bit or else -EBUSY 70 **/ 71int wx_check_for_msg_pf(struct wx *wx, u16 vf) 72{ 73 u32 index = vf / 16, vf_bit = vf % 16; 74 75 return wx_check_for_bit_pf(wx, 76 FIELD_PREP(WX_MBVFICR_VFREQ_MASK, 77 BIT(vf_bit)), 78 index); 79} 80 81/** 82 * wx_write_mbx_pf - Places a message in the mailbox 83 * @wx: pointer to the HW structure 84 * @msg: The message buffer 85 * @size: Length of buffer 86 * @vf: the VF index 87 * 88 * Return: return 0 on success and -EINVAL/-EBUSY on failure 89 **/ 90int wx_write_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf) 91{ 92 struct wx_mbx_info *mbx = &wx->mbx; 93 int ret, i; 94 95 /* mbx->size is up to 15 */ 96 if (size > mbx->size) { 97 wx_err(wx, "Invalid mailbox message size %d", size); 98 return -EINVAL; 99 } 100 101 /* lock the mailbox to prevent pf/vf race condition */ 102 ret = wx_obtain_mbx_lock_pf(wx, vf); 103 if (ret) 104 return ret; 105 106 /* flush msg and acks as we are overwriting the message buffer */ 107 wx_check_for_msg_pf(wx, vf); 108 wx_check_for_ack_pf(wx, vf); 109 110 /* copy the caller specified message to the mailbox memory buffer */ 111 for (i = 0; i < size; i++) 112 wr32a(wx, WX_PXMBMEM(vf), i, msg[i]); 113 114 /* Interrupt VF to tell it a message has been sent and release buffer */ 115 /* set mirrored mailbox flags */ 116 wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_STS); 117 wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_STS); 118 119 return 0; 120} 121 122/** 123 * wx_read_mbx_pf - Read a message from the mailbox 124 * @wx: pointer to the HW structure 125 * @msg: The message buffer 126 * @size: Length of buffer 127 * @vf: the VF index 128 * 129 * Return: return 0 on success and -EBUSY on failure 130 **/ 131int wx_read_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf) 132{ 133 struct wx_mbx_info *mbx = &wx->mbx; 134 int ret; 135 u16 i; 136 137 /* limit read to size of mailbox and mbx->size is up to 15 */ 138 if (size > mbx->size) 139 size = mbx->size; 140 141 /* lock the mailbox to prevent pf/vf race condition */ 142 ret = wx_obtain_mbx_lock_pf(wx, vf); 143 if (ret) 144 return ret; 145 146 for (i = 0; i < size; i++) 147 msg[i] = rd32a(wx, WX_PXMBMEM(vf), i); 148 149 /* Acknowledge the message and release buffer */ 150 /* set mirrored mailbox flags */ 151 wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_ACK); 152 wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_ACK); 153 154 return 0; 155} 156 157/** 158 * wx_check_for_rst_pf - checks to see if the VF has reset 159 * @wx: pointer to the HW structure 160 * @vf: the VF index 161 * 162 * Return: return 0 on success and -EBUSY on failure 163 **/ 164int wx_check_for_rst_pf(struct wx *wx, u16 vf) 165{ 166 u32 reg_offset = WX_VF_REG_OFFSET(vf); 167 u32 vf_shift = WX_VF_IND_SHIFT(vf); 168 u32 vflre = 0; 169 170 vflre = rd32(wx, WX_VFLRE(reg_offset)); 171 if (!(vflre & BIT(vf_shift))) 172 return -EBUSY; 173 wr32(wx, WX_VFLREC(reg_offset), BIT(vf_shift)); 174 175 return 0; 176} 177 178static u32 wx_read_v2p_mailbox(struct wx *wx) 179{ 180 u32 mailbox = rd32(wx, WX_VXMAILBOX); 181 182 mailbox |= wx->mbx.mailbox; 183 wx->mbx.mailbox |= mailbox & WX_VXMAILBOX_R2C_BITS; 184 185 return mailbox; 186} 187 188static u32 wx_mailbox_get_lock_vf(struct wx *wx) 189{ 190 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_VFU); 191 return wx_read_v2p_mailbox(wx); 192} 193 194/** 195 * wx_obtain_mbx_lock_vf - obtain mailbox lock 196 * @wx: pointer to the HW structure 197 * 198 * Return: return 0 on success and -EBUSY on failure 199 **/ 200static int wx_obtain_mbx_lock_vf(struct wx *wx) 201{ 202 int count = 5, ret; 203 u32 mailbox; 204 205 ret = readx_poll_timeout_atomic(wx_mailbox_get_lock_vf, wx, mailbox, 206 (mailbox & WX_VXMAILBOX_VFU), 207 1, count); 208 if (ret) 209 wx_err(wx, "Failed to obtain mailbox lock for VF.\n"); 210 211 return ret; 212} 213 214static int wx_check_for_bit_vf(struct wx *wx, u32 mask) 215{ 216 u32 mailbox = wx_read_v2p_mailbox(wx); 217 218 wx->mbx.mailbox &= ~mask; 219 220 return (mailbox & mask ? 0 : -EBUSY); 221} 222 223/** 224 * wx_check_for_ack_vf - checks to see if the PF has ACK'd 225 * @wx: pointer to the HW structure 226 * 227 * Return: return 0 if the PF has set the status bit or else -EBUSY 228 **/ 229static int wx_check_for_ack_vf(struct wx *wx) 230{ 231 /* read clear the pf ack bit */ 232 return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFACK); 233} 234 235/** 236 * wx_check_for_msg_vf - checks to see if the PF has sent mail 237 * @wx: pointer to the HW structure 238 * 239 * Return: return 0 if the PF has got req bit or else -EBUSY 240 **/ 241int wx_check_for_msg_vf(struct wx *wx) 242{ 243 /* read clear the pf sts bit */ 244 return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFSTS); 245} 246 247/** 248 * wx_check_for_rst_vf - checks to see if the PF has reset 249 * @wx: pointer to the HW structure 250 * 251 * Return: return 0 if the PF has set the reset done and -EBUSY on failure 252 **/ 253int wx_check_for_rst_vf(struct wx *wx) 254{ 255 /* read clear the pf reset done bit */ 256 return wx_check_for_bit_vf(wx, 257 WX_VXMAILBOX_RSTD | 258 WX_VXMAILBOX_RSTI); 259} 260 261/** 262 * wx_poll_for_msg - Wait for message notification 263 * @wx: pointer to the HW structure 264 * 265 * Return: return 0 if the VF has successfully received a message notification 266 **/ 267static int wx_poll_for_msg(struct wx *wx) 268{ 269 struct wx_mbx_info *mbx = &wx->mbx; 270 u32 val; 271 272 return readx_poll_timeout_atomic(wx_check_for_msg_vf, wx, val, 273 (val == 0), mbx->udelay, mbx->timeout); 274} 275 276/** 277 * wx_poll_for_ack - Wait for message acknowledgment 278 * @wx: pointer to the HW structure 279 * 280 * Return: return 0 if the VF has successfully received a message ack 281 **/ 282static int wx_poll_for_ack(struct wx *wx) 283{ 284 struct wx_mbx_info *mbx = &wx->mbx; 285 u32 val; 286 287 return readx_poll_timeout_atomic(wx_check_for_ack_vf, wx, val, 288 (val == 0), mbx->udelay, mbx->timeout); 289} 290 291/** 292 * wx_read_posted_mbx - Wait for message notification and receive message 293 * @wx: pointer to the HW structure 294 * @msg: The message buffer 295 * @size: Length of buffer 296 * 297 * Return: returns 0 if it successfully received a message notification and 298 * copied it into the receive buffer. 299 **/ 300int wx_read_posted_mbx(struct wx *wx, u32 *msg, u16 size) 301{ 302 int ret; 303 304 ret = wx_poll_for_msg(wx); 305 /* if ack received read message, otherwise we timed out */ 306 if (ret) 307 return ret; 308 309 return wx_read_mbx_vf(wx, msg, size); 310} 311 312/** 313 * wx_write_posted_mbx - Write a message to the mailbox, wait for ack 314 * @wx: pointer to the HW structure 315 * @msg: The message buffer 316 * @size: Length of buffer 317 * 318 * Return: returns 0 if it successfully copied message into the buffer and 319 * received an ack to that message within delay * timeout period 320 **/ 321int wx_write_posted_mbx(struct wx *wx, u32 *msg, u16 size) 322{ 323 int ret; 324 325 /* send msg */ 326 ret = wx_write_mbx_vf(wx, msg, size); 327 /* if msg sent wait until we receive an ack */ 328 if (ret) 329 return ret; 330 331 return wx_poll_for_ack(wx); 332} 333 334/** 335 * wx_write_mbx_vf - Write a message to the mailbox 336 * @wx: pointer to the HW structure 337 * @msg: The message buffer 338 * @size: Length of buffer 339 * 340 * Return: returns 0 if it successfully copied message into the buffer 341 **/ 342int wx_write_mbx_vf(struct wx *wx, u32 *msg, u16 size) 343{ 344 struct wx_mbx_info *mbx = &wx->mbx; 345 int ret, i; 346 347 /* mbx->size is up to 15 */ 348 if (size > mbx->size) { 349 wx_err(wx, "Invalid mailbox message size %d", size); 350 return -EINVAL; 351 } 352 353 /* lock the mailbox to prevent pf/vf race condition */ 354 ret = wx_obtain_mbx_lock_vf(wx); 355 if (ret) 356 return ret; 357 358 /* flush msg and acks as we are overwriting the message buffer */ 359 wx_check_for_msg_vf(wx); 360 wx_check_for_ack_vf(wx); 361 362 /* copy the caller specified message to the mailbox memory buffer */ 363 for (i = 0; i < size; i++) 364 wr32a(wx, WX_VXMBMEM, i, msg[i]); 365 366 /* Drop VFU and interrupt the PF to tell it a message has been sent */ 367 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_REQ); 368 369 return 0; 370} 371 372/** 373 * wx_read_mbx_vf - Reads a message from the inbox intended for vf 374 * @wx: pointer to the HW structure 375 * @msg: The message buffer 376 * @size: Length of buffer 377 * 378 * Return: returns 0 if it successfully copied message into the buffer 379 **/ 380int wx_read_mbx_vf(struct wx *wx, u32 *msg, u16 size) 381{ 382 struct wx_mbx_info *mbx = &wx->mbx; 383 int ret, i; 384 385 /* limit read to size of mailbox and mbx->size is up to 15 */ 386 if (size > mbx->size) 387 size = mbx->size; 388 389 /* lock the mailbox to prevent pf/vf race condition */ 390 ret = wx_obtain_mbx_lock_vf(wx); 391 if (ret) 392 return ret; 393 394 /* copy the message from the mailbox memory buffer */ 395 for (i = 0; i < size; i++) 396 msg[i] = rd32a(wx, WX_VXMBMEM, i); 397 398 /* Acknowledge receipt and release mailbox, then we're done */ 399 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_ACK); 400 401 return 0; 402} 403 404int wx_init_mbx_params_vf(struct wx *wx) 405{ 406 wx->vfinfo = kzalloc(sizeof(struct vf_data_storage), 407 GFP_KERNEL); 408 if (!wx->vfinfo) 409 return -ENOMEM; 410 411 /* Initialize mailbox parameters */ 412 wx->mbx.size = WX_VXMAILBOX_SIZE; 413 wx->mbx.mailbox = WX_VXMAILBOX; 414 wx->mbx.udelay = 10; 415 wx->mbx.timeout = 1000; 416 417 return 0; 418} 419EXPORT_SYMBOL(wx_init_mbx_params_vf);
~/
Read-only file preview.