Linux Audio

Check our new training course

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