1 /******************************************************************************* 2 3 Intel 82599 Virtual Function driver 4 Copyright(c) 1999 - 2015 Intel Corporation. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms and conditions of the GNU General Public License, 8 version 2, as published by the Free Software Foundation. 9 10 This program is distributed in the hope it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 more details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program; if not, see <http://www.gnu.org/licenses/>. 17 18 The full GNU General Public License is included in this distribution in 19 the file called "COPYING". 20 21 Contact Information: 22 e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 24 25 *******************************************************************************/ 26 27 #include "mbx.h" 28 #include "ixgbevf.h" 29 30 /** 31 * ixgbevf_poll_for_msg - Wait for message notification 32 * @hw: pointer to the HW structure 33 * 34 * returns 0 if it successfully received a message notification 35 **/ 36 static s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw) 37 { 38 struct ixgbe_mbx_info *mbx = &hw->mbx; 39 int countdown = mbx->timeout; 40 41 while (countdown && mbx->ops.check_for_msg(hw)) { 42 countdown--; 43 udelay(mbx->udelay); 44 } 45 46 /* if we failed, all future posted messages fail until reset */ 47 if (!countdown) 48 mbx->timeout = 0; 49 50 return countdown ? 0 : IXGBE_ERR_MBX; 51 } 52 53 /** 54 * ixgbevf_poll_for_ack - Wait for message acknowledgment 55 * @hw: pointer to the HW structure 56 * 57 * returns 0 if it successfully received a message acknowledgment 58 **/ 59 static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) 60 { 61 struct ixgbe_mbx_info *mbx = &hw->mbx; 62 int countdown = mbx->timeout; 63 64 while (countdown && mbx->ops.check_for_ack(hw)) { 65 countdown--; 66 udelay(mbx->udelay); 67 } 68 69 /* if we failed, all future posted messages fail until reset */ 70 if (!countdown) 71 mbx->timeout = 0; 72 73 return countdown ? 0 : IXGBE_ERR_MBX; 74 } 75 76 /** 77 * ixgbevf_read_posted_mbx - Wait for message notification and receive message 78 * @hw: pointer to the HW structure 79 * @msg: The message buffer 80 * @size: Length of buffer 81 * 82 * returns 0 if it successfully received a message notification and 83 * copied it into the receive buffer. 84 **/ 85 static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) 86 { 87 struct ixgbe_mbx_info *mbx = &hw->mbx; 88 s32 ret_val = -IXGBE_ERR_MBX; 89 90 if (!mbx->ops.read) 91 goto out; 92 93 ret_val = ixgbevf_poll_for_msg(hw); 94 95 /* if ack received read message, otherwise we timed out */ 96 if (!ret_val) 97 ret_val = mbx->ops.read(hw, msg, size); 98 out: 99 return ret_val; 100 } 101 102 /** 103 * ixgbevf_write_posted_mbx - Write a message to the mailbox, wait for ack 104 * @hw: pointer to the HW structure 105 * @msg: The message buffer 106 * @size: Length of buffer 107 * 108 * returns 0 if it successfully copied message into the buffer and 109 * received an ack to that message within delay * timeout period 110 **/ 111 static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) 112 { 113 struct ixgbe_mbx_info *mbx = &hw->mbx; 114 s32 ret_val = -IXGBE_ERR_MBX; 115 116 /* exit if either we can't write or there isn't a defined timeout */ 117 if (!mbx->ops.write || !mbx->timeout) 118 goto out; 119 120 /* send msg */ 121 ret_val = mbx->ops.write(hw, msg, size); 122 123 /* if msg sent wait until we receive an ack */ 124 if (!ret_val) 125 ret_val = ixgbevf_poll_for_ack(hw); 126 out: 127 return ret_val; 128 } 129 130 /** 131 * ixgbevf_read_v2p_mailbox - read v2p mailbox 132 * @hw: pointer to the HW structure 133 * 134 * This function is used to read the v2p mailbox without losing the read to 135 * clear status bits. 136 **/ 137 static u32 ixgbevf_read_v2p_mailbox(struct ixgbe_hw *hw) 138 { 139 u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); 140 141 v2p_mailbox |= hw->mbx.v2p_mailbox; 142 hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; 143 144 return v2p_mailbox; 145 } 146 147 /** 148 * ixgbevf_check_for_bit_vf - Determine if a status bit was set 149 * @hw: pointer to the HW structure 150 * @mask: bitmask for bits to be tested and cleared 151 * 152 * This function is used to check for the read to clear bits within 153 * the V2P mailbox. 154 **/ 155 static s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) 156 { 157 u32 v2p_mailbox = ixgbevf_read_v2p_mailbox(hw); 158 s32 ret_val = IXGBE_ERR_MBX; 159 160 if (v2p_mailbox & mask) 161 ret_val = 0; 162 163 hw->mbx.v2p_mailbox &= ~mask; 164 165 return ret_val; 166 } 167 168 /** 169 * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail 170 * @hw: pointer to the HW structure 171 * 172 * returns 0 if the PF has set the Status bit or else ERR_MBX 173 **/ 174 static s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw) 175 { 176 s32 ret_val = IXGBE_ERR_MBX; 177 178 if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { 179 ret_val = 0; 180 hw->mbx.stats.reqs++; 181 } 182 183 return ret_val; 184 } 185 186 /** 187 * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd 188 * @hw: pointer to the HW structure 189 * 190 * returns 0 if the PF has set the ACK bit or else ERR_MBX 191 **/ 192 static s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw) 193 { 194 s32 ret_val = IXGBE_ERR_MBX; 195 196 if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { 197 ret_val = 0; 198 hw->mbx.stats.acks++; 199 } 200 201 return ret_val; 202 } 203 204 /** 205 * ixgbevf_check_for_rst_vf - checks to see if the PF has reset 206 * @hw: pointer to the HW structure 207 * 208 * returns true if the PF has set the reset done bit or else false 209 **/ 210 static s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw) 211 { 212 s32 ret_val = IXGBE_ERR_MBX; 213 214 if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | 215 IXGBE_VFMAILBOX_RSTI))) { 216 ret_val = 0; 217 hw->mbx.stats.rsts++; 218 } 219 220 return ret_val; 221 } 222 223 /** 224 * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock 225 * @hw: pointer to the HW structure 226 * 227 * return 0 if we obtained the mailbox lock 228 **/ 229 static s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw) 230 { 231 s32 ret_val = IXGBE_ERR_MBX; 232 233 /* Take ownership of the buffer */ 234 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); 235 236 /* reserve mailbox for VF use */ 237 if (ixgbevf_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) 238 ret_val = 0; 239 240 return ret_val; 241 } 242 243 /** 244 * ixgbevf_write_mbx_vf - Write a message to the mailbox 245 * @hw: pointer to the HW structure 246 * @msg: The message buffer 247 * @size: Length of buffer 248 * 249 * returns 0 if it successfully copied message into the buffer 250 **/ 251 static s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) 252 { 253 s32 ret_val; 254 u16 i; 255 256 /* lock the mailbox to prevent PF/VF race condition */ 257 ret_val = ixgbevf_obtain_mbx_lock_vf(hw); 258 if (ret_val) 259 goto out_no_write; 260 261 /* flush msg and acks as we are overwriting the message buffer */ 262 ixgbevf_check_for_msg_vf(hw); 263 ixgbevf_check_for_ack_vf(hw); 264 265 /* copy the caller specified message to the mailbox memory buffer */ 266 for (i = 0; i < size; i++) 267 IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); 268 269 /* update stats */ 270 hw->mbx.stats.msgs_tx++; 271 272 /* Drop VFU and interrupt the PF to tell it a message has been sent */ 273 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); 274 275 out_no_write: 276 return ret_val; 277 } 278 279 /** 280 * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for VF 281 * @hw: pointer to the HW structure 282 * @msg: The message buffer 283 * @size: Length of buffer 284 * 285 * returns 0 if it successfully read message from buffer 286 **/ 287 static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) 288 { 289 s32 ret_val = 0; 290 u16 i; 291 292 /* lock the mailbox to prevent PF/VF race condition */ 293 ret_val = ixgbevf_obtain_mbx_lock_vf(hw); 294 if (ret_val) 295 goto out_no_read; 296 297 /* copy the message from the mailbox memory buffer */ 298 for (i = 0; i < size; i++) 299 msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); 300 301 /* Acknowledge receipt and release mailbox, then we're done */ 302 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); 303 304 /* update stats */ 305 hw->mbx.stats.msgs_rx++; 306 307 out_no_read: 308 return ret_val; 309 } 310 311 /** 312 * ixgbevf_init_mbx_params_vf - set initial values for VF mailbox 313 * @hw: pointer to the HW structure 314 * 315 * Initializes the hw->mbx struct to correct values for VF mailbox 316 */ 317 static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) 318 { 319 struct ixgbe_mbx_info *mbx = &hw->mbx; 320 321 /* start mailbox as timed out and let the reset_hw call set the timeout 322 * value to begin communications 323 */ 324 mbx->timeout = 0; 325 mbx->udelay = IXGBE_VF_MBX_INIT_DELAY; 326 327 mbx->size = IXGBE_VFMAILBOX_SIZE; 328 329 mbx->stats.msgs_tx = 0; 330 mbx->stats.msgs_rx = 0; 331 mbx->stats.reqs = 0; 332 mbx->stats.acks = 0; 333 mbx->stats.rsts = 0; 334 335 return 0; 336 } 337 338 const struct ixgbe_mbx_operations ixgbevf_mbx_ops = { 339 .init_params = ixgbevf_init_mbx_params_vf, 340 .read = ixgbevf_read_mbx_vf, 341 .write = ixgbevf_write_mbx_vf, 342 .read_posted = ixgbevf_read_posted_mbx, 343 .write_posted = ixgbevf_write_posted_mbx, 344 .check_for_msg = ixgbevf_check_for_msg_vf, 345 .check_for_ack = ixgbevf_check_for_ack_vf, 346 .check_for_rst = ixgbevf_check_for_rst_vf, 347 }; 348 349 /* Mailbox operations when running on Hyper-V. 350 * On Hyper-V, PF/VF communication is not through the 351 * hardware mailbox; this communication is through 352 * a software mediated path. 353 * Most mail box operations are noop while running on 354 * Hyper-V. 355 */ 356 const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = { 357 .init_params = ixgbevf_init_mbx_params_vf, 358 .check_for_rst = ixgbevf_check_for_rst_vf, 359 }; 360