summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/dpa
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2013-12-14 02:43:39 (GMT)
committerScott Wood <scottwood@freescale.com>2013-12-14 02:45:02 (GMT)
commit5709059c4e110944712dc1f3d66a203a924c151a (patch)
tree3f5ff4c45d2b1089c3f4504771a78e847b3ac073 /drivers/net/ethernet/freescale/dpa
parentb7c81aa3ab2ac2c140e278b6d0e9a0b95112cf0b (diff)
parent3dea020415467452d6ca2e907e21af07954741cf (diff)
downloadlinux-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.c104
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth.h25
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c5
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h12
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c124
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_non_sg.c7
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c106
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c7
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac-api.c41
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.h5
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);