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