diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/sdk_dpaa')
10 files changed, 97 insertions, 82 deletions
diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig index 92118b7..b21d236 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig @@ -20,6 +20,29 @@ config FSL_DPAA_CEETM help Enable QoS offloading support through the CEETM hardware block. +config FSL_DPAA_CEETM_CCS_THRESHOLD_1G + hex "CEETM egress congestion threshold on 1G ports" + depends on FSL_DPAA_CEETM + range 0x1000 0x10000000 + default "0x000a0000" + help + The size in bytes of the CEETM egress Class Congestion State threshold on 1G ports. + The threshold needs to be configured keeping in mind the following factors: + - A threshold too large will buffer frames for a long time in the TX queues, + when a small shaping rate is configured. This will cause buffer pool depletion + or out of memory errors. This in turn will cause frame loss on RX; + - A threshold too small will cause unnecessary frame loss by entering + congestion too often. + +config FSL_DPAA_CEETM_CCS_THRESHOLD_10G + hex "CEETM egress congestion threshold on 10G ports" + depends on FSL_DPAA_CEETM + range 0x1000 0x20000000 + default "0x00640000" + help + The size in bytes of the CEETM egress Class Congestion State threshold on 10G ports. + See FSL_DPAA_CEETM_CCS_THRESHOLD_1G for details. + config FSL_DPAA_OFFLINE_PORTS bool "Offline Ports support" depends on FSL_SDK_DPAA_ETH diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c index 7026f91..1f76aa3 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c @@ -775,6 +775,17 @@ static int dpa_private_netdev_init(struct net_device *net_dev) /* Advertise NETIF_F_HW_ACCEL_MQ to avoid Tx timeout warnings */ net_dev->features |= NETIF_F_HW_ACCEL_MQ; +#ifndef CONFIG_PPC + /* Due to the A010022 FMan errata, we can not use contig frames larger + * than 4K, nor S/G frames. We need to stop advertising S/G and GSO + * support. + */ + if (unlikely(dpaa_errata_a010022)) { + net_dev->hw_features &= ~NETIF_F_SG; + net_dev->features &= ~NETIF_F_GSO; + } +#endif + return dpa_netdev_init(net_dev, mac_addr, tx_timeout); } @@ -863,7 +874,7 @@ static int dpa_priv_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, for (i = 0; i < count; i++) { int err; - err = dpa_bp_alloc(&dpa_bp[i]); + err = dpa_bp_alloc(&dpa_bp[i], net_dev->dev.parent); if (err < 0) { dpa_bp_free(priv); priv->dpa_bp = NULL; diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h index b1703bc..57c9bef 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h @@ -514,17 +514,6 @@ 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 != htons(ETH_P_8021Q)) - || (skb->len > mtu + 4)) - return -1; - - return 0; -} - static inline uint16_t dpa_get_headroom(struct dpa_buffer_layout_s *bl) { uint16_t headroom; diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c index 507e77c..be6e4f8 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c @@ -176,7 +176,7 @@ int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, for (i = 0; i < count; i++) { int err; - err = dpa_bp_alloc(&dpa_bp[i]); + err = dpa_bp_alloc(&dpa_bp[i], net_dev->dev.parent); if (err < 0) { dpa_bp_free(priv); priv->dpa_bp = NULL; diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c index cac613b..b090db1 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c @@ -69,24 +69,27 @@ static void get_dcp_and_sp(struct net_device *dev, enum qm_dc_portal *dcp_id, static void ceetm_ern(struct qman_portal *portal, struct qman_fq *fq, const struct qm_mr_entry *msg) { - struct net_device *net_dev; - struct ceetm_class *cls; + struct dpa_percpu_priv_s *dpa_percpu_priv; struct ceetm_class_stats *cstats = NULL; const struct dpa_priv_s *dpa_priv; - struct dpa_percpu_priv_s *dpa_percpu_priv; - struct sk_buff *skb; struct qm_fd fd = msg->ern.fd; + struct net_device *net_dev; + struct ceetm_fq *ceetm_fq; + struct ceetm_class *cls; + struct sk_buff *skb; - net_dev = ((struct ceetm_fq *)fq)->net_dev; + ceetm_fq = container_of(fq, struct ceetm_fq, fq); + net_dev = ceetm_fq->net_dev; dpa_priv = netdev_priv(net_dev); dpa_percpu_priv = raw_cpu_ptr(dpa_priv->percpu_priv); /* Increment DPA counters */ dpa_percpu_priv->stats.tx_dropped++; dpa_percpu_priv->stats.tx_fifo_errors++; + count_ern(dpa_percpu_priv, msg); /* Increment CEETM counters */ - cls = ((struct ceetm_fq *)fq)->ceetm_cls; + cls = ceetm_fq->ceetm_cls; switch (cls->type) { case CEETM_PRIO: cstats = this_cpu_ptr(cls->prio.cstats); @@ -99,11 +102,15 @@ static void ceetm_ern(struct qman_portal *portal, struct qman_fq *fq, if (cstats) cstats->ern_drop_count++; + /* Release the buffers that were supposed to be recycled. */ if (fd.bpid != 0xff) { dpa_fd_release(net_dev, &fd); return; } + /* Release the frames that were supposed to return on the + * confirmation path. + */ skb = _dpa_cleanup_tx_fd(dpa_priv, &fd); dev_kfree_skb_any(skb); } @@ -125,16 +132,16 @@ static void ceetm_cscn(struct qm_ceetm_ccg *ccg, void *cb_ctx, int congested) break; } + ceetm_fq->congested = congested; + if (congested) { dpa_priv->cgr_data.congestion_start_jiffies = jiffies; - netif_tx_stop_all_queues(dpa_priv->net_dev); dpa_priv->cgr_data.cgr_congested_count++; if (cstats) cstats->congested_count++; } else { dpa_priv->cgr_data.congested_jiffies += (jiffies - dpa_priv->cgr_data.congestion_start_jiffies); - netif_tx_wake_all_queues(dpa_priv->net_dev); } } @@ -148,6 +155,7 @@ static int ceetm_alloc_fq(struct ceetm_fq **fq, struct net_device *dev, (*fq)->net_dev = dev; (*fq)->ceetm_cls = cls; + (*fq)->congested = 0; return 0; } @@ -185,9 +193,9 @@ static int ceetm_config_ccg(struct qm_ceetm_ccg **ccg, /* Set the congestion state thresholds according to the link speed */ if (dpa_priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) - cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_10G; + cs_th = CONFIG_FSL_DPAA_CEETM_CCS_THRESHOLD_10G; else - cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_1G; + cs_th = CONFIG_FSL_DPAA_CEETM_CCS_THRESHOLD_1G; qm_cgr_cs_thres_set64(&ccg_params.cs_thres_in, cs_th, 1); qm_cgr_cs_thres_set64(&ccg_params.cs_thres_out, @@ -1908,17 +1916,22 @@ static struct ceetm_class *ceetm_classify(struct sk_buff *skb, int __hot ceetm_tx(struct sk_buff *skb, struct net_device *net_dev) { - int ret; - bool act_drop = false; + const int queue_mapping = dpa_get_queue_mapping(skb); struct Qdisc *sch = net_dev->qdisc; - struct ceetm_class *cl; - struct dpa_priv_s *priv_dpa; - struct qman_fq *egress_fq, *conf_fq; - struct ceetm_qdisc *priv = qdisc_priv(sch); - struct ceetm_qdisc_stats *qstats = this_cpu_ptr(priv->root.qstats); struct ceetm_class_stats *cstats; - const int queue_mapping = dpa_get_queue_mapping(skb); - spinlock_t *root_lock = qdisc_lock(sch); + struct ceetm_qdisc_stats *qstats; + struct dpa_priv_s *priv_dpa; + struct ceetm_fq *ceetm_fq; + struct ceetm_qdisc *priv; + struct qman_fq *conf_fq; + struct ceetm_class *cl; + spinlock_t *root_lock; + bool act_drop = false; + int ret; + + root_lock = qdisc_lock(sch); + priv = qdisc_priv(sch); + qstats = this_cpu_ptr(priv->root.qstats); spin_lock(root_lock); cl = ceetm_classify(skb, sch, &ret, &act_drop); @@ -1945,11 +1958,11 @@ int __hot ceetm_tx(struct sk_buff *skb, struct net_device *net_dev) */ switch (cl->type) { case CEETM_PRIO: - egress_fq = &cl->prio.fq->fq; + ceetm_fq = cl->prio.fq; cstats = this_cpu_ptr(cl->prio.cstats); break; case CEETM_WBFS: - egress_fq = &cl->wbfs.fq->fq; + ceetm_fq = cl->wbfs.fq; cstats = this_cpu_ptr(cl->wbfs.cstats); break; default: @@ -1957,8 +1970,16 @@ int __hot ceetm_tx(struct sk_buff *skb, struct net_device *net_dev) goto drop; } + /* If the FQ is congested, avoid enqueuing the frame and dropping it + * when it returns on the ERN path. Drop it here directly instead. + */ + if (unlikely(ceetm_fq->congested)) { + qstats->drops++; + goto drop; + } + bstats_update(&cstats->bstats, skb); - return dpa_tx_extended(skb, net_dev, egress_fq, conf_fq); + return dpa_tx_extended(skb, net_dev, &ceetm_fq->fq, conf_fq); drop: dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h index 63cc3475..0ff3b9d 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h @@ -105,6 +105,7 @@ struct ceetm_fq { struct qman_fq fq; struct net_device *net_dev; struct ceetm_class *ceetm_cls; + int congested; /* Congestion status */ }; struct root_q { diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c index 19a8a3c..bbaf29c 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c @@ -469,14 +469,18 @@ int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) #ifdef CONFIG_FSL_DPAA_1588 struct dpa_priv_s *priv = netdev_priv(dev); #endif - int ret = 0; + int ret = -EINVAL; - /* at least one timestamping feature must be enabled */ -#ifdef CONFIG_FSL_DPAA_TS if (!netif_running(dev)) -#endif return -EINVAL; + if (cmd == SIOCGMIIREG) { + if (!dev->phydev) + ret = -EINVAL; + else + ret = phy_mii_ioctl(dev->phydev, rq, cmd); + } + #ifdef CONFIG_FSL_DPAA_TS if (cmd == SIOCSHWTSTAMP) return dpa_ts_ioctl(dev, rq, cmd); @@ -711,11 +715,10 @@ void dpa_set_buffers_layout(struct mac_device *mac_dev, EXPORT_SYMBOL(dpa_set_buffers_layout); int __attribute__((nonnull)) -dpa_bp_alloc(struct dpa_bp *dpa_bp) +dpa_bp_alloc(struct dpa_bp *dpa_bp, struct device *dev) { int err; struct bman_pool_params bp_params; - struct platform_device *pdev; if (dpa_bp->size == 0 || dpa_bp->config_count == 0) { pr_err("Buffer pool is not properly initialized! Missing size or initial number of buffers"); @@ -748,44 +751,25 @@ dpa_bp_alloc(struct dpa_bp *dpa_bp) dpa_bp->bpid = (uint8_t)bman_get_params(dpa_bp->pool)->bpid; - pdev = platform_device_register_simple("dpaa_eth_bpool", - dpa_bp->bpid, NULL, 0); - if (IS_ERR(pdev)) { - pr_err("platform_device_register_simple() failed\n"); - err = PTR_ERR(pdev); - goto pdev_register_failed; - } - { - struct dma_map_ops *ops = get_dma_ops(&pdev->dev); - ops->dma_supported = NULL; - } - err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40)); if (err) { pr_err("dma_coerce_mask_and_coherent() failed\n"); - goto pdev_mask_failed; + goto bman_free_pool; } -#ifdef CONFIG_FMAN_ARM - /* force coherency */ - pdev->dev.archdata.dma_coherent = true; - arch_setup_dma_ops(&pdev->dev, 0, 0, NULL, true); -#endif - dpa_bp->dev = &pdev->dev; + dpa_bp->dev = dev; if (dpa_bp->seed_cb) { err = dpa_bp->seed_cb(dpa_bp); if (err) - goto pool_seed_failed; + goto bman_free_pool; } dpa_bpid2pool_map(dpa_bp->bpid, dpa_bp); return 0; -pool_seed_failed: -pdev_mask_failed: - platform_device_unregister(pdev); -pdev_register_failed: +bman_free_pool: bman_free_pool(dpa_bp->pool); return err; @@ -847,9 +831,6 @@ _dpa_bp_free(struct dpa_bp *dpa_bp) dpa_bp_array[bp->bpid] = NULL; bman_free_pool(bp->pool); - - if (bp->dev) - platform_device_unregister(to_platform_device(bp->dev)); } void __cold __attribute__((nonnull)) diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h index 41db430..b039328 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h @@ -164,7 +164,7 @@ void dpa_set_rx_mode(struct net_device *net_dev); void dpa_set_buffers_layout(struct mac_device *mac_dev, struct dpa_buffer_layout_s *layout); int __attribute__((nonnull)) -dpa_bp_alloc(struct dpa_bp *dpa_bp); +dpa_bp_alloc(struct dpa_bp *dpa_bp, struct device *dev); void __cold __attribute__((nonnull)) dpa_bp_free(struct dpa_priv_s *priv); struct dpa_bp *dpa_bpid2pool(int bpid); diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c index 11b47e8..32e62e6 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c @@ -616,13 +616,6 @@ void __hot _dpa_rx(struct net_device *net_dev, (*count_ptr)--; skb->protocol = eth_type_trans(skb, net_dev); - /* IP Reassembled frames are allowed to be larger than MTU */ - if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) && - !(fd_status & FM_FD_IPR))) { - percpu_stats->rx_dropped++; - goto drop_bad_frame; - } - skb_len = skb->len; #ifdef CONFIG_FSL_DPAA_DBG_LOOP @@ -655,10 +648,6 @@ void __hot _dpa_rx(struct net_device *net_dev, packet_dropped: return; -drop_bad_frame: - dev_kfree_skb(skb); - return; - _release_frame: dpa_fd_release(net_dev, fd); } diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c index 60133b0..a6bfcea 100644 --- a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c @@ -76,7 +76,7 @@ static const char phy_str[][11] = { [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid", [PHY_INTERFACE_MODE_RTBI] = "rtbi", [PHY_INTERFACE_MODE_XGMII] = "xgmii", - [PHY_INTERFACE_MODE_SGMII_2500] = "sgmii-2500", + [PHY_INTERFACE_MODE_2500SGMII] = "sgmii-2500", }; static phy_interface_t __pure __attribute__((nonnull)) str2phy(const char *str) @@ -103,7 +103,7 @@ static const uint16_t phy2speed[] = { [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, [PHY_INTERFACE_MODE_XGMII] = SPEED_10000, - [PHY_INTERFACE_MODE_SGMII_2500] = SPEED_2500, + [PHY_INTERFACE_MODE_2500SGMII] = SPEED_2500, }; static struct mac_device * __cold |