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