mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-25 10:15:11 +02:00
ar71xx: ag71xx: implement get_port_{link,stats} callbacks
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@29626 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
c400bf085d
commit
b042bd4e4d
@ -229,6 +229,49 @@
|
|||||||
|
|
||||||
#define sw_to_ar7240(_dev) container_of(_dev, struct ar7240sw, swdev)
|
#define sw_to_ar7240(_dev) container_of(_dev, struct ar7240sw, swdev)
|
||||||
|
|
||||||
|
struct ar7240sw_port_stat {
|
||||||
|
unsigned long rx_broadcast;
|
||||||
|
unsigned long rx_pause;
|
||||||
|
unsigned long rx_multicast;
|
||||||
|
unsigned long rx_fcs_error;
|
||||||
|
unsigned long rx_align_error;
|
||||||
|
unsigned long rx_runt;
|
||||||
|
unsigned long rx_fragments;
|
||||||
|
unsigned long rx_64byte;
|
||||||
|
unsigned long rx_128byte;
|
||||||
|
unsigned long rx_256byte;
|
||||||
|
unsigned long rx_512byte;
|
||||||
|
unsigned long rx_1024byte;
|
||||||
|
unsigned long rx_1518byte;
|
||||||
|
unsigned long rx_maxbyte;
|
||||||
|
unsigned long rx_toolong;
|
||||||
|
unsigned long rx_good_byte;
|
||||||
|
unsigned long rx_bad_byte;
|
||||||
|
unsigned long rx_overflow;
|
||||||
|
unsigned long filtered;
|
||||||
|
|
||||||
|
unsigned long tx_broadcast;
|
||||||
|
unsigned long tx_pause;
|
||||||
|
unsigned long tx_multicast;
|
||||||
|
unsigned long tx_underrun;
|
||||||
|
unsigned long tx_64byte;
|
||||||
|
unsigned long tx_128byte;
|
||||||
|
unsigned long tx_256byte;
|
||||||
|
unsigned long tx_512byte;
|
||||||
|
unsigned long tx_1024byte;
|
||||||
|
unsigned long tx_1518byte;
|
||||||
|
unsigned long tx_maxbyte;
|
||||||
|
unsigned long tx_oversize;
|
||||||
|
unsigned long tx_byte;
|
||||||
|
unsigned long tx_collision;
|
||||||
|
unsigned long tx_abortcol;
|
||||||
|
unsigned long tx_multicol;
|
||||||
|
unsigned long tx_singlecol;
|
||||||
|
unsigned long tx_excdefer;
|
||||||
|
unsigned long tx_defer;
|
||||||
|
unsigned long tx_xlatecol;
|
||||||
|
};
|
||||||
|
|
||||||
struct ar7240sw {
|
struct ar7240sw {
|
||||||
struct mii_bus *mii_bus;
|
struct mii_bus *mii_bus;
|
||||||
struct ag71xx_switch_platform_data *swdata;
|
struct ag71xx_switch_platform_data *swdata;
|
||||||
@ -241,6 +284,9 @@ struct ar7240sw {
|
|||||||
u8 vlan_tagged;
|
u8 vlan_tagged;
|
||||||
u16 pvid[AR7240_NUM_PORTS];
|
u16 pvid[AR7240_NUM_PORTS];
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
|
||||||
|
rwlock_t stats_lock;
|
||||||
|
struct ar7240sw_port_stat port_stats[AR7240_NUM_PORTS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ar7240sw_hw_stat {
|
struct ar7240sw_hw_stat {
|
||||||
@ -451,6 +497,47 @@ int ar7240sw_phy_write(struct mii_bus *mii, unsigned phy_addr,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ar7240sw_capture_stats(struct ar7240sw *as)
|
||||||
|
{
|
||||||
|
struct mii_bus *mii = as->mii_bus;
|
||||||
|
int port;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
write_lock(&as->stats_lock);
|
||||||
|
|
||||||
|
/* Capture the hardware statistics for all ports */
|
||||||
|
ar7240sw_reg_write(mii, AR7240_REG_MIB_FUNCTION0,
|
||||||
|
(AR7240_MIB_FUNC_CAPTURE << AR7240_MIB_FUNC_S));
|
||||||
|
|
||||||
|
/* Wait for the capturing to complete. */
|
||||||
|
ret = ar7240sw_reg_wait(mii, AR7240_REG_MIB_FUNCTION0,
|
||||||
|
AR7240_MIB_BUSY, 0, 10);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
for (port = 0; port < AR7240_NUM_PORTS; port++) {
|
||||||
|
unsigned int base;
|
||||||
|
struct ar7240sw_port_stat *stats;
|
||||||
|
|
||||||
|
base = AR7240_REG_STATS_BASE(port);
|
||||||
|
stats = &as->port_stats[port];
|
||||||
|
|
||||||
|
#define READ_STAT(_r) ar7240sw_reg_read(mii, base + AR7240_STATS_ ## _r)
|
||||||
|
|
||||||
|
stats->rx_good_byte += READ_STAT(RXGOODBYTE);
|
||||||
|
stats->tx_byte += READ_STAT(TXBYTE);
|
||||||
|
|
||||||
|
#undef READ_STAT
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
write_unlock(&as->stats_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void ar7240sw_disable_port(struct ar7240sw *as, unsigned port)
|
static void ar7240sw_disable_port(struct ar7240sw *as, unsigned port)
|
||||||
{
|
{
|
||||||
ar7240sw_reg_write(as->mii_bus, AR7240_REG_PORT_CTRL(port),
|
ar7240sw_reg_write(as->mii_bus, AR7240_REG_PORT_CTRL(port),
|
||||||
@ -843,6 +930,58 @@ ar7240_reset_switch(struct switch_dev *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ar7240_get_port_link(struct switch_dev *dev, int port,
|
||||||
|
struct switch_port_link *link)
|
||||||
|
{
|
||||||
|
struct ar7240sw *as = sw_to_ar7240(dev);
|
||||||
|
struct mii_bus *mii = as->mii_bus;
|
||||||
|
u32 status;
|
||||||
|
|
||||||
|
if (port > AR7240_NUM_PORTS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port));
|
||||||
|
|
||||||
|
link->link = !!(status & AR7240_PORT_STATUS_LINK_UP);
|
||||||
|
link->aneg = !!(status & AR7240_PORT_STATUS_LINK_AUTO);
|
||||||
|
link->duplex = !!(status & AR7240_PORT_STATUS_DUPLEX);
|
||||||
|
link->tx_flow = !!(status & AR7240_PORT_STATUS_TXFLOW);
|
||||||
|
link->rx_flow = !!(status & AR7240_PORT_STATUS_RXFLOW);
|
||||||
|
switch (status & AR7240_PORT_STATUS_SPEED_M) {
|
||||||
|
case AR7240_PORT_STATUS_SPEED_10:
|
||||||
|
link->speed = SWITCH_PORT_SPEED_10;
|
||||||
|
break;
|
||||||
|
case AR7240_PORT_STATUS_SPEED_100:
|
||||||
|
link->speed = SWITCH_PORT_SPEED_100;
|
||||||
|
break;
|
||||||
|
case AR7240_PORT_STATUS_SPEED_1000:
|
||||||
|
link->speed = SWITCH_PORT_SPEED_1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ar7240_get_port_stats(struct switch_dev *dev, int port,
|
||||||
|
struct switch_port_stats *stats)
|
||||||
|
{
|
||||||
|
struct ar7240sw *as = sw_to_ar7240(dev);
|
||||||
|
|
||||||
|
if (port > AR7240_NUM_PORTS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ar7240sw_capture_stats(as);
|
||||||
|
|
||||||
|
read_lock(&as->stats_lock);
|
||||||
|
stats->rx_bytes = as->port_stats[port].rx_good_byte;
|
||||||
|
stats->tx_bytes = as->port_stats[port].tx_byte;
|
||||||
|
read_unlock(&as->stats_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct switch_attr ar7240_globals[] = {
|
static struct switch_attr ar7240_globals[] = {
|
||||||
{
|
{
|
||||||
.type = SWITCH_TYPE_INT,
|
.type = SWITCH_TYPE_INT,
|
||||||
@ -895,6 +1034,8 @@ static const struct switch_dev_ops ar7240_ops = {
|
|||||||
.set_vlan_ports = ar7240_set_ports,
|
.set_vlan_ports = ar7240_set_ports,
|
||||||
.apply_config = ar7240_hw_apply,
|
.apply_config = ar7240_hw_apply,
|
||||||
.reset_switch = ar7240_reset_switch,
|
.reset_switch = ar7240_reset_switch,
|
||||||
|
.get_port_link = ar7240_get_port_link,
|
||||||
|
.get_port_stats = ar7240_get_port_stats,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ar7240sw *ar7240_probe(struct ag71xx *ag)
|
static struct ar7240sw *ar7240_probe(struct ag71xx *ag)
|
||||||
@ -1034,6 +1175,7 @@ int __devinit ag71xx_ar7240_init(struct ag71xx *ag)
|
|||||||
ag->phy_priv = as;
|
ag->phy_priv = as;
|
||||||
ar7240sw_reset(as);
|
ar7240sw_reset(as);
|
||||||
|
|
||||||
|
rwlock_init(&as->stats_lock);
|
||||||
INIT_DELAYED_WORK(&ag->link_work, link_function);
|
INIT_DELAYED_WORK(&ag->link_work, link_function);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user