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