Linux Audio

Check our new training course

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