diff options
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth.c | 310 |
1 files changed, 193 insertions, 117 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c index 3307675..c776ec2 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c @@ -3890,10 +3890,6 @@ dpaa_eth_probe(struct platform_device *_of_dev) struct device_node *dpa_node; struct dpa_bp *dpa_bp; struct dpa_fq *dpa_fq, *tmp; - struct list_head rxfqlist; - struct list_head txfqlist; - struct list_head proxy_fq_list; - struct list_head *fq_list; size_t count; struct net_device *net_dev = NULL; struct dpa_priv_s *priv = NULL; @@ -3903,30 +3899,19 @@ dpaa_eth_probe(struct platform_device *_of_dev) struct fm_port *txport = NULL; struct dpa_buffer_layout_s *buf_layout = NULL; struct mac_device *mac_dev; - const struct of_device_id *match; + struct task_struct *kth; /* Interface type results as a side effect of the probing process */ bool is_private = false; bool is_macless = false; bool is_shared = false; - bool is_proxy = false; dev = &_of_dev->dev; dpa_node = dev->of_node; - match = of_match_device(dpa_match, dev); - if (!match) - return -EINVAL; - if (!of_device_is_available(dpa_node)) return -ENODEV; - /* If it's not an fsl,dpa-ethernet node, we just serve as a proxy - * initializer driver, and don't do any linux device setup - * proxy interfaces have fsl,dpa-ethernet-init as compatible string - */ - is_proxy = strcmp(match->compatible, "fsl,dpa-ethernet") != 0; - /* Get the buffer pools assigned to this interface */ dpa_bp = dpa_bp_probe(_of_dev, &count); if (IS_ERR(dpa_bp)) @@ -3938,22 +3923,20 @@ dpaa_eth_probe(struct platform_device *_of_dev) * Allocate this early, so we can store relevant information in * the private area (needed by 1588 code in dpa_mac_probe) */ - if (!is_proxy) { - net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); - if (!net_dev) { - dev_err(dev, "alloc_etherdev_mq() failed\n"); - return -ENOMEM; - } + net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); + if (!net_dev) { + dev_err(dev, "alloc_etherdev_mq() failed\n"); + return -ENOMEM; + } - /* Do this here, so we can be verbose early */ - SET_NETDEV_DEV(net_dev, dev); - dev_set_drvdata(dev, net_dev); + /* Do this here, so we can be verbose early */ + SET_NETDEV_DEV(net_dev, dev); + dev_set_drvdata(dev, net_dev); - priv = netdev_priv(net_dev); - priv->net_dev = net_dev; + priv = netdev_priv(net_dev); + priv->net_dev = net_dev; - priv->msg_enable = netif_msg_init(debug, -1); - } + priv->msg_enable = netif_msg_init(debug, -1); mac_dev = dpa_mac_probe(_of_dev); if (IS_ERR(mac_dev)) { @@ -3992,29 +3975,21 @@ dpaa_eth_probe(struct platform_device *_of_dev) default_buf_size = dpa_bp->size; } - INIT_LIST_HEAD(&rxfqlist); - INIT_LIST_HEAD(&txfqlist); - - if (is_proxy) { - INIT_LIST_HEAD(&proxy_fq_list); - fq_list = &proxy_fq_list; - } else { - INIT_LIST_HEAD(&priv->dpa_fq_list); - fq_list = &priv->dpa_fq_list; - } + INIT_LIST_HEAD(&priv->dpa_fq_list); memset(&port_fqs, 0, sizeof(port_fqs)); if (!is_macless) { - err = dpa_fq_probe_mac(dev, fq_list, &port_fqs, + err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs, is_shared, RX); if (!err) - err = dpa_fq_probe_mac(dev, fq_list, &port_fqs, - is_shared, TX); + err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, + &port_fqs, is_shared, TX); } else { - err = dpa_fq_probe_macless(dev, fq_list, RX); + err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, RX); if (!err) - err = dpa_fq_probe_macless(dev, fq_list, TX); + err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, + TX); } if (err < 0) @@ -4025,72 +4000,69 @@ dpaa_eth_probe(struct platform_device *_of_dev) * We support a number of configurations: * 1) Private interface - An optimized linux ethernet driver with * a real network connection. - * 2) Shared interface - A device intended for virtual connections - * or for a real interface that is shared between partitions - * 3) Proxy initializer - Just configures the MAC on behalf of - * another partition. - * 4) MAC-less interface - A netdevice over configurable FQs. + * 2) Shared interface - A device for a real interface that is shared + * between partitions. + * 3) MAC-less interface - A netdevice over configurable FQs intended + * for virtual connections. */ /* bp init */ - if (!is_proxy) { - struct task_struct *kth; - err = dpa_bp_create(net_dev, dpa_bp, count); + err = dpa_bp_create(net_dev, dpa_bp, count); - if (err < 0) - goto bp_create_failed; + if (err < 0) + goto bp_create_failed; - priv->mac_dev = mac_dev; + priv->mac_dev = mac_dev; - priv->channel = dpa_get_channel(dev, dpa_node); + priv->channel = dpa_get_channel(dev, dpa_node); - if (priv->channel < 0) { - err = priv->channel; - goto get_channel_failed; - } + if (priv->channel < 0) { + err = priv->channel; + goto get_channel_failed; + } - /* Start a thread that will walk the cpus with affine portals - * and add this pool channel to each's dequeue mask. */ - kth = kthread_run(dpaa_eth_add_channel, - (void *)(unsigned long)priv->channel, - "dpaa_%p:%d", net_dev, priv->channel); - if (!kth) { - err = -ENOMEM; - goto add_channel_failed; - } + /* Start a thread that will walk the cpus with affine portals + * and add this pool channel to each's dequeue mask. + */ + kth = kthread_run(dpaa_eth_add_channel, + (void *)(unsigned long)priv->channel, + "dpaa_%p:%d", net_dev, priv->channel); + if (!kth) { + err = -ENOMEM; + goto add_channel_failed; + } - dpa_fq_setup(priv); + dpa_fq_setup(priv); - /* - * Create a congestion group for this netdev, with - * dynamically-allocated CGR ID. - * Must be executed after probing the MAC, but before - * assigning the egress FQs to the CGRs. - * Don't create a congestion group for MAC-less interfaces. - */ - if (!is_macless) { - err = dpaa_eth_cgr_init(priv); - if (err < 0) { - dev_err(dev, "Error initializing CGR\n"); - goto cgr_init_failed; - } + /* + * Create a congestion group for this netdev, with + * dynamically-allocated CGR ID. + * Must be executed after probing the MAC, but before + * assigning the egress FQs to the CGRs. + * Don't create a congestion group for MAC-less interfaces. + */ + if (!is_macless) { + err = dpaa_eth_cgr_init(priv); + if (err < 0) { + dev_err(dev, "Error initializing CGR\n"); + goto cgr_init_failed; } + } - /* Add the FQs to the interface, and make them active */ - list_for_each_entry_safe(dpa_fq, tmp, fq_list, list) { - err = dpa_fq_init(dpa_fq); - if (err < 0) - goto fq_alloc_failed; - } + /* Add the FQs to the interface, and make them active */ + list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { + err = dpa_fq_init(dpa_fq); + if (err < 0) + goto fq_alloc_failed; + } - if (!is_macless) { - priv->buf_layout = buf_layout; - priv->tx_headroom = - dpa_get_headroom(&priv->buf_layout[TX]); - } else { - priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; - } + if (!is_macless) { + priv->buf_layout = buf_layout; + priv->tx_headroom = + dpa_get_headroom(&priv->buf_layout[TX]); + } else { + priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; } /* All real interfaces need their ports initialized */ @@ -4108,26 +4080,6 @@ dpaa_eth_probe(struct platform_device *_of_dev) fm_port_pcd_bind(rxport, &rx_port_pcd_param); } - /* - * Proxy interfaces need to be started, and the allocated - * memory freed - */ - if (is_proxy) { - devm_kfree(dev, dpa_bp); - - /* Free FQ structures */ - devm_kfree(dev, port_fqs.rx_defq); - devm_kfree(dev, port_fqs.rx_errq); - devm_kfree(dev, port_fqs.tx_defq); - devm_kfree(dev, port_fqs.tx_errq); - - if (!is_macless) - for_each_port_device(i, mac_dev->port_dev) - fm_port_enable(mac_dev->port_dev[i]); - - return 0; /* Proxy interface initialization ended */ - } - /* Now we need to initialize either a private or shared interface */ priv->percpu_priv = alloc_percpu(*priv->percpu_priv); @@ -4188,16 +4140,115 @@ mac_probe_failed: return err; } +static const struct of_device_id dpa_proxy_match[]; +static int +dpaa_eth_proxy_probe(struct platform_device *_of_dev) +{ + int err = 0, i; + struct device *dev; + struct device_node *dpa_node; + struct dpa_bp *dpa_bp; + struct list_head proxy_fq_list; + size_t count; + struct dpa_priv_s *priv = NULL; + struct fm_port_fqs port_fqs; + struct fm_port *rxport = NULL; + struct fm_port *txport = NULL; + struct dpa_buffer_layout_s *buf_layout = NULL; + struct mac_device *mac_dev; + + dev = &_of_dev->dev; + + dpa_node = dev->of_node; + + if (!of_device_is_available(dpa_node)) + return -ENODEV; + + /* Get the buffer pools assigned to this interface */ + dpa_bp = dpa_bp_probe(_of_dev, &count); + if (IS_ERR(dpa_bp)) + return PTR_ERR(dpa_bp); + + mac_dev = dpa_mac_probe(_of_dev); + if (IS_ERR(mac_dev)) + return PTR_ERR(mac_dev); + + rxport = mac_dev->port_dev[RX]; + txport = mac_dev->port_dev[TX]; + + /* We have physical ports, so we need to establish + * the buffer layout. + */ + buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout), + GFP_KERNEL); + if (!buf_layout) { + dev_err(dev, "devm_kzalloc() failed\n"); + return -ENOMEM; + } + dpa_set_buffer_layout(priv, rxport, &buf_layout[RX], RX); + dpa_set_buffer_layout(priv, txport, &buf_layout[TX], TX); + + INIT_LIST_HEAD(&proxy_fq_list); + + memset(&port_fqs, 0, sizeof(port_fqs)); + + err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, false, RX); + if (!err) + err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, false, + TX); + + if (err < 0) + return err; + + /* Proxy initializer - Just configures the MAC on behalf of + * another partition. + */ + + /* All real interfaces need their ports initialized */ + dpaa_eth_init_tx_port(txport, port_fqs.tx_errq, + port_fqs.tx_defq, &buf_layout[TX]); + dpaa_eth_init_rx_port(rxport, dpa_bp, count, port_fqs.rx_errq, + port_fqs.rx_defq, &buf_layout[RX]); + { + struct fm_port_pcd_param rx_port_pcd_param; + + rx_port_pcd_param.cba = dpa_alloc_pcd_fqids; + rx_port_pcd_param.cbf = dpa_free_pcd_fqids; + rx_port_pcd_param.dev = dev; + fm_port_pcd_bind(rxport, &rx_port_pcd_param); + } + /* Proxy interfaces need to be started, and the allocated + * memory freed + */ + devm_kfree(dev, dpa_bp); + + /* Free FQ structures */ + devm_kfree(dev, port_fqs.rx_defq); + devm_kfree(dev, port_fqs.rx_errq); + devm_kfree(dev, port_fqs.tx_defq); + devm_kfree(dev, port_fqs.tx_errq); + + for_each_port_device(i, mac_dev->port_dev) + fm_port_enable(mac_dev->port_dev[i]); + + return 0; /* Proxy interface initialization ended */ +} + static const struct of_device_id dpa_match[] = { { .compatible = "fsl,dpa-ethernet" }, + {} +}; +MODULE_DEVICE_TABLE(of, dpa_match); + +static const struct of_device_id dpa_proxy_match[] = { { .compatible = "fsl,dpa-ethernet-init" }, {} }; -MODULE_DEVICE_TABLE(of, dpa_match); +MODULE_DEVICE_TABLE(of, dpa_proxy_match); static int __cold dpa_remove(struct platform_device *of_dev) { @@ -4251,6 +4302,16 @@ static struct platform_driver dpa_driver = { .remove = dpa_remove }; +static struct platform_driver dpa_proxy_driver = { + .driver = { + .name = KBUILD_MODNAME"-proxy", + .of_match_table = dpa_proxy_match, + .owner = THIS_MODULE, + }, + .probe = dpaa_eth_proxy_probe, + .remove = dpa_remove +}; + static int __init __cold dpa_load(void) { int _errno; @@ -4271,6 +4332,16 @@ static int __init __cold dpa_load(void) pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", KBUILD_BASENAME".c", __func__); + _errno = platform_driver_register(&dpa_proxy_driver); + if (unlikely(_errno < 0)) { + pr_err(KBUILD_MODNAME"-proxy" + ": %s:%hu:%s(): platform_driver_register() = %d\n", + KBUILD_BASENAME".c", __LINE__, __func__, _errno); + } + + pr_debug(KBUILD_MODNAME"-proxy" ": %s:%s() ->\n", + KBUILD_BASENAME".c", __func__); + return _errno; } module_init(dpa_load); @@ -4284,5 +4355,10 @@ static void __exit __cold dpa_unload(void) pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", KBUILD_BASENAME".c", __func__); + + platform_driver_unregister(&dpa_proxy_driver); + + pr_debug(KBUILD_MODNAME"-proxy" ": %s:%s() ->\n", + KBUILD_BASENAME".c", __func__); } module_exit(dpa_unload); |