static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val) { u32 _val; int ret; *val = 0; ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_READ_CAPTURED | GLOBAL_STATS_OP_HIST_RX_TX | stat); if (ret < 0) return; ret = mv88e6xxx_stats_wait(ds); if (ret < 0) return; ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_32); if (ret < 0) return; _val = ret << 16; ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_01); if (ret < 0) return; *val = _val | ret; }
static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val) { u32 _val; int ret; *val = 0; ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat); if (ret < 0) return; ret = mv88e6xxx_stats_wait(ds); if (ret < 0) return; ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e); if (ret < 0) return; _val = ret << 16; ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f); if (ret < 0) return; *val = _val | ret; }
static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int nr_stats, struct mv88e6xxx_hw_stat *stats, int port, uint64_t *data) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; int i; mutex_lock(&ps->stats_mutex); ret = mv88e6xxx_stats_snapshot(ds, port); if (ret < 0) { mutex_unlock(&ps->stats_mutex); return; } /* Read each of the counters. */ for (i = 0; i < nr_stats; i++) { struct mv88e6xxx_hw_stat *s = stats + i; u32 low; u32 high = 0; if (s->reg >= 0x100) { int ret; ret = mv88e6xxx_reg_read(ds, REG_PORT(port), s->reg - 0x100); if (ret < 0) goto error; low = ret; if (s->sizeof_stat == 4) { ret = mv88e6xxx_reg_read(ds, REG_PORT(port), s->reg - 0x100 + 1); if (ret < 0) goto error; high = ret; } data[i] = (((u64)high) << 16) | low; continue; } mv88e6xxx_stats_read(ds, s->reg, &low); if (s->sizeof_stat == 8) mv88e6xxx_stats_read(ds, s->reg + 1, &high); data[i] = (((u64)high) << 32) | low; } error: mutex_unlock(&ps->stats_mutex); }
void mv88e6xxx_poll_link(struct dsa_switch *ds) { int i; for (i = 0; i < DSA_MAX_PORTS; i++) { struct net_device *dev; int uninitialized_var(port_status); int link; int speed; int duplex; int fc; dev = ds->ports[i]; if (dev == NULL) continue; link = 0; if (dev->flags & IFF_UP) { port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00); if (port_status < 0) continue; link = !!(port_status & 0x0800); } if (!link) { if (netif_carrier_ok(dev)) { netdev_info(dev, "link down\n"); netif_carrier_off(dev); } continue; } switch (port_status & 0x0300) { case 0x0000: speed = 10; break; case 0x0100: speed = 100; break; case 0x0200: speed = 1000; break; default: speed = -1; break; } duplex = (port_status & 0x0400) ? 1 : 0; fc = (port_status & 0x8000) ? 1 : 0; if (!netif_carrier_ok(dev)) { netdev_info(dev, "link up, %d Mb/s, %s duplex, flow control %sabled\n", speed, duplex ? "full" : "half", fc ? "en" : "dis"); netif_carrier_on(dev); } } }
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int reg; mutex_lock(&ps->phy_mutex); reg = _mv88e6xxx_phy_read_indirect(ds, port, 16); if (reg < 0) goto out; e->eee_enabled = !!(reg & 0x0200); e->tx_lpi_enabled = !!(reg & 0x0100); reg = mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS); if (reg < 0) goto out; e->eee_active = !!(reg & PORT_STATUS_EEE); reg = 0; out: mutex_unlock(&ps->phy_mutex); return reg; }
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum) { int ret; ret = mv88e6xxx_ppu_access_get(ds); if (ret >= 0) { ret = mv88e6xxx_reg_read(ds, addr, regnum); mv88e6xxx_ppu_access_put(ds); } return ret; }
void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, struct ethtool_regs *regs, void *_p) { u16 *p = _p; int i; regs->version = 0; memset(p, 0xff, 32 * sizeof(u16)); for (i = 0; i < 32; i++) { int ret; ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i); if (ret >= 0) p[i] = ret; } }
static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->eeprom_mutex); ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, GLOBAL2_EEPROM_OP_READ | (addr & GLOBAL2_EEPROM_OP_ADDR_MASK)); if (ret < 0) goto error; ret = mv88e6xxx_eeprom_busy_wait(ds); if (ret < 0) goto error; ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA); error: mutex_unlock(&ps->eeprom_mutex); return ret; }
int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) { if (addr >= 0) return mv88e6xxx_reg_read(ds, addr, regnum); return 0xffff; }