aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:51:27 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 06:59:20 -0400
commitb651957c202cabc8d5abfc5ad1ddc2607daf6a4f (patch)
treea7c1fcf82835fcb4a69961dbce82de31470ffb3f /drivers/net
parent5cd5e2e98205df377d93fb8dd15c6f3ed4bfa1d6 (diff)
fm10k: Add support for PF <-> VF mailbox
This patch adds support for the PF <-> VF mailbox. It functions similar to the PF <-> SM mailbox however there are several modifications made to improve the reliability of the mailbox itself. In addition the PF/VF mailbox is much smaller an only supports a total size of 16 DWORDs vs the 1024 DWORDS provided for the PF/SM mailbox. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_mbx.c770
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_mbx.h64
2 files changed, 834 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
index 2609847bbdea..a6a66fd9e2c2 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
@@ -511,6 +511,148 @@ static s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
511 return 0; 511 return 0;
512} 512}
513 513
514/* pre-generated data for generating the CRC based on the poly 0xAC9A. */
515static 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 */
560static 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 **/
588static 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 **/
617static 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 */
638static 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
514/** 656/**
515 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO 657 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
516 * @mbx: pointer to mailbox 658 * @mbx: pointer to mailbox
@@ -686,6 +828,204 @@ static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
686} 828}
687 829
688/** 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 **/
836static 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 **/
851static 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 **/
877static 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 **/
899static 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 **/
930static 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 **/
996static 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/**
689 * fm10k_mbx_reset_work- Reset internal pointers for any pending work 1029 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
690 * @mbx: pointer to mailbox 1030 * @mbx: pointer to mailbox
691 * 1031 *
@@ -731,6 +1071,359 @@ static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
731} 1071}
732 1072
733/** 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 **/
1080static 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 **/
1105static 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 **/
1151static 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 **/
1192static 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, tail;
1198 s32 err;
1199
1200 /* we will need to pull all of the fields for verification */
1201 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1202 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1203
1204 /* We should not be receiving disconnect if Rx is incomplete */
1205 if (mbx->pushed)
1206 return FM10K_MBX_ERR_TAIL;
1207
1208 /* we have already verified mbx->head == tail so we know this is 0 */
1209 mbx->head_len = 0;
1210
1211 /* verify the checksum on the incoming header is correct */
1212 err = fm10k_mbx_verify_remote_crc(mbx);
1213 if (err)
1214 return err;
1215
1216 switch (state) {
1217 case FM10K_STATE_DISCONNECT:
1218 case FM10K_STATE_OPEN:
1219 /* state doesn't change if we still have work to do */
1220 if (!fm10k_mbx_tx_complete(mbx))
1221 break;
1222
1223 /* verify the head indicates we completed all transmits */
1224 if (head != mbx->tail)
1225 return FM10K_MBX_ERR_HEAD;
1226
1227 /* reset any in-progress work */
1228 fm10k_mbx_connect_reset(mbx);
1229 break;
1230 default:
1231 break;
1232 }
1233
1234 return fm10k_mbx_create_reply(hw, mbx, head);
1235}
1236
1237/**
1238 * fm10k_mbx_process_error - Process error header
1239 * @mbx: pointer to mailbox
1240 *
1241 * This function will read an incoming error header and reply with the
1242 * appropriate message. It will return a value indicating the number of
1243 * data DWORDs on success, or will return a negative value on failure.
1244 **/
1245static s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1246 struct fm10k_mbx_info *mbx)
1247{
1248 const u32 *hdr = &mbx->mbx_hdr;
1249 s32 err_no;
1250 u16 head;
1251
1252 /* we will need to pull all of the fields for verification */
1253 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1254
1255 /* we only have lower 10 bits of error number os add upper bits */
1256 err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO);
1257 err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO);
1258
1259 switch (mbx->state) {
1260 case FM10K_STATE_OPEN:
1261 case FM10K_STATE_DISCONNECT:
1262 /* flush any uncompleted work */
1263 fm10k_mbx_reset_work(mbx);
1264
1265 /* reset CRC seeds */
1266 mbx->local = FM10K_MBX_CRC_SEED;
1267 mbx->remote = FM10K_MBX_CRC_SEED;
1268
1269 /* reset tail index and size to prepare for reconnect */
1270 mbx->tail = head;
1271
1272 /* if open then reset max_size and go back to connect */
1273 if (mbx->state == FM10K_STATE_OPEN) {
1274 mbx->state = FM10K_STATE_CONNECT;
1275 break;
1276 }
1277
1278 /* send a connect message to get data flowing again */
1279 fm10k_mbx_create_connect_hdr(mbx);
1280 return 0;
1281 default:
1282 break;
1283 }
1284
1285 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1286}
1287
1288/**
1289 * fm10k_mbx_process - Process mailbox interrupt
1290 * @hw: pointer to hardware structure
1291 * @mbx: pointer to mailbox
1292 *
1293 * This function will process incoming mailbox events and generate mailbox
1294 * replies. It will return a value indicating the number of DWORDs
1295 * transmitted excluding header on success or a negative value on error.
1296 **/
1297static s32 fm10k_mbx_process(struct fm10k_hw *hw,
1298 struct fm10k_mbx_info *mbx)
1299{
1300 s32 err;
1301
1302 /* we do not read mailbox if closed */
1303 if (mbx->state == FM10K_STATE_CLOSED)
1304 return 0;
1305
1306 /* copy data from mailbox */
1307 err = fm10k_mbx_read(hw, mbx);
1308 if (err)
1309 return err;
1310
1311 /* validate type, source, and destination */
1312 err = fm10k_mbx_validate_msg_hdr(mbx);
1313 if (err < 0)
1314 goto msg_err;
1315
1316 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1317 case FM10K_MSG_CONNECT:
1318 err = fm10k_mbx_process_connect(hw, mbx);
1319 break;
1320 case FM10K_MSG_DATA:
1321 err = fm10k_mbx_process_data(hw, mbx);
1322 break;
1323 case FM10K_MSG_DISCONNECT:
1324 err = fm10k_mbx_process_disconnect(hw, mbx);
1325 break;
1326 case FM10K_MSG_ERROR:
1327 err = fm10k_mbx_process_error(hw, mbx);
1328 break;
1329 default:
1330 err = FM10K_MBX_ERR_TYPE;
1331 break;
1332 }
1333
1334msg_err:
1335 /* notify partner of errors on our end */
1336 if (err < 0)
1337 fm10k_mbx_create_error_msg(mbx, err);
1338
1339 /* copy data from mailbox */
1340 fm10k_mbx_write(hw, mbx);
1341
1342 return err;
1343}
1344
1345/**
1346 * fm10k_mbx_disconnect - Shutdown mailbox connection
1347 * @hw: pointer to hardware structure
1348 * @mbx: pointer to mailbox
1349 *
1350 * This function will shut down the mailbox. It places the mailbox first
1351 * in the disconnect state, it then allows up to a predefined timeout for
1352 * the mailbox to transition to close on its own. If this does not occur
1353 * then the mailbox will be forced into the closed state.
1354 *
1355 * Any mailbox transactions not completed before calling this function
1356 * are not guaranteed to complete and may be dropped.
1357 **/
1358static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1359 struct fm10k_mbx_info *mbx)
1360{
1361 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1362
1363 /* Place mbx in ready to disconnect state */
1364 mbx->state = FM10K_STATE_DISCONNECT;
1365
1366 /* trigger interrupt to start shutdown process */
1367 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1368 FM10K_MBX_INTERRUPT_DISABLE);
1369 do {
1370 udelay(FM10K_MBX_POLL_DELAY);
1371 mbx->ops.process(hw, mbx);
1372 timeout -= FM10K_MBX_POLL_DELAY;
1373 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1374
1375 /* in case we didn't close just force the mailbox into shutdown */
1376 fm10k_mbx_connect_reset(mbx);
1377 fm10k_mbx_update_max_size(mbx, 0);
1378
1379 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1380}
1381
1382/**
1383 * fm10k_mbx_connect - Start mailbox connection
1384 * @hw: pointer to hardware structure
1385 * @mbx: pointer to mailbox
1386 *
1387 * This function will initiate a mailbox connection. It will populate the
1388 * mailbox with a broadcast connect message and then initialize the lock.
1389 * This is safe since the connect message is a single DWORD so the mailbox
1390 * transaction is guaranteed to be atomic.
1391 *
1392 * This function will return an error if the mailbox has not been initiated
1393 * or is currently in use.
1394 **/
1395static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1396{
1397 /* we cannot connect an uninitialized mailbox */
1398 if (!mbx->rx.buffer)
1399 return FM10K_MBX_ERR_NO_SPACE;
1400
1401 /* we cannot connect an already connected mailbox */
1402 if (mbx->state != FM10K_STATE_CLOSED)
1403 return FM10K_MBX_ERR_BUSY;
1404
1405 /* mailbox timeout can now become active */
1406 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1407
1408 /* Place mbx in ready to connect state */
1409 mbx->state = FM10K_STATE_CONNECT;
1410
1411 /* initialize header of remote mailbox */
1412 fm10k_mbx_create_disconnect_hdr(mbx);
1413 fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1414
1415 /* enable interrupt and notify other party of new message */
1416 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1417 FM10K_MBX_INTERRUPT_ENABLE;
1418
1419 /* generate and load connect header into mailbox */
1420 fm10k_mbx_create_connect_hdr(mbx);
1421 fm10k_mbx_write(hw, mbx);
1422
1423 return 0;
1424}
1425
1426/**
734 * fm10k_mbx_validate_handlers - Validate layout of message parsing data 1427 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
735 * @msg_data: handlers for mailbox events 1428 * @msg_data: handlers for mailbox events
736 * 1429 *
@@ -806,6 +1499,83 @@ static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
806} 1499}
807 1500
808/** 1501/**
1502 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1503 * @hw: pointer to hardware structure
1504 * @mbx: pointer to mailbox
1505 * @msg_data: handlers for mailbox events
1506 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1507 *
1508 * This function initializes the mailbox for use. It will split the
1509 * buffer provided an use that th populate both the Tx and Rx FIFO by
1510 * evenly splitting it. In order to allow for easy masking of head/tail
1511 * the value reported in size must be a power of 2 and is reported in
1512 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1513 * error.
1514 **/
1515s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1516 const struct fm10k_msg_data *msg_data, u8 id)
1517{
1518 /* initialize registers */
1519 switch (hw->mac.type) {
1520 case fm10k_mac_pf:
1521 /* there are only 64 VF <-> PF mailboxes */
1522 if (id < 64) {
1523 mbx->mbx_reg = FM10K_MBX(id);
1524 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1525 break;
1526 }
1527 /* fallthough */
1528 default:
1529 return FM10K_MBX_ERR_NO_MBX;
1530 }
1531
1532 /* start out in closed state */
1533 mbx->state = FM10K_STATE_CLOSED;
1534
1535 /* validate layout of handlers before assigning them */
1536 if (fm10k_mbx_validate_handlers(msg_data))
1537 return FM10K_ERR_PARAM;
1538
1539 /* initialize the message handlers */
1540 mbx->msg_data = msg_data;
1541
1542 /* start mailbox as timed out and let the reset_hw call
1543 * set the timeout value to begin communications
1544 */
1545 mbx->timeout = 0;
1546 mbx->udelay = FM10K_MBX_INIT_DELAY;
1547
1548 /* initalize tail and head */
1549 mbx->tail = 1;
1550 mbx->head = 1;
1551
1552 /* initialize CRC seeds */
1553 mbx->local = FM10K_MBX_CRC_SEED;
1554 mbx->remote = FM10K_MBX_CRC_SEED;
1555
1556 /* Split buffer for use by Tx/Rx FIFOs */
1557 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1558 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1559
1560 /* initialize the FIFOs, sizes are in 4 byte increments */
1561 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1562 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1563 FM10K_MBX_RX_BUFFER_SIZE);
1564
1565 /* initialize function pointers */
1566 mbx->ops.connect = fm10k_mbx_connect;
1567 mbx->ops.disconnect = fm10k_mbx_disconnect;
1568 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1569 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1570 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1571 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1572 mbx->ops.process = fm10k_mbx_process;
1573 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1574
1575 return 0;
1576}
1577
1578/**
809 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO 1579 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
810 * @mbx: pointer to mailbox 1580 * @mbx: pointer to mailbox
811 * 1581 *
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h
index f5ba86f0f725..0419a7f0035e 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h
@@ -99,6 +99,39 @@ enum fm10k_mbx_state {
99 FM10K_STATE_DISCONNECT, 99 FM10K_STATE_DISCONNECT,
100}; 100};
101 101
102/* PF/VF Mailbox header format
103 * 3 2 1 0
104 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
105 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 * | Size/Err_no/CRC | Rsvd0 | Head | Tail | Type |
107 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 *
109 * The layout above describes the format for the header used in the PF/VF
110 * mailbox. The header is broken out into the following fields:
111 * Type: There are 4 supported message types
112 * 0x8: Data header - used to transport message data
113 * 0xC: Connect header - used to establish connection
114 * 0xD: Disconnect header - used to tear down a connection
115 * 0xE: Error header - used to address message exceptions
116 * Tail: Tail index for local FIFO
117 * Tail index actually consists of two parts. The MSB of
118 * the head is a loop tracker, it is 0 on an even numbered
119 * loop through the FIFO, and 1 on the odd numbered loops.
120 * To get the actual mailbox offset based on the tail it
121 * is necessary to add bit 3 to bit 0 and clear bit 3. This
122 * gives us a valid range of 0x1 - 0xE.
123 * Head: Head index for remote FIFO
124 * Head index follows the same format as the tail index.
125 * Rsvd0: Reserved 0 portion of the mailbox header
126 * CRC: Running CRC for all data since connect plus current message header
127 * Size: Maximum message size - Applies only to connect headers
128 * The maximum message size is provided during connect to avoid
129 * jamming the mailbox with messages that do not fit.
130 * Err_no: Error number - Applies only to error headers
131 * The error number provides a indication of the type of error
132 * experienced.
133 */
134
102/* macros for retriving and setting header values */ 135/* macros for retriving and setting header values */
103#define FM10K_MSG_HDR_MASK(name) \ 136#define FM10K_MSG_HDR_MASK(name) \
104 ((0x1u << FM10K_MSG_##name##_SIZE) - 1) 137 ((0x1u << FM10K_MSG_##name##_SIZE) - 1)
@@ -107,6 +140,35 @@ enum fm10k_mbx_state {
107#define FM10K_MSG_HDR_FIELD_GET(value, name) \ 140#define FM10K_MSG_HDR_FIELD_GET(value, name) \
108 ((u16)((value) >> FM10K_MSG_##name##_SHIFT) & FM10K_MSG_HDR_MASK(name)) 141 ((u16)((value) >> FM10K_MSG_##name##_SHIFT) & FM10K_MSG_HDR_MASK(name))
109 142
143/* offsets shared between all headers */
144#define FM10K_MSG_TYPE_SHIFT 0
145#define FM10K_MSG_TYPE_SIZE 4
146#define FM10K_MSG_TAIL_SHIFT 4
147#define FM10K_MSG_TAIL_SIZE 4
148#define FM10K_MSG_HEAD_SHIFT 8
149#define FM10K_MSG_HEAD_SIZE 4
150#define FM10K_MSG_RSVD0_SHIFT 12
151#define FM10K_MSG_RSVD0_SIZE 4
152
153/* offsets for data/disconnect headers */
154#define FM10K_MSG_CRC_SHIFT 16
155#define FM10K_MSG_CRC_SIZE 16
156
157/* offsets for connect headers */
158#define FM10K_MSG_CONNECT_SIZE_SHIFT 16
159#define FM10K_MSG_CONNECT_SIZE_SIZE 16
160
161/* offsets for error headers */
162#define FM10K_MSG_ERR_NO_SHIFT 16
163#define FM10K_MSG_ERR_NO_SIZE 16
164
165enum fm10k_msg_type {
166 FM10K_MSG_DATA = 0x8,
167 FM10K_MSG_CONNECT = 0xC,
168 FM10K_MSG_DISCONNECT = 0xD,
169 FM10K_MSG_ERROR = 0xE,
170};
171
110/* HNI/SM Mailbox FIFO format 172/* HNI/SM Mailbox FIFO format
111 * 3 2 1 0 173 * 3 2 1 0
112 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 174 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -237,6 +299,8 @@ struct fm10k_mbx_info {
237 u32 buffer[FM10K_MBX_BUFFER_SIZE]; 299 u32 buffer[FM10K_MBX_BUFFER_SIZE];
238}; 300};
239 301
302s32 fm10k_pfvf_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *,
303 const struct fm10k_msg_data *, u8);
240s32 fm10k_sm_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *, 304s32 fm10k_sm_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *,
241 const struct fm10k_msg_data *); 305 const struct fm10k_msg_data *);
242 306