root/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c

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

DEFINITIONS

This source file includes following definitions.
  1. fm10k_fifo_init
  2. fm10k_fifo_used
  3. fm10k_fifo_unused
  4. fm10k_fifo_empty
  5. fm10k_fifo_head_offset
  6. fm10k_fifo_tail_offset
  7. fm10k_fifo_head_len
  8. fm10k_fifo_head_drop
  9. fm10k_fifo_drop_all
  10. fm10k_mbx_index_len
  11. fm10k_mbx_tail_add
  12. fm10k_mbx_tail_sub
  13. fm10k_mbx_head_add
  14. fm10k_mbx_head_sub
  15. fm10k_mbx_pushed_tail_len
  16. fm10k_fifo_write_copy
  17. fm10k_fifo_enqueue
  18. fm10k_mbx_validate_msg_size
  19. fm10k_mbx_write_copy
  20. fm10k_mbx_pull_head
  21. fm10k_mbx_read_copy
  22. fm10k_mbx_push_tail
  23. fm10k_crc_16b
  24. fm10k_fifo_crc
  25. fm10k_mbx_update_local_crc
  26. fm10k_mbx_verify_remote_crc
  27. fm10k_mbx_rx_ready
  28. fm10k_mbx_tx_ready
  29. fm10k_mbx_tx_complete
  30. fm10k_mbx_dequeue_rx
  31. fm10k_mbx_enqueue_tx
  32. fm10k_mbx_read
  33. fm10k_mbx_write
  34. fm10k_mbx_create_connect_hdr
  35. fm10k_mbx_create_data_hdr
  36. fm10k_mbx_create_disconnect_hdr
  37. fm10k_mbx_create_fake_disconnect_hdr
  38. fm10k_mbx_create_error_msg
  39. fm10k_mbx_validate_msg_hdr
  40. fm10k_mbx_create_reply
  41. fm10k_mbx_reset_work
  42. fm10k_mbx_update_max_size
  43. fm10k_mbx_connect_reset
  44. fm10k_mbx_process_connect
  45. fm10k_mbx_process_data
  46. fm10k_mbx_process_disconnect
  47. fm10k_mbx_process_error
  48. fm10k_mbx_process
  49. fm10k_mbx_disconnect
  50. fm10k_mbx_connect
  51. fm10k_mbx_validate_handlers
  52. fm10k_mbx_register_handlers
  53. fm10k_pfvf_mbx_init
  54. fm10k_sm_mbx_create_data_hdr
  55. fm10k_sm_mbx_create_connect_hdr
  56. fm10k_sm_mbx_connect_reset
  57. fm10k_sm_mbx_connect
  58. fm10k_sm_mbx_disconnect
  59. fm10k_sm_mbx_validate_fifo_hdr
  60. fm10k_sm_mbx_process_error
  61. fm10k_sm_mbx_create_error_msg
  62. fm10k_sm_mbx_receive
  63. fm10k_sm_mbx_transmit
  64. fm10k_sm_mbx_create_reply
  65. fm10k_sm_mbx_process_reset
  66. fm10k_sm_mbx_process_version_1
  67. fm10k_sm_mbx_process
  68. fm10k_sm_mbx_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright(c) 2013 - 2019 Intel Corporation. */
   3 
   4 #include "fm10k_common.h"
   5 
   6 /**
   7  *  fm10k_fifo_init - Initialize a message FIFO
   8  *  @fifo: pointer to FIFO
   9  *  @buffer: pointer to memory to be used to store FIFO
  10  *  @size: maximum message size to store in FIFO, must be 2^n - 1
  11  **/
  12 static void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
  13 {
  14         fifo->buffer = buffer;
  15         fifo->size = size;
  16         fifo->head = 0;
  17         fifo->tail = 0;
  18 }
  19 
  20 /**
  21  *  fm10k_fifo_used - Retrieve used space in FIFO
  22  *  @fifo: pointer to FIFO
  23  *
  24  *  This function returns the number of DWORDs used in the FIFO
  25  **/
  26 static u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
  27 {
  28         return fifo->tail - fifo->head;
  29 }
  30 
  31 /**
  32  *  fm10k_fifo_unused - Retrieve unused space in FIFO
  33  *  @fifo: pointer to FIFO
  34  *
  35  *  This function returns the number of unused DWORDs in the FIFO
  36  **/
  37 static u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
  38 {
  39         return fifo->size + fifo->head - fifo->tail;
  40 }
  41 
  42 /**
  43  *  fm10k_fifo_empty - Test to verify if FIFO is empty
  44  *  @fifo: pointer to FIFO
  45  *
  46  *  This function returns true if the FIFO is empty, else false
  47  **/
  48 static bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
  49 {
  50         return fifo->head == fifo->tail;
  51 }
  52 
  53 /**
  54  *  fm10k_fifo_head_offset - returns indices of head with given offset
  55  *  @fifo: pointer to FIFO
  56  *  @offset: offset to add to head
  57  *
  58  *  This function returns the indices into the FIFO based on head + offset
  59  **/
  60 static u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
  61 {
  62         return (fifo->head + offset) & (fifo->size - 1);
  63 }
  64 
  65 /**
  66  *  fm10k_fifo_tail_offset - returns indices of tail with given offset
  67  *  @fifo: pointer to FIFO
  68  *  @offset: offset to add to tail
  69  *
  70  *  This function returns the indices into the FIFO based on tail + offset
  71  **/
  72 static u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
  73 {
  74         return (fifo->tail + offset) & (fifo->size - 1);
  75 }
  76 
  77 /**
  78  *  fm10k_fifo_head_len - Retrieve length of first message in FIFO
  79  *  @fifo: pointer to FIFO
  80  *
  81  *  This function returns the size of the first message in the FIFO
  82  **/
  83 static u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
  84 {
  85         u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
  86 
  87         /* verify there is at least 1 DWORD in the fifo so *head is valid */
  88         if (fm10k_fifo_empty(fifo))
  89                 return 0;
  90 
  91         /* retieve the message length */
  92         return FM10K_TLV_DWORD_LEN(*head);
  93 }
  94 
  95 /**
  96  *  fm10k_fifo_head_drop - Drop the first message in FIFO
  97  *  @fifo: pointer to FIFO
  98  *
  99  *  This function returns the size of the message dropped from the FIFO
 100  **/
 101 static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
 102 {
 103         u16 len = fm10k_fifo_head_len(fifo);
 104 
 105         /* update head so it is at the start of next frame */
 106         fifo->head += len;
 107 
 108         return len;
 109 }
 110 
 111 /**
 112  *  fm10k_fifo_drop_all - Drop all messages in FIFO
 113  *  @fifo: pointer to FIFO
 114  *
 115  *  This function resets the head pointer to drop all messages in the FIFO and
 116  *  ensure the FIFO is empty.
 117  **/
 118 static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
 119 {
 120         fifo->head = fifo->tail;
 121 }
 122 
 123 /**
 124  *  fm10k_mbx_index_len - Convert a head/tail index into a length value
 125  *  @mbx: pointer to mailbox
 126  *  @head: head index
 127  *  @tail: head index
 128  *
 129  *  This function takes the head and tail index and determines the length
 130  *  of the data indicated by this pair.
 131  **/
 132 static u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
 133 {
 134         u16 len = tail - head;
 135 
 136         /* we wrapped so subtract 2, one for index 0, one for all 1s index */
 137         if (len > tail)
 138                 len -= 2;
 139 
 140         return len & ((mbx->mbmem_len << 1) - 1);
 141 }
 142 
 143 /**
 144  *  fm10k_mbx_tail_add - Determine new tail value with added offset
 145  *  @mbx: pointer to mailbox
 146  *  @offset: length to add to tail offset
 147  *
 148  *  This function takes the local tail index and recomputes it for
 149  *  a given length added as an offset.
 150  **/
 151 static u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
 152 {
 153         u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
 154 
 155         /* add/sub 1 because we cannot have offset 0 or all 1s */
 156         return (tail > mbx->tail) ? --tail : ++tail;
 157 }
 158 
 159 /**
 160  *  fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
 161  *  @mbx: pointer to mailbox
 162  *  @offset: length to add to tail offset
 163  *
 164  *  This function takes the local tail index and recomputes it for
 165  *  a given length added as an offset.
 166  **/
 167 static u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
 168 {
 169         u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
 170 
 171         /* sub/add 1 because we cannot have offset 0 or all 1s */
 172         return (tail < mbx->tail) ? ++tail : --tail;
 173 }
 174 
 175 /**
 176  *  fm10k_mbx_head_add - Determine new head value with added offset
 177  *  @mbx: pointer to mailbox
 178  *  @offset: length to add to head offset
 179  *
 180  *  This function takes the local head index and recomputes it for
 181  *  a given length added as an offset.
 182  **/
 183 static u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
 184 {
 185         u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
 186 
 187         /* add/sub 1 because we cannot have offset 0 or all 1s */
 188         return (head > mbx->head) ? --head : ++head;
 189 }
 190 
 191 /**
 192  *  fm10k_mbx_head_sub - Determine new head value with subtracted offset
 193  *  @mbx: pointer to mailbox
 194  *  @offset: length to add to head offset
 195  *
 196  *  This function takes the local head index and recomputes it for
 197  *  a given length added as an offset.
 198  **/
 199 static u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
 200 {
 201         u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
 202 
 203         /* sub/add 1 because we cannot have offset 0 or all 1s */
 204         return (head < mbx->head) ? ++head : --head;
 205 }
 206 
 207 /**
 208  *  fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
 209  *  @mbx: pointer to mailbox
 210  *
 211  *  This function will return the length of the message currently being
 212  *  pushed onto the tail of the Rx queue.
 213  **/
 214 static u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
 215 {
 216         u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
 217 
 218         /* pushed tail is only valid if pushed is set */
 219         if (!mbx->pushed)
 220                 return 0;
 221 
 222         return FM10K_TLV_DWORD_LEN(*tail);
 223 }
 224 
 225 /**
 226  *  fm10k_fifo_write_copy - pulls data off of msg and places it in FIFO
 227  *  @fifo: pointer to FIFO
 228  *  @msg: message array to populate
 229  *  @tail_offset: additional offset to add to tail pointer
 230  *  @len: length of FIFO to copy into message header
 231  *
 232  *  This function will take a message and copy it into a section of the
 233  *  FIFO.  In order to get something into a location other than just
 234  *  the tail you can use tail_offset to adjust the pointer.
 235  **/
 236 static void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
 237                                   const u32 *msg, u16 tail_offset, u16 len)
 238 {
 239         u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
 240         u32 *tail = fifo->buffer + end;
 241 
 242         /* track when we should cross the end of the FIFO */
 243         end = fifo->size - end;
 244 
 245         /* copy end of message before start of message */
 246         if (end < len)
 247                 memcpy(fifo->buffer, msg + end, (len - end) << 2);
 248         else
 249                 end = len;
 250 
 251         /* Copy remaining message into Tx FIFO */
 252         memcpy(tail, msg, end << 2);
 253 }
 254 
 255 /**
 256  *  fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
 257  *  @fifo: pointer to FIFO
 258  *  @msg: message array to read
 259  *
 260  *  This function enqueues a message up to the size specified by the length
 261  *  contained in the first DWORD of the message and will place at the tail
 262  *  of the FIFO.  It will return 0 on success, or a negative value on error.
 263  **/
 264 static s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
 265 {
 266         u16 len = FM10K_TLV_DWORD_LEN(*msg);
 267 
 268         /* verify parameters */
 269         if (len > fifo->size)
 270                 return FM10K_MBX_ERR_SIZE;
 271 
 272         /* verify there is room for the message */
 273         if (len > fm10k_fifo_unused(fifo))
 274                 return FM10K_MBX_ERR_NO_SPACE;
 275 
 276         /* Copy message into FIFO */
 277         fm10k_fifo_write_copy(fifo, msg, 0, len);
 278 
 279         /* memory barrier to guarantee FIFO is written before tail update */
 280         wmb();
 281 
 282         /* Update Tx FIFO tail */
 283         fifo->tail += len;
 284 
 285         return 0;
 286 }
 287 
 288 /**
 289  *  fm10k_mbx_validate_msg_size - Validate incoming message based on size
 290  *  @mbx: pointer to mailbox
 291  *  @len: length of data pushed onto buffer
 292  *
 293  *  This function analyzes the frame and will return a non-zero value when
 294  *  the start of a message larger than the mailbox is detected.
 295  **/
 296 static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
 297 {
 298         struct fm10k_mbx_fifo *fifo = &mbx->rx;
 299         u16 total_len = 0, msg_len;
 300 
 301         /* length should include previous amounts pushed */
 302         len += mbx->pushed;
 303 
 304         /* offset in message is based off of current message size */
 305         do {
 306                 u32 *msg;
 307 
 308                 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
 309                 msg_len = FM10K_TLV_DWORD_LEN(*msg);
 310                 total_len += msg_len;
 311         } while (total_len < len);
 312 
 313         /* message extends out of pushed section, but fits in FIFO */
 314         if ((len < total_len) && (msg_len <= mbx->max_size))
 315                 return 0;
 316 
 317         /* return length of invalid section */
 318         return (len < total_len) ? len : (len - total_len);
 319 }
 320 
 321 /**
 322  *  fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
 323  *  @hw: pointer to hardware structure
 324  *  @mbx: pointer to mailbox
 325  *
 326  *  This function will take a section of the Tx FIFO and copy it into the
 327  *  mailbox memory.  The offset in mbmem is based on the lower bits of the
 328  *  tail and len determines the length to copy.
 329  **/
 330 static void fm10k_mbx_write_copy(struct fm10k_hw *hw,
 331                                  struct fm10k_mbx_info *mbx)
 332 {
 333         struct fm10k_mbx_fifo *fifo = &mbx->tx;
 334         u32 mbmem = mbx->mbmem_reg;
 335         u32 *head = fifo->buffer;
 336         u16 end, len, tail, mask;
 337 
 338         if (!mbx->tail_len)
 339                 return;
 340 
 341         /* determine data length and mbmem tail index */
 342         mask = mbx->mbmem_len - 1;
 343         len = mbx->tail_len;
 344         tail = fm10k_mbx_tail_sub(mbx, len);
 345         if (tail > mask)
 346                 tail++;
 347 
 348         /* determine offset in the ring */
 349         end = fm10k_fifo_head_offset(fifo, mbx->pulled);
 350         head += end;
 351 
 352         /* memory barrier to guarantee data is ready to be read */
 353         rmb();
 354 
 355         /* Copy message from Tx FIFO */
 356         for (end = fifo->size - end; len; head = fifo->buffer) {
 357                 do {
 358                         /* adjust tail to match offset for FIFO */
 359                         tail &= mask;
 360                         if (!tail)
 361                                 tail++;
 362 
 363                         mbx->tx_mbmem_pulled++;
 364 
 365                         /* write message to hardware FIFO */
 366                         fm10k_write_reg(hw, mbmem + tail++, *(head++));
 367                 } while (--len && --end);
 368         }
 369 }
 370 
 371 /**
 372  *  fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
 373  *  @hw: pointer to hardware structure
 374  *  @mbx: pointer to mailbox
 375  *  @head: acknowledgement number last received
 376  *
 377  *  This function will push the tail index forward based on the remote
 378  *  head index.  It will then pull up to mbmem_len DWORDs off of the
 379  *  head of the FIFO and will place it in the MBMEM registers
 380  *  associated with the mailbox.
 381  **/
 382 static void fm10k_mbx_pull_head(struct fm10k_hw *hw,
 383                                 struct fm10k_mbx_info *mbx, u16 head)
 384 {
 385         u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
 386         struct fm10k_mbx_fifo *fifo = &mbx->tx;
 387 
 388         /* update number of bytes pulled and update bytes in transit */
 389         mbx->pulled += mbx->tail_len - ack;
 390 
 391         /* determine length of data to pull, reserve space for mbmem header */
 392         mbmem_len = mbx->mbmem_len - 1;
 393         len = fm10k_fifo_used(fifo) - mbx->pulled;
 394         if (len > mbmem_len)
 395                 len = mbmem_len;
 396 
 397         /* update tail and record number of bytes in transit */
 398         mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
 399         mbx->tail_len = len;
 400 
 401         /* drop pulled messages from the FIFO */
 402         for (len = fm10k_fifo_head_len(fifo);
 403              len && (mbx->pulled >= len);
 404              len = fm10k_fifo_head_len(fifo)) {
 405                 mbx->pulled -= fm10k_fifo_head_drop(fifo);
 406                 mbx->tx_messages++;
 407                 mbx->tx_dwords += len;
 408         }
 409 
 410         /* Copy message out from the Tx FIFO */
 411         fm10k_mbx_write_copy(hw, mbx);
 412 }
 413 
 414 /**
 415  *  fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
 416  *  @hw: pointer to hardware structure
 417  *  @mbx: pointer to mailbox
 418  *
 419  *  This function will take a section of the mailbox memory and copy it
 420  *  into the Rx FIFO.  The offset is based on the lower bits of the
 421  *  head and len determines the length to copy.
 422  **/
 423 static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
 424                                 struct fm10k_mbx_info *mbx)
 425 {
 426         struct fm10k_mbx_fifo *fifo = &mbx->rx;
 427         u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
 428         u32 *tail = fifo->buffer;
 429         u16 end, len, head;
 430 
 431         /* determine data length and mbmem head index */
 432         len = mbx->head_len;
 433         head = fm10k_mbx_head_sub(mbx, len);
 434         if (head >= mbx->mbmem_len)
 435                 head++;
 436 
 437         /* determine offset in the ring */
 438         end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
 439         tail += end;
 440 
 441         /* Copy message into Rx FIFO */
 442         for (end = fifo->size - end; len; tail = fifo->buffer) {
 443                 do {
 444                         /* adjust head to match offset for FIFO */
 445                         head &= mbx->mbmem_len - 1;
 446                         if (!head)
 447                                 head++;
 448 
 449                         mbx->rx_mbmem_pushed++;
 450 
 451                         /* read message from hardware FIFO */
 452                         *(tail++) = fm10k_read_reg(hw, mbmem + head++);
 453                 } while (--len && --end);
 454         }
 455 
 456         /* memory barrier to guarantee FIFO is written before tail update */
 457         wmb();
 458 }
 459 
 460 /**
 461  *  fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
 462  *  @hw: pointer to hardware structure
 463  *  @mbx: pointer to mailbox
 464  *  @tail: tail index of message
 465  *
 466  *  This function will first validate the tail index and size for the
 467  *  incoming message.  It then updates the acknowledgment number and
 468  *  copies the data into the FIFO.  It will return the number of messages
 469  *  dequeued on success and a negative value on error.
 470  **/
 471 static s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
 472                                struct fm10k_mbx_info *mbx,
 473                                u16 tail)
 474 {
 475         struct fm10k_mbx_fifo *fifo = &mbx->rx;
 476         u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
 477 
 478         /* determine length of data to push */
 479         len = fm10k_fifo_unused(fifo) - mbx->pushed;
 480         if (len > seq)
 481                 len = seq;
 482 
 483         /* update head and record bytes received */
 484         mbx->head = fm10k_mbx_head_add(mbx, len);
 485         mbx->head_len = len;
 486 
 487         /* nothing to do if there is no data */
 488         if (!len)
 489                 return 0;
 490 
 491         /* Copy msg into Rx FIFO */
 492         fm10k_mbx_read_copy(hw, mbx);
 493 
 494         /* determine if there are any invalid lengths in message */
 495         if (fm10k_mbx_validate_msg_size(mbx, len))
 496                 return FM10K_MBX_ERR_SIZE;
 497 
 498         /* Update pushed */
 499         mbx->pushed += len;
 500 
 501         /* flush any completed messages */
 502         for (len = fm10k_mbx_pushed_tail_len(mbx);
 503              len && (mbx->pushed >= len);
 504              len = fm10k_mbx_pushed_tail_len(mbx)) {
 505                 fifo->tail += len;
 506                 mbx->pushed -= len;
 507                 mbx->rx_messages++;
 508                 mbx->rx_dwords += len;
 509         }
 510 
 511         return 0;
 512 }
 513 
 514 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
 515 static const u16 fm10k_crc_16b_table[256] = {
 516         0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
 517         0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
 518         0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
 519         0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
 520         0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
 521         0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
 522         0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
 523         0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
 524         0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
 525         0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
 526         0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
 527         0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
 528         0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
 529         0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
 530         0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
 531         0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
 532         0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
 533         0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
 534         0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
 535         0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
 536         0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
 537         0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
 538         0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
 539         0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
 540         0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
 541         0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
 542         0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
 543         0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
 544         0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
 545         0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
 546         0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
 547         0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
 548 
 549 /**
 550  *  fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
 551  *  @data: pointer to data to process
 552  *  @seed: seed value for CRC
 553  *  @len: length measured in 16 bits words
 554  *
 555  *  This function will generate a CRC based on the polynomial 0xAC9A and
 556  *  whatever value is stored in the seed variable.  Note that this
 557  *  value inverts the local seed and the result in order to capture all
 558  *  leading and trailing zeros.
 559  */
 560 static u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
 561 {
 562         u32 result = seed;
 563 
 564         while (len--) {
 565                 result ^= *(data++);
 566                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
 567                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
 568 
 569                 if (!(len--))
 570                         break;
 571 
 572                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
 573                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
 574         }
 575 
 576         return (u16)result;
 577 }
 578 
 579 /**
 580  *  fm10k_fifo_crc - generate a CRC based off of FIFO data
 581  *  @fifo: pointer to FIFO
 582  *  @offset: offset point for start of FIFO
 583  *  @len: number of DWORDS words to process
 584  *  @seed: seed value for CRC
 585  *
 586  *  This function generates a CRC for some region of the FIFO
 587  **/
 588 static u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
 589                           u16 len, u16 seed)
 590 {
 591         u32 *data = fifo->buffer + offset;
 592 
 593         /* track when we should cross the end of the FIFO */
 594         offset = fifo->size - offset;
 595 
 596         /* if we are in 2 blocks process the end of the FIFO first */
 597         if (offset < len) {
 598                 seed = fm10k_crc_16b(data, seed, offset * 2);
 599                 data = fifo->buffer;
 600                 len -= offset;
 601         }
 602 
 603         /* process any remaining bits */
 604         return fm10k_crc_16b(data, seed, len * 2);
 605 }
 606 
 607 /**
 608  *  fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
 609  *  @mbx: pointer to mailbox
 610  *  @head: head index provided by remote mailbox
 611  *
 612  *  This function will generate the CRC for all data from the end of the
 613  *  last head update to the current one.  It uses the result of the
 614  *  previous CRC as the seed for this update.  The result is stored in
 615  *  mbx->local.
 616  **/
 617 static void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
 618 {
 619         u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
 620 
 621         /* determine the offset for the start of the region to be pulled */
 622         head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
 623 
 624         /* update local CRC to include all of the pulled data */
 625         mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
 626 }
 627 
 628 /**
 629  *  fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
 630  *  @mbx: pointer to mailbox
 631  *
 632  *  This function will take all data that has been provided from the remote
 633  *  end and generate a CRC for it.  This is stored in mbx->remote.  The
 634  *  CRC for the header is then computed and if the result is non-zero this
 635  *  is an error and we signal an error dropping all data and resetting the
 636  *  connection.
 637  */
 638 static s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
 639 {
 640         struct fm10k_mbx_fifo *fifo = &mbx->rx;
 641         u16 len = mbx->head_len;
 642         u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
 643         u16 crc;
 644 
 645         /* update the remote CRC if new data has been received */
 646         if (len)
 647                 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
 648 
 649         /* process the full header as we have to validate the CRC */
 650         crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
 651 
 652         /* notify other end if we have a problem */
 653         return crc ? FM10K_MBX_ERR_CRC : 0;
 654 }
 655 
 656 /**
 657  *  fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
 658  *  @mbx: pointer to mailbox
 659  *
 660  *  This function returns true if there is a message in the Rx FIFO to dequeue.
 661  **/
 662 static bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
 663 {
 664         u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
 665 
 666         return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
 667 }
 668 
 669 /**
 670  *  fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
 671  *  @mbx: pointer to mailbox
 672  *  @len: verify free space is >= this value
 673  *
 674  *  This function returns true if the mailbox is in a state ready to transmit.
 675  **/
 676 static bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
 677 {
 678         u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
 679 
 680         return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
 681 }
 682 
 683 /**
 684  *  fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
 685  *  @mbx: pointer to mailbox
 686  *
 687  *  This function returns true if the Tx FIFO is empty.
 688  **/
 689 static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
 690 {
 691         return fm10k_fifo_empty(&mbx->tx);
 692 }
 693 
 694 /**
 695  *  fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
 696  *  @hw: pointer to hardware structure
 697  *  @mbx: pointer to mailbox
 698  *
 699  *  This function dequeues messages and hands them off to the TLV parser.
 700  *  It will return the number of messages processed when called.
 701  **/
 702 static u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
 703                                 struct fm10k_mbx_info *mbx)
 704 {
 705         struct fm10k_mbx_fifo *fifo = &mbx->rx;
 706         s32 err;
 707         u16 cnt;
 708 
 709         /* parse Rx messages out of the Rx FIFO to empty it */
 710         for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
 711                 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
 712                                           mbx, mbx->msg_data);
 713                 if (err < 0)
 714                         mbx->rx_parse_err++;
 715 
 716                 fm10k_fifo_head_drop(fifo);
 717         }
 718 
 719         /* shift remaining bytes back to start of FIFO */
 720         memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
 721 
 722         /* shift head and tail based on the memory we moved */
 723         fifo->tail -= fifo->head;
 724         fifo->head = 0;
 725 
 726         return cnt;
 727 }
 728 
 729 /**
 730  *  fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
 731  *  @hw: pointer to hardware structure
 732  *  @mbx: pointer to mailbox
 733  *  @msg: message array to read
 734  *
 735  *  This function enqueues a message up to the size specified by the length
 736  *  contained in the first DWORD of the message and will place at the tail
 737  *  of the FIFO.  It will return 0 on success, or a negative value on error.
 738  **/
 739 static s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
 740                                 struct fm10k_mbx_info *mbx, const u32 *msg)
 741 {
 742         u32 countdown = mbx->timeout;
 743         s32 err;
 744 
 745         switch (mbx->state) {
 746         case FM10K_STATE_CLOSED:
 747         case FM10K_STATE_DISCONNECT:
 748                 return FM10K_MBX_ERR_NO_MBX;
 749         default:
 750                 break;
 751         }
 752 
 753         /* enqueue the message on the Tx FIFO */
 754         err = fm10k_fifo_enqueue(&mbx->tx, msg);
 755 
 756         /* if it failed give the FIFO a chance to drain */
 757         while (err && countdown) {
 758                 countdown--;
 759                 udelay(mbx->udelay);
 760                 mbx->ops.process(hw, mbx);
 761                 err = fm10k_fifo_enqueue(&mbx->tx, msg);
 762         }
 763 
 764         /* if we failed treat the error */
 765         if (err) {
 766                 mbx->timeout = 0;
 767                 mbx->tx_busy++;
 768         }
 769 
 770         /* begin processing message, ignore errors as this is just meant
 771          * to start the mailbox flow so we are not concerned if there
 772          * is a bad error, or the mailbox is already busy with a request
 773          */
 774         if (!mbx->tail_len)
 775                 mbx->ops.process(hw, mbx);
 776 
 777         return 0;
 778 }
 779 
 780 /**
 781  *  fm10k_mbx_read - Copies the mbmem to local message buffer
 782  *  @hw: pointer to hardware structure
 783  *  @mbx: pointer to mailbox
 784  *
 785  *  This function copies the message from the mbmem to the message array
 786  **/
 787 static s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
 788 {
 789         /* only allow one reader in here at a time */
 790         if (mbx->mbx_hdr)
 791                 return FM10K_MBX_ERR_BUSY;
 792 
 793         /* read to capture initial interrupt bits */
 794         if (fm10k_read_reg(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
 795                 mbx->mbx_lock = FM10K_MBX_ACK;
 796 
 797         /* write back interrupt bits to clear */
 798         fm10k_write_reg(hw, mbx->mbx_reg,
 799                         FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
 800 
 801         /* read remote header */
 802         mbx->mbx_hdr = fm10k_read_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
 803 
 804         return 0;
 805 }
 806 
 807 /**
 808  *  fm10k_mbx_write - Copies the local message buffer to mbmem
 809  *  @hw: pointer to hardware structure
 810  *  @mbx: pointer to mailbox
 811  *
 812  *  This function copies the message from the the message array to mbmem
 813  **/
 814 static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
 815 {
 816         u32 mbmem = mbx->mbmem_reg;
 817 
 818         /* write new msg header to notify recipient of change */
 819         fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
 820 
 821         /* write mailbox to send interrupt */
 822         if (mbx->mbx_lock)
 823                 fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
 824 
 825         /* we no longer are using the header so free it */
 826         mbx->mbx_hdr = 0;
 827         mbx->mbx_lock = 0;
 828 }
 829 
 830 /**
 831  *  fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
 832  *  @mbx: pointer to mailbox
 833  *
 834  *  This function returns a connection mailbox header
 835  **/
 836 static void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
 837 {
 838         mbx->mbx_lock |= FM10K_MBX_REQ;
 839 
 840         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
 841                        FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
 842                        FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
 843 }
 844 
 845 /**
 846  *  fm10k_mbx_create_data_hdr - Generate a data mailbox header
 847  *  @mbx: pointer to mailbox
 848  *
 849  *  This function returns a data mailbox header
 850  **/
 851 static void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
 852 {
 853         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
 854                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
 855                   FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
 856         struct fm10k_mbx_fifo *fifo = &mbx->tx;
 857         u16 crc;
 858 
 859         if (mbx->tail_len)
 860                 mbx->mbx_lock |= FM10K_MBX_REQ;
 861 
 862         /* generate CRC for data in flight and header */
 863         crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
 864                              mbx->tail_len, mbx->local);
 865         crc = fm10k_crc_16b(&hdr, crc, 1);
 866 
 867         /* load header to memory to be written */
 868         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
 869 }
 870 
 871 /**
 872  *  fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
 873  *  @mbx: pointer to mailbox
 874  *
 875  *  This function returns a disconnect mailbox header
 876  **/
 877 static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
 878 {
 879         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
 880                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
 881                   FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
 882         u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
 883 
 884         mbx->mbx_lock |= FM10K_MBX_ACK;
 885 
 886         /* load header to memory to be written */
 887         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
 888 }
 889 
 890 /**
 891  *  fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mbox hdr
 892  *  @mbx: pointer to mailbox
 893  *
 894  *  This function creates a fake disconnect header for loading into remote
 895  *  mailbox header. The primary purpose is to prevent errors on immediate
 896  *  start up after mbx->connect.
 897  **/
 898 static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
 899 {
 900         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
 901                   FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
 902                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
 903         u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
 904 
 905         mbx->mbx_lock |= FM10K_MBX_ACK;
 906 
 907         /* load header to memory to be written */
 908         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
 909 }
 910 
 911 /**
 912  *  fm10k_mbx_create_error_msg - Generate an error message
 913  *  @mbx: pointer to mailbox
 914  *  @err: local error encountered
 915  *
 916  *  This function will interpret the error provided by err, and based on
 917  *  that it may shift the message by 1 DWORD and then place an error header
 918  *  at the start of the message.
 919  **/
 920 static void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
 921 {
 922         /* only generate an error message for these types */
 923         switch (err) {
 924         case FM10K_MBX_ERR_TAIL:
 925         case FM10K_MBX_ERR_HEAD:
 926         case FM10K_MBX_ERR_TYPE:
 927         case FM10K_MBX_ERR_SIZE:
 928         case FM10K_MBX_ERR_RSVD0:
 929         case FM10K_MBX_ERR_CRC:
 930                 break;
 931         default:
 932                 return;
 933         }
 934 
 935         mbx->mbx_lock |= FM10K_MBX_REQ;
 936 
 937         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
 938                        FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
 939                        FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
 940 }
 941 
 942 /**
 943  *  fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
 944  *  @mbx: pointer to mailbox
 945  *
 946  *  This function will parse up the fields in the mailbox header and return
 947  *  an error if the header contains any of a number of invalid configurations
 948  *  including unrecognized type, invalid route, or a malformed message.
 949  **/
 950 static s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
 951 {
 952         u16 type, rsvd0, head, tail, size;
 953         const u32 *hdr = &mbx->mbx_hdr;
 954 
 955         type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
 956         rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
 957         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
 958         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
 959         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
 960 
 961         if (rsvd0)
 962                 return FM10K_MBX_ERR_RSVD0;
 963 
 964         switch (type) {
 965         case FM10K_MSG_DISCONNECT:
 966                 /* validate that all data has been received */
 967                 if (tail != mbx->head)
 968                         return FM10K_MBX_ERR_TAIL;
 969 
 970                 /* fall through */
 971         case FM10K_MSG_DATA:
 972                 /* validate that head is moving correctly */
 973                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
 974                         return FM10K_MBX_ERR_HEAD;
 975                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
 976                         return FM10K_MBX_ERR_HEAD;
 977 
 978                 /* validate that tail is moving correctly */
 979                 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
 980                         return FM10K_MBX_ERR_TAIL;
 981                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
 982                         break;
 983 
 984                 return FM10K_MBX_ERR_TAIL;
 985         case FM10K_MSG_CONNECT:
 986                 /* validate size is in range and is power of 2 mask */
 987                 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
 988                         return FM10K_MBX_ERR_SIZE;
 989 
 990                 /* fall through */
 991         case FM10K_MSG_ERROR:
 992                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
 993                         return FM10K_MBX_ERR_HEAD;
 994                 /* neither create nor error include a tail offset */
 995                 if (tail)
 996                         return FM10K_MBX_ERR_TAIL;
 997 
 998                 break;
 999         default:
1000                 return FM10K_MBX_ERR_TYPE;
1001         }
1002 
1003         return 0;
1004 }
1005 
1006 /**
1007  *  fm10k_mbx_create_reply - Generate reply based on state and remote head
1008  *  @hw: pointer to hardware structure
1009  *  @mbx: pointer to mailbox
1010  *  @head: acknowledgement number
1011  *
1012  *  This function will generate an outgoing message based on the current
1013  *  mailbox state and the remote FIFO head.  It will return the length
1014  *  of the outgoing message excluding header on success, and a negative value
1015  *  on error.
1016  **/
1017 static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1018                                   struct fm10k_mbx_info *mbx, u16 head)
1019 {
1020         switch (mbx->state) {
1021         case FM10K_STATE_OPEN:
1022         case FM10K_STATE_DISCONNECT:
1023                 /* update our checksum for the outgoing data */
1024                 fm10k_mbx_update_local_crc(mbx, head);
1025 
1026                 /* as long as other end recognizes us keep sending data */
1027                 fm10k_mbx_pull_head(hw, mbx, head);
1028 
1029                 /* generate new header based on data */
1030                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1031                         fm10k_mbx_create_data_hdr(mbx);
1032                 else
1033                         fm10k_mbx_create_disconnect_hdr(mbx);
1034                 break;
1035         case FM10K_STATE_CONNECT:
1036                 /* send disconnect even if we aren't connected */
1037                 fm10k_mbx_create_connect_hdr(mbx);
1038                 break;
1039         case FM10K_STATE_CLOSED:
1040                 /* generate new header based on data */
1041                 fm10k_mbx_create_disconnect_hdr(mbx);
1042         default:
1043                 break;
1044         }
1045 
1046         return 0;
1047 }
1048 
1049 /**
1050  *  fm10k_mbx_reset_work- Reset internal pointers for any pending work
1051  *  @mbx: pointer to mailbox
1052  *
1053  *  This function will reset all internal pointers so any work in progress
1054  *  is dropped.  This call should occur every time we transition from the
1055  *  open state to the connect state.
1056  **/
1057 static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1058 {
1059         u16 len, head, ack;
1060 
1061         /* reset our outgoing max size back to Rx limits */
1062         mbx->max_size = mbx->rx.size - 1;
1063 
1064         /* update mbx->pulled to account for tail_len and ack */
1065         head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1066         ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1067         mbx->pulled += mbx->tail_len - ack;
1068 
1069         /* now drop any messages which have started or finished transmitting */
1070         while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1071                 len = fm10k_fifo_head_drop(&mbx->tx);
1072                 mbx->tx_dropped++;
1073                 if (mbx->pulled >= len)
1074                         mbx->pulled -= len;
1075                 else
1076                         mbx->pulled = 0;
1077         }
1078 
1079         /* just do a quick resysnc to start of message */
1080         mbx->pushed = 0;
1081         mbx->pulled = 0;
1082         mbx->tail_len = 0;
1083         mbx->head_len = 0;
1084         mbx->rx.tail = 0;
1085         mbx->rx.head = 0;
1086 }
1087 
1088 /**
1089  *  fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1090  *  @mbx: pointer to mailbox
1091  *  @size: new value for max_size
1092  *
1093  *  This function updates the max_size value and drops any outgoing messages
1094  *  at the head of the Tx FIFO if they are larger than max_size. It does not
1095  *  drop all messages, as this is too difficult to parse and remove them from
1096  *  the FIFO. Instead, rely on the checking to ensure that messages larger
1097  *  than max_size aren't pushed into the memory buffer.
1098  **/
1099 static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1100 {
1101         u16 len;
1102 
1103         mbx->max_size = size;
1104 
1105         /* flush any oversized messages from the queue */
1106         for (len = fm10k_fifo_head_len(&mbx->tx);
1107              len > size;
1108              len = fm10k_fifo_head_len(&mbx->tx)) {
1109                 fm10k_fifo_head_drop(&mbx->tx);
1110                 mbx->tx_dropped++;
1111         }
1112 }
1113 
1114 /**
1115  *  fm10k_mbx_connect_reset - Reset following request for reset
1116  *  @mbx: pointer to mailbox
1117  *
1118  *  This function resets the mailbox to either a disconnected state
1119  *  or a connect state depending on the current mailbox state
1120  **/
1121 static void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1122 {
1123         /* just do a quick resysnc to start of frame */
1124         fm10k_mbx_reset_work(mbx);
1125 
1126         /* reset CRC seeds */
1127         mbx->local = FM10K_MBX_CRC_SEED;
1128         mbx->remote = FM10K_MBX_CRC_SEED;
1129 
1130         /* we cannot exit connect until the size is good */
1131         if (mbx->state == FM10K_STATE_OPEN)
1132                 mbx->state = FM10K_STATE_CONNECT;
1133         else
1134                 mbx->state = FM10K_STATE_CLOSED;
1135 }
1136 
1137 /**
1138  *  fm10k_mbx_process_connect - Process connect header
1139  *  @hw: pointer to hardware structure
1140  *  @mbx: pointer to mailbox
1141  *
1142  *  This function will read an incoming connect header and reply with the
1143  *  appropriate message.  It will return a value indicating the number of
1144  *  data DWORDs on success, or will return a negative value on failure.
1145  **/
1146 static s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1147                                      struct fm10k_mbx_info *mbx)
1148 {
1149         const enum fm10k_mbx_state state = mbx->state;
1150         const u32 *hdr = &mbx->mbx_hdr;
1151         u16 size, head;
1152 
1153         /* we will need to pull all of the fields for verification */
1154         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1155         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1156 
1157         switch (state) {
1158         case FM10K_STATE_DISCONNECT:
1159         case FM10K_STATE_OPEN:
1160                 /* reset any in-progress work */
1161                 fm10k_mbx_connect_reset(mbx);
1162                 break;
1163         case FM10K_STATE_CONNECT:
1164                 /* we cannot exit connect until the size is good */
1165                 if (size > mbx->rx.size) {
1166                         mbx->max_size = mbx->rx.size - 1;
1167                 } else {
1168                         /* record the remote system requesting connection */
1169                         mbx->state = FM10K_STATE_OPEN;
1170 
1171                         fm10k_mbx_update_max_size(mbx, size);
1172                 }
1173                 break;
1174         default:
1175                 break;
1176         }
1177 
1178         /* align our tail index to remote head index */
1179         mbx->tail = head;
1180 
1181         return fm10k_mbx_create_reply(hw, mbx, head);
1182 }
1183 
1184 /**
1185  *  fm10k_mbx_process_data - Process data header
1186  *  @hw: pointer to hardware structure
1187  *  @mbx: pointer to mailbox
1188  *
1189  *  This function will read an incoming data header and reply with the
1190  *  appropriate message.  It will return a value indicating the number of
1191  *  data DWORDs on success, or will return a negative value on failure.
1192  **/
1193 static s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1194                                   struct fm10k_mbx_info *mbx)
1195 {
1196         const u32 *hdr = &mbx->mbx_hdr;
1197         u16 head, tail;
1198         s32 err;
1199 
1200         /* we will need to pull all of the fields for verification */
1201         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1202         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1203 
1204         /* if we are in connect just update our data and go */
1205         if (mbx->state == FM10K_STATE_CONNECT) {
1206                 mbx->tail = head;
1207                 mbx->state = FM10K_STATE_OPEN;
1208         }
1209 
1210         /* abort on message size errors */
1211         err = fm10k_mbx_push_tail(hw, mbx, tail);
1212         if (err < 0)
1213                 return err;
1214 
1215         /* verify the checksum on the incoming data */
1216         err = fm10k_mbx_verify_remote_crc(mbx);
1217         if (err)
1218                 return err;
1219 
1220         /* process messages if we have received any */
1221         fm10k_mbx_dequeue_rx(hw, mbx);
1222 
1223         return fm10k_mbx_create_reply(hw, mbx, head);
1224 }
1225 
1226 /**
1227  *  fm10k_mbx_process_disconnect - Process disconnect header
1228  *  @hw: pointer to hardware structure
1229  *  @mbx: pointer to mailbox
1230  *
1231  *  This function will read an incoming disconnect header and reply with the
1232  *  appropriate message.  It will return a value indicating the number of
1233  *  data DWORDs on success, or will return a negative value on failure.
1234  **/
1235 static s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1236                                         struct fm10k_mbx_info *mbx)
1237 {
1238         const enum fm10k_mbx_state state = mbx->state;
1239         const u32 *hdr = &mbx->mbx_hdr;
1240         u16 head;
1241         s32 err;
1242 
1243         /* we will need to pull the header field for verification */
1244         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1245 
1246         /* We should not be receiving disconnect if Rx is incomplete */
1247         if (mbx->pushed)
1248                 return FM10K_MBX_ERR_TAIL;
1249 
1250         /* we have already verified mbx->head == tail so we know this is 0 */
1251         mbx->head_len = 0;
1252 
1253         /* verify the checksum on the incoming header is correct */
1254         err = fm10k_mbx_verify_remote_crc(mbx);
1255         if (err)
1256                 return err;
1257 
1258         switch (state) {
1259         case FM10K_STATE_DISCONNECT:
1260         case FM10K_STATE_OPEN:
1261                 /* state doesn't change if we still have work to do */
1262                 if (!fm10k_mbx_tx_complete(mbx))
1263                         break;
1264 
1265                 /* verify the head indicates we completed all transmits */
1266                 if (head != mbx->tail)
1267                         return FM10K_MBX_ERR_HEAD;
1268 
1269                 /* reset any in-progress work */
1270                 fm10k_mbx_connect_reset(mbx);
1271                 break;
1272         default:
1273                 break;
1274         }
1275 
1276         return fm10k_mbx_create_reply(hw, mbx, head);
1277 }
1278 
1279 /**
1280  *  fm10k_mbx_process_error - Process error header
1281  *  @hw: pointer to hardware structure
1282  *  @mbx: pointer to mailbox
1283  *
1284  *  This function will read an incoming error header and reply with the
1285  *  appropriate message.  It will return a value indicating the number of
1286  *  data DWORDs on success, or will return a negative value on failure.
1287  **/
1288 static s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1289                                    struct fm10k_mbx_info *mbx)
1290 {
1291         const u32 *hdr = &mbx->mbx_hdr;
1292         u16 head;
1293 
1294         /* we will need to pull all of the fields for verification */
1295         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1296 
1297         switch (mbx->state) {
1298         case FM10K_STATE_OPEN:
1299         case FM10K_STATE_DISCONNECT:
1300                 /* flush any uncompleted work */
1301                 fm10k_mbx_reset_work(mbx);
1302 
1303                 /* reset CRC seeds */
1304                 mbx->local = FM10K_MBX_CRC_SEED;
1305                 mbx->remote = FM10K_MBX_CRC_SEED;
1306 
1307                 /* reset tail index and size to prepare for reconnect */
1308                 mbx->tail = head;
1309 
1310                 /* if open then reset max_size and go back to connect */
1311                 if (mbx->state == FM10K_STATE_OPEN) {
1312                         mbx->state = FM10K_STATE_CONNECT;
1313                         break;
1314                 }
1315 
1316                 /* send a connect message to get data flowing again */
1317                 fm10k_mbx_create_connect_hdr(mbx);
1318                 return 0;
1319         default:
1320                 break;
1321         }
1322 
1323         return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1324 }
1325 
1326 /**
1327  *  fm10k_mbx_process - Process mailbox interrupt
1328  *  @hw: pointer to hardware structure
1329  *  @mbx: pointer to mailbox
1330  *
1331  *  This function will process incoming mailbox events and generate mailbox
1332  *  replies.  It will return a value indicating the number of DWORDs
1333  *  transmitted excluding header on success or a negative value on error.
1334  **/
1335 static s32 fm10k_mbx_process(struct fm10k_hw *hw,
1336                              struct fm10k_mbx_info *mbx)
1337 {
1338         s32 err;
1339 
1340         /* we do not read mailbox if closed */
1341         if (mbx->state == FM10K_STATE_CLOSED)
1342                 return 0;
1343 
1344         /* copy data from mailbox */
1345         err = fm10k_mbx_read(hw, mbx);
1346         if (err)
1347                 return err;
1348 
1349         /* validate type, source, and destination */
1350         err = fm10k_mbx_validate_msg_hdr(mbx);
1351         if (err < 0)
1352                 goto msg_err;
1353 
1354         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1355         case FM10K_MSG_CONNECT:
1356                 err = fm10k_mbx_process_connect(hw, mbx);
1357                 break;
1358         case FM10K_MSG_DATA:
1359                 err = fm10k_mbx_process_data(hw, mbx);
1360                 break;
1361         case FM10K_MSG_DISCONNECT:
1362                 err = fm10k_mbx_process_disconnect(hw, mbx);
1363                 break;
1364         case FM10K_MSG_ERROR:
1365                 err = fm10k_mbx_process_error(hw, mbx);
1366                 break;
1367         default:
1368                 err = FM10K_MBX_ERR_TYPE;
1369                 break;
1370         }
1371 
1372 msg_err:
1373         /* notify partner of errors on our end */
1374         if (err < 0)
1375                 fm10k_mbx_create_error_msg(mbx, err);
1376 
1377         /* copy data from mailbox */
1378         fm10k_mbx_write(hw, mbx);
1379 
1380         return err;
1381 }
1382 
1383 /**
1384  *  fm10k_mbx_disconnect - Shutdown mailbox connection
1385  *  @hw: pointer to hardware structure
1386  *  @mbx: pointer to mailbox
1387  *
1388  *  This function will shut down the mailbox.  It places the mailbox first
1389  *  in the disconnect state, it then allows up to a predefined timeout for
1390  *  the mailbox to transition to close on its own.  If this does not occur
1391  *  then the mailbox will be forced into the closed state.
1392  *
1393  *  Any mailbox transactions not completed before calling this function
1394  *  are not guaranteed to complete and may be dropped.
1395  **/
1396 static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1397                                  struct fm10k_mbx_info *mbx)
1398 {
1399         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1400 
1401         /* Place mbx in ready to disconnect state */
1402         mbx->state = FM10K_STATE_DISCONNECT;
1403 
1404         /* trigger interrupt to start shutdown process */
1405         fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1406                                           FM10K_MBX_INTERRUPT_DISABLE);
1407         do {
1408                 udelay(FM10K_MBX_POLL_DELAY);
1409                 mbx->ops.process(hw, mbx);
1410                 timeout -= FM10K_MBX_POLL_DELAY;
1411         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1412 
1413         /* in case we didn't close, just force the mailbox into shutdown and
1414          * drop all left over messages in the FIFO.
1415          */
1416         fm10k_mbx_connect_reset(mbx);
1417         fm10k_fifo_drop_all(&mbx->tx);
1418 
1419         fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1420 }
1421 
1422 /**
1423  *  fm10k_mbx_connect - Start mailbox connection
1424  *  @hw: pointer to hardware structure
1425  *  @mbx: pointer to mailbox
1426  *
1427  *  This function will initiate a mailbox connection.  It will populate the
1428  *  mailbox with a broadcast connect message and then initialize the lock.
1429  *  This is safe since the connect message is a single DWORD so the mailbox
1430  *  transaction is guaranteed to be atomic.
1431  *
1432  *  This function will return an error if the mailbox has not been initiated
1433  *  or is currently in use.
1434  **/
1435 static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1436 {
1437         /* we cannot connect an uninitialized mailbox */
1438         if (!mbx->rx.buffer)
1439                 return FM10K_MBX_ERR_NO_SPACE;
1440 
1441         /* we cannot connect an already connected mailbox */
1442         if (mbx->state != FM10K_STATE_CLOSED)
1443                 return FM10K_MBX_ERR_BUSY;
1444 
1445         /* mailbox timeout can now become active */
1446         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1447 
1448         /* Place mbx in ready to connect state */
1449         mbx->state = FM10K_STATE_CONNECT;
1450 
1451         fm10k_mbx_reset_work(mbx);
1452 
1453         /* initialize header of remote mailbox */
1454         fm10k_mbx_create_fake_disconnect_hdr(mbx);
1455         fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1456 
1457         /* enable interrupt and notify other party of new message */
1458         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1459                         FM10K_MBX_INTERRUPT_ENABLE;
1460 
1461         /* generate and load connect header into mailbox */
1462         fm10k_mbx_create_connect_hdr(mbx);
1463         fm10k_mbx_write(hw, mbx);
1464 
1465         return 0;
1466 }
1467 
1468 /**
1469  *  fm10k_mbx_validate_handlers - Validate layout of message parsing data
1470  *  @msg_data: handlers for mailbox events
1471  *
1472  *  This function validates the layout of the message parsing data.  This
1473  *  should be mostly static, but it is important to catch any errors that
1474  *  are made when constructing the parsers.
1475  **/
1476 static s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1477 {
1478         const struct fm10k_tlv_attr *attr;
1479         unsigned int id;
1480 
1481         /* Allow NULL mailboxes that transmit but don't receive */
1482         if (!msg_data)
1483                 return 0;
1484 
1485         while (msg_data->id != FM10K_TLV_ERROR) {
1486                 /* all messages should have a function handler */
1487                 if (!msg_data->func)
1488                         return FM10K_ERR_PARAM;
1489 
1490                 /* parser is optional */
1491                 attr = msg_data->attr;
1492                 if (attr) {
1493                         while (attr->id != FM10K_TLV_ERROR) {
1494                                 id = attr->id;
1495                                 attr++;
1496                                 /* ID should always be increasing */
1497                                 if (id >= attr->id)
1498                                         return FM10K_ERR_PARAM;
1499                                 /* ID should fit in results array */
1500                                 if (id >= FM10K_TLV_RESULTS_MAX)
1501                                         return FM10K_ERR_PARAM;
1502                         }
1503 
1504                         /* verify terminator is in the list */
1505                         if (attr->id != FM10K_TLV_ERROR)
1506                                 return FM10K_ERR_PARAM;
1507                 }
1508 
1509                 id = msg_data->id;
1510                 msg_data++;
1511                 /* ID should always be increasing */
1512                 if (id >= msg_data->id)
1513                         return FM10K_ERR_PARAM;
1514         }
1515 
1516         /* verify terminator is in the list */
1517         if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1518                 return FM10K_ERR_PARAM;
1519 
1520         return 0;
1521 }
1522 
1523 /**
1524  *  fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1525  *  @mbx: pointer to mailbox
1526  *  @msg_data: handlers for mailbox events
1527  *
1528  *  This function associates a set of message handling ops with a mailbox.
1529  **/
1530 static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1531                                        const struct fm10k_msg_data *msg_data)
1532 {
1533         /* validate layout of handlers before assigning them */
1534         if (fm10k_mbx_validate_handlers(msg_data))
1535                 return FM10K_ERR_PARAM;
1536 
1537         /* initialize the message handlers */
1538         mbx->msg_data = msg_data;
1539 
1540         return 0;
1541 }
1542 
1543 /**
1544  *  fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1545  *  @hw: pointer to hardware structure
1546  *  @mbx: pointer to mailbox
1547  *  @msg_data: handlers for mailbox events
1548  *  @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1549  *
1550  *  This function initializes the mailbox for use.  It will split the
1551  *  buffer provided and use that to populate both the Tx and Rx FIFO by
1552  *  evenly splitting it.  In order to allow for easy masking of head/tail
1553  *  the value reported in size must be a power of 2 and is reported in
1554  *  DWORDs, not bytes.  Any invalid values will cause the mailbox to return
1555  *  error.
1556  **/
1557 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1558                         const struct fm10k_msg_data *msg_data, u8 id)
1559 {
1560         /* initialize registers */
1561         switch (hw->mac.type) {
1562         case fm10k_mac_vf:
1563                 mbx->mbx_reg = FM10K_VFMBX;
1564                 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1565                 break;
1566         case fm10k_mac_pf:
1567                 /* there are only 64 VF <-> PF mailboxes */
1568                 if (id < 64) {
1569                         mbx->mbx_reg = FM10K_MBX(id);
1570                         mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1571                         break;
1572                 }
1573                 /* fall through */
1574         default:
1575                 return FM10K_MBX_ERR_NO_MBX;
1576         }
1577 
1578         /* start out in closed state */
1579         mbx->state = FM10K_STATE_CLOSED;
1580 
1581         /* validate layout of handlers before assigning them */
1582         if (fm10k_mbx_validate_handlers(msg_data))
1583                 return FM10K_ERR_PARAM;
1584 
1585         /* initialize the message handlers */
1586         mbx->msg_data = msg_data;
1587 
1588         /* start mailbox as timed out and let the reset_hw call
1589          * set the timeout value to begin communications
1590          */
1591         mbx->timeout = 0;
1592         mbx->udelay = FM10K_MBX_INIT_DELAY;
1593 
1594         /* initialize tail and head */
1595         mbx->tail = 1;
1596         mbx->head = 1;
1597 
1598         /* initialize CRC seeds */
1599         mbx->local = FM10K_MBX_CRC_SEED;
1600         mbx->remote = FM10K_MBX_CRC_SEED;
1601 
1602         /* Split buffer for use by Tx/Rx FIFOs */
1603         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1604         mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1605 
1606         /* initialize the FIFOs, sizes are in 4 byte increments */
1607         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1608         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1609                         FM10K_MBX_RX_BUFFER_SIZE);
1610 
1611         /* initialize function pointers */
1612         mbx->ops.connect = fm10k_mbx_connect;
1613         mbx->ops.disconnect = fm10k_mbx_disconnect;
1614         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1615         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1616         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1617         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1618         mbx->ops.process = fm10k_mbx_process;
1619         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1620 
1621         return 0;
1622 }
1623 
1624 /**
1625  *  fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1626  *  @mbx: pointer to mailbox
1627  *
1628  *  This function returns a data mailbox header
1629  **/
1630 static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1631 {
1632         if (mbx->tail_len)
1633                 mbx->mbx_lock |= FM10K_MBX_REQ;
1634 
1635         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1636                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1637                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1638 }
1639 
1640 /**
1641  *  fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1642  *  @mbx: pointer to mailbox
1643  *  @err: error flags to report if any
1644  *
1645  *  This function returns a connection mailbox header
1646  **/
1647 static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1648 {
1649         if (mbx->local)
1650                 mbx->mbx_lock |= FM10K_MBX_REQ;
1651 
1652         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1653                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1654                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1655                        FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1656 }
1657 
1658 /**
1659  *  fm10k_sm_mbx_connect_reset - Reset following request for reset
1660  *  @mbx: pointer to mailbox
1661  *
1662  *  This function resets the mailbox to a just connected state
1663  **/
1664 static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1665 {
1666         /* flush any uncompleted work */
1667         fm10k_mbx_reset_work(mbx);
1668 
1669         /* set local version to max and remote version to 0 */
1670         mbx->local = FM10K_SM_MBX_VERSION;
1671         mbx->remote = 0;
1672 
1673         /* initialize tail and head */
1674         mbx->tail = 1;
1675         mbx->head = 1;
1676 
1677         /* reset state back to connect */
1678         mbx->state = FM10K_STATE_CONNECT;
1679 }
1680 
1681 /**
1682  *  fm10k_sm_mbx_connect - Start switch manager mailbox connection
1683  *  @hw: pointer to hardware structure
1684  *  @mbx: pointer to mailbox
1685  *
1686  *  This function will initiate a mailbox connection with the switch
1687  *  manager.  To do this it will first disconnect the mailbox, and then
1688  *  reconnect it in order to complete a reset of the mailbox.
1689  *
1690  *  This function will return an error if the mailbox has not been initiated
1691  *  or is currently in use.
1692  **/
1693 static s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1694 {
1695         /* we cannot connect an uninitialized mailbox */
1696         if (!mbx->rx.buffer)
1697                 return FM10K_MBX_ERR_NO_SPACE;
1698 
1699         /* we cannot connect an already connected mailbox */
1700         if (mbx->state != FM10K_STATE_CLOSED)
1701                 return FM10K_MBX_ERR_BUSY;
1702 
1703         /* mailbox timeout can now become active */
1704         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1705 
1706         /* Place mbx in ready to connect state */
1707         mbx->state = FM10K_STATE_CONNECT;
1708         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1709 
1710         /* reset interface back to connect */
1711         fm10k_sm_mbx_connect_reset(mbx);
1712 
1713         /* enable interrupt and notify other party of new message */
1714         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1715                         FM10K_MBX_INTERRUPT_ENABLE;
1716 
1717         /* generate and load connect header into mailbox */
1718         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1719         fm10k_mbx_write(hw, mbx);
1720 
1721         return 0;
1722 }
1723 
1724 /**
1725  *  fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1726  *  @hw: pointer to hardware structure
1727  *  @mbx: pointer to mailbox
1728  *
1729  *  This function will shut down the mailbox.  It places the mailbox first
1730  *  in the disconnect state, it then allows up to a predefined timeout for
1731  *  the mailbox to transition to close on its own.  If this does not occur
1732  *  then the mailbox will be forced into the closed state.
1733  *
1734  *  Any mailbox transactions not completed before calling this function
1735  *  are not guaranteed to complete and may be dropped.
1736  **/
1737 static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1738                                     struct fm10k_mbx_info *mbx)
1739 {
1740         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1741 
1742         /* Place mbx in ready to disconnect state */
1743         mbx->state = FM10K_STATE_DISCONNECT;
1744 
1745         /* trigger interrupt to start shutdown process */
1746         fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1747                                           FM10K_MBX_INTERRUPT_DISABLE);
1748         do {
1749                 udelay(FM10K_MBX_POLL_DELAY);
1750                 mbx->ops.process(hw, mbx);
1751                 timeout -= FM10K_MBX_POLL_DELAY;
1752         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1753 
1754         /* in case we didn't close just force the mailbox into shutdown */
1755         mbx->state = FM10K_STATE_CLOSED;
1756         mbx->remote = 0;
1757         fm10k_mbx_reset_work(mbx);
1758         fm10k_fifo_drop_all(&mbx->tx);
1759 
1760         fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1761 }
1762 
1763 /**
1764  *  fm10k_sm_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1765  *  @mbx: pointer to mailbox
1766  *
1767  *  This function will parse up the fields in the mailbox header and return
1768  *  an error if the header contains any of a number of invalid configurations
1769  *  including unrecognized offsets or version numbers.
1770  **/
1771 static s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1772 {
1773         const u32 *hdr = &mbx->mbx_hdr;
1774         u16 tail, head, ver;
1775 
1776         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1777         ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1778         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1779 
1780         switch (ver) {
1781         case 0:
1782                 break;
1783         case FM10K_SM_MBX_VERSION:
1784                 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1785                         return FM10K_MBX_ERR_HEAD;
1786                 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1787                         return FM10K_MBX_ERR_TAIL;
1788                 if (mbx->tail < head)
1789                         head += mbx->mbmem_len - 1;
1790                 if (tail < mbx->head)
1791                         tail += mbx->mbmem_len - 1;
1792                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1793                         return FM10K_MBX_ERR_HEAD;
1794                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1795                         break;
1796                 return FM10K_MBX_ERR_TAIL;
1797         default:
1798                 return FM10K_MBX_ERR_SRC;
1799         }
1800 
1801         return 0;
1802 }
1803 
1804 /**
1805  *  fm10k_sm_mbx_process_error - Process header with error flag set
1806  *  @mbx: pointer to mailbox
1807  *
1808  *  This function is meant to respond to a request where the error flag
1809  *  is set.  As a result we will terminate a connection if one is present
1810  *  and fall back into the reset state with a connection header of version
1811  *  0 (RESET).
1812  **/
1813 static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1814 {
1815         const enum fm10k_mbx_state state = mbx->state;
1816 
1817         switch (state) {
1818         case FM10K_STATE_DISCONNECT:
1819                 /* if there is an error just disconnect */
1820                 mbx->remote = 0;
1821                 break;
1822         case FM10K_STATE_OPEN:
1823                 /* flush any uncompleted work */
1824                 fm10k_sm_mbx_connect_reset(mbx);
1825                 break;
1826         case FM10K_STATE_CONNECT:
1827                 /* try connnecting at lower version */
1828                 if (mbx->remote) {
1829                         while (mbx->local > 1)
1830                                 mbx->local--;
1831                         mbx->remote = 0;
1832                 }
1833                 break;
1834         default:
1835                 break;
1836         }
1837 
1838         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1839 }
1840 
1841 /**
1842  *  fm10k_sm_mbx_create_error_msg - Process an error in FIFO header
1843  *  @mbx: pointer to mailbox
1844  *  @err: local error encountered
1845  *
1846  *  This function will interpret the error provided by err, and based on
1847  *  that it may set the error bit in the local message header
1848  **/
1849 static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1850 {
1851         /* only generate an error message for these types */
1852         switch (err) {
1853         case FM10K_MBX_ERR_TAIL:
1854         case FM10K_MBX_ERR_HEAD:
1855         case FM10K_MBX_ERR_SRC:
1856         case FM10K_MBX_ERR_SIZE:
1857         case FM10K_MBX_ERR_RSVD0:
1858                 break;
1859         default:
1860                 return;
1861         }
1862 
1863         /* process it as though we received an error, and send error reply */
1864         fm10k_sm_mbx_process_error(mbx);
1865         fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1866 }
1867 
1868 /**
1869  *  fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1870  *  @hw: pointer to hardware structure
1871  *  @mbx: pointer to mailbox
1872  *  @tail: tail index of message
1873  *
1874  *  This function will dequeue one message from the Rx switch manager mailbox
1875  *  FIFO and place it in the Rx mailbox FIFO for processing by software.
1876  **/
1877 static s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1878                                 struct fm10k_mbx_info *mbx,
1879                                 u16 tail)
1880 {
1881         /* reduce length by 1 to convert to a mask */
1882         u16 mbmem_len = mbx->mbmem_len - 1;
1883         s32 err;
1884 
1885         /* push tail in front of head */
1886         if (tail < mbx->head)
1887                 tail += mbmem_len;
1888 
1889         /* copy data to the Rx FIFO */
1890         err = fm10k_mbx_push_tail(hw, mbx, tail);
1891         if (err < 0)
1892                 return err;
1893 
1894         /* process messages if we have received any */
1895         fm10k_mbx_dequeue_rx(hw, mbx);
1896 
1897         /* guarantee head aligns with the end of the last message */
1898         mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1899         mbx->pushed = 0;
1900 
1901         /* clear any extra bits left over since index adds 1 extra bit */
1902         if (mbx->head > mbmem_len)
1903                 mbx->head -= mbmem_len;
1904 
1905         return err;
1906 }
1907 
1908 /**
1909  *  fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1910  *  @hw: pointer to hardware structure
1911  *  @mbx: pointer to mailbox
1912  *  @head: head index of message
1913  *
1914  *  This function will dequeue one message from the Tx mailbox FIFO and place
1915  *  it in the Tx switch manager mailbox FIFO for processing by hardware.
1916  **/
1917 static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1918                                   struct fm10k_mbx_info *mbx, u16 head)
1919 {
1920         struct fm10k_mbx_fifo *fifo = &mbx->tx;
1921         /* reduce length by 1 to convert to a mask */
1922         u16 mbmem_len = mbx->mbmem_len - 1;
1923         u16 tail_len, len = 0;
1924 
1925         /* push head behind tail */
1926         if (mbx->tail < head)
1927                 head += mbmem_len;
1928 
1929         fm10k_mbx_pull_head(hw, mbx, head);
1930 
1931         /* determine msg aligned offset for end of buffer */
1932         do {
1933                 u32 *msg;
1934 
1935                 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1936                 tail_len = len;
1937                 len += FM10K_TLV_DWORD_LEN(*msg);
1938         } while ((len <= mbx->tail_len) && (len < mbmem_len));
1939 
1940         /* guarantee we stop on a message boundary */
1941         if (mbx->tail_len > tail_len) {
1942                 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1943                 mbx->tail_len = tail_len;
1944         }
1945 
1946         /* clear any extra bits left over since index adds 1 extra bit */
1947         if (mbx->tail > mbmem_len)
1948                 mbx->tail -= mbmem_len;
1949 }
1950 
1951 /**
1952  *  fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1953  *  @hw: pointer to hardware structure
1954  *  @mbx: pointer to mailbox
1955  *  @head: acknowledgement number
1956  *
1957  *  This function will generate an outgoing message based on the current
1958  *  mailbox state and the remote FIFO head.  It will return the length
1959  *  of the outgoing message excluding header on success, and a negative value
1960  *  on error.
1961  **/
1962 static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1963                                       struct fm10k_mbx_info *mbx, u16 head)
1964 {
1965         switch (mbx->state) {
1966         case FM10K_STATE_OPEN:
1967         case FM10K_STATE_DISCONNECT:
1968                 /* flush out Tx data */
1969                 fm10k_sm_mbx_transmit(hw, mbx, head);
1970 
1971                 /* generate new header based on data */
1972                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1973                         fm10k_sm_mbx_create_data_hdr(mbx);
1974                 } else {
1975                         mbx->remote = 0;
1976                         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1977                 }
1978                 break;
1979         case FM10K_STATE_CONNECT:
1980         case FM10K_STATE_CLOSED:
1981                 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1982                 break;
1983         default:
1984                 break;
1985         }
1986 }
1987 
1988 /**
1989  *  fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1990  *  @hw: pointer to hardware structure
1991  *  @mbx: pointer to mailbox
1992  *
1993  *  This function is meant to respond to a request where the version data
1994  *  is set to 0.  As such we will either terminate the connection or go
1995  *  into the connect state in order to re-establish the connection.  This
1996  *  function can also be used to respond to an error as the connection
1997  *  resetting would also be a means of dealing with errors.
1998  **/
1999 static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2000                                       struct fm10k_mbx_info *mbx)
2001 {
2002         s32 err = 0;
2003         const enum fm10k_mbx_state state = mbx->state;
2004 
2005         switch (state) {
2006         case FM10K_STATE_DISCONNECT:
2007                 /* drop remote connections and disconnect */
2008                 mbx->state = FM10K_STATE_CLOSED;
2009                 mbx->remote = 0;
2010                 mbx->local = 0;
2011                 break;
2012         case FM10K_STATE_OPEN:
2013                 /* flush any incomplete work */
2014                 fm10k_sm_mbx_connect_reset(mbx);
2015                 err = FM10K_ERR_RESET_REQUESTED;
2016                 break;
2017         case FM10K_STATE_CONNECT:
2018                 /* Update remote value to match local value */
2019                 mbx->remote = mbx->local;
2020         default:
2021                 break;
2022         }
2023 
2024         fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2025 
2026         return err;
2027 }
2028 
2029 /**
2030  *  fm10k_sm_mbx_process_version_1 - Process header with version == 1
2031  *  @hw: pointer to hardware structure
2032  *  @mbx: pointer to mailbox
2033  *
2034  *  This function is meant to process messages received when the remote
2035  *  mailbox is active.
2036  **/
2037 static s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2038                                           struct fm10k_mbx_info *mbx)
2039 {
2040         const u32 *hdr = &mbx->mbx_hdr;
2041         u16 head, tail;
2042         s32 len;
2043 
2044         /* pull all fields needed for verification */
2045         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2046         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2047 
2048         /* if we are in connect and wanting version 1 then start up and go */
2049         if (mbx->state == FM10K_STATE_CONNECT) {
2050                 if (!mbx->remote)
2051                         goto send_reply;
2052                 if (mbx->remote != 1)
2053                         return FM10K_MBX_ERR_SRC;
2054 
2055                 mbx->state = FM10K_STATE_OPEN;
2056         }
2057 
2058         do {
2059                 /* abort on message size errors */
2060                 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2061                 if (len < 0)
2062                         return len;
2063 
2064                 /* continue until we have flushed the Rx FIFO */
2065         } while (len);
2066 
2067 send_reply:
2068         fm10k_sm_mbx_create_reply(hw, mbx, head);
2069 
2070         return 0;
2071 }
2072 
2073 /**
2074  *  fm10k_sm_mbx_process - Process switch manager mailbox interrupt
2075  *  @hw: pointer to hardware structure
2076  *  @mbx: pointer to mailbox
2077  *
2078  *  This function will process incoming mailbox events and generate mailbox
2079  *  replies.  It will return a value indicating the number of DWORDs
2080  *  transmitted excluding header on success or a negative value on error.
2081  **/
2082 static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2083                                 struct fm10k_mbx_info *mbx)
2084 {
2085         s32 err;
2086 
2087         /* we do not read mailbox if closed */
2088         if (mbx->state == FM10K_STATE_CLOSED)
2089                 return 0;
2090 
2091         /* retrieve data from switch manager */
2092         err = fm10k_mbx_read(hw, mbx);
2093         if (err)
2094                 return err;
2095 
2096         err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2097         if (err < 0)
2098                 goto fifo_err;
2099 
2100         if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2101                 fm10k_sm_mbx_process_error(mbx);
2102                 goto fifo_err;
2103         }
2104 
2105         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2106         case 0:
2107                 err = fm10k_sm_mbx_process_reset(hw, mbx);
2108                 break;
2109         case FM10K_SM_MBX_VERSION:
2110                 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2111                 break;
2112         }
2113 
2114 fifo_err:
2115         if (err < 0)
2116                 fm10k_sm_mbx_create_error_msg(mbx, err);
2117 
2118         /* report data to switch manager */
2119         fm10k_mbx_write(hw, mbx);
2120 
2121         return err;
2122 }
2123 
2124 /**
2125  *  fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2126  *  @hw: pointer to hardware structure
2127  *  @mbx: pointer to mailbox
2128  *  @msg_data: handlers for mailbox events
2129  *
2130  *  This function initializes the PF/SM mailbox for use.  It will split the
2131  *  buffer provided and use that to populate both the Tx and Rx FIFO by
2132  *  evenly splitting it.  In order to allow for easy masking of head/tail
2133  *  the value reported in size must be a power of 2 and is reported in
2134  *  DWORDs, not bytes.  Any invalid values will cause the mailbox to return
2135  *  error.
2136  **/
2137 s32 fm10k_sm_mbx_init(struct fm10k_hw __always_unused *hw,
2138                       struct fm10k_mbx_info *mbx,
2139                       const struct fm10k_msg_data *msg_data)
2140 {
2141         mbx->mbx_reg = FM10K_GMBX;
2142         mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2143 
2144         /* start out in closed state */
2145         mbx->state = FM10K_STATE_CLOSED;
2146 
2147         /* validate layout of handlers before assigning them */
2148         if (fm10k_mbx_validate_handlers(msg_data))
2149                 return FM10K_ERR_PARAM;
2150 
2151         /* initialize the message handlers */
2152         mbx->msg_data = msg_data;
2153 
2154         /* start mailbox as timed out and let the reset_hw call
2155          * set the timeout value to begin communications
2156          */
2157         mbx->timeout = 0;
2158         mbx->udelay = FM10K_MBX_INIT_DELAY;
2159 
2160         /* Split buffer for use by Tx/Rx FIFOs */
2161         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2162         mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2163 
2164         /* initialize the FIFOs, sizes are in 4 byte increments */
2165         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2166         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2167                         FM10K_MBX_RX_BUFFER_SIZE);
2168 
2169         /* initialize function pointers */
2170         mbx->ops.connect = fm10k_sm_mbx_connect;
2171         mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2172         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2173         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2174         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2175         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2176         mbx->ops.process = fm10k_sm_mbx_process;
2177         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2178 
2179         return 0;
2180 }

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