1 /*
2 * Copyright 2008-2015 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Freescale Semiconductor nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* FM MAC ... */
34 #ifndef __FM_MAC_H
35 #define __FM_MAC_H
36
37 #include "fman.h"
38
39 #include <linux/slab.h>
40 #include <linux/phy.h>
41 #include <linux/if_ether.h>
42
43 struct fman_mac;
44 struct mac_device;
45
46 /* Ethernet Address */
47 typedef u8 enet_addr_t[ETH_ALEN];
48
49 #define ENET_ADDR_TO_UINT64(_enet_addr) \
50 (u64)(((u64)(_enet_addr)[0] << 40) | \
51 ((u64)(_enet_addr)[1] << 32) | \
52 ((u64)(_enet_addr)[2] << 24) | \
53 ((u64)(_enet_addr)[3] << 16) | \
54 ((u64)(_enet_addr)[4] << 8) | \
55 ((u64)(_enet_addr)[5]))
56
57 #define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
58 do { \
59 int i; \
60 for (i = 0; i < ETH_ALEN; i++) \
61 (_enet_addr)[i] = \
62 (u8)((_addr64) >> ((5 - i) * 8)); \
63 } while (0)
64
65 /* defaults */
66 #define DEFAULT_RESET_ON_INIT false
67
68 /* PFC defines */
69 #define FSL_FM_PAUSE_TIME_ENABLE 0xf000
70 #define FSL_FM_PAUSE_TIME_DISABLE 0
71 #define FSL_FM_PAUSE_THRESH_DEFAULT 0
72
73 #define FM_MAC_NO_PFC 0xff
74
75 /* HASH defines */
76 #define ETH_HASH_ENTRY_OBJ(ptr) \
77 hlist_entry_safe(ptr, struct eth_hash_entry, node)
78
79 /* FM MAC Exceptions */
80 enum fman_mac_exceptions {
81 FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
82 /* 10GEC MDIO scan event interrupt */
83 , FM_MAC_EX_10G_MDIO_CMD_CMPL
84 /* 10GEC MDIO command completion interrupt */
85 , FM_MAC_EX_10G_REM_FAULT
86 /* 10GEC, mEMAC Remote fault interrupt */
87 , FM_MAC_EX_10G_LOC_FAULT
88 /* 10GEC, mEMAC Local fault interrupt */
89 , FM_MAC_EX_10G_TX_ECC_ER
90 /* 10GEC, mEMAC Transmit frame ECC error interrupt */
91 , FM_MAC_EX_10G_TX_FIFO_UNFL
92 /* 10GEC, mEMAC Transmit FIFO underflow interrupt */
93 , FM_MAC_EX_10G_TX_FIFO_OVFL
94 /* 10GEC, mEMAC Transmit FIFO overflow interrupt */
95 , FM_MAC_EX_10G_TX_ER
96 /* 10GEC Transmit frame error interrupt */
97 , FM_MAC_EX_10G_RX_FIFO_OVFL
98 /* 10GEC, mEMAC Receive FIFO overflow interrupt */
99 , FM_MAC_EX_10G_RX_ECC_ER
100 /* 10GEC, mEMAC Receive frame ECC error interrupt */
101 , FM_MAC_EX_10G_RX_JAB_FRM
102 /* 10GEC Receive jabber frame interrupt */
103 , FM_MAC_EX_10G_RX_OVRSZ_FRM
104 /* 10GEC Receive oversized frame interrupt */
105 , FM_MAC_EX_10G_RX_RUNT_FRM
106 /* 10GEC Receive runt frame interrupt */
107 , FM_MAC_EX_10G_RX_FRAG_FRM
108 /* 10GEC Receive fragment frame interrupt */
109 , FM_MAC_EX_10G_RX_LEN_ER
110 /* 10GEC Receive payload length error interrupt */
111 , FM_MAC_EX_10G_RX_CRC_ER
112 /* 10GEC Receive CRC error interrupt */
113 , FM_MAC_EX_10G_RX_ALIGN_ER
114 /* 10GEC Receive alignment error interrupt */
115 , FM_MAC_EX_1G_BAB_RX
116 /* dTSEC Babbling receive error */
117 , FM_MAC_EX_1G_RX_CTL
118 /* dTSEC Receive control (pause frame) interrupt */
119 , FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
120 /* dTSEC Graceful transmit stop complete */
121 , FM_MAC_EX_1G_BAB_TX
122 /* dTSEC Babbling transmit error */
123 , FM_MAC_EX_1G_TX_CTL
124 /* dTSEC Transmit control (pause frame) interrupt */
125 , FM_MAC_EX_1G_TX_ERR
126 /* dTSEC Transmit error */
127 , FM_MAC_EX_1G_LATE_COL
128 /* dTSEC Late collision */
129 , FM_MAC_EX_1G_COL_RET_LMT
130 /* dTSEC Collision retry limit */
131 , FM_MAC_EX_1G_TX_FIFO_UNDRN
132 /* dTSEC Transmit FIFO underrun */
133 , FM_MAC_EX_1G_MAG_PCKT
134 /* dTSEC Magic Packet detection */
135 , FM_MAC_EX_1G_MII_MNG_RD_COMPLET
136 /* dTSEC MII management read completion */
137 , FM_MAC_EX_1G_MII_MNG_WR_COMPLET
138 /* dTSEC MII management write completion */
139 , FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
140 /* dTSEC Graceful receive stop complete */
141 , FM_MAC_EX_1G_DATA_ERR
142 /* dTSEC Internal data error on transmit */
143 , FM_MAC_1G_RX_DATA_ERR
144 /* dTSEC Internal data error on receive */
145 , FM_MAC_EX_1G_1588_TS_RX_ERR
146 /* dTSEC Time-Stamp Receive Error */
147 , FM_MAC_EX_1G_RX_MIB_CNT_OVFL
148 /* dTSEC MIB counter overflow */
149 , FM_MAC_EX_TS_FIFO_ECC_ERR
150 /* mEMAC Time-stamp FIFO ECC error interrupt;
151 * not supported on T4240/B4860 rev1 chips
152 */
153 , FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
154 /* mEMAC Magic Packet Indication Interrupt */
155 };
156
157 struct eth_hash_entry {
158 u64 addr; /* Ethernet Address */
159 struct list_head node;
160 };
161
162 typedef void (fman_mac_exception_cb)(struct mac_device *dev_id,
163 enum fman_mac_exceptions exceptions);
164
165 /* FMan MAC config input */
166 struct fman_mac_params {
167 /* MAC ID; numbering of dTSEC and 1G-mEMAC:
168 * 0 - FM_MAX_NUM_OF_1G_MACS;
169 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
170 * 0 - FM_MAX_NUM_OF_10G_MACS
171 */
172 u8 mac_id;
173 /* Note that the speed should indicate the maximum rate that
174 * this MAC should support rather than the actual speed;
175 */
176 u16 max_speed;
177 /* A handle to the FM object this port related to */
178 void *fm;
179 fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */
180 fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
181 /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
182 * and phy or backplane; Note: 1000BaseX auto-negotiation relates only
183 * to interface between MAC and phy/backplane, SGMII phy can still
184 * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps
185 */
186 bool basex_if;
187 };
188
189 struct eth_hash_t {
190 u16 size;
191 struct list_head *lsts;
192 };
193
194 static inline struct eth_hash_entry
dequeue_addr_from_hash_entry(struct list_head * addr_lst)195 *dequeue_addr_from_hash_entry(struct list_head *addr_lst)
196 {
197 struct eth_hash_entry *hash_entry = NULL;
198
199 if (!list_empty(addr_lst)) {
200 hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next);
201 list_del_init(&hash_entry->node);
202 }
203 return hash_entry;
204 }
205
free_hash_table(struct eth_hash_t * hash)206 static inline void free_hash_table(struct eth_hash_t *hash)
207 {
208 struct eth_hash_entry *hash_entry;
209 int i = 0;
210
211 if (hash) {
212 if (hash->lsts) {
213 for (i = 0; i < hash->size; i++) {
214 hash_entry =
215 dequeue_addr_from_hash_entry(&hash->lsts[i]);
216 while (hash_entry) {
217 kfree(hash_entry);
218 hash_entry =
219 dequeue_addr_from_hash_entry(&hash->
220 lsts[i]);
221 }
222 }
223
224 kfree(hash->lsts);
225 }
226
227 kfree(hash);
228 }
229 }
230
alloc_hash_table(u16 size)231 static inline struct eth_hash_t *alloc_hash_table(u16 size)
232 {
233 u32 i;
234 struct eth_hash_t *hash;
235
236 /* Allocate address hash table */
237 hash = kmalloc(sizeof(*hash), GFP_KERNEL);
238 if (!hash)
239 return NULL;
240
241 hash->size = size;
242
243 hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head),
244 GFP_KERNEL);
245 if (!hash->lsts) {
246 kfree(hash);
247 return NULL;
248 }
249
250 for (i = 0; i < hash->size; i++)
251 INIT_LIST_HEAD(&hash->lsts[i]);
252
253 return hash;
254 }
255
256 #endif /* __FM_MAC_H */
257