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 **/ 30 static 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 **/ 44 static 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 **/ 55 static 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 **/ 66 static 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 **/ 78 static 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 **/ 90 static 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 **/ 101 static 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 **/ 119 static 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 **/ 136 static 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 **/ 150 static 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 **/ 169 static 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 **/ 185 static 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 **/ 201 static 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 **/ 217 static 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 **/ 232 static 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 **/ 254 static 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 **/ 282 static 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 **/ 314 static 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 **/ 347 static 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 **/ 399 static 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 **/ 440 static 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 **/ 488 static 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. */ 532 static 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 */ 577 static 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 **/ 605 static 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 **/ 634 static 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 */ 655 static 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 **/ 679 static 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 **/ 693 static 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 **/ 706 static 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 **/ 719 static 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 **/ 756 static 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 **/ 804 static 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 **/ 831 static 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 **/ 853 static 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 **/ 868 static 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 **/ 894 static 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 **/ 915 static 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 **/ 937 static 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 **/ 967 static 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 **/ 1034 static 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 **/ 1074 static 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 **/ 1116 static 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 **/ 1138 static 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 **/ 1163 static 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 **/ 1210 static 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 **/ 1252 static 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 **/ 1305 static 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 **/ 1352 static 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 1389 msg_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 **/ 1413 static 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 **/ 1452 static 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 **/ 1493 static 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 **/ 1547 static 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 **/ 1574 s32 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 **/ 1647 static 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 **/ 1664 static 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 **/ 1681 static 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 **/ 1710 static 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 **/ 1754 static 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 **/ 1788 static 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 **/ 1830 static 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 **/ 1866 static 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 **/ 1894 static 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 **/ 1934 static 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 **/ 1978 static 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 **/ 2015 static 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 **/ 2053 static 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 2083 send_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 **/ 2098 static 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 2130 fifo_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 **/ 2153 s32 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 } 2196