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