diff options
author | Mandy Lavi <mandy.lavi@freescale.com> | 2013-03-24 16:40:18 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-08 23:07:26 (GMT) |
commit | 3cc514986cb4e457458cc826288b6c2107c97907 (patch) | |
tree | 2985e48afc5dd20f44d51ef6aafdae917ce2698f /drivers/net/ethernet/freescale/dpa | |
parent | 5767d52cec831b0e2927d34e91acd738cc1cb0ef (diff) | |
download | linux-fsl-qoriq-3cc514986cb4e457458cc826288b6c2107c97907.tar.xz |
fmd: fmd19 integration
Add fmd19 codebase, plus a minimal set of sources from dpaa-eth,
necessary for bare compilation
Change-Id: I390df8717671204e3d98a987135393bef4534e95
Signed-off-by: Mandy Lavi <mandy.lavi@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-on: http://git.am.freescale.net:8181/1029
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/dpa')
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/Kconfig | 98 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/Makefile | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth-common.h | 164 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth.h | 571 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac.h | 110 |
5 files changed, 964 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/Kconfig b/drivers/net/ethernet/freescale/dpa/Kconfig new file mode 100644 index 0000000..60e653f --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/Kconfig @@ -0,0 +1,98 @@ +config DPA_ETH + bool "DPAA Ethernet" +# FIXME enable this when all dependencies are merged +# depends on FSL_SOC && FSL_BMAN && FSL_QMAN && FSL_FMAN + select PHYLIB + ---help--- + Data Path Acceleration Architecture Ethernet driver, supporting the + Freescale QorIQ chips. + +config DPA_OFFLINE_PORTS + bool "Offline Ports support" + depends on DPA_ETH + default y + ---help--- + The Offline Parsing / Host Command ports (short: OH ports, of Offline ports) provide + most of the functionality of the regular, online ports, except they receive their + frames from a core or an accelerator on the SoC, via QMan frame queues, + rather than directly from the network. + Offline ports are configured via PCD (Parse-Classify-Distribute) schemes, just like + any online FMan port. They deliver the processed frames to frame queues, according + to the applied PCD configurations. + + Choosing this feature will not impact the functionality and/or performance of the system, + so it is safe to have it. + +config DPAA_ETH_SG_SUPPORT + bool + +choice DPAA_ETH_OPTIMIZE + prompt "Optimization choices for the DPAA Ethernet driver" + depends on DPA_ETH + default DPAA_ETH_OPTIMIZE_FOR_IPFWD + ---help--- + Compile-time switch between driver optimizations for forwarding use-cases and + termination scenarios. + + config DPAA_ETH_OPTIMIZE_FOR_IPFWD + bool "Optimize for forwarding" + select DPA_TX_RECYCLE if FMAN_T4240 + ---help--- + Optimize the DPAA-Ethernet driver for IP/IPSec forwarding use-cases. + + config DPAA_ETH_OPTIMIZE_FOR_TERM + bool "Optimize for termination" + select DPAA_ETH_SG_SUPPORT + ---help--- + Optimize the DPAA-Ethernet driver for termination (TCP, UDP) use-cases. + In particular, this choice enables Scatter-Gather (SG) support + in the driver, which is momentarily not accessible otherwise. +endchoice + +config DPA_TX_RECYCLE + bool + depends on FMAN_T4240 + +config FSL_DPA_1588 + tristate "IEEE 1588-compliant timestamping" + depends on DPA_ETH + default n + +choice DPA_ETH_WQ_ASSIGN + prompt "WorkQueue assignment scheme for FrameQueues" + depends on DPA_ETH + default DPA_ETH_WQ_MULTI + ---help--- + Selects the FrameQueue to WorkQueue assignment scheme. + + config DPA_ETH_WQ_LEGACY + bool "Legacy WQ assignment" + ---help--- + Statically-defined FQIDs are round-robin assigned to all WQs (0..7). PCD queues are always + in this category. Other frame queues may be those used for "MAC-less" or "shared MAC" configurations + of the driver. + Dynamically-defined FQIDs all go to WQ7. + config DPA_ETH_WQ_MULTI + bool "Multi-WQ assignment" + ---help--- + Tx Confirmation FQs go to WQ1. + Rx Default, Tx and PCD FQs go to WQ3. + Rx Error and Tx Error FQs go to WQ2. +endchoice + +config DPAA_ETH_USE_NDO_SELECT_QUEUE + bool "Use driver's Tx queue selection mechanism" + default y + depends on DPA_ETH + ---help--- + The DPAA-Ethernet driver defines a ndo_select_queue() callback for optimal selection + of the egress FQ. That will override the XPS support for this netdevice. + If for whatever reason you want to be in control of the egress FQ-to-CPU selection and mapping, + or simply don't want to use the driver's ndo_select_queue() callback, then unselect this + and use the standard XPS support instead. + +config DPAA_ETH_UNIT_TESTS + bool "Run Unit Tests for DPAA Ethernet" + depends on DPA_ETH + default y + diff --git a/drivers/net/ethernet/freescale/dpa/Makefile b/drivers/net/ethernet/freescale/dpa/Makefile new file mode 100644 index 0000000..54b3a96 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/Makefile @@ -0,0 +1,21 @@ +# +# Makefile for the Freescale Ethernet controllers +# +EXTRA_CFLAGS += -DVERSION=\"\" +# +#Include netcomm SW specific definitions +include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk + +EXTRA_CFLAGS += -I$(NET_DPA) + +#Netcomm SW tree +obj-$(CONFIG_FSL_FMAN) += ../fman/ +obj-$(CONFIG_FSL_DPA_1588) += dpaa_1588.o +obj-$(CONFIG_DPAA_ETH_SG_SUPPORT) += fsl-dpa-sg.o +obj-$(CONFIG_DPA_ETH) += fsl-mac.o fsl-dpa.o +obj-$(CONFIG_DPA_OFFLINE_PORTS) += fsl-oh.o + +fsl-dpa-objs := dpa-ethtool.o dpaa_eth.o dpaa_eth_sysfs.o xgmac_mdio.o +fsl-dpa-sg-objs := dpaa_eth_sg.o +fsl-mac-objs := mac.o mac-api.o +fsl-oh-objs := offline_port.o diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth-common.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth-common.h new file mode 100644 index 0000000..5b63688 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth-common.h @@ -0,0 +1,164 @@ +/* + * Copyright 2008-2012 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. + */ + +#ifndef __DPA_COMMON_H +#define __DPA_COMMON_H + +#include <linux/kernel.h> /* pr_*() */ +#include <linux/device.h> /* dev_*() */ +#include <linux/smp.h> /* smp_processor_id() */ + +/* The basename of the source file is being compiled */ +#define __file__ KBUILD_BASENAME".c" + +#define __hot + +#define cpu_printk(level, format, arg...) \ + pr_##level("cpu%d: " format, smp_processor_id(), ##arg) + +#define cpu_pr_emerg(format, arg...) \ + cpu_printk(emerg, format, ##arg) +#define cpu_pr_alert(format, arg...) \ + cpu_printk(alert, format, ##arg) +#define cpu_pr_crit(format, arg...) \ + cpu_printk(crit, format, ##arg) +#define cpu_pr_err(format, arg...) \ + cpu_printk(err, format, ##arg) +#define cpu_pr_warning(format, arg...) \ + cpu_printk(warning, format, ##arg) +#define cpu_pr_notice(format, arg...) \ + cpu_printk(notice, format, ##arg) +#define cpu_pr_info(format, arg...) \ + cpu_printk(info, format, ##arg) +#define cpu_pr_debug(format, arg...) \ + cpu_printk(debug, format, ##arg) + +/* Keep this in sync with the dev_*() definitions from linux/device.h */ +#define cpu_dev_printk(level, dev, format, arg...) \ + cpu_pr_##level("%s: %s: " format, dev_driver_string(dev), \ + dev_name(dev), ##arg) + +#define cpu_dev_emerg(dev, format, arg...) \ + cpu_dev_printk(emerg, dev, format, ##arg) +#define cpu_dev_alert(dev, format, arg...) \ + cpu_dev_printk(alert, dev, format, ##arg) +#define cpu_dev_crit(dev, format, arg...) \ + cpu_dev_printk(crit, dev, format, ##arg) +#define cpu_dev_err(dev, format, arg...) \ + cpu_dev_printk(err, dev, format, ##arg) +#define cpu_dev_warn(dev, format, arg...) \ + cpu_dev_printk(warning, dev, format, ##arg) +#define cpu_dev_notice(dev, format, arg...) \ + cpu_dev_printk(notice, dev, format, ##arg) +#define cpu_dev_info(dev, format, arg...) \ + cpu_dev_printk(info, dev, format, ##arg) +#define cpu_dev_dbg(dev, format, arg...) \ + cpu_dev_printk(debug, dev, format, ##arg) + +#define dpaa_eth_printk(level, dev, format, arg...) \ + cpu_dev_printk(level, dev, "%s:%hu:%s() " format, \ + __file__, __LINE__, __func__, ##arg) + +#define dpaa_eth_emerg(dev, format, arg...) \ + dpaa_eth_printk(emerg, dev, format, ##arg) +#define dpaa_eth_alert(dev, format, arg...) \ + dpaa_eth_printk(alert, dev, format, ##arg) +#define dpaa_eth_crit(dev, format, arg...) \ + dpaa_eth_printk(crit, dev, format, ##arg) +#define dpaa_eth_err(dev, format, arg...) \ + dpaa_eth_printk(err, dev, format, ##arg) +#define dpaa_eth_warning(dev, format, arg...) \ + dpaa_eth_printk(warning, dev, format, ##arg) +#define dpaa_eth_notice(dev, format, arg...) \ + dpaa_eth_printk(notice, dev, format, ##arg) +#define dpaa_eth_info(dev, format, arg...) \ + dpaa_eth_printk(info, dev, format, ##arg) +#define dpaa_eth_debug(dev, format, arg...) \ + dpaa_eth_printk(debug, dev, format, ##arg) + +#define cpu_netdev_emerg(net_dev, format, arg...) \ + dpaa_eth_emerg((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_alert(net_dev, format, arg...) \ + dpaa_eth_alert((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_crit(net_dev, format, arg...) \ + dpaa_eth_crit((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_err(net_dev, format, arg...) \ + dpaa_eth_err((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_warn(net_dev, format, arg...) \ + dpaa_eth_warning((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_notice(net_dev, format, arg...) \ + dpaa_eth_notice((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_info(net_dev, format, arg...) \ + dpaa_eth_info((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) +#define cpu_netdev_dbg(net_dev, format, arg...) \ + dpaa_eth_debug((net_dev)->dev.parent, "%s: " format, \ + (net_dev)->name , ##arg) + +/* Simple enum of FQ types - used for array indexing */ +enum {RX, TX}; + +/* More detailed FQ types - used for fine-grained WQ assignments */ +enum dpa_fq_type { + FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */ + FQ_TYPE_RX_ERROR, /* Rx Error FQs */ + FQ_TYPE_RX_PCD, /* User-defined PCDs */ + FQ_TYPE_TX, /* "Real" Tx FQs */ + FQ_TYPE_TX_CONFIRM, /* Tx Confirmation FQs (actually Rx FQs) */ + FQ_TYPE_TX_ERROR, /* Tx Error FQs (these are actually Rx FQs) */ +}; + + +#define DPA_PARSE_RESULTS_SIZE sizeof(t_FmPrsResult) +#define DPA_HASH_RESULTS_SIZE 16 + +#define DPA_TX_PRIV_DATA_SIZE 16 + +#define dpaa_eth_init_port(type, port, param, errq_id, defq_id, priv_size, \ + has_timer) \ +{ \ + param.errq = errq_id; \ + param.defq = defq_id; \ + param.priv_data_size = priv_size; \ + param.parse_results = true; \ + param.hash_results = true; \ + param.time_stamp = has_timer; \ + fm_set_##type##_port_params(port, ¶m); \ +} + +#endif /* __DPA_COMMON_H */ diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h new file mode 100644 index 0000000..79a67d3 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h @@ -0,0 +1,571 @@ +/* + * Copyright 2008-2012 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. + */ + +#ifndef __DPA_H +#define __DPA_H + +#include <linux/ethtool.h> /* struct ethtool_ops */ +#include <linux/netdevice.h> +#include <linux/list.h> /* struct list_head */ +#include <linux/workqueue.h> /* struct work_struct */ +#include <linux/skbuff.h> +#include <linux/hardirq.h> +#include <linux/if_vlan.h> /* vlan_eth_hdr */ +#include <linux/ip.h> /* ip_hdr */ +#include <linux/ipv6.h> /* ipv6_hdr */ +#ifdef CONFIG_DEBUG_FS +#include <linux/dcache.h> /* struct dentry */ +#endif + +#include <linux/fsl_qman.h> /* struct qman_fq */ + +#include "dpaa_eth-common.h" + +#include "fsl_fman.h" +#include "fm_ext.h" +#include "fm_port_ext.h" /* FM_PORT_FRM_ERR_* */ + +#include "mac.h" /* struct mac_device */ + +#ifdef CONFIG_DPAA_ETH_SG_SUPPORT +#define dpa_get_rx_extra_headroom() fm_get_rx_extra_headroom() +#else +#define dpa_get_rx_extra_headroom() dpa_rx_extra_headroom +#endif +#define dpa_get_max_frm() dpa_max_frm + +/* + * Currently we have the same max_frm on all interfaces, so these macros + * don't get a net_device argument. This will change in the future. + */ +#define dpa_get_min_mtu() 64 +#define dpa_get_max_mtu() \ + (dpa_get_max_frm() - (VLAN_ETH_HLEN + ETH_FCS_LEN)) + +#define DPA_RX_PRIV_DATA_SIZE (DPA_TX_PRIV_DATA_SIZE + \ + dpa_get_rx_extra_headroom()) +/* number of Tx queues to FMan */ +#define DPAA_ETH_TX_QUEUES NR_CPUS +#define DPAA_ETH_RX_QUEUES 128 + +#if defined(CONFIG_DPAA_FMAN_UNIT_TESTS) +/*TODO: temporary for fman pcd testing */ +#define FMAN_PCD_TESTS_MAX_NUM_RANGES 20 +#endif + +/* return codes for the dpaa-eth hooks */ +enum dpaa_eth_hook_result { + /* fd/skb was retained by the hook. + * + * On the Rx path, this means the Ethernet driver will _not_ + * deliver the skb to the stack. Instead, the hook implementation + * is expected to properly dispose of the skb. + * + * On the Tx path, the Ethernet driver's dpa_tx() function will + * immediately return NETDEV_TX_OK. The hook implementation is expected + * to free the skb. *DO*NOT* release it to BMan, or enqueue it to FMan, + * unless you know exactly what you're doing! + * + * On the confirmation/error paths, the Ethernet driver will _not_ + * perform any fd cleanup, nor update the interface statistics. + */ + DPAA_ETH_STOLEN, + /* + * fd/skb was returned to the Ethernet driver for regular processing. + * The hook is not allowed to, for instance, reallocate the skb (as if + * by linearizing, copying, cloning or reallocating the headroom). + */ + DPAA_ETH_CONTINUE +}; + +typedef enum dpaa_eth_hook_result (*dpaa_eth_ingress_hook_t)( + struct sk_buff *skb, struct net_device *net_dev, u32 fqid); +typedef enum dpaa_eth_hook_result (*dpaa_eth_egress_hook_t)( + struct sk_buff *skb, struct net_device *net_dev); +typedef enum dpaa_eth_hook_result (*dpaa_eth_confirm_hook_t)( + struct net_device *net_dev, const struct qm_fd *fd, u32 fqid); + +/* + * Various hooks used for unit-testing and/or fastpath optimizations. + * Currently only one set of such hooks is supported. + */ +struct dpaa_eth_hooks_s { + /* + * Invoked on the Tx private path, immediately after receiving the skb + * from the stack. + */ + dpaa_eth_egress_hook_t tx; + + /* + * Invoked on the Rx private path, right before passing the skb + * up the stack. At that point, the packet's protocol id has already + * been set. The skb's data pointer is now at the L3 header, and + * skb->mac_header points to the L2 header. skb->len has been adjusted + * to be the length of L3+payload (i.e., the length of the + * original frame minus the L2 header len). + * For more details on what the skb looks like, see eth_type_trans(). + */ + dpaa_eth_ingress_hook_t rx_default; + + /* Driver hook for the Rx error private path. */ + dpaa_eth_confirm_hook_t rx_error; + /* Driver hook for the Tx confirmation private path. */ + dpaa_eth_confirm_hook_t tx_confirm; + /* Driver hook for the Tx error private path. */ + dpaa_eth_confirm_hook_t tx_error; +}; + +void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks); + +#define DPA_BP_HEAD (DPA_TX_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE + \ + DPA_HASH_RESULTS_SIZE) +#define DPA_BP_SIZE(s) (DPA_BP_HEAD + dpa_get_rx_extra_headroom() + (s)) + +#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ + +#ifdef CONFIG_DPAA_ETH_SG_SUPPORT +#define DEFAULT_SKB_COUNT 64 /* maximum number of SKBs in each percpu list */ +/* + * We may want this value configurable. Must be <= PAGE_SIZE + * A lower value may help with recycling rates, at least on forwarding + */ +#define DEFAULT_BUF_SIZE PAGE_SIZE +/* + * Default amount data to be copied from the beginning of a frame into the + * linear part of the skb, in case we aren't using the hardware parser. + */ +#define DPA_COPIED_HEADERS_SIZE 128 + +#else +/* + * Default buffer size is based on L2 MAX_FRM value, minus the FCS which is + * stripped down by hardware. + */ +#define DEFAULT_BUF_SIZE DPA_BP_SIZE(dpa_get_max_frm() - ETH_FCS_LEN) +#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ + +/* + * Values for the L3R field of the FM Parse Results + */ +/* L3 Type field: First IP Present IPv4 */ +#define FM_L3_PARSE_RESULT_IPV4 0x8000 +/* L3 Type field: First IP Present IPv6 */ +#define FM_L3_PARSE_RESULT_IPV6 0x4000 + +/* + * Values for the L4R field of the FM Parse Results + * See $8.8.4.7.20 - L4 HXS - L4 Results from DPAA-Rev2 Reference Manual. + */ +/* L4 Type field: UDP */ +#define FM_L4_PARSE_RESULT_UDP 0x40 +/* L4 Type field: TCP */ +#define FM_L4_PARSE_RESULT_TCP 0x20 +/* + * This includes L4 checksum errors, but also other errors that the Hard Parser + * can detect, such as invalid combinations of TCP control flags, or bad UDP + * lengths. + */ +#define FM_L4_PARSE_ERROR 0x10 +/* Check if the hardware parser has run */ +#define FM_L4_HXS_RUN 0xE0 + +/* + * FD status field indicating whether the FM Parser has attempted to validate + * the L4 csum of the frame. + * Note that having this bit set doesn't necessarily imply that the checksum + * is valid. One would have to check the parse results to find that out. + */ +#define FM_FD_STAT_L4CV 0x00000004 + +#define FM_FD_STAT_ERRORS \ + (FM_PORT_FRM_ERR_DMA | FM_PORT_FRM_ERR_PHYSICAL | \ + FM_PORT_FRM_ERR_SIZE | FM_PORT_FRM_ERR_CLS_DISCARD | \ + FM_PORT_FRM_ERR_EXTRACTION | FM_PORT_FRM_ERR_NO_SCHEME | \ + FM_PORT_FRM_ERR_ILL_PLCR | FM_PORT_FRM_ERR_PRS_TIMEOUT | \ + FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | FM_PORT_FRM_ERR_PRS_HDR_ERR) + +#define FM_FD_STAT_ERR_PHYSICAL FM_PORT_FRM_ERR_PHYSICAL + +/* + * Check if the FMan Hardware Parser has run for L4 protocols. + * + * @parse_result_ptr must be of type (t_FmPrsResult *). + */ +#define fm_l4_hxs_has_run(parse_result_ptr) \ + ((parse_result_ptr)->l4r & FM_L4_HXS_RUN) +/* + * Iff the FMan Hardware Parser has run for L4 protocols, check error status. + * + * @parse_result_ptr must be of type (t_FmPrsResult *). + */ +#define fm_l4_hxs_error(parse_result_ptr) \ + ((parse_result_ptr)->l4r & FM_L4_PARSE_ERROR) +/* + * Check if the parsed frame was found to be a TCP segment. + * + * @parse_result_ptr must be of type (t_FmPrsResult *). + */ +#define fm_l4_frame_is_tcp(parse_result_ptr) \ + ((parse_result_ptr)->l4r & FM_L4_PARSE_RESULT_TCP) + +struct pcd_range { + uint32_t base; + uint32_t count; +}; + +struct dpa_fq { + struct qman_fq fq_base; + struct list_head list; + struct net_device *net_dev; + bool init; + uint32_t fqid; + uint32_t flags; + uint16_t channel; + uint8_t wq; + enum dpa_fq_type fq_type; +}; + +struct dpa_bp { + struct bman_pool *pool; + uint8_t bpid; + struct device *dev; + union { + /* + * The buffer pools used for the private ports are initialized + * with target_count buffers for each CPU; at runtime the + * number of buffers per CPU is constantly brought back to this + * level + */ + int target_count; + /* + * The configured value for the number of buffers in the pool, + * used for shared port buffer pools + */ + int config_count; + }; + size_t size; + bool seed_pool; + /* + * physical address of the contiguous memory used by the pool to store + * the buffers + */ + dma_addr_t paddr; + /* + * virtual address of the contiguous memory used by the pool to store + * the buffers + */ + void *vaddr; + int kernel_pool; + /* current number of buffers in the bpool alloted to this CPU */ + int *percpu_count; + atomic_t refs; +}; + +struct dpa_rx_errors { + u32 dme; /* DMA Error */ + u32 fpe; /* Frame Physical Error */ + u32 fse; /* Frame Size Error */ + u32 phe; /* Header Error */ + u32 cse; /* Checksum Validation Error */ +}; + +/* Counters for QMan ERN frames - one counter per rejection code */ +struct dpa_ern_cnt { + u32 cg_tdrop; /* Congestion group taildrop */ + u32 wred; /* WRED congestion */ + u32 err_cond; /* Error condition */ + u32 early_window; /* Order restoration, frame too early */ + u32 late_window; /* Order restoration, frame too late */ + u32 fq_tdrop; /* FQ taildrop */ + u32 fq_retired; /* FQ is retired */ + u32 orp_zero; /* ORP disabled */ +}; + +struct dpa_percpu_priv_s { + struct net_device *net_dev; + /* + * Pointer to the percpu_count of the shared buffer pool + * used for the private ports; this assumes there is only + * one bpool used + */ + int *dpa_bp_count; + struct dpa_bp *dpa_bp; + struct napi_struct napi; +#ifdef CONFIG_DPAA_ETH_SG_SUPPORT + /* a list of preallocated SKBs for this CPU */ + struct sk_buff_head skb_list; + /* current number of skbs in the CPU's list */ + int skb_count; +#endif + u32 start_tx; + u32 in_interrupt; + u32 ingress_calls; + u32 tx_returned; + u32 tx_confirm; + /* fragmented (non-linear) skbuffs received from the stack */ + u32 tx_frag_skbuffs; + /* + * Frames identified as L4 packets (by FMan's Hardware Parser, but for + * which the parsing failed due to some error condition. If we come + * across such frames, we drop them instead of passing them up the + * stack, which means the L4 stats in the stack won't increment. + */ + u32 l4_hxs_errors; + struct net_device_stats stats; + struct dpa_rx_errors rx_errors; + struct dpa_ern_cnt ern_cnt; +}; + +/* increment when adding new sysfs entries */ +#define DPA_MAX_NUM_OF_SYSFS_ATTRS 5 + +struct dpa_priv_s { + struct dpa_bp *dpa_bp; + size_t bp_count; + int shared; + struct net_device *net_dev; + + uint16_t channel; /* "fsl,qman-channel-id" */ + struct list_head dpa_fq_list; + struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES]; + + struct mac_device *mac_dev; + + struct dpa_percpu_priv_s *percpu_priv; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_file; +#endif + + uint32_t msg_enable; /* net_device message level */ + struct dpa_ptp_tsu *tsu; + +#if defined(CONFIG_DPAA_FMAN_UNIT_TESTS) +/* TODO: this is temporary until pcd support is implemented in dpaa */ + int priv_pcd_num_ranges; + struct pcd_range priv_pcd_ranges[FMAN_PCD_TESTS_MAX_NUM_RANGES]; +#endif + + struct { + /** + * All egress queues to a given net device belong to one + * (and the same) congestion group. + */ + struct qman_cgr cgr; + /* If congested, when it began. Used for performance stats. */ + u32 congestion_start_jiffies; + /* Number of jiffies the Tx port was congested. */ + u32 congested_jiffies; + /** + * Counter for the number of times the CGR + * entered congestion state + */ + u32 cgr_congested_count; + } cgr_data; + /* sysfs entries, last value must be NULL */ + struct device_attribute *sysfs_attrs[DPA_MAX_NUM_OF_SYSFS_ATTRS + 1]; +}; + +extern const struct ethtool_ops dpa_ethtool_ops; + +void __attribute__((nonnull)) +dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd); + +void dpa_make_private_pool(struct dpa_bp *dpa_bp); + +struct dpa_bp *dpa_bpid2pool(int bpid); + +void __hot _dpa_rx(struct net_device *net_dev, + const struct dpa_priv_s *priv, + struct dpa_percpu_priv_s *percpu_priv, + const struct qm_fd *fd, + u32 fqid); + +int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev); + +struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + const struct qm_fd *fd); + +int __hot _dpa_process_parse_results(const t_FmPrsResult *parse_results, + const struct qm_fd *fd, + struct sk_buff *skb, + int *use_gro, + unsigned int *hdr_size __maybe_unused); + +#ifdef CONFIG_DPAA_ETH_SG_SUPPORT +void dpa_bp_add_8_pages(struct dpa_bp *dpa_bp, int cpu_id); + +void dpa_list_add_skbs(struct dpa_percpu_priv_s *cpu_priv, int count); +#endif + +/* + * Turn on HW checksum computation for this outgoing frame. + * If the current protocol is not something we support in this regard + * (or if the stack has already computed the SW checksum), we do nothing. + * + * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value + * otherwise. + * + * Note that this function may modify the fd->cmd field and the skb data buffer + * (the Parse Results area). + */ +int dpa_enable_tx_csum(struct dpa_priv_s *priv, + struct sk_buff *skb, struct qm_fd *fd, char *parse_results); + +static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv) +{ + /* + * In case of threaded ISR for RT enable kernel, + * in_irq() does not return appropriate value, so use + * in_serving_softirq to distinguish softirq or irq context. + */ + if (unlikely(in_irq() || !in_serving_softirq())) { + /* Disable QMan IRQ and invoke NAPI */ + int ret = qman_irqsource_remove(QM_PIRQ_DQRI); + if (likely(!ret)) { + napi_schedule(&percpu_priv->napi); + return 1; + } + } + return 0; +} + +static inline ssize_t __const __must_check __attribute__((nonnull)) +dpa_fd_length(const struct qm_fd *fd) +{ + return fd->length20; +} + +static inline ssize_t __const __must_check __attribute__((nonnull)) +dpa_fd_offset(const struct qm_fd *fd) +{ + return fd->offset; +} + +/* Verifies if the skb length is below the interface MTU */ +static inline int dpa_check_rx_mtu(struct sk_buff *skb, int mtu) +{ + if (unlikely(skb->len > mtu)) + if ((skb->protocol != ETH_P_8021Q) || (skb->len > mtu + 4)) + return -1; + + return 0; +} + +void fm_mac_dump_regs(struct mac_device *mac_dev); + +/* Equivalent to a memset(0), but works faster */ +static inline void clear_fd(struct qm_fd *fd) +{ + fd->opaque_addr = 0; + fd->opaque = 0; + fd->cmd = 0; +} + +static inline int __hot dpa_xmit(struct dpa_priv_s *priv, + struct dpa_percpu_priv_s *percpu, int queue, + struct qm_fd *fd) +{ + int err, i; + + prefetchw(&percpu->start_tx); + for (i = 0; i < 100000; i++) { + err = qman_enqueue(priv->egress_fqs[queue], fd, 0); + if (err != -EBUSY) + break; + } + + if (unlikely(err < 0)) { + /* TODO differentiate b/w -EBUSY (EQCR full) and other codes? */ + percpu->stats.tx_errors++; + percpu->stats.tx_fifo_errors++; + return err; + } + + percpu->stats.tx_packets++; + percpu->stats.tx_bytes += dpa_fd_length(fd); + + return 0; +} + +#if defined CONFIG_DPA_ETH_WQ_LEGACY +#define DPA_NUM_WQS 8 +/* + * Older WQ assignment: statically-defined FQIDs (such as PCDs) are assigned + * round-robin to all WQs available. Dynamically-allocated FQIDs go to WQ7. + * + * Not necessarily the best scheme, but worked fine so far, so we might want + * to keep it around for a while. + */ +static inline void _dpa_assign_wq(struct dpa_fq *fq) +{ + fq->wq = fq->fqid ? fq->fqid % DPA_NUM_WQS : DPA_NUM_WQS - 1; +} +#elif defined CONFIG_DPA_ETH_WQ_MULTI +/* + * Use multiple WQs for FQ assignment: + * - Tx Confirmation queues go to WQ1. + * - Rx Default, Tx and PCD queues go to WQ3 (no differentiation between + * Rx and Tx traffic, or between Rx Default and Rx PCD frames). + * - Rx Error and Tx Error queues go to WQ2 (giving them a better chance + * to be scheduled, in case there are many more FQs in WQ3). + * This ensures that Tx-confirmed buffers are timely released. In particular, + * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they + * are greatly outnumbered by other FQs in the system (usually PCDs), while + * dequeue scheduling is round-robin. + */ +static inline void _dpa_assign_wq(struct dpa_fq *fq) +{ + switch (fq->fq_type) { + case FQ_TYPE_TX_CONFIRM: + fq->wq = 1; + break; + case FQ_TYPE_RX_DEFAULT: + case FQ_TYPE_TX: + case FQ_TYPE_RX_PCD: + fq->wq = 3; + break; + case FQ_TYPE_RX_ERROR: + case FQ_TYPE_TX_ERROR: + fq->wq = 2; + break; + default: + WARN(1, "Invalid FQ type %d for FQID %d!\n", + fq->fq_type, fq->fqid); + } +} +#else +/* This shouldn't happen, since we've made a "default" choice in the Kconfig. */ +#warning "No WQ assignment scheme chosen; Kconfig out-of-sync?" +#endif /* CONFIG_DPA_ETH_WQ_ASSIGN_* */ + + +#endif /* __DPA_H */ diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h new file mode 100644 index 0000000..5cdb57c --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/mac.h @@ -0,0 +1,110 @@ +/* Copyright 2008-2011 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. + */ + +#ifndef __MAC_H +#define __MAC_H + +#include <linux/device.h> /* struct device, BUS_ID_SIZE */ +#include <linux/if_ether.h> /* ETH_ALEN */ +#include <linux/phy.h> /* phy_interface_t, struct phy_device */ +#include <linux/list.h> + +#include "fsl_fman.h" /* struct port_device */ + +enum {DTSEC, XGMAC, MEMAC}; + +struct mac_device { + struct device *dev; + void *priv; + uint8_t cell_index; + struct resource *res; + void *vaddr; + uint8_t addr[ETH_ALEN]; + bool promisc; + + struct fm *fm_dev; + struct fm_port *port_dev[2]; + + phy_interface_t phy_if; + u32 if_support; + bool link; + bool half_duplex; + uint16_t speed; + uint16_t max_speed; + struct device_node *phy_node; + char fixed_bus_id[MII_BUS_ID_SIZE + 3]; + struct device_node *tbi_node; + struct phy_device *phy_dev; + void *fm; + /* List of multicast addresses */ + struct list_head mc_addr_list; + + int (*init_phy)(struct net_device *net_dev); + int (*init)(struct mac_device *mac_dev); + int (*start)(struct mac_device *mac_dev); + int (*stop)(struct mac_device *mac_dev); + int (*change_promisc)(struct mac_device *mac_dev); + int (*change_addr)(struct mac_device *mac_dev, uint8_t *addr); + int (*set_multi)(struct net_device *net_dev); + int (*uninit)(struct mac_device *mac_dev); + int (*ptp_enable)(struct mac_device *mac_dev); + int (*ptp_disable)(struct mac_device *mac_dev); + void *(*get_mac_handle)(struct mac_device *mac_dev); + int (*fm_rtc_enable)(struct net_device *net_dev); + int (*fm_rtc_disable)(struct net_device *net_dev); + int (*fm_rtc_get_cnt)(struct net_device *net_dev, uint64_t *ts); + int (*fm_rtc_set_cnt)(struct net_device *net_dev, uint64_t ts); + int (*fm_rtc_get_drift)(struct net_device *net_dev, uint32_t *drift); + int (*fm_rtc_set_drift)(struct net_device *net_dev, uint32_t drift); + int (*fm_rtc_set_alarm)(struct net_device *net_dev, uint32_t id, + uint64_t time); + int (*fm_rtc_set_fiper)(struct net_device *net_dev, uint32_t id, + uint64_t fiper); +}; + +struct mac_address { + uint8_t addr[ETH_ALEN]; + struct list_head list; +}; + +#define for_each_port_device(i, port_dev) \ + for (i = 0; i < ARRAY_SIZE(port_dev); i++) + +static inline void * __attribute((nonnull)) macdev_priv(const struct mac_device *mac_dev) +{ + return (void *)mac_dev + sizeof(*mac_dev); +} + +extern const char *mac_driver_description; +extern const size_t mac_sizeof_priv[]; +extern void (*const mac_setup[])(struct mac_device *mac_dev); + +#endif /* __MAC_H */ |