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