linux/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 1999 - 2018 Intel Corporation. */
   3
   4#include <linux/pci.h>
   5#include <linux/delay.h>
   6#include "ixgbe.h"
   7#include "ixgbe_mbx.h"
   8
   9/**
  10 *  ixgbe_read_mbx - Reads a message from the mailbox
  11 *  @hw: pointer to the HW structure
  12 *  @msg: The message buffer
  13 *  @size: Length of buffer
  14 *  @mbx_id: id of mailbox to read
  15 *
  16 *  returns SUCCESS if it successfully read message from buffer
  17 **/
  18s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
  19{
  20        struct ixgbe_mbx_info *mbx = &hw->mbx;
  21
  22        /* limit read to size of mailbox */
  23        if (size > mbx->size)
  24                size = mbx->size;
  25
  26        if (!mbx->ops)
  27                return IXGBE_ERR_MBX;
  28
  29        return mbx->ops->read(hw, msg, size, mbx_id);
  30}
  31
  32/**
  33 *  ixgbe_write_mbx - Write a message to the mailbox
  34 *  @hw: pointer to the HW structure
  35 *  @msg: The message buffer
  36 *  @size: Length of buffer
  37 *  @mbx_id: id of mailbox to write
  38 *
  39 *  returns SUCCESS if it successfully copied message into the buffer
  40 **/
  41s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
  42{
  43        struct ixgbe_mbx_info *mbx = &hw->mbx;
  44
  45        if (size > mbx->size)
  46                return IXGBE_ERR_MBX;
  47
  48        if (!mbx->ops)
  49                return IXGBE_ERR_MBX;
  50
  51        return mbx->ops->write(hw, msg, size, mbx_id);
  52}
  53
  54/**
  55 *  ixgbe_check_for_msg - checks to see if someone sent us mail
  56 *  @hw: pointer to the HW structure
  57 *  @mbx_id: id of mailbox to check
  58 *
  59 *  returns SUCCESS if the Status bit was found or else ERR_MBX
  60 **/
  61s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
  62{
  63        struct ixgbe_mbx_info *mbx = &hw->mbx;
  64
  65        if (!mbx->ops)
  66                return IXGBE_ERR_MBX;
  67
  68        return mbx->ops->check_for_msg(hw, mbx_id);
  69}
  70
  71/**
  72 *  ixgbe_check_for_ack - checks to see if someone sent us ACK
  73 *  @hw: pointer to the HW structure
  74 *  @mbx_id: id of mailbox to check
  75 *
  76 *  returns SUCCESS if the Status bit was found or else ERR_MBX
  77 **/
  78s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
  79{
  80        struct ixgbe_mbx_info *mbx = &hw->mbx;
  81
  82        if (!mbx->ops)
  83                return IXGBE_ERR_MBX;
  84
  85        return mbx->ops->check_for_ack(hw, mbx_id);
  86}
  87
  88/**
  89 *  ixgbe_check_for_rst - checks to see if other side has reset
  90 *  @hw: pointer to the HW structure
  91 *  @mbx_id: id of mailbox to check
  92 *
  93 *  returns SUCCESS if the Status bit was found or else ERR_MBX
  94 **/
  95s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
  96{
  97        struct ixgbe_mbx_info *mbx = &hw->mbx;
  98
  99        if (!mbx->ops)
 100                return IXGBE_ERR_MBX;
 101
 102        return mbx->ops->check_for_rst(hw, mbx_id);
 103}
 104
 105/**
 106 *  ixgbe_poll_for_msg - Wait for message notification
 107 *  @hw: pointer to the HW structure
 108 *  @mbx_id: id of mailbox to write
 109 *
 110 *  returns SUCCESS if it successfully received a message notification
 111 **/
 112static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 113{
 114        struct ixgbe_mbx_info *mbx = &hw->mbx;
 115        int countdown = mbx->timeout;
 116
 117        if (!countdown || !mbx->ops)
 118                return IXGBE_ERR_MBX;
 119
 120        while (mbx->ops->check_for_msg(hw, mbx_id)) {
 121                countdown--;
 122                if (!countdown)
 123                        return IXGBE_ERR_MBX;
 124                udelay(mbx->usec_delay);
 125        }
 126
 127        return 0;
 128}
 129
 130/**
 131 *  ixgbe_poll_for_ack - Wait for message acknowledgement
 132 *  @hw: pointer to the HW structure
 133 *  @mbx_id: id of mailbox to write
 134 *
 135 *  returns SUCCESS if it successfully received a message acknowledgement
 136 **/
 137static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 138{
 139        struct ixgbe_mbx_info *mbx = &hw->mbx;
 140        int countdown = mbx->timeout;
 141
 142        if (!countdown || !mbx->ops)
 143                return IXGBE_ERR_MBX;
 144
 145        while (mbx->ops->check_for_ack(hw, mbx_id)) {
 146                countdown--;
 147                if (!countdown)
 148                        return IXGBE_ERR_MBX;
 149                udelay(mbx->usec_delay);
 150        }
 151
 152        return 0;
 153}
 154
 155/**
 156 *  ixgbe_read_posted_mbx - Wait for message notification and receive message
 157 *  @hw: pointer to the HW structure
 158 *  @msg: The message buffer
 159 *  @size: Length of buffer
 160 *  @mbx_id: id of mailbox to write
 161 *
 162 *  returns SUCCESS if it successfully received a message notification and
 163 *  copied it into the receive buffer.
 164 **/
 165static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
 166                                 u16 mbx_id)
 167{
 168        struct ixgbe_mbx_info *mbx = &hw->mbx;
 169        s32 ret_val;
 170
 171        if (!mbx->ops)
 172                return IXGBE_ERR_MBX;
 173
 174        ret_val = ixgbe_poll_for_msg(hw, mbx_id);
 175        if (ret_val)
 176                return ret_val;
 177
 178        /* if ack received read message */
 179        return mbx->ops->read(hw, msg, size, mbx_id);
 180}
 181
 182/**
 183 *  ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
 184 *  @hw: pointer to the HW structure
 185 *  @msg: The message buffer
 186 *  @size: Length of buffer
 187 *  @mbx_id: id of mailbox to write
 188 *
 189 *  returns SUCCESS if it successfully copied message into the buffer and
 190 *  received an ack to that message within delay * timeout period
 191 **/
 192static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
 193                           u16 mbx_id)
 194{
 195        struct ixgbe_mbx_info *mbx = &hw->mbx;
 196        s32 ret_val;
 197
 198        /* exit if either we can't write or there isn't a defined timeout */
 199        if (!mbx->ops || !mbx->timeout)
 200                return IXGBE_ERR_MBX;
 201
 202        /* send msg */
 203        ret_val = mbx->ops->write(hw, msg, size, mbx_id);
 204        if (ret_val)
 205                return ret_val;
 206
 207        /* if msg sent wait until we receive an ack */
 208        return ixgbe_poll_for_ack(hw, mbx_id);
 209}
 210
 211static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
 212{
 213        u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
 214
 215        if (mbvficr & mask) {
 216                IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
 217                return 0;
 218        }
 219
 220        return IXGBE_ERR_MBX;
 221}
 222
 223/**
 224 *  ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
 225 *  @hw: pointer to the HW structure
 226 *  @vf_number: the VF index
 227 *
 228 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 229 **/
 230static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
 231{
 232        s32 index = IXGBE_MBVFICR_INDEX(vf_number);
 233        u32 vf_bit = vf_number % 16;
 234
 235        if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
 236                                    index)) {
 237                hw->mbx.stats.reqs++;
 238                return 0;
 239        }
 240
 241        return IXGBE_ERR_MBX;
 242}
 243
 244/**
 245 *  ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
 246 *  @hw: pointer to the HW structure
 247 *  @vf_number: the VF index
 248 *
 249 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 250 **/
 251static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
 252{
 253        s32 index = IXGBE_MBVFICR_INDEX(vf_number);
 254        u32 vf_bit = vf_number % 16;
 255
 256        if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
 257                                    index)) {
 258                hw->mbx.stats.acks++;
 259                return 0;
 260        }
 261
 262        return IXGBE_ERR_MBX;
 263}
 264
 265/**
 266 *  ixgbe_check_for_rst_pf - checks to see if the VF has reset
 267 *  @hw: pointer to the HW structure
 268 *  @vf_number: the VF index
 269 *
 270 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 271 **/
 272static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
 273{
 274        u32 reg_offset = (vf_number < 32) ? 0 : 1;
 275        u32 vf_shift = vf_number % 32;
 276        u32 vflre = 0;
 277
 278        switch (hw->mac.type) {
 279        case ixgbe_mac_82599EB:
 280                vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
 281                break;
 282        case ixgbe_mac_X540:
 283        case ixgbe_mac_X550:
 284        case ixgbe_mac_X550EM_x:
 285        case ixgbe_mac_x550em_a:
 286                vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
 287                break;
 288        default:
 289                break;
 290        }
 291
 292        if (vflre & BIT(vf_shift)) {
 293                IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), BIT(vf_shift));
 294                hw->mbx.stats.rsts++;
 295                return 0;
 296        }
 297
 298        return IXGBE_ERR_MBX;
 299}
 300
 301/**
 302 *  ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
 303 *  @hw: pointer to the HW structure
 304 *  @vf_number: the VF index
 305 *
 306 *  return SUCCESS if we obtained the mailbox lock
 307 **/
 308static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
 309{
 310        u32 p2v_mailbox;
 311
 312        /* Take ownership of the buffer */
 313        IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
 314
 315        /* reserve mailbox for vf use */
 316        p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
 317        if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
 318                return 0;
 319
 320        return IXGBE_ERR_MBX;
 321}
 322
 323/**
 324 *  ixgbe_write_mbx_pf - Places a message in the mailbox
 325 *  @hw: pointer to the HW structure
 326 *  @msg: The message buffer
 327 *  @size: Length of buffer
 328 *  @vf_number: the VF index
 329 *
 330 *  returns SUCCESS if it successfully copied message into the buffer
 331 **/
 332static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 333                              u16 vf_number)
 334{
 335        s32 ret_val;
 336        u16 i;
 337
 338        /* lock the mailbox to prevent pf/vf race condition */
 339        ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
 340        if (ret_val)
 341                return ret_val;
 342
 343        /* flush msg and acks as we are overwriting the message buffer */
 344        ixgbe_check_for_msg_pf(hw, vf_number);
 345        ixgbe_check_for_ack_pf(hw, vf_number);
 346
 347        /* copy the caller specified message to the mailbox memory buffer */
 348        for (i = 0; i < size; i++)
 349                IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
 350
 351        /* Interrupt VF to tell it a message has been sent and release buffer*/
 352        IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
 353
 354        /* update stats */
 355        hw->mbx.stats.msgs_tx++;
 356
 357        return 0;
 358}
 359
 360/**
 361 *  ixgbe_read_mbx_pf - Read a message from the mailbox
 362 *  @hw: pointer to the HW structure
 363 *  @msg: The message buffer
 364 *  @size: Length of buffer
 365 *  @vf_number: the VF index
 366 *
 367 *  This function copies a message from the mailbox buffer to the caller's
 368 *  memory buffer.  The presumption is that the caller knows that there was
 369 *  a message due to a VF request so no polling for message is needed.
 370 **/
 371static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 372                             u16 vf_number)
 373{
 374        s32 ret_val;
 375        u16 i;
 376
 377        /* lock the mailbox to prevent pf/vf race condition */
 378        ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
 379        if (ret_val)
 380                return ret_val;
 381
 382        /* copy the message to the mailbox memory buffer */
 383        for (i = 0; i < size; i++)
 384                msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
 385
 386        /* Acknowledge the message and release buffer */
 387        IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
 388
 389        /* update stats */
 390        hw->mbx.stats.msgs_rx++;
 391
 392        return 0;
 393}
 394
 395#ifdef CONFIG_PCI_IOV
 396/**
 397 *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
 398 *  @hw: pointer to the HW structure
 399 *
 400 *  Initializes the hw->mbx struct to correct values for pf mailbox
 401 */
 402void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
 403{
 404        struct ixgbe_mbx_info *mbx = &hw->mbx;
 405
 406        if (hw->mac.type != ixgbe_mac_82599EB &&
 407            hw->mac.type != ixgbe_mac_X550 &&
 408            hw->mac.type != ixgbe_mac_X550EM_x &&
 409            hw->mac.type != ixgbe_mac_x550em_a &&
 410            hw->mac.type != ixgbe_mac_X540)
 411                return;
 412
 413        mbx->timeout = 0;
 414        mbx->usec_delay = 0;
 415
 416        mbx->stats.msgs_tx = 0;
 417        mbx->stats.msgs_rx = 0;
 418        mbx->stats.reqs = 0;
 419        mbx->stats.acks = 0;
 420        mbx->stats.rsts = 0;
 421
 422        mbx->size = IXGBE_VFMAILBOX_SIZE;
 423}
 424#endif /* CONFIG_PCI_IOV */
 425
 426const struct ixgbe_mbx_operations mbx_ops_generic = {
 427        .read                   = ixgbe_read_mbx_pf,
 428        .write                  = ixgbe_write_mbx_pf,
 429        .read_posted            = ixgbe_read_posted_mbx,
 430        .write_posted           = ixgbe_write_posted_mbx,
 431        .check_for_msg          = ixgbe_check_for_msg_pf,
 432        .check_for_ack          = ixgbe_check_for_ack_pf,
 433        .check_for_rst          = ixgbe_check_for_rst_pf,
 434};
 435
 436