summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_rgmx.c167
1 files changed, 86 insertions, 81 deletions
diff --git a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
index b18c83a..ada0946 100644
--- a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
+++ b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
@@ -1015,10 +1015,9 @@ static u_int octeon_rgmx_pko_xmit_packet (struct rgmx_softc_dev *sc, void *out_b
* 3 words or less are left. We write our 2nd word now and then put in a chain link
* to new PKO cmd buf.
*/
- void *pko_cmd_buf = octeon_fpa_alloc(OCTEON_FPA_TX_CMDBUF_POOL);
- uint64_t phys_cmd_buf;
+ uint64_t phys_cmd_buf = octeon_fpa_alloc_phys(OCTEON_FPA_TX_CMDBUF_POOL);
- if (!pko_cmd_buf) {
+ if (!phys_cmd_buf) {
/*
* FPA pool for xmit-buffer-commands is empty.
*/
@@ -1026,7 +1025,6 @@ static u_int octeon_rgmx_pko_xmit_packet (struct rgmx_softc_dev *sc, void *out_b
octeon_spinlock_unlock(&(sc->outq_ptr[queue].lock));
return (0);
}
- phys_cmd_buf = OCTEON_PTR2PHYS(pko_cmd_buf);
xmit_cmd_ptr[1] = pko_pkt_word.word64;
xmit_cmd_ptr[2] = phys_cmd_buf;
@@ -1678,8 +1676,13 @@ static void octeon_rgmx_medstat (struct ifnet *ifp, struct ifmediareq *ifm)
break;
}
- /* Always full duplex. */
- ifm->ifm_active |= IFM_FDX;
+ /*
+ * Check duplex.
+ */
+ if (link_status.bits.duplex == 1)
+ ifm->ifm_active |= IFM_FDX;
+ else
+ ifm->ifm_active |= IFM_HDX;
RGMX_UNLOCK(sc);
}
@@ -1815,7 +1818,6 @@ static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data)
static void octeon_rgmx_init (void *xsc)
{
struct rgmx_softc_dev *sc = xsc;
- octeon_rgmx_rxx_rx_inbnd_t link_status;
/* Enable interrupts. */
/* For RGMX they are already enabled earlier */
@@ -1836,19 +1838,7 @@ static void octeon_rgmx_init (void *xsc)
/* Hopefully PKO is running and will pick up packets via the timer or receive loop */
/* Set link status. */
- octeon_rgmx_config_speed(sc->port, 0);
-
- RGMX_LOCK(sc);
- /*
- * Parse link status.
- */
- link_status.word64 = sc->link_status;
-
- if (link_status.bits.status)
- if_link_state_change(sc->ifp, LINK_STATE_UP);
- else
- if_link_state_change(sc->ifp, LINK_STATE_DOWN);
- RGMX_UNLOCK(sc);
+ octeon_rgmx_config_speed(sc->port, 1);
}
@@ -1863,7 +1853,6 @@ static void octeon_rgmx_config_speed (u_int port, u_int report_link)
uint64_t val64_tx_clk, val64_tx_slot, val64_tx_burst;
u_int last_enabled;
-
sc = get_rgmx_softc(port);
if (!sc) {
printf(" config_speed didn't find sc int:%u port:%u", iface, port);
@@ -1875,79 +1864,96 @@ static void octeon_rgmx_config_speed (u_int port, u_int report_link)
*/
link_status.word64 = oct_read64(OCTEON_RGMX_RXX_RX_INBND(index, iface));
+ RGMX_LOCK(sc);
+
/*
* Compre to prev known state. If same then nothing to do.
*/
if (link_status.word64 == sc->link_status) {
+ RGMX_UNLOCK(sc);
return;
}
-
- RGMX_LOCK(sc);
-
old_link_status.word64 = sc->link_status;
- sc->link_status = link_status.word64;
-
- last_enabled = octeon_rgmx_stop_port(port);
-
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
-
- /*
- * Duplex
- */
- gmx_cfg.bits.duplex = 1;
-
- switch (link_status.bits.speed) {
- case 0: /* 10Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
- case 1: /* 100Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
-
- case 2: /* 1Gbps */
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
-
- case 3: /* ?? */
- default:
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
- }
+ /*
+ * Compare to previous state modulo link status. If only link
+ * status is different, we don't need to change media.
+ */
+ if (old_link_status.bits.duplex != link_status.bits.duplex ||
+ old_link_status.bits.speed != link_status.bits.speed) {
+ last_enabled = octeon_rgmx_stop_port(port);
+
+ gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
- oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk);
- oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot);
- oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst);
+ /*
+ * Duplex
+ * XXX Set based on link_status.bits.duplex?
+ */
+ gmx_cfg.bits.duplex = 1;
+
+ switch (link_status.bits.speed) {
+ case 0: /* 10Mbps */
+ gmx_cfg.bits.speed = 0;
+ gmx_cfg.bits.slottime = 0;
+ val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0;
+ break;
+
+ case 1: /* 100Mbps */
+ gmx_cfg.bits.speed = 0;
+ gmx_cfg.bits.slottime = 0;
+ val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0;
+ break;
+
+ case 2: /* 1Gbps */
+ gmx_cfg.bits.speed = 1;
+ gmx_cfg.bits.slottime = 1;
+ val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
+ break;
+
+ case 3: /* ?? */
+ default:
+ gmx_cfg.bits.speed = 1;
+ gmx_cfg.bits.slottime = 1;
+ val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
+ break;
+ }
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
+ oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk);
+ oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot);
+ oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst);
+
+ oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
+
+ if (last_enabled) octeon_rgmx_start_port(port);
+ }
- if (last_enabled) octeon_rgmx_start_port(port);
+ /*
+ * Now check and possibly change link status.
+ */
+ if (link_status.bits.status != old_link_status.bits.status) {
+ if (report_link) {
+ if (link_status.bits.status) {
+ if_link_state_change(sc->ifp, LINK_STATE_UP);
+ } else {
+ if_link_state_change(sc->ifp, LINK_STATE_DOWN);
+ }
+ }
+ }
- if (link_status.bits.status != old_link_status.bits.status) {
+ if (report_link) {
+ sc->link_status = link_status.word64;
+ } else {
+ /*
+ * We can't update link status proper since we can't
+ * change it in the interface, so keep the old link
+ * status intact but note the current speed and duplex
+ * settings.
+ */
+ link_status.bits.status = old_link_status.bits.status;
+ sc->link_status = link_status.word64;
+ }
-//#define DEBUG_LINESTATUS
- if (link_status.bits.status) {
-#ifdef DEBUG_LINESTATUS
- printf(" %u/%u: Interface is now alive\n", iface, port);
-#endif
- if (report_link) if_link_state_change(sc->ifp, LINK_STATE_UP);
- } else {
-#ifdef DEBUG_LINESTATUS
- printf(" %u/%u: Interface went down\n", iface, port);
-#endif
- if (report_link) if_link_state_change(sc->ifp, LINK_STATE_DOWN);
- }
- }
RGMX_UNLOCK(sc);
-
}
@@ -2167,7 +2173,6 @@ static void octeon_config_rgmii_port (u_int port)
gmx_cfg.bits.en = 1;
oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
-
octeon_rgmx_config_speed(port, 0);
oct_write64(OCTEON_RGMX_TXX_THRESH(index, iface), 32);
OpenPOWER on IntegriCloud