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