mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 03:06:10 +00:00
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: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
d6aa60a10b
commit
f6ed1b3b35
9 changed files with 125 additions and 281 deletions
|
@ -1,7 +1,8 @@
|
|||
config OCTEON_ETHERNET
|
||||
tristate "Cavium Networks Octeon Ethernet support"
|
||||
depends on CPU_CAVIUM_OCTEON
|
||||
select MII
|
||||
select PHYLIB
|
||||
select MDIO_OCTEON
|
||||
help
|
||||
This driver supports the builtin ethernet ports on Cavium
|
||||
Networks' products in the Octeon family. This driver supports the
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
**********************************************************************/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <net/dst.h>
|
||||
|
||||
#include <asm/octeon/octeon.h>
|
||||
|
@ -34,86 +35,12 @@
|
|||
#include "ethernet-defines.h"
|
||||
#include "octeon-ethernet.h"
|
||||
#include "ethernet-mdio.h"
|
||||
#include "ethernet-util.h"
|
||||
|
||||
#include "cvmx-helper-board.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,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
down(&mdio_sem);
|
||||
ret = mii_ethtool_gset(&priv->mii_info, cmd);
|
||||
up(&mdio_sem);
|
||||
if (priv->phydev)
|
||||
return phy_ethtool_gset(priv->phydev, cmd);
|
||||
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
down(&mdio_sem);
|
||||
ret = mii_ethtool_sset(&priv->mii_info, cmd);
|
||||
up(&mdio_sem);
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
return ret;
|
||||
if (priv->phydev)
|
||||
return phy_ethtool_sset(priv->phydev, cmd);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cvm_oct_nway_reset(struct net_device *dev)
|
||||
{
|
||||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
down(&mdio_sem);
|
||||
ret = mii_nway_restart(&priv->mii_info);
|
||||
up(&mdio_sem);
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (priv->phydev)
|
||||
return phy_start_aneg(priv->phydev);
|
||||
|
||||
static u32 cvm_oct_get_link(struct net_device *dev)
|
||||
{
|
||||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
u32 ret;
|
||||
|
||||
down(&mdio_sem);
|
||||
ret = mii_link_ok(&priv->mii_info);
|
||||
up(&mdio_sem);
|
||||
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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,
|
||||
.set_settings = cvm_oct_set_settings,
|
||||
.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_tx_csum = ethtool_op_get_tx_csum,
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
struct mii_ioctl_data *data = if_mii(rq);
|
||||
unsigned int duplex_chg;
|
||||
int ret;
|
||||
|
||||
down(&mdio_sem);
|
||||
ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg);
|
||||
up(&mdio_sem);
|
||||
if (!netif_running(dev))
|
||||
return -EINVAL;
|
||||
|
||||
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
|
||||
*
|
||||
* 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);
|
||||
int phy_id = cvmx_helper_board_get_mii_address(priv->port);
|
||||
if (phy_id != -1) {
|
||||
priv->mii_info.dev = dev;
|
||||
priv->mii_info.phy_id = phy_id;
|
||||
priv->mii_info.phy_id_mask = 0xff;
|
||||
priv->mii_info.supports_gmii = 1;
|
||||
priv->mii_info.reg_num_mask = 0x1f;
|
||||
priv->mii_info.mdio_read = cvm_oct_mdio_read;
|
||||
priv->mii_info.mdio_write = cvm_oct_mdio_write;
|
||||
} else {
|
||||
/* Supply dummy MDIO routines so the kernel won't crash
|
||||
if the user tries to read them */
|
||||
priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read;
|
||||
priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write;
|
||||
|
||||
int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
|
||||
if (phy_addr != -1) {
|
||||
char phy_id[20];
|
||||
|
||||
snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
|
||||
|
||||
priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
|
||||
PHY_INTERFACE_MODE_GMII);
|
||||
|
||||
if (IS_ERR(priv->phydev)) {
|
||||
priv->phydev = NULL;
|
||||
return -1;
|
||||
}
|
||||
priv->last_link = 0;
|
||||
phy_start_aneg(priv->phydev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -43,4 +43,4 @@
|
|||
|
||||
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_mdio_setup_device(struct net_device *dev);
|
||||
int cvm_oct_phy_setup_device(struct net_device *dev);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* Contact Cavium Networks for more information
|
||||
**********************************************************************/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <net/dst.h>
|
||||
|
@ -38,112 +37,6 @@
|
|||
#include "cvmx-helper.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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,32 +147,36 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
|
|||
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
|
||||
gmxx_rxx_int_reg.u64);
|
||||
}
|
||||
|
||||
link_info = cvmx_helper_link_autoconf(priv->port);
|
||||
priv->link_info = link_info.u64;
|
||||
if (priv->phydev == NULL) {
|
||||
link_info = cvmx_helper_link_autoconf(priv->port);
|
||||
priv->link_info = link_info.u64;
|
||||
}
|
||||
spin_unlock_irqrestore(&global_register_lock, flags);
|
||||
|
||||
/* Tell Linux */
|
||||
if (link_info.s.link_up) {
|
||||
|
||||
if (!netif_carrier_ok(dev))
|
||||
netif_carrier_on(dev);
|
||||
if (priv->queue != -1)
|
||||
DEBUGPRINT
|
||||
("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
|
||||
dev->name, link_info.s.speed,
|
||||
(link_info.s.full_duplex) ? "Full" : "Half",
|
||||
priv->port, priv->queue);
|
||||
else
|
||||
DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
|
||||
dev->name, link_info.s.speed,
|
||||
(link_info.s.full_duplex) ? "Full" : "Half",
|
||||
priv->port);
|
||||
} else {
|
||||
|
||||
if (netif_carrier_ok(dev))
|
||||
netif_carrier_off(dev);
|
||||
DEBUGPRINT("%s: Link down\n", dev->name);
|
||||
if (priv->phydev == NULL) {
|
||||
/* Tell core. */
|
||||
if (link_info.s.link_up) {
|
||||
if (!netif_carrier_ok(dev))
|
||||
netif_carrier_on(dev);
|
||||
if (priv->queue != -1)
|
||||
DEBUGPRINT("%s: %u Mbps %s duplex, "
|
||||
"port %2d, queue %2d\n",
|
||||
dev->name, link_info.s.speed,
|
||||
(link_info.s.full_duplex) ?
|
||||
"Full" : "Half",
|
||||
priv->port, priv->queue);
|
||||
else
|
||||
DEBUGPRINT("%s: %u Mbps %s duplex, "
|
||||
"port %2d, POW\n",
|
||||
dev->name, link_info.s.speed,
|
||||
(link_info.s.full_duplex) ?
|
||||
"Full" : "Half",
|
||||
priv->port);
|
||||
} else {
|
||||
if (netif_carrier_ok(dev))
|
||||
netif_carrier_off(dev);
|
||||
DEBUGPRINT("%s: Link down\n", dev->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ int cvm_oct_sgmii_init(struct net_device *dev)
|
|||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
cvm_oct_common_init(dev);
|
||||
dev->netdev_ops->ndo_stop(dev);
|
||||
if (!octeon_is_simulation())
|
||||
if (!octeon_is_simulation() && priv->phydev == NULL)
|
||||
priv->poll = cvm_oct_sgmii_poll;
|
||||
|
||||
/* FIXME: Need autoneg logic */
|
||||
|
|
|
@ -112,7 +112,7 @@ int cvm_oct_xaui_init(struct net_device *dev)
|
|||
struct octeon_ethernet *priv = netdev_priv(dev);
|
||||
cvm_oct_common_init(dev);
|
||||
dev->netdev_ops->ndo_stop(dev);
|
||||
if (!octeon_is_simulation())
|
||||
if (!octeon_is_simulation() && priv->phydev == NULL)
|
||||
priv->poll = cvm_oct_xaui_poll;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <net/dst.h>
|
||||
|
||||
|
@ -132,8 +132,6 @@ static struct timer_list cvm_oct_poll_timer;
|
|||
*/
|
||||
struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
|
||||
|
||||
extern struct semaphore mdio_sem;
|
||||
|
||||
/**
|
||||
* Periodic timer tick for slow management operations
|
||||
*
|
||||
|
@ -160,13 +158,8 @@ static void cvm_do_timer(unsigned long arg)
|
|||
goto out;
|
||||
|
||||
priv = netdev_priv(cvm_oct_device[port]);
|
||||
if (priv->poll) {
|
||||
/* skip polling if we don't get the lock */
|
||||
if (!down_trylock(&mdio_sem)) {
|
||||
priv->poll(cvm_oct_device[port]);
|
||||
up(&mdio_sem);
|
||||
}
|
||||
}
|
||||
if (priv->poll)
|
||||
priv->poll(cvm_oct_device[port]);
|
||||
|
||||
queues_per_port = cvmx_pko_get_num_queues(port);
|
||||
/* Drain any pending packets in the free list */
|
||||
|
@ -524,7 +517,7 @@ int cvm_oct_common_init(struct net_device *dev)
|
|||
dev->features |= NETIF_F_LLTX;
|
||||
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_change_mtu(dev, dev->mtu);
|
||||
|
||||
|
@ -540,7 +533,10 @@ int cvm_oct_common_init(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 = {
|
||||
|
@ -627,6 +623,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
extern void octeon_mdiobus_force_mod_depencency(void);
|
||||
|
||||
/**
|
||||
* Module/ driver initialization. Creates the linux network
|
||||
* devices.
|
||||
|
@ -640,6 +638,7 @@ static int __init cvm_oct_init_module(void)
|
|||
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
|
||||
int qos;
|
||||
|
||||
octeon_mdiobus_force_mod_depencency();
|
||||
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
|
||||
|
||||
if (OCTEON_IS_MODEL(OCTEON_CN52XX))
|
||||
|
|
|
@ -50,9 +50,9 @@ struct octeon_ethernet {
|
|||
/* List of outstanding tx buffers per queue */
|
||||
struct sk_buff_head tx_free_list[16];
|
||||
/* Device statistics */
|
||||
struct net_device_stats stats
|
||||
; /* Generic MII info structure */
|
||||
struct mii_if_info mii_info;
|
||||
struct net_device_stats stats;
|
||||
struct phy_device *phydev;
|
||||
unsigned int last_link;
|
||||
/* Last negotiated link state */
|
||||
uint64_t link_info;
|
||||
/* Called periodically to check link status */
|
||||
|
|
Loading…
Reference in a new issue