root/drivers/net/ethernet/intel/igb/e1000_mbx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. igb_read_mbx
  2. igb_write_mbx
  3. igb_check_for_msg
  4. igb_check_for_ack
  5. igb_check_for_rst
  6. igb_unlock_mbx
  7. igb_poll_for_msg
  8. igb_poll_for_ack
  9. igb_read_posted_mbx
  10. igb_write_posted_mbx
  11. igb_check_for_bit_pf
  12. igb_check_for_msg_pf
  13. igb_check_for_ack_pf
  14. igb_check_for_rst_pf
  15. igb_obtain_mbx_lock_pf
  16. igb_release_mbx_lock_pf
  17. igb_write_mbx_pf
  18. igb_read_mbx_pf
  19. igb_init_mbx_params_pf

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright(c) 2007 - 2018 Intel Corporation. */
   3 
   4 #include "e1000_mbx.h"
   5 
   6 /**
   7  *  igb_read_mbx - Reads a message from the mailbox
   8  *  @hw: pointer to the HW structure
   9  *  @msg: The message buffer
  10  *  @size: Length of buffer
  11  *  @mbx_id: id of mailbox to read
  12  *
  13  *  returns SUCCESS if it successfully read message from buffer
  14  **/
  15 s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
  16                  bool unlock)
  17 {
  18         struct e1000_mbx_info *mbx = &hw->mbx;
  19         s32 ret_val = -E1000_ERR_MBX;
  20 
  21         /* limit read to size of mailbox */
  22         if (size > mbx->size)
  23                 size = mbx->size;
  24 
  25         if (mbx->ops.read)
  26                 ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock);
  27 
  28         return ret_val;
  29 }
  30 
  31 /**
  32  *  igb_write_mbx - Write a message to the mailbox
  33  *  @hw: pointer to the HW structure
  34  *  @msg: The message buffer
  35  *  @size: Length of buffer
  36  *  @mbx_id: id of mailbox to write
  37  *
  38  *  returns SUCCESS if it successfully copied message into the buffer
  39  **/
  40 s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
  41 {
  42         struct e1000_mbx_info *mbx = &hw->mbx;
  43         s32 ret_val = 0;
  44 
  45         if (size > mbx->size)
  46                 ret_val = -E1000_ERR_MBX;
  47 
  48         else if (mbx->ops.write)
  49                 ret_val = mbx->ops.write(hw, msg, size, mbx_id);
  50 
  51         return ret_val;
  52 }
  53 
  54 /**
  55  *  igb_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  **/
  61 s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
  62 {
  63         struct e1000_mbx_info *mbx = &hw->mbx;
  64         s32 ret_val = -E1000_ERR_MBX;
  65 
  66         if (mbx->ops.check_for_msg)
  67                 ret_val = mbx->ops.check_for_msg(hw, mbx_id);
  68 
  69         return ret_val;
  70 }
  71 
  72 /**
  73  *  igb_check_for_ack - checks to see if someone sent us ACK
  74  *  @hw: pointer to the HW structure
  75  *  @mbx_id: id of mailbox to check
  76  *
  77  *  returns SUCCESS if the Status bit was found or else ERR_MBX
  78  **/
  79 s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
  80 {
  81         struct e1000_mbx_info *mbx = &hw->mbx;
  82         s32 ret_val = -E1000_ERR_MBX;
  83 
  84         if (mbx->ops.check_for_ack)
  85                 ret_val = mbx->ops.check_for_ack(hw, mbx_id);
  86 
  87         return ret_val;
  88 }
  89 
  90 /**
  91  *  igb_check_for_rst - checks to see if other side has reset
  92  *  @hw: pointer to the HW structure
  93  *  @mbx_id: id of mailbox to check
  94  *
  95  *  returns SUCCESS if the Status bit was found or else ERR_MBX
  96  **/
  97 s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
  98 {
  99         struct e1000_mbx_info *mbx = &hw->mbx;
 100         s32 ret_val = -E1000_ERR_MBX;
 101 
 102         if (mbx->ops.check_for_rst)
 103                 ret_val = mbx->ops.check_for_rst(hw, mbx_id);
 104 
 105         return ret_val;
 106 }
 107 
 108 /**
 109  *  igb_unlock_mbx - unlock the mailbox
 110  *  @hw: pointer to the HW structure
 111  *  @mbx_id: id of mailbox to check
 112  *
 113  *  returns SUCCESS if the mailbox was unlocked or else ERR_MBX
 114  **/
 115 s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id)
 116 {
 117         struct e1000_mbx_info *mbx = &hw->mbx;
 118         s32 ret_val = -E1000_ERR_MBX;
 119 
 120         if (mbx->ops.unlock)
 121                 ret_val = mbx->ops.unlock(hw, mbx_id);
 122 
 123         return ret_val;
 124 }
 125 
 126 /**
 127  *  igb_poll_for_msg - Wait for message notification
 128  *  @hw: pointer to the HW structure
 129  *  @mbx_id: id of mailbox to write
 130  *
 131  *  returns SUCCESS if it successfully received a message notification
 132  **/
 133 static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
 134 {
 135         struct e1000_mbx_info *mbx = &hw->mbx;
 136         int countdown = mbx->timeout;
 137 
 138         if (!countdown || !mbx->ops.check_for_msg)
 139                 goto out;
 140 
 141         while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
 142                 countdown--;
 143                 if (!countdown)
 144                         break;
 145                 udelay(mbx->usec_delay);
 146         }
 147 
 148         /* if we failed, all future posted messages fail until reset */
 149         if (!countdown)
 150                 mbx->timeout = 0;
 151 out:
 152         return countdown ? 0 : -E1000_ERR_MBX;
 153 }
 154 
 155 /**
 156  *  igb_poll_for_ack - Wait for message acknowledgement
 157  *  @hw: pointer to the HW structure
 158  *  @mbx_id: id of mailbox to write
 159  *
 160  *  returns SUCCESS if it successfully received a message acknowledgement
 161  **/
 162 static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
 163 {
 164         struct e1000_mbx_info *mbx = &hw->mbx;
 165         int countdown = mbx->timeout;
 166 
 167         if (!countdown || !mbx->ops.check_for_ack)
 168                 goto out;
 169 
 170         while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
 171                 countdown--;
 172                 if (!countdown)
 173                         break;
 174                 udelay(mbx->usec_delay);
 175         }
 176 
 177         /* if we failed, all future posted messages fail until reset */
 178         if (!countdown)
 179                 mbx->timeout = 0;
 180 out:
 181         return countdown ? 0 : -E1000_ERR_MBX;
 182 }
 183 
 184 /**
 185  *  igb_read_posted_mbx - Wait for message notification and receive message
 186  *  @hw: pointer to the HW structure
 187  *  @msg: The message buffer
 188  *  @size: Length of buffer
 189  *  @mbx_id: id of mailbox to write
 190  *
 191  *  returns SUCCESS if it successfully received a message notification and
 192  *  copied it into the receive buffer.
 193  **/
 194 static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
 195                                u16 mbx_id)
 196 {
 197         struct e1000_mbx_info *mbx = &hw->mbx;
 198         s32 ret_val = -E1000_ERR_MBX;
 199 
 200         if (!mbx->ops.read)
 201                 goto out;
 202 
 203         ret_val = igb_poll_for_msg(hw, mbx_id);
 204 
 205         if (!ret_val)
 206                 ret_val = mbx->ops.read(hw, msg, size, mbx_id, true);
 207 out:
 208         return ret_val;
 209 }
 210 
 211 /**
 212  *  igb_write_posted_mbx - Write a message to the mailbox, wait for ack
 213  *  @hw: pointer to the HW structure
 214  *  @msg: The message buffer
 215  *  @size: Length of buffer
 216  *  @mbx_id: id of mailbox to write
 217  *
 218  *  returns SUCCESS if it successfully copied message into the buffer and
 219  *  received an ack to that message within delay * timeout period
 220  **/
 221 static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
 222                                 u16 mbx_id)
 223 {
 224         struct e1000_mbx_info *mbx = &hw->mbx;
 225         s32 ret_val = -E1000_ERR_MBX;
 226 
 227         /* exit if either we can't write or there isn't a defined timeout */
 228         if (!mbx->ops.write || !mbx->timeout)
 229                 goto out;
 230 
 231         /* send msg */
 232         ret_val = mbx->ops.write(hw, msg, size, mbx_id);
 233 
 234         /* if msg sent wait until we receive an ack */
 235         if (!ret_val)
 236                 ret_val = igb_poll_for_ack(hw, mbx_id);
 237 out:
 238         return ret_val;
 239 }
 240 
 241 static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
 242 {
 243         u32 mbvficr = rd32(E1000_MBVFICR);
 244         s32 ret_val = -E1000_ERR_MBX;
 245 
 246         if (mbvficr & mask) {
 247                 ret_val = 0;
 248                 wr32(E1000_MBVFICR, mask);
 249         }
 250 
 251         return ret_val;
 252 }
 253 
 254 /**
 255  *  igb_check_for_msg_pf - checks to see if the VF has sent mail
 256  *  @hw: pointer to the HW structure
 257  *  @vf_number: the VF index
 258  *
 259  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 260  **/
 261 static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
 262 {
 263         s32 ret_val = -E1000_ERR_MBX;
 264 
 265         if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
 266                 ret_val = 0;
 267                 hw->mbx.stats.reqs++;
 268         }
 269 
 270         return ret_val;
 271 }
 272 
 273 /**
 274  *  igb_check_for_ack_pf - checks to see if the VF has ACKed
 275  *  @hw: pointer to the HW structure
 276  *  @vf_number: the VF index
 277  *
 278  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 279  **/
 280 static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
 281 {
 282         s32 ret_val = -E1000_ERR_MBX;
 283 
 284         if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
 285                 ret_val = 0;
 286                 hw->mbx.stats.acks++;
 287         }
 288 
 289         return ret_val;
 290 }
 291 
 292 /**
 293  *  igb_check_for_rst_pf - checks to see if the VF has reset
 294  *  @hw: pointer to the HW structure
 295  *  @vf_number: the VF index
 296  *
 297  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
 298  **/
 299 static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
 300 {
 301         u32 vflre = rd32(E1000_VFLRE);
 302         s32 ret_val = -E1000_ERR_MBX;
 303 
 304         if (vflre & BIT(vf_number)) {
 305                 ret_val = 0;
 306                 wr32(E1000_VFLRE, BIT(vf_number));
 307                 hw->mbx.stats.rsts++;
 308         }
 309 
 310         return ret_val;
 311 }
 312 
 313 /**
 314  *  igb_obtain_mbx_lock_pf - obtain mailbox lock
 315  *  @hw: pointer to the HW structure
 316  *  @vf_number: the VF index
 317  *
 318  *  return SUCCESS if we obtained the mailbox lock
 319  **/
 320 static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
 321 {
 322         s32 ret_val = -E1000_ERR_MBX;
 323         u32 p2v_mailbox;
 324         int count = 10;
 325 
 326         do {
 327                 /* Take ownership of the buffer */
 328                 wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
 329 
 330                 /* reserve mailbox for vf use */
 331                 p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
 332                 if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
 333                         ret_val = 0;
 334                         break;
 335                 }
 336                 udelay(1000);
 337         } while (count-- > 0);
 338 
 339         return ret_val;
 340 }
 341 
 342 /**
 343  *  igb_release_mbx_lock_pf - release mailbox lock
 344  *  @hw: pointer to the HW structure
 345  *  @vf_number: the VF index
 346  *
 347  *  return SUCCESS if we released the mailbox lock
 348  **/
 349 static s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
 350 {
 351         u32 p2v_mailbox;
 352 
 353         /* drop PF lock of mailbox, if set */
 354         p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
 355         if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
 356                 wr32(E1000_P2VMAILBOX(vf_number),
 357                      p2v_mailbox & ~E1000_P2VMAILBOX_PFU);
 358 
 359         return 0;
 360 }
 361 
 362 /**
 363  *  igb_write_mbx_pf - Places a message in the mailbox
 364  *  @hw: pointer to the HW structure
 365  *  @msg: The message buffer
 366  *  @size: Length of buffer
 367  *  @vf_number: the VF index
 368  *
 369  *  returns SUCCESS if it successfully copied message into the buffer
 370  **/
 371 static s32 igb_write_mbx_pf(struct e1000_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 = igb_obtain_mbx_lock_pf(hw, vf_number);
 379         if (ret_val)
 380                 goto out_no_write;
 381 
 382         /* flush msg and acks as we are overwriting the message buffer */
 383         igb_check_for_msg_pf(hw, vf_number);
 384         igb_check_for_ack_pf(hw, vf_number);
 385 
 386         /* copy the caller specified message to the mailbox memory buffer */
 387         for (i = 0; i < size; i++)
 388                 array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
 389 
 390         /* Interrupt VF to tell it a message has been sent and release buffer*/
 391         wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
 392 
 393         /* update stats */
 394         hw->mbx.stats.msgs_tx++;
 395 
 396 out_no_write:
 397         return ret_val;
 398 
 399 }
 400 
 401 /**
 402  *  igb_read_mbx_pf - Read a message from the mailbox
 403  *  @hw: pointer to the HW structure
 404  *  @msg: The message buffer
 405  *  @size: Length of buffer
 406  *  @vf_number: the VF index
 407  *  @unlock: unlock the mailbox when done?
 408  *
 409  *  This function copies a message from the mailbox buffer to the caller's
 410  *  memory buffer.  The presumption is that the caller knows that there was
 411  *  a message due to a VF request so no polling for message is needed.
 412  **/
 413 static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
 414                            u16 vf_number, bool unlock)
 415 {
 416         s32 ret_val;
 417         u16 i;
 418 
 419         /* lock the mailbox to prevent pf/vf race condition */
 420         ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
 421         if (ret_val)
 422                 goto out_no_read;
 423 
 424         /* copy the message to the mailbox memory buffer */
 425         for (i = 0; i < size; i++)
 426                 msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
 427 
 428         /* Acknowledge the message and release mailbox lock (or not) */
 429         if (unlock)
 430                 wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
 431         else
 432                 wr32(E1000_P2VMAILBOX(vf_number),
 433                      E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU);
 434 
 435         /* update stats */
 436         hw->mbx.stats.msgs_rx++;
 437 
 438 out_no_read:
 439         return ret_val;
 440 }
 441 
 442 /**
 443  *  e1000_init_mbx_params_pf - set initial values for pf mailbox
 444  *  @hw: pointer to the HW structure
 445  *
 446  *  Initializes the hw->mbx struct to correct values for pf mailbox
 447  */
 448 s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
 449 {
 450         struct e1000_mbx_info *mbx = &hw->mbx;
 451 
 452         mbx->timeout = 0;
 453         mbx->usec_delay = 0;
 454 
 455         mbx->size = E1000_VFMAILBOX_SIZE;
 456 
 457         mbx->ops.read = igb_read_mbx_pf;
 458         mbx->ops.write = igb_write_mbx_pf;
 459         mbx->ops.read_posted = igb_read_posted_mbx;
 460         mbx->ops.write_posted = igb_write_posted_mbx;
 461         mbx->ops.check_for_msg = igb_check_for_msg_pf;
 462         mbx->ops.check_for_ack = igb_check_for_ack_pf;
 463         mbx->ops.check_for_rst = igb_check_for_rst_pf;
 464         mbx->ops.unlock = igb_release_mbx_lock_pf;
 465 
 466         mbx->stats.msgs_tx = 0;
 467         mbx->stats.msgs_rx = 0;
 468         mbx->stats.reqs = 0;
 469         mbx->stats.acks = 0;
 470         mbx->stats.rsts = 0;
 471 
 472         return 0;
 473 }
 474 

/* [<][>][^][v][top][bottom][index][help] */