Commit f6ed1b3b authored by David Daney's avatar David Daney Committed by Ralf Baechle

Staging: octeon-ethernet: Convert to use PHY Abstraction Layer.

The octeon-ethernet driver shares an mdio bus with the octeon-mgmt
driver.  Here we convert the octeon-ethernet driver to use the PHY
Abstraction Layer.
Signed-off-by: default avatarDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent d6aa60a1
config OCTEON_ETHERNET config OCTEON_ETHERNET
tristate "Cavium Networks Octeon Ethernet support" tristate "Cavium Networks Octeon Ethernet support"
depends on CPU_CAVIUM_OCTEON depends on CPU_CAVIUM_OCTEON
select MII select PHYLIB
select MDIO_OCTEON
help help
This driver supports the builtin ethernet ports on Cavium This driver supports the builtin ethernet ports on Cavium
Networks' products in the Octeon family. This driver supports the Networks' products in the Octeon family. This driver supports the
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
**********************************************************************/ **********************************************************************/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/mii.h> #include <linux/phy.h>
#include <net/dst.h> #include <net/dst.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
...@@ -34,86 +35,12 @@ ...@@ -34,86 +35,12 @@
#include "ethernet-defines.h" #include "ethernet-defines.h"
#include "octeon-ethernet.h" #include "octeon-ethernet.h"
#include "ethernet-mdio.h" #include "ethernet-mdio.h"
#include "ethernet-util.h"
#include "cvmx-helper-board.h" #include "cvmx-helper-board.h"
#include "cvmx-smix-defs.h" #include "cvmx-smix-defs.h"
DECLARE_MUTEX(mdio_sem);
/**
* Perform an MII read. Called by the generic MII routines
*
* @dev: Device to perform read for
* @phy_id: The MII phy id
* @location: Register location to read
* Returns Result from the read or zero on failure
*/
static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location)
{
union cvmx_smix_cmd smi_cmd;
union cvmx_smix_rd_dat smi_rd;
smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 1;
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = location;
cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
do {
if (!in_interrupt())
yield();
smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0));
} while (smi_rd.s.pending);
if (smi_rd.s.val)
return smi_rd.s.dat;
else
return 0;
}
static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id,
int location)
{
return 0xffff;
}
/**
* Perform an MII write. Called by the generic MII routines
*
* @dev: Device to perform write for
* @phy_id: The MII phy id
* @location: Register location to write
* @val: Value to write
*/
static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location,
int val)
{
union cvmx_smix_cmd smi_cmd;
union cvmx_smix_wr_dat smi_wr;
smi_wr.u64 = 0;
smi_wr.s.dat = val;
cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64);
smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 0;
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = location;
cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
do {
if (!in_interrupt())
yield();
smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0));
} while (smi_wr.s.pending);
}
static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id,
int location, int val)
{
}
static void cvm_oct_get_drvinfo(struct net_device *dev, static void cvm_oct_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
...@@ -125,49 +52,37 @@ static void cvm_oct_get_drvinfo(struct net_device *dev, ...@@ -125,49 +52,37 @@ static void cvm_oct_get_drvinfo(struct net_device *dev,
static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
int ret;
down(&mdio_sem); if (priv->phydev)
ret = mii_ethtool_gset(&priv->mii_info, cmd); return phy_ethtool_gset(priv->phydev, cmd);
up(&mdio_sem);
return ret; return -EINVAL;
} }
static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
int ret;
down(&mdio_sem); if (!capable(CAP_NET_ADMIN))
ret = mii_ethtool_sset(&priv->mii_info, cmd); return -EPERM;
up(&mdio_sem);
return ret; if (priv->phydev)
return phy_ethtool_sset(priv->phydev, cmd);
return -EINVAL;
} }
static int cvm_oct_nway_reset(struct net_device *dev) static int cvm_oct_nway_reset(struct net_device *dev)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
int ret;
down(&mdio_sem);
ret = mii_nway_restart(&priv->mii_info);
up(&mdio_sem);
return ret;
}
static u32 cvm_oct_get_link(struct net_device *dev) if (!capable(CAP_NET_ADMIN))
{ return -EPERM;
struct octeon_ethernet *priv = netdev_priv(dev);
u32 ret;
down(&mdio_sem); if (priv->phydev)
ret = mii_link_ok(&priv->mii_info); return phy_start_aneg(priv->phydev);
up(&mdio_sem);
return ret; return -EINVAL;
} }
const struct ethtool_ops cvm_oct_ethtool_ops = { const struct ethtool_ops cvm_oct_ethtool_ops = {
...@@ -175,7 +90,7 @@ const struct ethtool_ops cvm_oct_ethtool_ops = { ...@@ -175,7 +90,7 @@ const struct ethtool_ops cvm_oct_ethtool_ops = {
.get_settings = cvm_oct_get_settings, .get_settings = cvm_oct_get_settings,
.set_settings = cvm_oct_set_settings, .set_settings = cvm_oct_set_settings,
.nway_reset = cvm_oct_nway_reset, .nway_reset = cvm_oct_nway_reset,
.get_link = cvm_oct_get_link, .get_link = ethtool_op_get_link,
.get_sg = ethtool_op_get_sg, .get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum, .get_tx_csum = ethtool_op_get_tx_csum,
}; };
...@@ -191,41 +106,78 @@ const struct ethtool_ops cvm_oct_ethtool_ops = { ...@@ -191,41 +106,78 @@ const struct ethtool_ops cvm_oct_ethtool_ops = {
int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(rq);
unsigned int duplex_chg;
int ret;
down(&mdio_sem); if (!netif_running(dev))
ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg); return -EINVAL;
up(&mdio_sem);
return ret; if (!priv->phydev)
return -EINVAL;
return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
}
static void cvm_oct_adjust_link(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
cvmx_helper_link_info_t link_info;
if (priv->last_link != priv->phydev->link) {
priv->last_link = priv->phydev->link;
link_info.u64 = 0;
link_info.s.link_up = priv->last_link ? 1 : 0;
link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
link_info.s.speed = priv->phydev->speed;
cvmx_helper_link_set( priv->port, link_info);
if (priv->last_link) {
netif_carrier_on(dev);
if (priv->queue != -1)
DEBUGPRINT("%s: %u Mbps %s duplex, "
"port %2d, queue %2d\n",
dev->name, priv->phydev->speed,
priv->phydev->duplex ?
"Full" : "Half",
priv->port, priv->queue);
else
DEBUGPRINT("%s: %u Mbps %s duplex, "
"port %2d, POW\n",
dev->name, priv->phydev->speed,
priv->phydev->duplex ?
"Full" : "Half",
priv->port);
} else {
netif_carrier_off(dev);
DEBUGPRINT("%s: Link down\n", dev->name);
}
}
} }
/** /**
* Setup the MDIO device structures * Setup the PHY
* *
* @dev: Device to setup * @dev: Device to setup
* *
* Returns Zero on success, negative on failure * Returns Zero on success, negative on failure
*/ */
int cvm_oct_mdio_setup_device(struct net_device *dev) int cvm_oct_phy_setup_device(struct net_device *dev)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
int phy_id = cvmx_helper_board_get_mii_address(priv->port);
if (phy_id != -1) { int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
priv->mii_info.dev = dev; if (phy_addr != -1) {
priv->mii_info.phy_id = phy_id; char phy_id[20];
priv->mii_info.phy_id_mask = 0xff;
priv->mii_info.supports_gmii = 1; snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
priv->mii_info.reg_num_mask = 0x1f;
priv->mii_info.mdio_read = cvm_oct_mdio_read; priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
priv->mii_info.mdio_write = cvm_oct_mdio_write; PHY_INTERFACE_MODE_GMII);
} else {
/* Supply dummy MDIO routines so the kernel won't crash if (IS_ERR(priv->phydev)) {
if the user tries to read them */ priv->phydev = NULL;
priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read; return -1;
priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write; }
priv->last_link = 0;
phy_start_aneg(priv->phydev);
} }
return 0; return 0;
} }
...@@ -43,4 +43,4 @@ ...@@ -43,4 +43,4 @@
extern const struct ethtool_ops cvm_oct_ethtool_ops; extern const struct ethtool_ops cvm_oct_ethtool_ops;
int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
int cvm_oct_mdio_setup_device(struct net_device *dev); int cvm_oct_phy_setup_device(struct net_device *dev);
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
* Contact Cavium Networks for more information * Contact Cavium Networks for more information
**********************************************************************/ **********************************************************************/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mii.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -38,112 +37,6 @@ ...@@ -38,112 +37,6 @@
#include "cvmx-helper.h" #include "cvmx-helper.h"
#include "cvmx-pip.h" #include "cvmx-pip.h"
static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev,
int phy_id, int offset)
{
struct octeon_ethernet *priv = netdev_priv(dev);
priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset);
return ((uint64_t) priv->mii_info.
mdio_read(dev, phy_id,
0x1e) << 16) | (uint64_t) priv->mii_info.
mdio_read(dev, phy_id, 0x1f);
}
static int cvm_oct_stats_switch_show(struct seq_file *m, void *v)
{
static const int ports[] = { 0, 1, 2, 3, 9, -1 };
struct net_device *dev = cvm_oct_device[0];
int index = 0;
while (ports[index] != -1) {
/* Latch port */
struct octeon_ethernet *priv = netdev_priv(dev);
priv->mii_info.mdio_write(dev, 0x1b, 0x1d,
0xdc00 | ports[index]);
seq_printf(m, "\nSwitch Port %d\n", ports[index]);
seq_printf(m, "InGoodOctets: %12llu\t"
"OutOctets: %12llu\t"
"64 Octets: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b,
0x00) |
(cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32),
cvm_oct_stats_read_switch(dev, 0x1b,
0x0E) |
(cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32),
cvm_oct_stats_read_switch(dev, 0x1b, 0x08));
seq_printf(m, "InBadOctets: %12llu\t"
"OutUnicast: %12llu\t"
"65-127 Octets: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x02),
cvm_oct_stats_read_switch(dev, 0x1b, 0x10),
cvm_oct_stats_read_switch(dev, 0x1b, 0x09));
seq_printf(m, "InUnicast: %12llu\t"
"OutBroadcasts: %12llu\t"
"128-255 Octets: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x04),
cvm_oct_stats_read_switch(dev, 0x1b, 0x13),
cvm_oct_stats_read_switch(dev, 0x1b, 0x0A));
seq_printf(m, "InBroadcasts: %12llu\t"
"OutMulticasts: %12llu\t"
"256-511 Octets: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x06),
cvm_oct_stats_read_switch(dev, 0x1b, 0x12),
cvm_oct_stats_read_switch(dev, 0x1b, 0x0B));
seq_printf(m, "InMulticasts: %12llu\t"
"OutPause: %12llu\t"
"512-1023 Octets:%12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x07),
cvm_oct_stats_read_switch(dev, 0x1b, 0x15),
cvm_oct_stats_read_switch(dev, 0x1b, 0x0C));
seq_printf(m, "InPause: %12llu\t"
"Excessive: %12llu\t"
"1024-Max Octets:%12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x16),
cvm_oct_stats_read_switch(dev, 0x1b, 0x11),
cvm_oct_stats_read_switch(dev, 0x1b, 0x0D));
seq_printf(m, "InUndersize: %12llu\t"
"Collisions: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x18),
cvm_oct_stats_read_switch(dev, 0x1b, 0x1E));
seq_printf(m, "InFragments: %12llu\t"
"Deferred: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x19),
cvm_oct_stats_read_switch(dev, 0x1b, 0x05));
seq_printf(m, "InOversize: %12llu\t"
"Single: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x1A),
cvm_oct_stats_read_switch(dev, 0x1b, 0x14));
seq_printf(m, "InJabber: %12llu\t"
"Multiple: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x1B),
cvm_oct_stats_read_switch(dev, 0x1b, 0x17));
seq_printf(m, "In RxErr: %12llu\t"
"OutFCSErr: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x1C),
cvm_oct_stats_read_switch(dev, 0x1b, 0x03));
seq_printf(m, "InFCSErr: %12llu\t"
"Late: %12llu\n",
cvm_oct_stats_read_switch(dev, 0x1b, 0x1D),
cvm_oct_stats_read_switch(dev, 0x1b, 0x1F));
index++;
}
return 0;
}
/** /**
* User is reading /proc/octeon_ethernet_stats * User is reading /proc/octeon_ethernet_stats
* *
...@@ -215,11 +108,6 @@ static int cvm_oct_stats_show(struct seq_file *m, void *v) ...@@ -215,11 +108,6 @@ static int cvm_oct_stats_show(struct seq_file *m, void *v)
} }
} }
if (cvm_oct_device[0]) {
priv = netdev_priv(cvm_oct_device[0]);
if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
cvm_oct_stats_switch_show(m, v);
}
return 0; return 0;
} }
......
...@@ -147,33 +147,37 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) ...@@ -147,33 +147,37 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
gmxx_rxx_int_reg.u64); gmxx_rxx_int_reg.u64);
} }
if (priv->phydev == NULL) {
link_info = cvmx_helper_link_autoconf(priv->port); link_info = cvmx_helper_link_autoconf(priv->port);
priv->link_info = link_info.u64; priv->link_info = link_info.u64;
}
spin_unlock_irqrestore(&global_register_lock, flags); spin_unlock_irqrestore(&global_register_lock, flags);
/* Tell Linux */ if (priv->phydev == NULL) {
/* Tell core. */
if (link_info.s.link_up) { if (link_info.s.link_up) {
if (!netif_carrier_ok(dev)) if (!netif_carrier_ok(dev))
netif_carrier_on(dev); netif_carrier_on(dev);
if (priv->queue != -1) if (priv->queue != -1)
DEBUGPRINT DEBUGPRINT("%s: %u Mbps %s duplex, "
("%s: %u Mbps %s duplex, port %2d, queue %2d\n", "port %2d, queue %2d\n",
dev->name, link_info.s.speed, dev->name, link_info.s.speed,
(link_info.s.full_duplex) ? "Full" : "Half", (link_info.s.full_duplex) ?
"Full" : "Half",
priv->port, priv->queue); priv->port, priv->queue);
else else
DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", DEBUGPRINT("%s: %u Mbps %s duplex, "
"port %2d, POW\n",
dev->name, link_info.s.speed, dev->name, link_info.s.speed,
(link_info.s.full_duplex) ? "Full" : "Half", (link_info.s.full_duplex) ?
"Full" : "Half",
priv->port); priv->port);
} else { } else {
if (netif_carrier_ok(dev)) if (netif_carrier_ok(dev))
netif_carrier_off(dev); netif_carrier_off(dev);
DEBUGPRINT("%s: Link down\n", dev->name); DEBUGPRINT("%s: Link down\n", dev->name);
} }
}
} }
static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
......
...@@ -113,7 +113,7 @@ int cvm_oct_sgmii_init(struct net_device *dev) ...@@ -113,7 +113,7 @@ int cvm_oct_sgmii_init(struct net_device *dev)
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
cvm_oct_common_init(dev); cvm_oct_common_init(dev);
dev->netdev_ops->ndo_stop(dev); dev->netdev_ops->ndo_stop(dev);
if (!octeon_is_simulation()) if (!octeon_is_simulation() && priv->phydev == NULL)
priv->poll = cvm_oct_sgmii_poll; priv->poll = cvm_oct_sgmii_poll;
/* FIXME: Need autoneg logic */ /* FIXME: Need autoneg logic */
......
...@@ -112,7 +112,7 @@ int cvm_oct_xaui_init(struct net_device *dev) ...@@ -112,7 +112,7 @@ int cvm_oct_xaui_init(struct net_device *dev)
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
cvm_oct_common_init(dev); cvm_oct_common_init(dev);
dev->netdev_ops->ndo_stop(dev); dev->netdev_ops->ndo_stop(dev);
if (!octeon_is_simulation()) if (!octeon_is_simulation() && priv->phydev == NULL)
priv->poll = cvm_oct_xaui_poll; priv->poll = cvm_oct_xaui_poll;
return 0; return 0;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mii.h> #include <linux/phy.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -132,8 +132,6 @@ static struct timer_list cvm_oct_poll_timer; ...@@ -132,8 +132,6 @@ static struct timer_list cvm_oct_poll_timer;
*/ */
struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
extern struct semaphore mdio_sem;
/** /**
* Periodic timer tick for slow management operations * Periodic timer tick for slow management operations
* *
...@@ -160,13 +158,8 @@ static void cvm_do_timer(unsigned long arg) ...@@ -160,13 +158,8 @@ static void cvm_do_timer(unsigned long arg)
goto out; goto out;
priv = netdev_priv(cvm_oct_device[port]); priv = netdev_priv(cvm_oct_device[port]);
if (priv->poll) { if (priv->poll)
/* skip polling if we don't get the lock */
if (!down_trylock(&mdio_sem)) {
priv->poll(cvm_oct_device[port]); priv->poll(cvm_oct_device[port]);
up(&mdio_sem);
}
}
queues_per_port = cvmx_pko_get_num_queues(port); queues_per_port = cvmx_pko_get_num_queues(port);
/* Drain any pending packets in the free list */ /* Drain any pending packets in the free list */
...@@ -524,7 +517,7 @@ int cvm_oct_common_init(struct net_device *dev) ...@@ -524,7 +517,7 @@ int cvm_oct_common_init(struct net_device *dev)
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
cvm_oct_mdio_setup_device(dev); cvm_oct_phy_setup_device(dev);
dev->netdev_ops->ndo_set_mac_address(dev, &sa); dev->netdev_ops->ndo_set_mac_address(dev, &sa);
dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
...@@ -540,7 +533,10 @@ int cvm_oct_common_init(struct net_device *dev) ...@@ -540,7 +533,10 @@ int cvm_oct_common_init(struct net_device *dev)
void cvm_oct_common_uninit(struct net_device *dev) void cvm_oct_common_uninit(struct net_device *dev)
{ {
/* Currently nothing to do */ struct octeon_ethernet *priv = netdev_priv(dev);
if (priv->phydev)
phy_disconnect(priv->phydev);
} }
static const struct net_device_ops cvm_oct_npi_netdev_ops = { static const struct net_device_ops cvm_oct_npi_netdev_ops = {
...@@ -627,6 +623,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = { ...@@ -627,6 +623,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
#endif #endif
}; };
extern void octeon_mdiobus_force_mod_depencency(void);
/** /**
* Module/ driver initialization. Creates the linux network * Module/ driver initialization. Creates the linux network
* devices. * devices.
...@@ -640,6 +638,7 @@ static int __init cvm_oct_init_module(void) ...@@ -640,6 +638,7 @@ static int __init cvm_oct_init_module(void)
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos; int qos;
octeon_mdiobus_force_mod_depencency();
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
if (OCTEON_IS_MODEL(OCTEON_CN52XX)) if (OCTEON_IS_MODEL(OCTEON_CN52XX))
......
...@@ -50,9 +50,9 @@ struct octeon_ethernet { ...@@ -50,9 +50,9 @@ struct octeon_ethernet {
/* List of outstanding tx buffers per queue */ /* List of outstanding tx buffers per queue */
struct sk_buff_head tx_free_list[16]; struct sk_buff_head tx_free_list[16];
/* Device statistics */ /* Device statistics */
struct net_device_stats stats struct net_device_stats stats;
; /* Generic MII info structure */ struct phy_device *phydev;
struct mii_if_info mii_info; unsigned int last_link;
/* Last negotiated link state */ /* Last negotiated link state */
uint64_t link_info; uint64_t link_info;
/* Called periodically to check link status */ /* Called periodically to check link status */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment