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