1 /*
2  *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
3  *
4  *  Written by Anish Bhatt (anish@chelsio.com)
5  *
6  *  This program is free software; you can redistribute it and/or modify it
7  *  under the terms and conditions of the GNU General Public License,
8  *  version 2, as published by the Free Software Foundation.
9  *
10  *  This program is distributed in the hope it will be useful, but WITHOUT
11  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  *  more details.
14  *
15  *  The full GNU General Public License is included in this distribution in
16  *  the file called "COPYING".
17  *
18  */
19 
20 #ifndef __CXGB4_DCB_H
21 #define __CXGB4_DCB_H
22 
23 #include <linux/netdevice.h>
24 #include <linux/dcbnl.h>
25 #include <net/dcbnl.h>
26 
27 #ifdef CONFIG_CHELSIO_T4_DCB
28 
29 #define CXGB4_DCBX_FW_SUPPORT \
30 	(DCB_CAP_DCBX_VER_CEE | \
31 	 DCB_CAP_DCBX_VER_IEEE | \
32 	 DCB_CAP_DCBX_LLD_MANAGED)
33 #define CXGB4_DCBX_HOST_SUPPORT \
34 	(DCB_CAP_DCBX_VER_CEE | \
35 	 DCB_CAP_DCBX_VER_IEEE | \
36 	 DCB_CAP_DCBX_HOST)
37 
38 #define CXGB4_MAX_PRIORITY      CXGB4_MAX_DCBX_APP_SUPPORTED
39 #define CXGB4_MAX_TCS           CXGB4_MAX_DCBX_APP_SUPPORTED
40 
41 #define INIT_PORT_DCB_CMD(__pcmd, __port, __op, __action) \
42 	do { \
43 		memset(&(__pcmd), 0, sizeof(__pcmd)); \
44 		(__pcmd).op_to_portid = \
45 			cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | \
46 				    FW_CMD_REQUEST_F | \
47 				    FW_CMD_##__op##_F | \
48 				    FW_PORT_CMD_PORTID_V(__port)); \
49 		(__pcmd).action_to_len16 = \
50 			cpu_to_be32(FW_PORT_CMD_ACTION_V(__action) | \
51 				    FW_LEN16(pcmd)); \
52 	} while (0)
53 
54 #define INIT_PORT_DCB_READ_PEER_CMD(__pcmd, __port) \
55 	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_RECV)
56 
57 #define INIT_PORT_DCB_READ_LOCAL_CMD(__pcmd, __port) \
58 	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_TRANS)
59 
60 #define INIT_PORT_DCB_READ_SYNC_CMD(__pcmd, __port) \
61 	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_DET)
62 
63 #define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \
64 	INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG)
65 
66 #define IEEE_FAUX_SYNC(__dev, __dcb) \
67 	do { \
68 		if ((__dcb)->dcb_version == FW_PORT_DCB_VER_IEEE) \
69 			cxgb4_dcb_state_fsm((__dev), \
70 					    CXGB4_DCB_STATE_FW_ALLSYNCED); \
71 	} while (0)
72 
73 /* States we can be in for a port's Data Center Bridging.
74  */
75 enum cxgb4_dcb_state {
76 	CXGB4_DCB_STATE_START,		/* initial unknown state */
77 	CXGB4_DCB_STATE_HOST,		/* we're using Host DCB (if at all) */
78 	CXGB4_DCB_STATE_FW_INCOMPLETE,	/* using firmware DCB, incomplete */
79 	CXGB4_DCB_STATE_FW_ALLSYNCED,	/* using firmware DCB, all sync'ed */
80 };
81 
82 /* Data Center Bridging state input for the Finite State Machine.
83  */
84 enum cxgb4_dcb_state_input {
85 	/* Input from the firmware.
86 	 */
87 	CXGB4_DCB_INPUT_FW_DISABLED,	/* firmware DCB disabled */
88 	CXGB4_DCB_INPUT_FW_ENABLED,	/* firmware DCB enabled */
89 	CXGB4_DCB_INPUT_FW_INCOMPLETE,	/* firmware reports incomplete DCB */
90 	CXGB4_DCB_INPUT_FW_ALLSYNCED,	/* firmware reports all sync'ed */
91 
92 };
93 
94 /* Firmware DCB messages that we've received so far ...
95  */
96 enum cxgb4_dcb_fw_msgs {
97 	CXGB4_DCB_FW_PGID	= 0x01,
98 	CXGB4_DCB_FW_PGRATE	= 0x02,
99 	CXGB4_DCB_FW_PRIORATE	= 0x04,
100 	CXGB4_DCB_FW_PFC	= 0x08,
101 	CXGB4_DCB_FW_APP_ID	= 0x10,
102 };
103 
104 #define CXGB4_MAX_DCBX_APP_SUPPORTED 8
105 
106 /* Data Center Bridging support;
107  */
108 struct port_dcb_info {
109 	enum cxgb4_dcb_state state;	/* DCB State Machine */
110 	enum cxgb4_dcb_fw_msgs msgs;	/* DCB Firmware messages received */
111 	unsigned int supported;		/* OS DCB capabilities supported */
112 	bool enabled;			/* OS Enabled state */
113 
114 	/* Cached copies of DCB information sent by the firmware (in Host
115 	 * Native Endian format).
116 	 */
117 	u32	pgid;			/* Priority Group[0..7] */
118 	u8	dcb_version;		/* Running DCBx version */
119 	u8	pfcen;			/* Priority Flow Control[0..7] */
120 	u8	pg_num_tcs_supported;	/* max PG Traffic Classes */
121 	u8	pfc_num_tcs_supported;	/* max PFC Traffic Classes */
122 	u8	pgrate[8];		/* Priority Group Rate[0..7] */
123 	u8	priorate[8];		/* Priority Rate[0..7] */
124 	u8	tsa[8];			/* TSA Algorithm[0..7] */
125 	struct app_priority { /* Application Information */
126 		u8	user_prio_map;	/* Priority Map bitfield */
127 		u8	sel_field;	/* Protocol ID interpretation */
128 		u16	protocolid;	/* Protocol ID */
129 	} app_priority[CXGB4_MAX_DCBX_APP_SUPPORTED];
130 };
131 
132 void cxgb4_dcb_state_init(struct net_device *);
133 void cxgb4_dcb_version_init(struct net_device *);
134 void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input);
135 void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *);
136 void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *);
137 extern const struct dcbnl_rtnl_ops cxgb4_dcb_ops;
138 
139 static inline __u8 bitswap_1(unsigned char val)
140 {
141 	return ((val & 0x80) >> 7) |
142 	       ((val & 0x40) >> 5) |
143 	       ((val & 0x20) >> 3) |
144 	       ((val & 0x10) >> 1) |
145 	       ((val & 0x08) << 1) |
146 	       ((val & 0x04) << 3) |
147 	       ((val & 0x02) << 5) |
148 	       ((val & 0x01) << 7);
149 }
150 #define CXGB4_DCB_ENABLED true
151 
152 #else /* !CONFIG_CHELSIO_T4_DCB */
153 
154 static inline void cxgb4_dcb_state_init(struct net_device *dev)
155 {
156 }
157 
158 #define CXGB4_DCB_ENABLED false
159 
160 #endif /* !CONFIG_CHELSIO_T4_DCB */
161 
162 #endif /* __CXGB4_DCB_H */
163