247 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright 2008-2015 Freescale Semiconductor Inc.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions are met:
 | |
|  *     * Redistributions of source code must retain the above copyright
 | |
|  *       notice, this list of conditions and the following disclaimer.
 | |
|  *     * Redistributions in binary form must reproduce the above copyright
 | |
|  *       notice, this list of conditions and the following disclaimer in the
 | |
|  *       documentation and/or other materials provided with the distribution.
 | |
|  *     * Neither the name of Freescale Semiconductor nor the
 | |
|  *       names of its contributors may be used to endorse or promote products
 | |
|  *       derived from this software without specific prior written permission.
 | |
|  *
 | |
|  *
 | |
|  * ALTERNATIVELY, this software may be distributed under the terms of the
 | |
|  * GNU General Public License ("GPL") as published by the Free Software
 | |
|  * Foundation, either version 2 of that License or (at your option) any
 | |
|  * later version.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
 | |
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | |
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | |
|  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
 | |
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | |
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | |
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | |
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | |
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| /* FM MAC ... */
 | |
| #ifndef __FM_MAC_H
 | |
| #define __FM_MAC_H
 | |
| 
 | |
| #include "fman.h"
 | |
| 
 | |
| #include <linux/slab.h>
 | |
| #include <linux/phy.h>
 | |
| #include <linux/if_ether.h>
 | |
| 
 | |
| struct fman_mac;
 | |
| struct mac_device;
 | |
| 
 | |
| /* Ethernet Address */
 | |
| typedef u8 enet_addr_t[ETH_ALEN];
 | |
| 
 | |
| #define ENET_ADDR_TO_UINT64(_enet_addr)		\
 | |
| 	(u64)(((u64)(_enet_addr)[0] << 40) |		\
 | |
| 	      ((u64)(_enet_addr)[1] << 32) |		\
 | |
| 	      ((u64)(_enet_addr)[2] << 24) |		\
 | |
| 	      ((u64)(_enet_addr)[3] << 16) |		\
 | |
| 	      ((u64)(_enet_addr)[4] << 8) |		\
 | |
| 	      ((u64)(_enet_addr)[5]))
 | |
| 
 | |
| #define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
 | |
| 	do { \
 | |
| 		int i; \
 | |
| 		for (i = 0; i < ETH_ALEN; i++) \
 | |
| 			(_enet_addr)[i] = \
 | |
| 			(u8)((_addr64) >> ((5 - i) * 8)); \
 | |
| 	} while (0)
 | |
| 
 | |
| /* defaults */
 | |
| #define DEFAULT_RESET_ON_INIT                 false
 | |
| 
 | |
| /* PFC defines */
 | |
| #define FSL_FM_PAUSE_TIME_ENABLE	0xf000
 | |
| #define FSL_FM_PAUSE_TIME_DISABLE	0
 | |
| #define FSL_FM_PAUSE_THRESH_DEFAULT	0
 | |
| 
 | |
| #define FM_MAC_NO_PFC   0xff
 | |
| 
 | |
| /* HASH defines */
 | |
| #define ETH_HASH_ENTRY_OBJ(ptr)	\
 | |
| 	hlist_entry_safe(ptr, struct eth_hash_entry, node)
 | |
| 
 | |
| /* FM MAC Exceptions */
 | |
| enum fman_mac_exceptions {
 | |
| 	FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
 | |
| 	/* 10GEC MDIO scan event interrupt */
 | |
| 	, FM_MAC_EX_10G_MDIO_CMD_CMPL
 | |
| 	/* 10GEC MDIO command completion interrupt */
 | |
| 	, FM_MAC_EX_10G_REM_FAULT
 | |
| 	/* 10GEC, mEMAC Remote fault interrupt */
 | |
| 	, FM_MAC_EX_10G_LOC_FAULT
 | |
| 	/* 10GEC, mEMAC Local fault interrupt */
 | |
| 	, FM_MAC_EX_10G_TX_ECC_ER
 | |
| 	/* 10GEC, mEMAC Transmit frame ECC error interrupt */
 | |
| 	, FM_MAC_EX_10G_TX_FIFO_UNFL
 | |
| 	/* 10GEC, mEMAC Transmit FIFO underflow interrupt */
 | |
| 	, FM_MAC_EX_10G_TX_FIFO_OVFL
 | |
| 	/* 10GEC, mEMAC Transmit FIFO overflow interrupt */
 | |
| 	, FM_MAC_EX_10G_TX_ER
 | |
| 	/* 10GEC Transmit frame error interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_FIFO_OVFL
 | |
| 	/* 10GEC, mEMAC Receive FIFO overflow interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_ECC_ER
 | |
| 	/* 10GEC, mEMAC Receive frame ECC error interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_JAB_FRM
 | |
| 	/* 10GEC Receive jabber frame interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_OVRSZ_FRM
 | |
| 	/* 10GEC Receive oversized frame interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_RUNT_FRM
 | |
| 	/* 10GEC Receive runt frame interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_FRAG_FRM
 | |
| 	/* 10GEC Receive fragment frame interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_LEN_ER
 | |
| 	/* 10GEC Receive payload length error interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_CRC_ER
 | |
| 	/* 10GEC Receive CRC error interrupt */
 | |
| 	, FM_MAC_EX_10G_RX_ALIGN_ER
 | |
| 	/* 10GEC Receive alignment error interrupt */
 | |
| 	, FM_MAC_EX_1G_BAB_RX
 | |
| 	/* dTSEC Babbling receive error */
 | |
| 	, FM_MAC_EX_1G_RX_CTL
 | |
| 	/* dTSEC Receive control (pause frame) interrupt */
 | |
| 	, FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
 | |
| 	/* dTSEC Graceful transmit stop complete */
 | |
| 	, FM_MAC_EX_1G_BAB_TX
 | |
| 	/* dTSEC Babbling transmit error */
 | |
| 	, FM_MAC_EX_1G_TX_CTL
 | |
| 	/* dTSEC Transmit control (pause frame) interrupt */
 | |
| 	, FM_MAC_EX_1G_TX_ERR
 | |
| 	/* dTSEC Transmit error */
 | |
| 	, FM_MAC_EX_1G_LATE_COL
 | |
| 	/* dTSEC Late collision */
 | |
| 	, FM_MAC_EX_1G_COL_RET_LMT
 | |
| 	/* dTSEC Collision retry limit */
 | |
| 	, FM_MAC_EX_1G_TX_FIFO_UNDRN
 | |
| 	/* dTSEC Transmit FIFO underrun */
 | |
| 	, FM_MAC_EX_1G_MAG_PCKT
 | |
| 	/* dTSEC Magic Packet detection */
 | |
| 	, FM_MAC_EX_1G_MII_MNG_RD_COMPLET
 | |
| 	/* dTSEC MII management read completion */
 | |
| 	, FM_MAC_EX_1G_MII_MNG_WR_COMPLET
 | |
| 	/* dTSEC MII management write completion */
 | |
| 	, FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
 | |
| 	/* dTSEC Graceful receive stop complete */
 | |
| 	, FM_MAC_EX_1G_DATA_ERR
 | |
| 	/* dTSEC Internal data error on transmit */
 | |
| 	, FM_MAC_1G_RX_DATA_ERR
 | |
| 	/* dTSEC Internal data error on receive */
 | |
| 	, FM_MAC_EX_1G_1588_TS_RX_ERR
 | |
| 	/* dTSEC Time-Stamp Receive Error */
 | |
| 	, FM_MAC_EX_1G_RX_MIB_CNT_OVFL
 | |
| 	/* dTSEC MIB counter overflow */
 | |
| 	, FM_MAC_EX_TS_FIFO_ECC_ERR
 | |
| 	/* mEMAC Time-stamp FIFO ECC error interrupt;
 | |
| 	 * not supported on T4240/B4860 rev1 chips
 | |
| 	 */
 | |
| 	, FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
 | |
| 	/* mEMAC Magic Packet Indication Interrupt */
 | |
| };
 | |
