diff options
author | Scott Wood <scottwood@freescale.com> | 2013-12-14 02:43:39 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2013-12-14 02:45:02 (GMT) |
commit | 5709059c4e110944712dc1f3d66a203a924c151a (patch) | |
tree | 3f5ff4c45d2b1089c3f4504771a78e847b3ac073 /drivers/net/ethernet/freescale/dpa | |
parent | b7c81aa3ab2ac2c140e278b6d0e9a0b95112cf0b (diff) | |
parent | 3dea020415467452d6ca2e907e21af07954741cf (diff) | |
download | linux-fsl-qoriq-5709059c4e110944712dc1f3d66a203a924c151a.tar.xz |
Merge remote-tracking branch 'origin/master' into merge
Conflicts:
arch/powerpc/boot/dts/b4qds.dts
drivers/crypto/caam/Makefile
Diffstat (limited to 'drivers/net/ethernet/freescale/dpa')
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth.c | 104 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth.h | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c | 124 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c | 106 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac-api.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac.h | 5 |
10 files changed, 363 insertions, 73 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c index 9cd3214..11d87bf 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c @@ -116,6 +116,8 @@ int dpa_free_pcd_fqids(struct device *, uint32_t) __attribute__((weak)); uint8_t dpa_priv_common_bpid; +extern u16 qman_portal_max; + /* A set of callbacks for hooking into the fastpath at different points. */ struct dpaa_eth_hooks_s dpaa_eth_hooks; /* @@ -275,12 +277,15 @@ void __hot _dpa_process_parse_results(const fm_prs_result_t *parse_results, static int dpaa_eth_poll(struct napi_struct *napi, int budget) { - int cleaned = qman_poll_dqrr(budget); + struct dpa_napi_portal *np = + container_of(napi, struct dpa_napi_portal, napi); + + int cleaned = qman_p_poll_dqrr(np->p, budget); if (cleaned < budget) { int tmp; napi_complete(napi); - tmp = qman_irqsource_add(QM_PIRQ_DQRI); + tmp = qman_p_irqsource_add(np->p, QM_PIRQ_DQRI); BUG_ON(tmp); } @@ -337,7 +342,7 @@ priv_rx_error_dqrr(struct qman_portal *portal, percpu_priv = __this_cpu_ptr(priv->percpu_priv); - if (dpaa_eth_napi_schedule(percpu_priv)) + if (dpaa_eth_napi_schedule(percpu_priv, portal)) return qman_cb_dqrr_stop; if (unlikely(dpaa_eth_refill_bpools(priv->dpa_bp))) @@ -371,7 +376,7 @@ priv_rx_default_dqrr(struct qman_portal *portal, /* IRQ handler, non-migratable; safe to use __this_cpu_ptr here */ percpu_priv = __this_cpu_ptr(priv->percpu_priv); - if (unlikely(dpaa_eth_napi_schedule(percpu_priv))) + if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal))) return qman_cb_dqrr_stop; /* Vale of plenty: make sure we didn't run out of buffers */ @@ -383,7 +388,7 @@ priv_rx_default_dqrr(struct qman_portal *portal, */ dpa_fd_release(net_dev, &dq->fd); else - _dpa_rx(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); + _dpa_rx(net_dev, portal, priv, percpu_priv, &dq->fd, fq->fqid); return qman_cb_dqrr_consume; } @@ -402,7 +407,7 @@ priv_tx_conf_error_dqrr(struct qman_portal *portal, percpu_priv = __this_cpu_ptr(priv->percpu_priv); - if (dpaa_eth_napi_schedule(percpu_priv)) + if (dpaa_eth_napi_schedule(percpu_priv, portal)) return qman_cb_dqrr_stop; _dpa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); @@ -428,7 +433,7 @@ priv_tx_conf_default_dqrr(struct qman_portal *portal, /* Non-migratable context, safe to use __this_cpu_ptr */ percpu_priv = __this_cpu_ptr(priv->percpu_priv); - if (dpaa_eth_napi_schedule(percpu_priv)) + if (dpaa_eth_napi_schedule(percpu_priv, portal)) return qman_cb_dqrr_stop; _dpa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); @@ -479,22 +484,26 @@ static const dpa_fq_cbs_t private_fq_cbs = { static void dpaa_eth_napi_enable(struct dpa_priv_s *priv) { struct dpa_percpu_priv_s *percpu_priv; - int i; + int i, j; for_each_possible_cpu(i) { percpu_priv = per_cpu_ptr(priv->percpu_priv, i); - napi_enable(&percpu_priv->napi); + + for (j = 0; j < qman_portal_max; j++) + napi_enable(&percpu_priv->np[j].napi); } } static void dpaa_eth_napi_disable(struct dpa_priv_s *priv) { struct dpa_percpu_priv_s *percpu_priv; - int i; + int i, j; for_each_possible_cpu(i) { percpu_priv = per_cpu_ptr(priv->percpu_priv, i); - napi_disable(&percpu_priv->napi); + + for (j = 0; j < qman_portal_max; j++) + napi_disable(&percpu_priv->np[j].napi); } } @@ -543,11 +552,17 @@ static void dpaa_eth_poll_controller(struct net_device *net_dev) struct dpa_priv_s *priv = netdev_priv(net_dev); struct dpa_percpu_priv_s *percpu_priv = __this_cpu_ptr(priv->percpu_priv); - struct napi_struct napi = percpu_priv->napi; + struct qman_portal *p; + const struct qman_portal_config *pc; + struct dpa_napi_portal *np; + + p = (struct qman_portal *)qman_get_affine_portal(smp_processor_id()); + pc = qman_p_get_portal_config(p); + np = &percpu_priv->np[pc->index]; - qman_irqsource_remove(QM_PIRQ_DQRI); - qman_poll_dqrr(napi.weight); - qman_irqsource_add(QM_PIRQ_DQRI); + qman_p_irqsource_remove(np->p, QM_PIRQ_DQRI); + qman_p_poll_dqrr(np->p, np->napi.weight); + qman_p_irqsource_add(np->p, QM_PIRQ_DQRI); } #endif @@ -573,6 +588,50 @@ static const struct net_device_ops dpa_private_ops = { #endif }; +static int dpa_private_napi_add(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct dpa_percpu_priv_s *percpu_priv; + int i, cpu; + + for_each_possible_cpu(cpu) { + percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); + + percpu_priv->np = devm_kzalloc(net_dev->dev.parent, + qman_portal_max * sizeof(struct dpa_napi_portal), + GFP_KERNEL); + + if (unlikely(percpu_priv->np == NULL)) { + dev_err(net_dev->dev.parent, "devm_kzalloc() failed\n"); + return -ENOMEM; + } + + for (i = 0; i < qman_portal_max; i++) + netif_napi_add(net_dev, &percpu_priv->np[i].napi, + dpaa_eth_poll, DPA_NAPI_WEIGHT); + } + + return 0; +} + +void dpa_private_napi_del(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct dpa_percpu_priv_s *percpu_priv; + int i, cpu; + + for_each_possible_cpu(cpu) { + percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); + + if (percpu_priv->np) { + for (i = 0; i < qman_portal_max; i++) + netif_napi_del(&percpu_priv->np[i].napi); + + devm_kfree(net_dev->dev.parent, percpu_priv->np); + } + } +} + static int dpa_private_netdev_init(struct device_node *dpa_node, struct net_device *net_dev) { @@ -587,13 +646,9 @@ static int dpa_private_netdev_init(struct device_node *dpa_node, for_each_possible_cpu(i) { percpu_priv = per_cpu_ptr(priv->percpu_priv, i); percpu_priv->net_dev = net_dev; - - netif_napi_add(net_dev, &percpu_priv->napi, dpaa_eth_poll, - DPA_NAPI_WEIGHT); } net_dev->netdev_ops = &dpa_private_ops; - mac_addr = priv->mac_dev->addr; net_dev->mem_start = priv->mac_dev->res->start; @@ -827,6 +882,12 @@ dpaa_eth_priv_probe(struct platform_device *_of_dev) memset(percpu_priv, 0, sizeof(*percpu_priv)); } + /* Initialize NAPI */ + err = dpa_private_napi_add(net_dev); + + if (err < 0) + goto napi_add_failed; + err = dpa_private_netdev_init(dpa_node, net_dev); if (err < 0) @@ -838,9 +899,12 @@ dpaa_eth_priv_probe(struct platform_device *_of_dev) return 0; +napi_add_failed: netdev_init_failed: - if (net_dev) + if (net_dev) { + dpa_private_napi_del(net_dev); free_percpu(priv->percpu_priv); + } alloc_percpu_failed: fq_alloc_failed: if (net_dev) { diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h index d179fda..6844d9a 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h @@ -380,9 +380,14 @@ struct dpa_ern_cnt { u64 orp_zero; /* ORP disabled */ }; +struct dpa_napi_portal { + struct napi_struct napi; + struct qman_portal *p; +}; + struct dpa_percpu_priv_s { struct net_device *net_dev; - struct napi_struct napi; + struct dpa_napi_portal *np; u64 in_interrupt; u64 tx_returned; u64 tx_confirm; @@ -453,6 +458,8 @@ struct dpa_priv_s { struct dpa_buffer_layout_s *buf_layout; uint16_t rx_headroom; char if_type[30]; + + void *peer; }; struct fm_port_fqs { @@ -466,6 +473,7 @@ struct fm_port_fqs { int dpa_bp_priv_seed(struct dpa_bp *dpa_bp); int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp); void __hot _dpa_rx(struct net_device *net_dev, + struct qman_portal *portal, const struct dpa_priv_s *priv, struct dpa_percpu_priv_s *percpu_priv, const struct qm_fd *fd, @@ -496,7 +504,8 @@ int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp); 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) +static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv, + struct qman_portal *portal) { /* In case of threaded ISR for RT enable kernel, * in_irq() does not return appropriate value, so use @@ -504,9 +513,15 @@ static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv) */ if (unlikely(in_irq() || !in_serving_softirq())) { /* Disable QMan IRQ and invoke NAPI */ - int ret = qman_irqsource_remove(QM_PIRQ_DQRI); + int ret = qman_p_irqsource_remove(portal, QM_PIRQ_DQRI); if (likely(!ret)) { - napi_schedule(&percpu_priv->napi); + const struct qman_portal_config *pc = + qman_p_get_portal_config(portal); + struct dpa_napi_portal *np = + &percpu_priv->np[pc->index]; + + np->p = portal; + napi_schedule(&np->napi); percpu_priv->in_interrupt++; return 1; } @@ -570,6 +585,8 @@ int fm_mac_dump_regs(struct mac_device *h_dev, char *buf, int n); void dpaa_eth_sysfs_remove(struct device *dev); void dpaa_eth_sysfs_init(struct device *dev); +void dpa_private_napi_del(struct net_device *net_dev); + /* Equivalent to a memset(0), but works faster */ static inline void clear_fd(struct qm_fd *fd) { diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c index c599052..0d1de6c 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c @@ -129,7 +129,7 @@ int __cold dpa_start(struct net_device *net_dev) priv = netdev_priv(net_dev); mac_dev = priv->mac_dev; - err = mac_dev->init_phy(net_dev); + err = mac_dev->init_phy(net_dev, priv->mac_dev); if (err < 0) { if (netif_msg_ifup(priv)) netdev_err(net_dev, "init_phy() = %d\n", err); @@ -471,6 +471,7 @@ int __cold dpa_remove(struct platform_device *of_dev) err = dpa_fq_free(dev, &priv->dpa_fq_list); + dpa_private_napi_del(net_dev); free_percpu(priv->percpu_priv); dpa_bp_free(priv, priv->dpa_bp); @@ -613,7 +614,7 @@ void dpa_set_rx_mode(struct net_device *net_dev) _errno); } - _errno = priv->mac_dev->set_multi(net_dev); + _errno = priv->mac_dev->set_multi(net_dev, priv->mac_dev); if (unlikely(_errno < 0) && netif_msg_drv(priv)) netdev_err(net_dev, "mac_dev->set_multi() = %d\n", _errno); } diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h index 6ee9825..9964915 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h @@ -125,4 +125,16 @@ void count_ern(struct dpa_percpu_priv_s *percpu_priv, int dpa_enable_tx_csum(struct dpa_priv_s *priv, struct sk_buff *skb, struct qm_fd *fd, char *parse_results); +struct proxy_device { + struct mac_device *mac_dev; +}; + +/* mac device control functions exposed by proxy interface*/ +int dpa_proxy_start(struct net_device *net_dev); +int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev); +int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev, + struct net_device *net_dev); +int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev, + struct net_device *net_dev); + #endif /* __DPAA_ETH_COMMON_H */ diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c index 8065a81..119f891 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c @@ -76,7 +76,10 @@ int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev); /* forward declarations */ static int __cold dpa_macless_start(struct net_device *net_dev); static int __cold dpa_macless_stop(struct net_device *net_dev); -static int dpa_set_macless_address(struct net_device *net_dev, void *addr); +static int __cold dpa_macless_set_address(struct net_device *net_dev, + void *addr); +static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev); + static int dpaa_eth_macless_probe(struct platform_device *_of_dev); static netdev_features_t dpa_macless_fix_features(struct net_device *dev, netdev_features_t features); @@ -89,7 +92,8 @@ static const struct net_device_ops dpa_macless_ops = { .ndo_stop = dpa_macless_stop, .ndo_tx_timeout = dpa_timeout, .ndo_get_stats64 = dpa_get_stats64, - .ndo_set_mac_address = dpa_set_macless_address, + .ndo_set_mac_address = dpa_macless_set_address, + .ndo_set_rx_mode = dpa_macless_set_rx_mode, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE .ndo_select_queue = dpa_select_queue, @@ -125,37 +129,66 @@ static const char macless_frame_queues[][25] = { static int __cold dpa_macless_start(struct net_device *net_dev) { + const struct dpa_priv_s *priv = netdev_priv(net_dev); + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; + netif_tx_start_all_queues(net_dev); + if (proxy_dev) + dpa_proxy_start(net_dev); + + return 0; } static int __cold dpa_macless_stop(struct net_device *net_dev) { + const struct dpa_priv_s *priv = netdev_priv(net_dev); + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; + netif_tx_stop_all_queues(net_dev); + if (proxy_dev) + dpa_proxy_stop(proxy_dev, net_dev); + return 0; } -static int dpa_set_macless_address(struct net_device *net_dev, void *addr) +static int dpa_macless_set_address(struct net_device *net_dev, void *addr) { - const struct dpa_priv_s *priv; + const struct dpa_priv_s *priv = netdev_priv(net_dev); + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; int _errno; - priv = netdev_priv(net_dev); - _errno = eth_mac_addr(net_dev, addr); if (_errno < 0) { if (netif_msg_drv(priv)) - netdev_err(net_dev, - "eth_mac_addr() = %d\n", - _errno); + netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno); return _errno; } + if (proxy_dev) { + _errno = dpa_proxy_set_mac_address(proxy_dev, net_dev); + if (_errno < 0) { + if (netif_msg_drv(priv)) + netdev_err(net_dev, "proxy_set_mac_address() = %d\n", + _errno); + return _errno; + } + } + return 0; } +static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev) +{ + const struct dpa_priv_s *priv = netdev_priv(net_dev); + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; + + if (proxy_dev) + dpa_proxy_set_rx_mode(proxy_dev, net_dev); +} + static netdev_features_t dpa_macless_fix_features(struct net_device *dev, netdev_features_t features) { @@ -178,20 +211,32 @@ static int dpa_macless_netdev_init(struct device_node *dpa_node, struct net_device *net_dev) { struct dpa_priv_s *priv = netdev_priv(net_dev); + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; struct device *dev = net_dev->dev.parent; const uint8_t *mac_addr; net_dev->netdev_ops = &dpa_macless_ops; - /* Get the MAC address */ - mac_addr = of_get_mac_address(dpa_node); - if (mac_addr == NULL) { - if (netif_msg_probe(priv)) - dev_err(dev, "No MAC address found!\n"); - return -EINVAL; - } + if (proxy_dev) { + struct mac_device *mac_dev = proxy_dev->mac_dev; + net_dev->mem_start = mac_dev->res->start; + net_dev->mem_end = mac_dev->res->end; + + return dpa_netdev_init(dpa_node, net_dev, mac_dev->addr, + tx_timeout); + } else { + /* Get the MAC address from device tree */ + mac_addr = of_get_mac_address(dpa_node); + + if (mac_addr == NULL) { + if (netif_msg_probe(priv)) + dev_err(dev, "No MAC address found!\n"); + return -EINVAL; + } - return dpa_netdev_init(dpa_node, net_dev, mac_addr, tx_timeout); + return dpa_netdev_init(dpa_node, net_dev, mac_addr, + tx_timeout); + } } /* Probing of FQs for MACless ports */ @@ -223,6 +268,41 @@ static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, return 0; } +struct proxy_device *dpa_macless_proxy_probe(struct platform_device *_of_dev) +{ + struct device *dev; + const phandle *proxy_prop; + struct proxy_device *proxy_dev; + struct device_node *proxy_node; + struct platform_device *proxy_pdev; + int lenp; + + dev = &_of_dev->dev; + + proxy_prop = of_get_property(dev->of_node, "proxy", &lenp); + if (!proxy_prop) + return NULL; + + proxy_node = of_find_node_by_phandle(*proxy_prop); + if (!proxy_node) { + dev_err(dev, "Cannot find proxy node\n"); + return NULL; + } + + proxy_pdev = of_find_device_by_node(proxy_node); + if (!proxy_pdev) { + of_node_put(proxy_node); + dev_err(dev, "Cannot find device represented by proxy node\n"); + return NULL; + } + + proxy_dev = dev_get_drvdata(&proxy_pdev->dev); + + of_node_put(proxy_node); + + return proxy_dev; +} + static int dpaa_eth_macless_probe(struct platform_device *_of_dev) { int err = 0, i; @@ -234,6 +314,7 @@ static int dpaa_eth_macless_probe(struct platform_device *_of_dev) struct net_device *net_dev = NULL; struct dpa_priv_s *priv = NULL; struct dpa_percpu_priv_s *percpu_priv; + static struct proxy_device *proxy_dev; struct fm_port_fqs port_fqs; struct task_struct *kth; static u8 macless_idx; @@ -250,6 +331,8 @@ static int dpaa_eth_macless_probe(struct platform_device *_of_dev) if (IS_ERR(dpa_bp)) return PTR_ERR(dpa_bp); + proxy_dev = dpa_macless_proxy_probe(_of_dev); + dpa_bp->seed_cb = dpa_bp_shared_port_seed; /* Allocate this early, so we can store relevant information in @@ -270,6 +353,8 @@ static int dpaa_eth_macless_probe(struct platform_device *_of_dev) sprintf(priv->if_type, "macless%d", macless_idx++); priv->msg_enable = netif_msg_init(debug, -1); + /* control over proxy's mac device */ + priv->peer = (void *)proxy_dev; INIT_LIST_HEAD(&priv->dpa_fq_list); @@ -397,7 +482,10 @@ static int __init __cold dpa_macless_load(void) return _errno; } -module_init(dpa_macless_load); +/* waits for proxy to initialize first, in case MAC device reference + * is needed + */ +late_initcall(dpa_macless_load); static void __exit __cold dpa_macless_unload(void) { diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c index f1f9fce..d608881 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c @@ -294,6 +294,7 @@ static int dpa_process_one(struct dpa_percpu_priv_s *percpu_priv, } void __hot _dpa_rx(struct net_device *net_dev, + struct qman_portal *portal, const struct dpa_priv_s *priv, struct dpa_percpu_priv_s *percpu_priv, const struct qm_fd *fd, @@ -370,8 +371,12 @@ void __hot _dpa_rx(struct net_device *net_dev, if (use_gro) { gro_result_t gro_result; + const struct qman_portal_config *pc = + qman_p_get_portal_config(portal); + struct dpa_napi_portal *np = &percpu_priv->np[pc->index]; - gro_result = napi_gro_receive(&percpu_priv->napi, skb); + np->p = portal; + gro_result = napi_gro_receive(&np->napi, skb); /* If frame is dropped by the stack, rx_dropped counter is * incremented automatically, so no need for us to update it */ diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c index adb1125..1c1a121 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c @@ -74,6 +74,8 @@ static struct platform_driver dpa_proxy_driver = { .remove = dpa_eth_proxy_remove }; +static struct proxy_device *proxy_dev; + static int dpaa_eth_proxy_probe(struct platform_device *_of_dev) { int err = 0, i; @@ -102,6 +104,15 @@ static int dpaa_eth_proxy_probe(struct platform_device *_of_dev) if (IS_ERR(mac_dev)) return PTR_ERR(mac_dev); + proxy_dev = devm_kzalloc(dev, sizeof(*proxy_dev), GFP_KERNEL); + if (!proxy_dev) { + dev_err(dev, "devm_kzalloc() failed\n"); + return -ENOMEM; + } + + proxy_dev->mac_dev = mac_dev; + dev_set_drvdata(dev, proxy_dev); + /* We have physical ports, so we need to establish * the buffer layout. */ @@ -150,8 +161,103 @@ static int dpaa_eth_proxy_probe(struct platform_device *_of_dev) return 0; /* Proxy interface initialization ended */ } +int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev, + struct net_device *net_dev) +{ + struct mac_device *mac_dev; + int _errno; + + mac_dev = proxy_dev->mac_dev; + + _errno = mac_dev->change_addr(mac_dev->get_mac_handle(mac_dev), + net_dev->dev_addr); + if (_errno < 0) + return _errno; + + return 0; +} + +int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev, + struct net_device *net_dev) +{ + struct mac_device *mac_dev = proxy_dev->mac_dev; + int _errno; + + _errno = mac_dev->set_multi(net_dev, mac_dev); + if (unlikely(_errno < 0)) + return _errno; + + return 0; +} + +int dpa_proxy_start(struct net_device *net_dev) +{ + struct mac_device *mac_dev; + const struct dpa_priv_s *priv; + struct proxy_device *proxy_dev; + int _errno; + int i; + + priv = netdev_priv(net_dev); + proxy_dev = (struct proxy_device *)priv->peer; + mac_dev = proxy_dev->mac_dev; + + _errno = mac_dev->init_phy(net_dev, mac_dev); + if (_errno < 0) { + if (netif_msg_drv(priv)) + netdev_err(net_dev, "init_phy() = %d\n", + _errno); + return _errno; + } + + for_each_port_device(i, mac_dev->port_dev) + fm_port_enable(mac_dev->port_dev[i]); + + _errno = mac_dev->start(mac_dev); + if (_errno < 0) { + if (netif_msg_drv(priv)) + netdev_err(net_dev, "mac_dev->start() = %d\n", + _errno); + return _errno; + } + + return _errno; +} + +int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev) +{ + struct mac_device *mac_dev = proxy_dev->mac_dev; + const struct dpa_priv_s *priv = netdev_priv(net_dev); + int _errno, i; + + _errno = mac_dev->stop(mac_dev); + if (_errno < 0) { + if (netif_msg_drv(priv)) + netdev_err(net_dev, "mac_dev->stop() = %d\n", + _errno); + return _errno; + } + + for_each_port_device(i, mac_dev->port_dev) + fm_port_disable(mac_dev->port_dev[i]); + + if (mac_dev->phy_dev) + phy_disconnect(mac_dev->phy_dev); + mac_dev->phy_dev = NULL; + + return _errno; +} + static int __cold dpa_eth_proxy_remove(struct platform_device *of_dev) { + struct device *dev; + + dev = &of_dev->dev; + dev_set_drvdata(dev, NULL); + + if (proxy_dev) + kfree(proxy_dev); + return 0; } diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c index 38580c9..eade30a 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c @@ -505,6 +505,7 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, } void __hot _dpa_rx(struct net_device *net_dev, + struct qman_portal *portal, const struct dpa_priv_s *priv, struct dpa_percpu_priv_s *percpu_priv, const struct qm_fd *fd, @@ -573,8 +574,12 @@ void __hot _dpa_rx(struct net_device *net_dev, if (use_gro) { gro_result_t gro_result; + const struct qman_portal_config *pc = + qman_p_get_portal_config(portal); + struct dpa_napi_portal *np = &percpu_priv->np[pc->index]; - gro_result = napi_gro_receive(&percpu_priv->napi, skb); + np->p = portal; + gro_result = napi_gro_receive(&np->napi, skb); /* If frame is dropped by the stack, rx_dropped counter is * incremented automatically, so no need for us to update it */ diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c index 438fe1f..09889e4 100644 --- a/drivers/net/ethernet/freescale/dpa/mac-api.c +++ b/drivers/net/ethernet/freescale/dpa/mac-api.c @@ -41,6 +41,7 @@ #include <linux/netdevice.h> #include "dpaa_eth.h" +#include "dpaa_eth_common.h" #include "mac.h" #include "lnxwrp_fsl_fman.h" @@ -285,17 +286,14 @@ static int __cold stop(struct mac_device *mac_dev) return fm_mac_disable(mac_dev->get_mac_handle(mac_dev)); } -static int __cold set_multi(struct net_device *net_dev) +static int __cold set_multi(struct net_device *net_dev, + struct mac_device *mac_dev) { - struct dpa_priv_s *priv; - struct mac_device *mac_dev; struct mac_priv_s *mac_priv; struct mac_address *old_addr, *tmp; struct netdev_hw_addr *ha; int _errno; - priv = netdev_priv(net_dev); - mac_dev = priv->mac_dev; mac_priv = macdev_priv(mac_dev); /* Clear previous address list */ @@ -330,7 +328,9 @@ static int __cold set_multi(struct net_device *net_dev) static void adjust_link(struct net_device *net_dev) { struct dpa_priv_s *priv = netdev_priv(net_dev); - struct mac_device *mac_dev = priv->mac_dev; + struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; + struct mac_device *mac_dev = proxy_dev ? proxy_dev->mac_dev : + priv->mac_dev; struct phy_device *phy_dev = mac_dev->phy_dev; fm_mac_adjust_link(mac_dev->get_mac_handle(mac_dev), @@ -340,15 +340,11 @@ static void adjust_link(struct net_device *net_dev) /* Initializes driver's PHY state, and attaches to the PHY. * Returns 0 on success. */ -static int dtsec_init_phy(struct net_device *net_dev) +static int dtsec_init_phy(struct net_device *net_dev, + struct mac_device *mac_dev) { - struct dpa_priv_s *priv; - struct mac_device *mac_dev; struct phy_device *phy_dev; - priv = netdev_priv(net_dev); - mac_dev = priv->mac_dev; - if (!mac_dev->phy_node) phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, &adjust_link, 0, mac_dev->phy_if); @@ -364,18 +360,17 @@ static int dtsec_init_phy(struct net_device *net_dev) } /* Remove any features not supported by the controller */ - phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->supported &= mac_dev->if_support; phy_dev->advertising = phy_dev->supported; - priv->mac_dev->phy_dev = phy_dev; + mac_dev->phy_dev = phy_dev; return 0; } -static int xgmac_init_phy(struct net_device *net_dev) +static int xgmac_init_phy(struct net_device *net_dev, + struct mac_device *mac_dev) { - struct dpa_priv_s *priv = netdev_priv(net_dev); - struct mac_device *mac_dev = priv->mac_dev; struct phy_device *phy_dev; if (!mac_dev->phy_node) @@ -392,7 +387,7 @@ static int xgmac_init_phy(struct net_device *net_dev) return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); } - phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->supported &= mac_dev->if_support; phy_dev->advertising = phy_dev->supported; mac_dev->phy_dev = phy_dev; @@ -400,15 +395,11 @@ static int xgmac_init_phy(struct net_device *net_dev) return 0; } -static int memac_init_phy(struct net_device *net_dev) +static int memac_init_phy(struct net_device *net_dev, + struct mac_device *mac_dev) { - struct dpa_priv_s *priv; - struct mac_device *mac_dev; struct phy_device *phy_dev; - priv = netdev_priv(net_dev); - mac_dev = priv->mac_dev; - if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { if (!mac_dev->phy_node) { mac_dev->phy_dev = NULL; @@ -434,7 +425,7 @@ static int memac_init_phy(struct net_device *net_dev) } /* Remove any features not supported by the controller */ - phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->supported &= mac_dev->if_support; phy_dev->advertising = phy_dev->supported; mac_dev->phy_dev = phy_dev; diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h index 270ee90..37abc7f 100644 --- a/drivers/net/ethernet/freescale/dpa/mac.h +++ b/drivers/net/ethernet/freescale/dpa/mac.h @@ -72,13 +72,14 @@ struct mac_device { u32 tx_pause; struct fm_mac_dev *(*get_mac_handle)(struct mac_device *mac_dev); - int (*init_phy)(struct net_device *net_dev); + int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev); int (*init)(struct mac_device *mac_dev); int (*start)(struct mac_device *mac_dev); int (*stop)(struct mac_device *mac_dev); int (*set_promisc)(struct fm_mac_dev *fm_mac_dev, bool enable); int (*change_addr)(struct fm_mac_dev *fm_mac_dev, uint8_t *addr); - int (*set_multi)(struct net_device *net_dev); + int (*set_multi)(struct net_device *net_dev, + struct mac_device *mac_dev); int (*uninit)(struct fm_mac_dev *fm_mac_dev); int (*ptp_enable)(struct fm_mac_dev *fm_mac_dev); int (*ptp_disable)(struct fm_mac_dev *fm_mac_dev); |