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 **/ 15 static 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 36 static 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 **/ 54 int 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 **/ 71 int 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 **/ 90 int 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 **/ 131 int 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 **/ 164 int 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