| 
 | |
| struct eth_hash_entry {
 | |
| 	u64 addr;		/* Ethernet Address  */
 | |
| 	struct list_head node;
 | |
| };
 | |
| 
 | |
| typedef void (fman_mac_exception_cb)(struct mac_device *dev_id,
 | |
| 				     enum fman_mac_exceptions exceptions);
 | |
| 
 | |
| /* FMan MAC config input */
 | |
| struct fman_mac_params {
 | |
| 	/* MAC ID; numbering of dTSEC and 1G-mEMAC:
 | |
| 	 * 0 - FM_MAX_NUM_OF_1G_MACS;
 | |
| 	 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
 | |
| 	 * 0 - FM_MAX_NUM_OF_10G_MACS
 | |
| 	 */
 | |
| 	u8 mac_id;
 | |
| 	/* A handle to the FM object this port related to */
 | |
| 	void *fm;
 | |
| 	fman_mac_exception_cb *event_cb;    /* MDIO Events Callback Routine */
 | |
| 	fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
 | |
| };
 | |
| 
 | |
| struct eth_hash_t {
 | |
| 	u16 size;
 | |
| 	struct list_head *lsts;
 | |
| };
 | |
| 
 | |
| static inline struct eth_hash_entry
 | |
| *dequeue_addr_from_hash_entry(struct list_head *addr_lst)
 | |
| {
 | |
| 	struct eth_hash_entry *hash_entry = NULL;
 | |
| 
 | |
| 	if (!list_empty(addr_lst)) {
 | |
| 		hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next);
 | |
| 		list_del_init(&hash_entry->node);
 | |
| 	}
 | |
| 	return hash_entry;
 | |
| }
 | |
| 
 | |
| static inline void free_hash_table(struct eth_hash_t *hash)
 | |
| {
 | |
| 	struct eth_hash_entry *hash_entry;
 | |
| 	int i = 0;
 | |
| 
 | |
| 	if (hash) {
 | |
| 		if (hash->lsts) {
 | |
| 			for (i = 0; i < hash->size; i++) {
 | |
| 				hash_entry =
 | |
| 				dequeue_addr_from_hash_entry(&hash->lsts[i]);
 | |
| 				while (hash_entry) {
 | |
| 					kfree(hash_entry);
 | |
| 					hash_entry =
 | |
| 					dequeue_addr_from_hash_entry(&hash->
 | |
| 								     lsts[i]);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			kfree(hash->lsts);
 | |
| 		}
 | |
| 
 | |
| 		kfree(hash);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static inline struct eth_hash_t *alloc_hash_table(u16 size)
 | |
| {
 | |
| 	u32 i;
 | |
| 	struct eth_hash_t *hash;
 | |
| 
 | |
| 	/* Allocate address hash table */
 | |
| 	hash = kmalloc(sizeof(*hash), GFP_KERNEL);
 | |
| 	if (!hash)
 | |
| 		return NULL;
 | |
| 
 | |
| 	hash->size = size;
 | |
| 
 | |
| 	hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head),
 | |
| 				   GFP_KERNEL);
 | |
| 	if (!hash->lsts) {
 | |
| 		kfree(hash);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	for (i = 0; i < hash->size; i++)
 | |
| 		INIT_LIST_HEAD(&hash->lsts[i]);
 | |
| 
 | |
| 	return hash;
 | |
| }
 | |
| 
 | |
| #endif /* __FM_MAC_H */
 |