diff options
Diffstat (limited to 'drivers/staging/octeon/ethernet.c')
-rw-r--r-- | drivers/staging/octeon/ethernet.c | 115 |
1 files changed, 77 insertions, 38 deletions
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index fbbe866..f9dba23 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/module.h> @@ -180,10 +164,7 @@ static void cvm_oct_configure_common_hw(void) } #endif - if (USE_RED) - cvmx_helper_setup_red(num_packet_buffers / 4, - num_packet_buffers / 8); - + cvmx_helper_setup_red(num_packet_buffers / 4, num_packet_buffers / 8); } /** @@ -206,11 +187,10 @@ int cvm_oct_free_work(void *work_queue_entry) if (unlikely(!segment_ptr.s.i)) cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), segment_ptr.s.pool, - DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE / - 128)); + CVMX_FPA_PACKET_POOL_SIZE / 128); segment_ptr = next_ptr; } - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); + cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); return 0; } @@ -468,11 +448,8 @@ int cvm_oct_common_init(struct net_device *dev) && (always_use_pow || strstr(pow_send_list, dev->name))) priv->queue = -1; - if (priv->queue != -1) { - dev->features |= NETIF_F_SG; - if (USE_HW_TCPUDP_CHECKSUM) - dev->features |= NETIF_F_IP_CSUM; - } + if (priv->queue != -1) + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; /* We do our own locking, Linux doesn't need to */ dev->features |= NETIF_F_LLTX; @@ -488,6 +465,9 @@ int cvm_oct_common_init(struct net_device *dev) memset(dev->netdev_ops->ndo_get_stats(dev), 0, sizeof(struct net_device_stats)); + if (dev->netdev_ops->ndo_stop) + dev->netdev_ops->ndo_stop(dev); + return 0; } @@ -499,6 +479,66 @@ void cvm_oct_common_uninit(struct net_device *dev) phy_disconnect(priv->phydev); } +int cvm_oct_common_open(struct net_device *dev, + void (*link_poll)(struct net_device *), bool poll_now) +{ + union cvmx_gmxx_prtx_cfg gmx_cfg; + struct octeon_ethernet *priv = netdev_priv(dev); + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + cvmx_helper_link_info_t link_info; + int rv; + + rv = cvm_oct_phy_setup_device(dev); + if (rv) + return rv; + + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); + gmx_cfg.s.en = 1; + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); + + if (octeon_is_simulation()) + return 0; + + if (priv->phydev) { + int r = phy_read_status(priv->phydev); + + if (r == 0 && priv->phydev->link == 0) + netif_carrier_off(dev); + cvm_oct_adjust_link(dev); + } else { + link_info = cvmx_helper_link_get(priv->port); + if (!link_info.s.link_up) + netif_carrier_off(dev); + priv->poll = link_poll; + if (poll_now) + link_poll(dev); + } + + return 0; +} + +void cvm_oct_link_poll(struct net_device *dev) +{ + struct octeon_ethernet *priv = netdev_priv(dev); + cvmx_helper_link_info_t link_info; + + link_info = cvmx_helper_link_get(priv->port); + if (link_info.u64 == priv->link_info) + return; + + link_info = cvmx_helper_link_autoconf(priv->port); + priv->link_info = link_info.u64; + + if (link_info.s.link_up) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); + } + cvm_oct_note_carrier(priv, link_info); +} + static const struct net_device_ops cvm_oct_npi_netdev_ops = { .ndo_init = cvm_oct_common_init, .ndo_uninit = cvm_oct_common_uninit, @@ -514,9 +554,9 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = { }; static const struct net_device_ops cvm_oct_xaui_netdev_ops = { .ndo_init = cvm_oct_xaui_init, - .ndo_uninit = cvm_oct_xaui_uninit, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_xaui_open, - .ndo_stop = cvm_oct_xaui_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, @@ -529,9 +569,9 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = { }; static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { .ndo_init = cvm_oct_sgmii_init, - .ndo_uninit = cvm_oct_sgmii_uninit, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_sgmii_open, - .ndo_stop = cvm_oct_sgmii_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, @@ -559,7 +599,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { .ndo_init = cvm_oct_rgmii_init, .ndo_uninit = cvm_oct_rgmii_uninit, .ndo_open = cvm_oct_rgmii_open, - .ndo_stop = cvm_oct_rgmii_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, @@ -625,7 +665,6 @@ static int cvm_oct_probe(struct platform_device *pdev) struct device_node *pip; octeon_mdiobus_force_mod_depencency(); - pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); pip = pdev->dev.of_node; if (!pip) { |