/*------------------------------------------------------------------------------------------*\ * Copyright (C) 2008,2009 AVM GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) #include #endif /*--- #if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) ---*/ #if defined(CONFIG_AVM_LED) #include #endif /*--- #if defined(CONFIG_AVM_LED) ---*/ #include #if defined(CONFIG_AVM_POWER) #include #endif /*--- #if defined(CONFIG_AVM_POWER) ---*/ #if !defined(CONFIG_NETCHIP_ADM69961) #define CONFIG_NETCHIP_ADM69961 #endif #include #include #include #include #include "cpmac_if.h" #include "cpmac_const.h" #include "cpmac_debug.h" #include "cpmac_eth.h" #include "cpphy_const.h" #include "cpphy_types.h" #include "cpphy_mdio.h" #include "adm6996.h" #include "tantos.h" #include "cpphy_adm6996.h" #include "cpphy_ar8216.h" #include "cpphy_mgmt.h" #include #include #include "cpphy_if_g.h" static cpphy_mdio_t *power_mdio; /* FIXME Is there a cleaner solution? */ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_power_init(cpphy_mdio_t *mdio) { unsigned int port; power_mdio = mdio; /* Prepare a default timeout */ mdio->adm_power.timeout = CPMAC_TICK_LENGTH; if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ)) { /* The switch is not accessible (e.g. ProfiVoIP CPU 2) */ return; } /* Initialize the power management for the PHYs */ mdio->adm_power.setup.time_on = CPMAC_ADM_PHY_PUP_TO; mdio->adm_power.setup.time_off = CPMAC_ADM_PHY_PDN_TO; if(mdio->switch_use_EMV) { for(port = 0; port < mdio->switch_ports; port++) { if(port < 4) { mdio->adm_power.setup.mode[port] = ADM_PHY_POWER_ON; } else { mdio->adm_power.setup.mode[port] = ADM_PHY_POWER_OFF; } mdio->adm_power.port_mode[port] = CPPHY_POWER_MODE_LINK_LOST; } mdio->adm_power.linked_ports = 0xf; cpphy_mgmt_power(mdio); } else { for(port = 0; port < mdio->switch_ports; port++) { mdio->adm_power.setup.mode[port] = ADM_PHY_POWER_ON; mdio->adm_power.port_on[port] = 1; } } adm_switch_port_power_config(mdio, &mdio->adm_power.setup, 1); /* There is no handle from the power management, therefor use it like this. */ # if defined(CONFIG_AVM_POWER) mdio->power_handle = PowerManagmentRegister("ethernet", adm_power_config); # endif /*--- #if defined(CONFIG_AVM_POWER) ---*/ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int cpphy_mgmt_check_link_orig(cpphy_mdio_t *mdio) { unsigned int device, port, old_linked = mdio->linked; # if defined(CONFIG_AVM_POWERMETER) unsigned int portset = 0, powervalue = 100; # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ switch(mdio->cpmac_switch) { case AVM_CPMAC_SWITCH_ADM6996: case AVM_CPMAC_SWITCH_ADM6996L: case AVM_CPMAC_SWITCH_TANTOS: case AVM_CPMAC_SWITCH_ANY: /* There is no checking of the link without read access */ adm_check_link(mdio); break; case AVM_CPMAC_SWITCH_AR8216: ar_check_link_orig(mdio); break; case AVM_CPMAC_SWITCH_NONE: default: return mdio->linked; } if(old_linked != mdio->linked) { cpphy_mgmt_event_dataupdate(mdio); /* Linked ports could have changed */ } for(port = 0; port < TANTOS_MAX_PORTS ; port++) { unsigned int port_linked = (mdio->linked & (1 << (port + mdio->led_port_offset))) ? 1 : 0; if(port < CPMAC_MAX_LED_HANDLES) { if(port_linked != mdio->cpmac_priv->led[port].on) { mdio->cpmac_priv->led[port].on = port_linked; DEB_INFOTRC("Set LAN LED %u to '%s'\n", port, port_linked ? "on" : "off"); # if defined(CONFIG_AVM_LED) if(mdio->cpmac_priv->led[port].handle != 0) { avm_led_action_with_handle(mdio->cpmac_priv->led[port].handle, port_linked ? avm_led_on : avm_led_off); } # endif /*--- #if defined(CONFIG_AVM_LED) ---*/ # if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) if(led_event_action) { (*led_event_action)(LEDCTL_VERSION, event_lan1_active + (port << 1) + (port_linked ? 0 : 1), 1); } # endif /*--- #if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) ---*/ } } # if defined(CONFIG_AVM_POWERMETER) if((port < mdio->switch_ports) && (mdio->adm_power.port_on)) { powervalue += 10; /* Port is powered */ if(port_linked) { /* Port is linked */ portset |= (1 << port); powervalue += mdio->event_data.port[port].speed100 ? 57 : 90; /* 100 MBit/s? */ } } # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ } cpphy_mgmt_power(mdio); # if defined(CONFIG_AVM_POWERMETER) PowerManagmentRessourceInfo(powerdevice_ethernet, PM_ETHERNET_PARAM(portset, powervalue)); # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ for(device = 0; device < mdio->cpmac_priv->devices; device++) { unsigned int carrier = netif_carrier_ok(mdio->cpmac_priv->devs[device]); /*--- DEB_TEST("[cpphy_mgmt_check_link] '%s' carrier %s linked = %#x %#x = ports\n", ---*/ /*--- mdio->cpmac_priv->devs[device]->name, ---*/ /*--- carrier ? "on " : "off", ---*/ /*--- mdio->linked, mdio->cpmac_priv->dev_ports[device]); ---*/ if(mdio->linked & mdio->cpmac_priv->dev_ports[device]) { if(!carrier) { netif_carrier_on(mdio->cpmac_priv->devs[device]); DEB_INFOTRC("Switching carrier on for device %s\n", mdio->cpmac_priv->devs[device]->name); } } else if(carrier) { netif_carrier_off(mdio->cpmac_priv->devs[device]); DEB_INFOTRC("Switching carrier off for device %s\n", mdio->cpmac_priv->devs[device]->name); } } return mdio->linked; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int cpphy_mgmt_check_link_emv(cpphy_mdio_t *mdio) { unsigned int device, port; # if defined(CONFIG_AVM_POWERMETER) unsigned int portset = 0, powervalue = 100; # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ switch(mdio->cpmac_switch) { case AVM_CPMAC_SWITCH_ADM6996: case AVM_CPMAC_SWITCH_ADM6996L: case AVM_CPMAC_SWITCH_TANTOS: case AVM_CPMAC_SWITCH_ANY: /* There is no checking of the link without read access */ adm_check_link(mdio); break; case AVM_CPMAC_SWITCH_AR8216: ar_check_link_emv(mdio); break; case AVM_CPMAC_SWITCH_NONE: default: return mdio->linked; } if(mdio->event_update_needed) { cpphy_mgmt_event_dataupdate(mdio); /* Linked ports could have changed */ } for(port = 0; port < TANTOS_MAX_PORTS ; port++) { unsigned int port_linked = (mdio->linked & (1 << port)) ? 1 : 0; if(port < CPMAC_MAX_LED_HANDLES) { if(port_linked != mdio->cpmac_priv->led[port].on) { mdio->cpmac_priv->led[port].on = port_linked; DEB_INFOTRC("Set LAN LED %u to '%s'\n", port, port_linked ? "on" : "off"); # if defined(CONFIG_AVM_LED) if(mdio->cpmac_priv->led[port].handle != 0) { avm_led_action_with_handle(mdio->cpmac_priv->led[port].handle, port_linked ? avm_led_on : avm_led_off); } # endif /*--- #if defined(CONFIG_AVM_LED) ---*/ # if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) if(led_event_action) { (*led_event_action)(LEDCTL_VERSION, event_lan1_active + (port << 1) + (port_linked ? 0 : 1), 1); } # endif /*--- #if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) ---*/ } } # if defined(CONFIG_AVM_POWERMETER) if((port < mdio->switch_ports) && (mdio->adm_power.current_mode == CPPHY_POWER_MODE_ON)) { powervalue += 10; /* Port is powered */ if(port_linked) { /* Port is linked */ portset |= (1 << port); powervalue += mdio->event_data.port[port].speed100 ? 57 : 90; /* 100 MBit/s? */ } } # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ } cpphy_mgmt_power(mdio); # if defined(CONFIG_AVM_POWERMETER) PowerManagmentRessourceInfo(powerdevice_ethernet, PM_ETHERNET_PARAM(portset, powervalue)); # endif /*--- #if defined(CONFIG_AVM_POWERMETER) ---*/ for(device = 0; device < mdio->cpmac_priv->devices; device++) { unsigned int carrier = netif_carrier_ok(mdio->cpmac_priv->devs[device]); /*--- DEB_TEST("[cpphy_mgmt_check_link] '%s' carrier %s linked = %#x %#x = ports\n", ---*/ /*--- mdio->cpmac_priv->devs[device]->name, ---*/ /*--- carrier ? "on " : "off", ---*/ /*--- mdio->linked, mdio->cpmac_priv->dev_ports[device]); ---*/ if(mdio->linked & mdio->cpmac_priv->dev_ports[device]) { if(!carrier) { netif_carrier_on(mdio->cpmac_priv->devs[device]); DEB_INFOTRC("Switching carrier on for device %s\n", mdio->cpmac_priv->devs[device]->name); } } else if(carrier) { netif_carrier_off(mdio->cpmac_priv->devs[device]); DEB_INFOTRC("Switching carrier off for device %s\n", mdio->cpmac_priv->devs[device]->name); } } return mdio->linked; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int cpphy_mgmt_check_link(cpphy_mdio_t *mdio) { if(mdio->switch_use_EMV) { return cpphy_mgmt_check_link_emv(mdio); } else { return cpphy_mgmt_check_link_orig(mdio); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_event_dataupdate(cpphy_mdio_t *mdio) { unsigned int port, changes = 0; /* Update LAN-LED-state */ /* TODO Does this exist twice now? (Another time in check_link) */ /* Switch LED control happens in cpphy_adm6996.c */ mdio->event_update_needed = 0; if(!mdio->cpmac_switch) { # if defined(CONFIG_AVM_LED) if(mdio->cpmac_priv->led[mdio->cpmac_priv->inst].handle != 0) { avm_led_action_with_handle(mdio->cpmac_priv->led[mdio->cpmac_priv->inst].handle, (mdio->state == CPPHY_MDIO_ST_LINKED) ? avm_led_on : avm_led_off); } # endif /*--- #if defined(CONFIG_AVM_LED) ---*/ # if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) if(led_event_action) { (*led_event_action)(LEDCTL_VERSION, event_lan1_active + (mdio->cpmac_priv->inst << 1) + (mdio->state == CPPHY_MDIO_ST_LINKED) ? 0 : 1, 1); } # endif /*--- #if defined(CONFIG_AVM_LED_EVENTS) || defined(CONFIG_AVM_LED_EVENTS_MODULE) ---*/ } switch(mdio->cpmac_switch) { case AVM_CPMAC_SWITCH_ADM6996: case AVM_CPMAC_SWITCH_ADM6996L: break; /* At the moment done directly in adm_check_link */ /* The data in the adm_serial_register got updated by a previous call to *\ \* ADM_GET_SERIAL_REG(REG_ADM_LC_STATUS0) */ break; case AVM_CPMAC_SWITCH_TANTOS: for(port = 0; port < 5; port++) { changes |= mdio->event_data.port[port].link != tantos_ports->port[port].PS.link; } if(changes) { for(port = 0; port < 5; port++) { mdio->event_data.port[port].link = tantos_ports->port[port].PS.link; mdio->event_data.port[port].speed100 = tantos_ports->port[port].PS.speed; mdio->event_data.port[port].fullduplex = tantos_ports->port[port].PS.duplex; } } break; case AVM_CPMAC_SWITCH_AR8216: if(mdio->switch_use_EMV) { /* Everything is already up to date */ changes = 1; } else { for(port = 0; port < 4; port++) { unsigned int link, status; status = cpphy_mdio_user_access_read(mdio, AR8216_MII_PHY_STATUS, port); link = (status & ATHR_PHY_STATUS_LINK) ? 1 : 0; changes |= (link != mdio->event_data.port[port].link); mdio->event_data.port[port].link = link; mdio->event_data.port[port].speed100 = (((status & ATHR_PHY_STATUS_SPEED_MASK) >> ATHR_PHY_STATUS_SPEED_SHIFT) == 1) ? 1 : 0; mdio->event_data.port[port].fullduplex = (status & ATHR_PHY_STATUS_DUPLEX) ? 1 : 0; } } break; case AVM_CPMAC_SWITCH_NONE: if(mdio->event_data.port[mdio->inst].link != (mdio->state == CPPHY_MDIO_ST_LINKED)) { /* Nothing to do for low phy when switch is connected to high cpmac */ /* -> dont register low cpphy driver at cpmac */ changes = 1; mdio->event_data.port[mdio->inst].link = (mdio->state == CPPHY_MDIO_ST_LINKED); mdio->event_data.port[mdio->inst].speed100 = !mdio->slow_speed; mdio->event_data.port[mdio->inst].fullduplex = !mdio->half_duplex; } } if(changes) { switch(mdio->cpmac_switch) { case AVM_CPMAC_SWITCH_ADM6996: case AVM_CPMAC_SWITCH_ADM6996L: case AVM_CPMAC_SWITCH_TANTOS: case AVM_CPMAC_SWITCH_AR8216: DEB_TRC("[cpphy_mgmt_event_dataupdate] Port stati: 0 %s%s%s 1 %s%s%s 2 %s%s%s 3 %s%s%s (linked = %#x)\n", mdio->event_data.port[0].link ? "up" : "down", mdio->event_data.port[0].link ? (mdio->event_data.port[0].speed100 ? " 100" : " 10") : "", mdio->event_data.port[0].link ? (mdio->event_data.port[0].fullduplex ? " FD" : " HD") : "", mdio->event_data.port[1].link ? "up" : "down", mdio->event_data.port[1].link ? (mdio->event_data.port[1].speed100 ? " 100" : " 10") : "", mdio->event_data.port[1].link ? (mdio->event_data.port[1].fullduplex ? " FD" : " HD") : "", mdio->event_data.port[2].link ? "up" : "down", mdio->event_data.port[2].link ? (mdio->event_data.port[2].speed100 ? " 100" : " 10") : "", mdio->event_data.port[2].link ? (mdio->event_data.port[2].fullduplex ? " FD" : " HD") : "", mdio->event_data.port[3].link ? "up" : "down", mdio->event_data.port[3].link ? (mdio->event_data.port[3].speed100 ? " 100" : " 10") : "", mdio->event_data.port[3].link ? (mdio->event_data.port[3].fullduplex ? " FD" : " HD") : "", mdio->linked); break; case AVM_CPMAC_SWITCH_NONE: default: DEB_TRC("[cpphy_mgmt_event_dataupdate] Phy %u status: %s%s%s\n", mdio->inst, mdio->event_data.port[mdio->inst].link ? "up" : "down", mdio->event_data.port[mdio->inst].link ? (mdio->event_data.port[mdio->inst].speed100 ? " 100" : " 10") : "", mdio->event_data.port[mdio->inst].link ? (mdio->event_data.port[mdio->inst].fullduplex ? " FD" : " HD") : ""); break; } cpmac_main_event_update(); } } /*------------------------------------------------------------------------------------------*\ * Switch port power, assume link status is uptodate \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_power_orig(cpphy_mdio_t *mdio) { unsigned int port, from = 0, to = mdio->switch_ports - 1; unsigned int portset = 0; /* There is no power saving without write access */ if(!(mdio->Mode & CPPHY_SWITCH_MODE_WRITE)) { mdio->adm_power.timeout = CPMAC_TICK_LENGTH; return; } /* Switch to different state than last run and use correct timeout*/ mdio->adm_power.current_on = !mdio->adm_power.current_on; /* If global powerdown is needed, disable roundrobin for this run */ if(mdio->global_power) { if(mdio->global_power == CPPHY_POWER_GLOBAL_ON) { DEB_INFOTRC("Global powerup active\n"); mdio->adm_power.current_on = 1; } else if(mdio->global_power == CPPHY_POWER_GLOBAL_OFF) { DEB_INFOTRC("Global powerdown active\n"); mdio->adm_power.current_on = 0; } else { DEB_ERR("[cpphy_mgmt_power] Internal error: Global power with unknown value %u\n", mdio->global_power); } } else if(mdio->adm_power.roundrobin) { /* If we are going to activate a port, it should be the next one */ if(mdio->adm_power.current_on) { mdio->adm_power.current_port = (mdio->adm_power.current_port == 4) ? 0 : (mdio->adm_power.current_port + 1); } from = to = mdio->adm_power.current_port; } mdio->adm_power.timeout = (mdio->global_power == CPPHY_POWER_GLOBAL_OFF) ? CPMAC_TICK_LENGTH : (mdio->adm_power.current_on) ? mdio->adm_power.setup.time_on : mdio->adm_power.setup.time_off; for(port = from; port <= to; port++) { if( !mdio->adm_power.port_on[port] /* If the port is disabled, */ || !mdio->event_data.port[port].link /* without link */ || mdio->global_power) { /* or a global power requested */ unsigned int turn_on = 0; if( ((mdio->adm_power.setup.mode[port] == ADM_PHY_POWER_SAVE) && mdio->adm_power.current_on) || (mdio->adm_power.setup.mode[port] == ADM_PHY_POWER_ON)) { turn_on = 1; } else { /*--- (mdio->adm_power.setup.mode[port] == ADM_PHY_POWER_OFF) ---*/ turn_on = 0; } switch(mdio->global_power) { case CPPHY_POWER_GLOBAL_ON: if( (mdio->adm_power.setup.mode[port] == ADM_PHY_POWER_SAVE) || (mdio->adm_power.setup.mode[port] == ADM_PHY_POWER_ON)) { turn_on = 1; } break; case CPPHY_POWER_GLOBAL_OFF: turn_on = 0; break; default: break; } if(mdio->adm_power.port_on[port] != turn_on) { /*--- DEB_TEST("Power %s PHY %u\n", turn_on ? "up" : "down", port); ---*/ switch(mdio->cpmac_switch) { case AVM_CPMAC_SWITCH_ADM6996: case AVM_CPMAC_SWITCH_ADM6996L: case AVM_CPMAC_SWITCH_TANTOS: adm_switch_port_power(mdio, port, turn_on); mdio->adm_power.port_on[port] = turn_on; break; case AVM_CPMAC_SWITCH_AR8216: if(mdio->global_power == CPPHY_POWER_GLOBAL_ON) { portset |= 1 << port; break; } /* Setting port 0 would reset all other ports! */ if((port != 0) || turn_on || ((mdio->linked & 0xf) == 0)) { ar_switch_port_power_orig(mdio, port, turn_on); mdio->adm_power.port_on[port] = turn_on; } break; case AVM_CPMAC_SWITCH_ANY: /* How to do power control should be known */ case AVM_CPMAC_SWITCH_NONE: default: mdio->adm_power.port_on[port] = turn_on; break; } } } } if(mdio->global_power == CPPHY_POWER_GLOBAL_ON) { mdio->global_power = CPPHY_POWER_GLOBAL_NONE; if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_AR8216) { ar_switch_port_power_on_boot_orig(mdio, portset); } } } #define NEXT_PORT { mdio->adm_power.current_port = (port >= to) ? from : (port + 1); } /*------------------------------------------------------------------------------------------*\ * Switch port power, assume link status is uptodate \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_power_emv(cpphy_mdio_t *mdio) { unsigned int port, from = 0, to = mdio->switch_ports - 1; /* There is no power saving without write access */ if(!(mdio->Mode & CPPHY_SWITCH_MODE_WRITE)) { mdio->adm_power.timeout = CPMAC_TICK_LENGTH; return; } /* Global power modes */ if(mdio->global_power) { DEB_TEST("Global power%s active\n", (mdio->global_power == CPPHY_POWER_GLOBAL_OFF) ? "off" : "on"); if(mdio->global_power == CPPHY_POWER_GLOBAL_OFF) { /* Driver startup */ mdio->adm_power.timeout = CPMAC_TICK_LENGTH; /*--- ar_switch_port_power_emv(mdio, 0, CPPHY_POWER_MODE_ON_IDLE_MDI); ---*/ ar_switch_port_power_emv(mdio, 0, CPPHY_POWER_MODE_OFF); ar_switch_port_power_emv(mdio, 1, CPPHY_POWER_MODE_OFF); ar_switch_port_power_emv(mdio, 2, CPPHY_POWER_MODE_OFF); ar_switch_port_power_emv(mdio, 3, CPPHY_POWER_MODE_OFF); ar_switch_port_power_emv(mdio, 4, CPPHY_POWER_MODE_ON_IDLE_MDI); } else { /* Driver activation */ mdio->adm_power.timeout = CPMAC_ADM_PHY_PUP_TEST_10_TO; mdio->global_power = CPPHY_POWER_GLOBAL_NONE; ar_boot_power_on_emv(mdio); ar_switch_port_power_emv(mdio, 0, CPPHY_POWER_MODE_LINK_LOST); mdio->adm_power.time_to_wait_to[0] = jiffies; ar_switch_port_power_emv(mdio, 1, CPPHY_POWER_MODE_LINK_LOST); mdio->adm_power.time_to_wait_to[1] = jiffies + 1 * CPMAC_ADM_PHY_PUP_IDLE_MDI + ((2 * HZ) / 10); ar_switch_port_power_emv(mdio, 2, CPPHY_POWER_MODE_LINK_LOST); mdio->adm_power.time_to_wait_to[2] = jiffies + 2 * CPMAC_ADM_PHY_PUP_IDLE_MDI + ((4 * HZ) / 10); ar_switch_port_power_emv(mdio, 3, CPPHY_POWER_MODE_LINK_LOST); mdio->adm_power.time_to_wait_to[3] = jiffies + 3 * CPMAC_ADM_PHY_PUP_IDLE_MDI + ((6 * HZ) / 10); mdio->adm_power.current_port = 0; mdio->linked = 0xf; } return; } /* Normal sequence for all relevant ports */ from = 0; to = 3; port = mdio->adm_power.current_port; /* Switch to different state than last run and use correct timeout*/ mdio->adm_power.timeout = CPMAC_ADM_PHY_PUP_TEST_10_TO / 5; switch(mdio->adm_power.port_mode[port]) { case CPPHY_POWER_MODE_ON: if(ar_switch_test_link(mdio, port)) { NEXT_PORT; break; /* Do not change state as there is a link */ } /* Wait at least CPMAC_ADM_PHY_PUP_LINKLOSS_TO */ mdio->adm_power.time_to_wait_to[port] = jiffies + CPMAC_ADM_PHY_PUP_LINKLOSS_TO; mdio->adm_power.port_mode[port] = CPPHY_POWER_MODE_LINK_LOST; NEXT_PORT; break; case CPPHY_POWER_MODE_LINK_LOST: if(time_after(mdio->adm_power.time_to_wait_to[port], jiffies)) { NEXT_PORT; break; } mdio->linked &= ~(1 << port); /* If there is a link, it will be checked in the ON_MDIX function */ ar_switch_port_power_emv(mdio, port, CPPHY_POWER_MODE_ON_MDIX); mdio->adm_power.time_to_wait_to[port] = jiffies + CPMAC_ADM_PHY_PUP_NORMAL_MDIX; DEB_TEST("[cpphy_mgmt_power] ports linked: %#x\n", mdio->linked); break; case CPPHY_POWER_MODE_ON_MDIX: if(time_after(mdio->adm_power.time_to_wait_to[port], jiffies)) { NEXT_PORT; break; } /* Do not toggle port 0 if at least one port is linked */ if((port != 0) || (mdio->linked == 0)) { ar_switch_port_power_emv(mdio, port, CPPHY_POWER_MODE_ON_MDI_MLT3); mdio->adm_power.time_to_wait_to[port] = jiffies + CPMAC_ADM_PHY_PUP_IDLE_MDI; } else { if(ar_switch_test_link(mdio, port)) { ar_switch_port_power_emv(mdio, port, CPPHY_POWER_MODE_ON); } mdio->adm_power.time_to_wait_to[port] = jiffies + CPMAC_ADM_PHY_PUP_NORMAL_MDIX; } NEXT_PORT; break; case CPPHY_POWER_MODE_ON_MDI_MLT3: if(time_after(mdio->adm_power.time_to_wait_to[port], jiffies)) { NEXT_PORT; break; } ar_switch_port_power_emv(mdio, port, CPPHY_POWER_MODE_ON_MDIX); mdio->adm_power.time_to_wait_to[port] = jiffies + CPMAC_ADM_PHY_PUP_NORMAL_MDIX; NEXT_PORT; break; default: DEB_ERR("[cpphy_mgmt_power] Illegal power mode encountered! (%u)\n", mdio->adm_power.current_mode); return; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_power(cpphy_mdio_t *mdio) { if(mdio->switch_use_EMV) { cpphy_mgmt_power_emv(mdio); } else { cpphy_mgmt_power_orig(mdio); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ cpmac_err_t adm_switch_port_power_config_orig(cpphy_mdio_t *mdio, adm_phy_power_setup_t *setup, unsigned char set) { unsigned int i; if(!set) { setup->time_on = mdio->adm_power.setup.time_on; setup->time_off = mdio->adm_power.roundrobin ? (4 * ( mdio->adm_power.setup.time_on + mdio->adm_power.setup.time_off)) : mdio->adm_power.setup.time_off; for(i = 0; i < 5; i++) { setup->mode[i] = mdio->adm_power.setup.mode[i]; } } else { mdio->adm_power.timeout = 0; mdio->adm_power.current_on = 1; mdio->adm_power.current_port = 0; mdio->adm_power.roundrobin = ((setup->time_on * 4) < setup->time_off); mdio->adm_power.setup.time_on = setup->time_on; mdio->adm_power.setup.time_off = mdio->adm_power.roundrobin ? ((setup->time_off - (4 * setup->time_on)) / 4) : setup->time_off; DEB_INFOTRC("Power setup: %s with %u on and %u off\n", mdio->adm_power.roundrobin ? "roundrobin" : "normal", mdio->adm_power.setup.time_on, mdio->adm_power.setup.time_off); for(i = 0; i < 5; i++) { mdio->adm_power.setup.mode[i] = setup->mode[i]; } } return CPMAC_ERR_NOERR; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ cpmac_err_t adm_switch_port_power_config_emv(cpphy_mdio_t *mdio, adm_phy_power_setup_t *setup, unsigned char set) { unsigned int i; if(!set) { setup->time_on = mdio->adm_power.setup.time_on; setup->time_off = mdio->adm_power.roundrobin ? (4 * ( mdio->adm_power.setup.time_on + mdio->adm_power.setup.time_off)) : mdio->adm_power.setup.time_off; for(i = 0; i < 5; i++) { setup->mode[i] = mdio->adm_power.setup.mode[i]; } } else { mdio->adm_power.timeout = 0; mdio->adm_power.current_mode = CPPHY_POWER_MODE_ON; mdio->adm_power.current_port = 0; mdio->adm_power.setup.time_on = setup->time_on; if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_AR8216) { mdio->adm_power.roundrobin = (((CPMAC_ADM_PHY_PUP_MDI_TO + CPMAC_ADM_PHY_PUP_MDIX_TO) * 4) < CPMAC_ADM_PHY_PUP_MUTE_TO); mdio->adm_power.setup.time_off = mdio->adm_power.roundrobin ? ((CPMAC_ADM_PHY_PUP_MUTE_TO - (4 * (CPMAC_ADM_PHY_PUP_MDI_TO + CPMAC_ADM_PHY_PUP_MDIX_TO))) / 4) : CPMAC_ADM_PHY_PUP_MUTE_TO; } else { mdio->adm_power.roundrobin = ((setup->time_on * 4) < setup->time_off); mdio->adm_power.setup.time_off = mdio->adm_power.roundrobin ? ((setup->time_off - (4 * setup->time_on)) / 4) : setup->time_off; } DEB_INFOTRC("Power setup: %s with %u on and %u off\n", mdio->adm_power.roundrobin ? "roundrobin" : "normal", mdio->adm_power.setup.time_on, mdio->adm_power.setup.time_off); for(i = 0; i < 5; i++) { mdio->adm_power.setup.mode[i] = setup->mode[i]; } cpphy_mgmt_power(mdio); } return CPMAC_ERR_NOERR; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ cpmac_err_t adm_switch_port_power_config(cpphy_mdio_t *mdio, adm_phy_power_setup_t *setup, unsigned char set) { if(mdio->switch_use_EMV) { return adm_switch_port_power_config_emv(mdio, setup, set); } else { return adm_switch_port_power_config_orig(mdio, setup, set); } } #if defined(CONFIG_AVM_POWER) /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int adm_power_config(int state) { union _powermanagment_ethernet_state pstate; if(power_mdio->switch_use_EMV) { return 0; } pstate.Register = state; if(pstate.Bits.port > 4) { DEB_ERR("adm_power_config tried to set mode for port %u\n", pstate.Bits.port); return -1; } power_mdio->adm_power.setup.mode[pstate.Bits.port] = pstate.Bits.status; DEB_TRC("adm_power_config sets mode %u for port %u\n", pstate.Bits.status, pstate.Bits.port); return 0; } #endif /*--- #if defined(CONFIG_AVM_POWER) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void cpmac_work(void *data) { cpphy_mdio_t *mdio = (cpphy_mdio_t *) data; unsigned long next_run; unsigned long next_wait; unsigned int something_done, i; assert(mdio != NULL); for( ; ; ) { mdio->work_to_do = 0; if(mdio->stop_work) { DEB_TRC("[cpmac_work] Stop work\n"); break; } something_done = 0; next_run = jiffies + 100000; /* Waiting should be a lot shorter than this */ for(i = 0; i < CPMAC_WORK_MAX_ITEMS; i++) { if(mdio->work[i].active) { if(time_after_eq(jiffies, mdio->work[i].next_run)) { /* It is time to run this item */ assert(mdio->work[i].item); mdio->work[i].next_run = jiffies + mdio->work[i].item(mdio); something_done = 1; break; /* Restart queue checking */ } if(time_after(next_run, mdio->work[i].next_run)) { next_run = mdio->work[i].next_run; } } } if(!something_done) { next_wait = next_run - jiffies; if(time_after(next_run, jiffies)) { wait_event_interruptible_timeout(mdio->waitqueue, mdio->work_to_do, next_wait); } else { DEB_TEST("[cpmac_work] Not waiting\n"); } } } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_work_start(cpphy_mdio_t *mdio) { mdio->stop_work = 0; INIT_WORK(&mdio->cpmac_work, cpmac_work, (void *) mdio); cancel_delayed_work(&mdio->cpmac_work); queue_delayed_work(cpmac_global.workqueue, &mdio->cpmac_work, 0); } /*------------------------------------------------------------------------------------------*\ * Add a function to be managed \*------------------------------------------------------------------------------------------*/ cpmac_err_t cpphy_mgmt_work_add(cpphy_mdio_t *mdio, cpmac_work_ident_t ident, cpmac_work_function function, unsigned long initial_timeout) { DEB_INFOTRC("[cpphy_mgmt_work_add] Function for ID %u with timeout %lu added!\n", ident, initial_timeout); if((mdio->work[ident].item != NULL) && (mdio->work[ident].item != function)) { DEB_ERR("[cpphy_mgmt_work_add] Different function for ID %u already added!\n", ident); return CPMAC_ERR_INTERNAL; } mdio->work[ident].item = function; if(time_after(mdio->work[ident].next_run, jiffies + initial_timeout)) { mdio->work[ident].next_run = jiffies + initial_timeout; } mdio->work[ident].active = 1; mdio->work_to_do = 1; wake_up_interruptible_sync(&mdio->waitqueue); return CPMAC_ERR_NOERR; } /*------------------------------------------------------------------------------------------*\ * Remove a function to be managed \*------------------------------------------------------------------------------------------*/ cpmac_err_t cpphy_mgmt_work_del(cpphy_mdio_t *mdio, cpmac_work_ident_t ident) { if(mdio->work[ident].active == 0) { DEB_WARN("[cpphy_mgmt_work_del] Function for ID %u is not set!\n", ident); return CPMAC_ERR_INTERNAL; } mdio->work[ident].active = 0; return CPMAC_ERR_NOERR; } /*------------------------------------------------------------------------------------------*\ * Schedule the work item after the given timeout; 0 means as soon as possible \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_work_schedule(cpphy_mdio_t *mdio, cpmac_work_ident_t ident, unsigned long timeout) { mdio->work[ident].next_run = jiffies + timeout; mdio->work[ident].active = 1; mdio->work_to_do = 1; wake_up_interruptible_sync(&mdio->waitqueue); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_work_stop(cpphy_mdio_t *mdio) { mdio->stop_work = 1; mdio->work_to_do = 1; wake_up(&mdio->waitqueue); flush_workqueue(cpmac_global.workqueue); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ cpmac_err_t cpphy_mgmt_init(cpphy_mdio_t *mdio) { unsigned int i; init_waitqueue_head(&mdio->waitqueue); mdio->work_to_do = 1; for(i = 0; i < CPMAC_MAX_WORK_ITEMS; i++) { mdio->work[i].active = 0; mdio->work[i].item = NULL; mdio->work[i].next_run = 0; } return CPMAC_ERR_NOERR; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_deinit(cpphy_mdio_t *mdio) { cpphy_mgmt_work_stop(mdio); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_support_data(cpphy_mdio_t *mdio) { cpphy_cppi_t *cppi = mdio->cpmac_priv->cppi; unsigned int i; cpphy_tcb_t *tcb; local_irq_disable(); # if defined(CONFIG_MIPS_UR8) DEB_SUPPORT("UR8 registers\n"); DEB_SUPPORT(" ID_VER = %#x\n", mdio->cpmac_priv->CPGMAC_F->ID_VER); DEB_SUPPORT(" MAC_IN_VECTOR = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_IN_VECTOR); DEB_SUPPORT(" MAC_EOI_VECTOR = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_EOI_VECTOR); DEB_SUPPORT(" MAC_INT_STATRAW = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_INT_STATRAW); DEB_SUPPORT(" MAC_INT_STATMASKED = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_INT_STATMASKED); DEB_SUPPORT(" MAC_INT_MASKSET = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_INT_MASKSET); DEB_SUPPORT(" MAC_INT_MASKCLEAR = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_INT_MASKCLEAR); DEB_SUPPORT(" RX_MBP_ENABLE = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_MBP_ENABLE.Reg); DEB_SUPPORT(" RX_UNICAST_SET = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_UNICAST_SET.Reg); DEB_SUPPORT(" RX_UNICAST_CLEAR = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_UNICAST_CLEAR.Reg); DEB_SUPPORT(" RX_MAX_LEN = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_MAX_LEN.Reg); DEB_SUPPORT(" MAC_CONTROL = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_CONTROL.Reg); DEB_SUPPORT(" MAC_STATUS = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_STATUS.Reg); DEB_SUPPORT(" FIFO_CONTROL = %#x\n", mdio->cpmac_priv->CPGMAC_F->FIFO_CONTROL); DEB_SUPPORT(" SOFT_RESET = %#x\n", mdio->cpmac_priv->CPGMAC_F->SOFT_RESET); DEB_SUPPORT(" MAC_SRC_ADDR_LOW = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_SRC_ADDR_LOW.Reg); DEB_SUPPORT(" MAC_SRC_ADDR_HIGH = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_SRC_ADDR_HIGH.Reg); DEB_SUPPORT(" MAC_HASH1 = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_HASH1); DEB_SUPPORT(" MAC_HASH2 = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_HASH2); DEB_SUPPORT(" BOFF_TEST = %#x\n", mdio->cpmac_priv->CPGMAC_F->BOFF_TEST.Reg); DEB_SUPPORT(" TPACE_TEST = %#x\n", mdio->cpmac_priv->CPGMAC_F->TPACE_TEST); DEB_SUPPORT(" RX_PAUSE = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_PAUSE); DEB_SUPPORT(" TX_PAUSE = %#x\n", mdio->cpmac_priv->CPGMAC_F->TX_PAUSE); DEB_SUPPORT(" PORT_VLAN = %#x\n", mdio->cpmac_priv->CPGMAC_F->PORT_VLAN); DEB_SUPPORT(" RX_FLOW_THRESH = %#x\n", mdio->cpmac_priv->CPGMAC_F->RX_FLOW_THRESH); DEB_SUPPORT(" MAC_ADDR_LOW = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_ADDR_LOW.Reg); DEB_SUPPORT(" MAC_ADDR_HIGH = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_ADDR_HIGH.Reg); DEB_SUPPORT(" MAC_INDEX = %#x\n", mdio->cpmac_priv->CPGMAC_F->MAC_INDEX); DEB_SUPPORT(" STATISTICS:\n"); DEB_SUPPORT(" RxGoodFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxGoodFrames); DEB_SUPPORT(" RxBroadcastFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxBroadcastFrames); DEB_SUPPORT(" RxMulticastFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxMulticastFrames); DEB_SUPPORT(" RxPauseFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxPauseFrames); DEB_SUPPORT(" RxCRCErrors = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxCRCErrors); DEB_SUPPORT(" RxAlignCodeErrors = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxAlignCodeErrors); DEB_SUPPORT(" RxOversizedFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxOversizedFrames); DEB_SUPPORT(" RxJabberFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxJabberFrames); DEB_SUPPORT(" RxUndersizedFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxUndersizedFrames); DEB_SUPPORT(" RxFragments = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxFragments); DEB_SUPPORT(" RxFilteredFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxFilteredFrames); DEB_SUPPORT(" RxQOSFilteredFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxQOSFilteredFrames); DEB_SUPPORT(" RxOctets = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxOctets); DEB_SUPPORT(" TxGoodFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxGoodFrames); DEB_SUPPORT(" TxBroadcastFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxBroadcastFrames); DEB_SUPPORT(" TxMulticastFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxMulticastFrames); DEB_SUPPORT(" TxPauseFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxPauseFrames); DEB_SUPPORT(" TxDeferredFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxDeferredFrames); DEB_SUPPORT(" TxCollisionFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxCollisionFrames); DEB_SUPPORT(" TxSingleCollFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxSingleCollFrames); DEB_SUPPORT(" TxMultiCollFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxMultiCollFrames); DEB_SUPPORT(" TxExcessiveCollisions = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxExcessiveCollisions); DEB_SUPPORT(" TxLateCollisions = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxLateCollisions); DEB_SUPPORT(" TxUnderrun = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxUnderrun); DEB_SUPPORT(" TxCarrierSenseErrors = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxCarrierSenseErrors); DEB_SUPPORT(" TxOctets = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.TxOctets); DEB_SUPPORT(" Tx64octetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx64octetFrames); DEB_SUPPORT(" Tx65t127octetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx65t127octetFrames); DEB_SUPPORT(" Tx128t255octetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx128t255octetFrames); DEB_SUPPORT(" Tx256t511octetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx256t511octetFrames); DEB_SUPPORT(" Tx512t1023octetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx512t1023octetFrames); DEB_SUPPORT(" Tx1024tUoctetFrames = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.Tx1024tUoctetFrames); DEB_SUPPORT(" NetOctets = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.NetOctets); DEB_SUPPORT(" RxSofOverruns = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxSofOverruns); DEB_SUPPORT(" RxMofOverruns = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxMofOverruns); DEB_SUPPORT(" RxDmaOverruns = %u\n", mdio->cpmac_priv->CPGMAC_F->STATISTIC.RxDmaOverruns); DEB_SUPPORT("NWSS registers\n"); DEB_SUPPORT(" MAC0 Tx Channel tx_A = %#x, tx_B = %#x\n", mdio->cpmac_priv->UR8_NWSS->Channel_Cfg[UR8_TX_MAC0].tx_A.Register, mdio->cpmac_priv->UR8_NWSS->Channel_Cfg[UR8_TX_MAC0].tx_B.Register); DEB_SUPPORT(" MAC0 Rx Channel rx_A = %#x, rx_B = %#x\n", mdio->cpmac_priv->UR8_NWSS->Channel_Cfg[UR8_TX_MAC0].rx_A.Register, mdio->cpmac_priv->UR8_NWSS->Channel_Cfg[UR8_TX_MAC0].rx_B.Register); DEB_SUPPORT(" Queue tx_int_enable = %#x\n", mdio->cpmac_priv->UR8_QUEUE->tx_int_enable_set.Register); DEB_SUPPORT(" Queue tx_int_end = %#x\n", mdio->cpmac_priv->UR8_QUEUE->tx_int_end.Register); DEB_SUPPORT(" Queue rx_int_enable = %#x\n", mdio->cpmac_priv->UR8_QUEUE->rx_int_enable_set.Register); DEB_SUPPORT(" Queue rx_int_end = %#x\n", mdio->cpmac_priv->UR8_QUEUE->rx_int_end.Register); DEB_SUPPORT(" Queue rx starvation count = %#x\n", mdio->cpmac_priv->UR8_QUEUE->queue_starvation_count.Register); DEB_SUPPORT("\n"); # endif /*--- #if defined(CONFIG_MIPS_UR8) ---*/ DEB_SUPPORT("tcb management normal : %u alloced, %u freed\n", cppi->support.tcbs_alloced, cppi->support.tcbs_freed); DEB_SUPPORT("tcb management dynamic: %u alloced, %u freed\n", cppi->support.tcbs_alloced_dynamic, cppi->support.tcbs_freed_dynamic); for(i = 0; i < CPPHY_PRIO_QUEUES; i++) { unsigned int count = 0; DEB_SUPPORT("tx priority queue %u:\n", i); DEB_SUPPORT(" MaxSize = %u\n", cppi->TxPrioQueues.q[i].MaxSize); DEB_SUPPORT(" Free = %u\n", atomic_read(&cppi->TxPrioQueues.q[i].Free)); for(tcb = (cpphy_tcb_t *) cppi->TxPrioQueues.q[i].First; tcb != NULL; tcb = (cpphy_tcb_t *) tcb->Next, count++) ; DEB_SUPPORT(" Counted = %u\n", count); DEB_SUPPORT(" MaxDMAFree = %u\n", cppi->TxPrioQueues.q[i].MaxDMAFree); DEB_SUPPORT(" DMAFree = %u\n", atomic_read(&cppi->TxPrioQueues.q[i].DMAFree)); DEB_SUPPORT(" Pause = %u\n", cppi->TxPrioQueues.q[i].Pause); DEB_SUPPORT(" PauseInit = %u\n", cppi->TxPrioQueues.q[i].PauseInit); DEB_SUPPORT(" BytesEnqueued = %u\n", cppi->TxPrioQueues.q[i].BytesEnqueued); DEB_SUPPORT(" BytesDequeued = %u\n", cppi->TxPrioQueues.q[i].BytesDequeued); DEB_SUPPORT(" First = %p\n", cppi->TxPrioQueues.q[i].First); DEB_SUPPORT(" Last = %p\n", cppi->TxPrioQueues.q[i].Last); DEB_SUPPORT("\n"); } DEB_SUPPORT("\n"); local_irq_enable(); tasklet_schedule(&mdio->cpmac_priv->tasklet); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpphy_mgmt_debug(cpphy_mdio_t *mdio) { mdio = mdio; }