1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* Copyright(c) 2013 - 2018 Intel Corporation. */ 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun #ifndef _FM10K_MBX_H_ 5*4882a593Smuzhiyun #define _FM10K_MBX_H_ 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun /* forward declaration */ 8*4882a593Smuzhiyun struct fm10k_mbx_info; 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #include "fm10k_type.h" 11*4882a593Smuzhiyun #include "fm10k_tlv.h" 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun /* PF Mailbox Registers */ 14*4882a593Smuzhiyun #define FM10K_MBMEM(_n) ((_n) + 0x18000) 15*4882a593Smuzhiyun #define FM10K_MBMEM_VF(_n, _m) (((_n) * 0x10) + (_m) + 0x18000) 16*4882a593Smuzhiyun #define FM10K_MBMEM_SM(_n) ((_n) + 0x18400) 17*4882a593Smuzhiyun #define FM10K_MBMEM_PF(_n) ((_n) + 0x18600) 18*4882a593Smuzhiyun /* XOR provides means of switching from Tx to Rx FIFO */ 19*4882a593Smuzhiyun #define FM10K_MBMEM_PF_XOR (FM10K_MBMEM_SM(0) ^ FM10K_MBMEM_PF(0)) 20*4882a593Smuzhiyun #define FM10K_MBX(_n) ((_n) + 0x18800) 21*4882a593Smuzhiyun #define FM10K_MBX_REQ 0x00000002 22*4882a593Smuzhiyun #define FM10K_MBX_ACK 0x00000004 23*4882a593Smuzhiyun #define FM10K_MBX_REQ_INTERRUPT 0x00000008 24*4882a593Smuzhiyun #define FM10K_MBX_ACK_INTERRUPT 0x00000010 25*4882a593Smuzhiyun #define FM10K_MBX_INTERRUPT_ENABLE 0x00000020 26*4882a593Smuzhiyun #define FM10K_MBX_INTERRUPT_DISABLE 0x00000040 27*4882a593Smuzhiyun #define FM10K_MBX_GLOBAL_REQ_INTERRUPT 0x00000200 28*4882a593Smuzhiyun #define FM10K_MBX_GLOBAL_ACK_INTERRUPT 0x00000400 29*4882a593Smuzhiyun #define FM10K_MBICR(_n) ((_n) + 0x18840) 30*4882a593Smuzhiyun #define FM10K_GMBX 0x18842 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun /* VF Mailbox Registers */ 33*4882a593Smuzhiyun #define FM10K_VFMBX 0x00010 34*4882a593Smuzhiyun #define FM10K_VFMBMEM(_n) ((_n) + 0x00020) 35*4882a593Smuzhiyun #define FM10K_VFMBMEM_LEN 16 36*4882a593Smuzhiyun #define FM10K_VFMBMEM_VF_XOR (FM10K_VFMBMEM_LEN / 2) 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun /* Delays/timeouts */ 39*4882a593Smuzhiyun #define FM10K_MBX_DISCONNECT_TIMEOUT 500 40*4882a593Smuzhiyun #define FM10K_MBX_POLL_DELAY 19 41*4882a593Smuzhiyun #define FM10K_MBX_INT_DELAY 20 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun /* PF/VF Mailbox state machine 44*4882a593Smuzhiyun * 45*4882a593Smuzhiyun * +----------+ connect() +----------+ 46*4882a593Smuzhiyun * | CLOSED | --------------> | CONNECT | 47*4882a593Smuzhiyun * +----------+ +----------+ 48*4882a593Smuzhiyun * ^ ^ | 49*4882a593Smuzhiyun * | rcv: rcv: | | rcv: 50*4882a593Smuzhiyun * | Connect Disconnect | | Connect 51*4882a593Smuzhiyun * | Disconnect Error | | Data 52*4882a593Smuzhiyun * | | | 53*4882a593Smuzhiyun * | | V 54*4882a593Smuzhiyun * +----------+ disconnect() +----------+ 55*4882a593Smuzhiyun * |DISCONNECT| <-------------- | OPEN | 56*4882a593Smuzhiyun * +----------+ +----------+ 57*4882a593Smuzhiyun * 58*4882a593Smuzhiyun * The diagram above describes the PF/VF mailbox state machine. There 59*4882a593Smuzhiyun * are four main states to this machine. 60*4882a593Smuzhiyun * Closed: This state represents a mailbox that is in a standby state 61*4882a593Smuzhiyun * with interrupts disabled. In this state the mailbox should not 62*4882a593Smuzhiyun * read the mailbox or write any data. The only means of exiting 63*4882a593Smuzhiyun * this state is for the system to make the connect() call for the 64*4882a593Smuzhiyun * mailbox, it will then transition to the connect state. 65*4882a593Smuzhiyun * Connect: In this state the mailbox is seeking a connection. It will 66*4882a593Smuzhiyun * post a connect message with no specified destination and will 67*4882a593Smuzhiyun * wait for a reply from the other side of the mailbox. This state 68*4882a593Smuzhiyun * is exited when either a connect with the local mailbox as the 69*4882a593Smuzhiyun * destination is received or when a data message is received with 70*4882a593Smuzhiyun * a valid sequence number. 71*4882a593Smuzhiyun * Open: In this state the mailbox is able to transfer data between the local 72*4882a593Smuzhiyun * entity and the remote. It will fall back to connect in the event of 73*4882a593Smuzhiyun * receiving either an error message, or a disconnect message. It will 74*4882a593Smuzhiyun * transition to disconnect on a call to disconnect(); 75*4882a593Smuzhiyun * Disconnect: In this state the mailbox is attempting to gracefully terminate 76*4882a593Smuzhiyun * the connection. It will do so at the first point where it knows 77*4882a593Smuzhiyun * that the remote endpoint is either done sending, or when the 78*4882a593Smuzhiyun * remote endpoint has fallen back into connect. 79*4882a593Smuzhiyun */ 80*4882a593Smuzhiyun enum fm10k_mbx_state { 81*4882a593Smuzhiyun FM10K_STATE_CLOSED, 82*4882a593Smuzhiyun FM10K_STATE_CONNECT, 83*4882a593Smuzhiyun FM10K_STATE_OPEN, 84*4882a593Smuzhiyun FM10K_STATE_DISCONNECT, 85*4882a593Smuzhiyun }; 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* PF/VF Mailbox header format 88*4882a593Smuzhiyun * 3 2 1 0 89*4882a593Smuzhiyun * 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 90*4882a593Smuzhiyun * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 91*4882a593Smuzhiyun * | Size/Err_no/CRC | Rsvd0 | Head | Tail | Type | 92*4882a593Smuzhiyun * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 93*4882a593Smuzhiyun * 94*4882a593Smuzhiyun * The layout above describes the format for the header used in the PF/VF 95*4882a593Smuzhiyun * mailbox. The header is broken out into the following fields: 96*4882a593Smuzhiyun * Type: There are 4 supported message types 97*4882a593Smuzhiyun * 0x8: Data header - used to transport message data 98*4882a593Smuzhiyun * 0xC: Connect header - used to establish connection 99*4882a593Smuzhiyun * 0xD: Disconnect header - used to tear down a connection 100*4882a593Smuzhiyun * 0xE: Error header - used to address message exceptions 101*4882a593Smuzhiyun * Tail: Tail index for local FIFO 102*4882a593Smuzhiyun * Tail index actually consists of two parts. The MSB of 103*4882a593Smuzhiyun * the head is a loop tracker, it is 0 on an even numbered 104*4882a593Smuzhiyun * loop through the FIFO, and 1 on the odd numbered loops. 105*4882a593Smuzhiyun * To get the actual mailbox offset based on the tail it 106*4882a593Smuzhiyun * is necessary to add bit 3 to bit 0 and clear bit 3. This 107*4882a593Smuzhiyun * gives us a valid range of 0x1 - 0xE. 108*4882a593Smuzhiyun * Head: Head index for remote FIFO 109*4882a593Smuzhiyun * Head index follows the same format as the tail index. 110*4882a593Smuzhiyun * Rsvd0: Reserved 0 portion of the mailbox header 111*4882a593Smuzhiyun * CRC: Running CRC for all data since connect plus current message header 112*4882a593Smuzhiyun * Size: Maximum message size - Applies only to connect headers 113*4882a593Smuzhiyun * The maximum message size is provided during connect to avoid 114*4882a593Smuzhiyun * jamming the mailbox with messages that do not fit. 115*4882a593Smuzhiyun * Err_no: Error number - Applies only to error headers 116*4882a593Smuzhiyun * The error number provides an indication of the type of error 117*4882a593Smuzhiyun * experienced. 118*4882a593Smuzhiyun */ 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun /* macros for retrieving and setting header values */ 121*4882a593Smuzhiyun #define FM10K_MSG_HDR_MASK(name) \ 122*4882a593Smuzhiyun ((0x1u << FM10K_MSG_##name##_SIZE) - 1) 123*4882a593Smuzhiyun #define FM10K_MSG_HDR_FIELD_SET(value, name) \ 124*4882a593Smuzhiyun (((u32)(value) & FM10K_MSG_HDR_MASK(name)) << FM10K_MSG_##name##_SHIFT) 125*4882a593Smuzhiyun #define FM10K_MSG_HDR_FIELD_GET(value, name) \ 126*4882a593Smuzhiyun ((u16)((value) >> FM10K_MSG_##name##_SHIFT) & FM10K_MSG_HDR_MASK(name)) 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun /* offsets shared between all headers */ 129*4882a593Smuzhiyun #define FM10K_MSG_TYPE_SHIFT 0 130*4882a593Smuzhiyun #define FM10K_MSG_TYPE_SIZE 4 131*4882a593Smuzhiyun #define FM10K_MSG_TAIL_SHIFT 4 132*4882a593Smuzhiyun #define FM10K_MSG_TAIL_SIZE 4 133*4882a593Smuzhiyun #define FM10K_MSG_HEAD_SHIFT 8 134*4882a593Smuzhiyun #define FM10K_MSG_HEAD_SIZE 4 135*4882a593Smuzhiyun #define FM10K_MSG_RSVD0_SHIFT 12 136*4882a593Smuzhiyun #define FM10K_MSG_RSVD0_SIZE 4 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun /* offsets for data/disconnect headers */ 139*4882a593Smuzhiyun #define FM10K_MSG_CRC_SHIFT 16 140*4882a593Smuzhiyun #define FM10K_MSG_CRC_SIZE 16 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun /* offsets for connect headers */ 143*4882a593Smuzhiyun #define FM10K_MSG_CONNECT_SIZE_SHIFT 16 144*4882a593Smuzhiyun #define FM10K_MSG_CONNECT_SIZE_SIZE 16 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun /* offsets for error headers */ 147*4882a593Smuzhiyun #define FM10K_MSG_ERR_NO_SHIFT 16 148*4882a593Smuzhiyun #define FM10K_MSG_ERR_NO_SIZE 16 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun enum fm10k_msg_type { 151*4882a593Smuzhiyun FM10K_MSG_DATA = 0x8, 152*4882a593Smuzhiyun FM10K_MSG_CONNECT = 0xC, 153*4882a593Smuzhiyun FM10K_MSG_DISCONNECT = 0xD, 154*4882a593Smuzhiyun FM10K_MSG_ERROR = 0xE, 155*4882a593Smuzhiyun }; 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun /* HNI/SM Mailbox FIFO format 158*4882a593Smuzhiyun * 3 2 1 0 159*4882a593Smuzhiyun * 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 160*4882a593Smuzhiyun * +-------+-----------------------+-------+-----------------------+ 161*4882a593Smuzhiyun * | Error | Remote Head |Version| Local Tail | 162*4882a593Smuzhiyun * +-------+-----------------------+-------+-----------------------+ 163*4882a593Smuzhiyun * | | 164*4882a593Smuzhiyun * . Local FIFO Data . 165*4882a593Smuzhiyun * . . 166*4882a593Smuzhiyun * +-------+-----------------------+-------+-----------------------+ 167*4882a593Smuzhiyun * 168*4882a593Smuzhiyun * The layout above describes the format for the FIFOs used by the host 169*4882a593Smuzhiyun * network interface and the switch manager to communicate messages back 170*4882a593Smuzhiyun * and forth. Both the HNI and the switch maintain one such FIFO. The 171*4882a593Smuzhiyun * layout in memory has the switch manager FIFO followed immediately by 172*4882a593Smuzhiyun * the HNI FIFO. For this reason I am using just the pointer to the 173*4882a593Smuzhiyun * HNI FIFO in the mailbox ops as the offset between the two is fixed. 174*4882a593Smuzhiyun * 175*4882a593Smuzhiyun * The header for the FIFO is broken out into the following fields: 176*4882a593Smuzhiyun * Local Tail: Offset into FIFO region for next DWORD to write. 177*4882a593Smuzhiyun * Version: Version info for mailbox, only values of 0/1 are supported. 178*4882a593Smuzhiyun * Remote Head: Offset into remote FIFO to indicate how much we have read. 179*4882a593Smuzhiyun * Error: Error indication, values TBD. 180*4882a593Smuzhiyun */ 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun /* version number for switch manager mailboxes */ 183*4882a593Smuzhiyun #define FM10K_SM_MBX_VERSION 1 184*4882a593Smuzhiyun #define FM10K_SM_MBX_FIFO_LEN (FM10K_MBMEM_PF_XOR - 1) 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun /* offsets shared between all SM FIFO headers */ 187*4882a593Smuzhiyun #define FM10K_MSG_SM_TAIL_SHIFT 0 188*4882a593Smuzhiyun #define FM10K_MSG_SM_TAIL_SIZE 12 189*4882a593Smuzhiyun #define FM10K_MSG_SM_VER_SHIFT 12 190*4882a593Smuzhiyun #define FM10K_MSG_SM_VER_SIZE 4 191*4882a593Smuzhiyun #define FM10K_MSG_SM_HEAD_SHIFT 16 192*4882a593Smuzhiyun #define FM10K_MSG_SM_HEAD_SIZE 12 193*4882a593Smuzhiyun #define FM10K_MSG_SM_ERR_SHIFT 28 194*4882a593Smuzhiyun #define FM10K_MSG_SM_ERR_SIZE 4 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun /* All error messages returned by mailbox functions 197*4882a593Smuzhiyun * The value -511 is 0xFE01 in hex. The idea is to order the errors 198*4882a593Smuzhiyun * from 0xFE01 - 0xFEFF so error codes are easily visible in the mailbox 199*4882a593Smuzhiyun * messages. This also helps to avoid error number collisions as Linux 200*4882a593Smuzhiyun * doesn't appear to use error numbers 256 - 511. 201*4882a593Smuzhiyun */ 202*4882a593Smuzhiyun #define FM10K_MBX_ERR(_n) ((_n) - 512) 203*4882a593Smuzhiyun #define FM10K_MBX_ERR_NO_MBX FM10K_MBX_ERR(0x01) 204*4882a593Smuzhiyun #define FM10K_MBX_ERR_NO_SPACE FM10K_MBX_ERR(0x03) 205*4882a593Smuzhiyun #define FM10K_MBX_ERR_TAIL FM10K_MBX_ERR(0x05) 206*4882a593Smuzhiyun #define FM10K_MBX_ERR_HEAD FM10K_MBX_ERR(0x06) 207*4882a593Smuzhiyun #define FM10K_MBX_ERR_SRC FM10K_MBX_ERR(0x08) 208*4882a593Smuzhiyun #define FM10K_MBX_ERR_TYPE FM10K_MBX_ERR(0x09) 209*4882a593Smuzhiyun #define FM10K_MBX_ERR_SIZE FM10K_MBX_ERR(0x0B) 210*4882a593Smuzhiyun #define FM10K_MBX_ERR_BUSY FM10K_MBX_ERR(0x0C) 211*4882a593Smuzhiyun #define FM10K_MBX_ERR_RSVD0 FM10K_MBX_ERR(0x0E) 212*4882a593Smuzhiyun #define FM10K_MBX_ERR_CRC FM10K_MBX_ERR(0x0F) 213*4882a593Smuzhiyun 214*4882a593Smuzhiyun #define FM10K_MBX_CRC_SEED 0xFFFF 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun struct fm10k_mbx_ops { 217*4882a593Smuzhiyun s32 (*connect)(struct fm10k_hw *, struct fm10k_mbx_info *); 218*4882a593Smuzhiyun void (*disconnect)(struct fm10k_hw *, struct fm10k_mbx_info *); 219*4882a593Smuzhiyun bool (*rx_ready)(struct fm10k_mbx_info *); 220*4882a593Smuzhiyun bool (*tx_ready)(struct fm10k_mbx_info *, u16); 221*4882a593Smuzhiyun bool (*tx_complete)(struct fm10k_mbx_info *); 222*4882a593Smuzhiyun s32 (*enqueue_tx)(struct fm10k_hw *, struct fm10k_mbx_info *, 223*4882a593Smuzhiyun const u32 *); 224*4882a593Smuzhiyun s32 (*process)(struct fm10k_hw *, struct fm10k_mbx_info *); 225*4882a593Smuzhiyun s32 (*register_handlers)(struct fm10k_mbx_info *, 226*4882a593Smuzhiyun const struct fm10k_msg_data *); 227*4882a593Smuzhiyun }; 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun struct fm10k_mbx_fifo { 230*4882a593Smuzhiyun u32 *buffer; 231*4882a593Smuzhiyun u16 head; 232*4882a593Smuzhiyun u16 tail; 233*4882a593Smuzhiyun u16 size; 234*4882a593Smuzhiyun }; 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun /* size of buffer to be stored in mailbox for FIFOs */ 237*4882a593Smuzhiyun #define FM10K_MBX_TX_BUFFER_SIZE 512 238*4882a593Smuzhiyun #define FM10K_MBX_RX_BUFFER_SIZE 128 239*4882a593Smuzhiyun #define FM10K_MBX_BUFFER_SIZE \ 240*4882a593Smuzhiyun (FM10K_MBX_TX_BUFFER_SIZE + FM10K_MBX_RX_BUFFER_SIZE) 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun /* minimum and maximum message size in dwords */ 243*4882a593Smuzhiyun #define FM10K_MBX_MSG_MAX_SIZE \ 244*4882a593Smuzhiyun ((FM10K_MBX_TX_BUFFER_SIZE - 1) & (FM10K_MBX_RX_BUFFER_SIZE - 1)) 245*4882a593Smuzhiyun #define FM10K_VFMBX_MSG_MTU ((FM10K_VFMBMEM_LEN / 2) - 1) 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun #define FM10K_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ 248*4882a593Smuzhiyun #define FM10K_MBX_INIT_DELAY 500 /* microseconds between retries */ 249*4882a593Smuzhiyun 250*4882a593Smuzhiyun struct fm10k_mbx_info { 251*4882a593Smuzhiyun /* function pointers for mailbox operations */ 252*4882a593Smuzhiyun struct fm10k_mbx_ops ops; 253*4882a593Smuzhiyun const struct fm10k_msg_data *msg_data; 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun /* message FIFOs */ 256*4882a593Smuzhiyun struct fm10k_mbx_fifo rx; 257*4882a593Smuzhiyun struct fm10k_mbx_fifo tx; 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun /* delay for handling timeouts */ 260*4882a593Smuzhiyun u32 timeout; 261*4882a593Smuzhiyun u32 udelay; 262*4882a593Smuzhiyun 263*4882a593Smuzhiyun /* mailbox state info */ 264*4882a593Smuzhiyun u32 mbx_reg, mbmem_reg, mbx_lock, mbx_hdr; 265*4882a593Smuzhiyun u16 max_size, mbmem_len; 266*4882a593Smuzhiyun u16 tail, tail_len, pulled; 267*4882a593Smuzhiyun u16 head, head_len, pushed; 268*4882a593Smuzhiyun u16 local, remote; 269*4882a593Smuzhiyun enum fm10k_mbx_state state; 270*4882a593Smuzhiyun 271*4882a593Smuzhiyun /* result of last mailbox test */ 272*4882a593Smuzhiyun s32 test_result; 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun /* statistics */ 275*4882a593Smuzhiyun u64 tx_busy; 276*4882a593Smuzhiyun u64 tx_dropped; 277*4882a593Smuzhiyun u64 tx_messages; 278*4882a593Smuzhiyun u64 tx_dwords; 279*4882a593Smuzhiyun u64 tx_mbmem_pulled; 280*4882a593Smuzhiyun u64 rx_messages; 281*4882a593Smuzhiyun u64 rx_dwords; 282*4882a593Smuzhiyun u64 rx_mbmem_pushed; 283*4882a593Smuzhiyun u64 rx_parse_err; 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun /* Buffer to store messages */ 286*4882a593Smuzhiyun u32 buffer[FM10K_MBX_BUFFER_SIZE]; 287*4882a593Smuzhiyun }; 288*4882a593Smuzhiyun 289*4882a593Smuzhiyun s32 fm10k_pfvf_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *, 290*4882a593Smuzhiyun const struct fm10k_msg_data *, u8); 291*4882a593Smuzhiyun s32 fm10k_sm_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *, 292*4882a593Smuzhiyun const struct fm10k_msg_data *); 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun #endif /* _FM10K_MBX_H_ */ 295