static int mv_gtw_set_port_based_vlan(unsigned int ports_mask) { unsigned int p, pl; unsigned char cnt; GT_LPORT port_list[MAX_SWITCH_PORTS]; for(p=0; p<qd_dev->numOfPorts; p++) { if( MV_BIT_CHECK(ports_mask, p) && (p != SWITCH_PORT_CPU) ) { ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("port based vlan, port %d: ",p)); for(pl=0,cnt=0; pl<qd_dev->numOfPorts; pl++) { if( MV_BIT_CHECK(ports_mask, pl) && (pl != p) ) { ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("%d ",pl)); port_list[cnt] = pl; cnt++; } } if( gvlnSetPortVlanPorts(qd_dev, p, port_list, cnt) != GT_OK) { printk("gvlnSetPortVlanPorts failed\n"); return -1; } ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("\n")); } } return 0; }
int mv_switch_port_based_vlan_set(unsigned int ports_mask, int set_cpu_port) { unsigned int p, pl; unsigned char cnt; GT_LPORT port_list[MAX_SWITCH_PORTS]; for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(ports_mask, p) && (set_cpu_port || (p != qd_cpu_port))) { SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("port based vlan, port %d: ", p)); for (pl = 0, cnt = 0; pl < qd_dev->numOfPorts; pl++) { if (MV_BIT_CHECK(ports_mask, pl) && (pl != p)) { SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("%d ", pl)); port_list[cnt] = pl; cnt++; } } if (gvlnSetPortVlanPorts(qd_dev, p, port_list, cnt) != GT_OK) { printk(KERN_ERR "gvlnSetPortVlanPorts failed\n"); return -1; } SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("\n")); } } return 0; }
static void mvPp2PlcrHwDump(int plcr) { int units, type, tokens; MV_U32 regVal; mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr); mvOsPrintf("%3d: ", plcr); regVal = mvPp2RdReg(MV_PP2_PLCR_ENABLE_REG); mvOsPrintf("%4s", MV_BIT_CHECK(regVal, plcr) ? "Yes" : "No"); regVal = mvPp2RdReg(MV_PP2_PLCR_BASE_PERIOD_REG); mvOsPrintf(" %6d", regVal & MV_PP2_PLCR_BASE_PERIOD_ALL_MASK); regVal = mvPp2RdReg(MV_PP2_PLCR_TOKEN_CFG_REG); units = regVal & MV_PP2_PLCR_TOKEN_UNIT_MASK; type = (regVal & MV_PP2_PLCR_TOKEN_TYPE_ALL_MASK) >> MV_PP2_PLCR_TOKEN_TYPE_OFFS; tokens = (regVal & MV_PP2_PLCR_TOKEN_VALUE_ALL_MASK) >> MV_PP2_PLCR_TOKEN_VALUE_OFFS; mvOsPrintf(" %5s %2d %5d", units ? "pkts" : "bytes", type, tokens); regVal = mvPp2RdReg(MV_PP2_PLCR_BUCKET_SIZE_REG); mvOsPrintf(" %04x %04x", (regVal & MV_PP2_PLCR_COMMIT_SIZE_ALL_MASK) >> MV_PP2_PLCR_COMMIT_SIZE_OFFS, (regVal & MV_PP2_PLCR_EXCESS_SIZE_ALL_MASK) >> MV_PP2_PLCR_EXCESS_SIZE_OFFS); regVal = mvPp2RdReg(MV_PP2_PLCR_COMMIT_TOKENS_REG); mvOsPrintf(" %08x", regVal); regVal = mvPp2RdReg(MV_PP2_PLCR_EXCESS_TOKENS_REG); mvOsPrintf(" %08x", regVal); mvOsPrintf("\n"); }
void mv_switch_link_update_event(MV_U32 port_mask, int force_link_check) { int p; unsigned short phy_cause = 0; for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(port_mask, p)) { if ((!qsgmii_module) || (p == gephy_on_port)) { /* liron, TODO: || (p == rgmiia_on_port) */ /* this is needed to clear the PHY interrupt */ gprtGetPhyIntStatus(qd_dev, p, &phy_cause); } else { phy_cause |= GT_LINK_STATUS_CHANGED; } if (force_link_check) phy_cause |= GT_LINK_STATUS_CHANGED; if (phy_cause & GT_LINK_STATUS_CHANGED) { char *link = NULL, *duplex = NULL, *speed = NULL; GT_BOOL flag; GT_PORT_SPEED_MODE speed_mode; if (gprtGetLinkState(qd_dev, p, &flag) != GT_OK) { printk(KERN_ERR "gprtGetLinkState failed (port %d)\n", p); link = "ERR"; } else link = (flag) ? "up" : "down"; if (flag) { if (gprtGetDuplex(qd_dev, p, &flag) != GT_OK) { printk(KERN_ERR "gprtGetDuplex failed (port %d)\n", p); duplex = "ERR"; } else duplex = (flag) ? "Full" : "Half"; if (gprtGetSpeedMode(qd_dev, p, &speed_mode) != GT_OK) { printk(KERN_ERR "gprtGetSpeedMode failed (port %d)\n", p); speed = "ERR"; } else { if (speed_mode == PORT_SPEED_1000_MBPS) speed = "1000Mbps"; else if (speed_mode == PORT_SPEED_100_MBPS) speed = "100Mbps"; else speed = "10Mbps"; } mv_eth_switch_update_link(p, 1); printk(KERN_ERR "Port %d: Link-%s, %s-duplex, Speed-%s.\n", mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p), link, duplex, speed); } else { mv_eth_switch_update_link(p, 0); printk(KERN_ERR "Port %d: Link-down\n", mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p)); } } } } }
int mv_eth_switch_vlan_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port) { int p; /* set port's default private vlan id and database number (DB per group): */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(port_map, p) && (p != cpu_port)) { if (gvlnSetPortVid(qd_dev, p, MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p)) != GT_OK) { printk(KERN_ERR "gvlnSetPortVid failed\n"); return -1; } if (gvlnSetPortVlanDBNum(qd_dev, p, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id)) != GT_OK) { printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n"); return -1; } } } /* set port's port-based vlan (CPU port is not part of VLAN) */ if (mv_switch_port_based_vlan_set((port_map & ~(1 << cpu_port)), 0) != 0) printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n"); /* set vtu with group vlan id (used in tx) */ if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), port_map | (1 << cpu_port)) != 0) printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); /* set vtu with each port private vlan id (used in rx) */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(port_map, p) && (p != cpu_port)) { if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p), MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), port_map & ~(1 << cpu_port)) != 0) { printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); } } } return 0; }
int mv_switch_promisc_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port, u8 promisc_on) { int i; if (promisc_on) { mv_switch_port_based_vlan_set((port_map | (1 << cpu_port)), 0); for (i = 0; i < qd_dev->numOfPorts; i++) { if (MV_BIT_CHECK(port_map, i) && (i != cpu_port)) { if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, i), MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), (port_map | (1 << cpu_port))) != 0) { printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); return -1; } } } } else { mv_switch_port_based_vlan_set((port_map & ~(1 << cpu_port)), 0); for (i = 0; i < qd_dev->numOfPorts; i++) { if (MV_BIT_CHECK(port_map, i) && (i != cpu_port)) { if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, i), MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), (port_map & ~(1 << cpu_port))) != 0) { printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); return -1; } } } } return 0; }
int mv_switch_port_add(int switch_port, u16 vlan_grp_id, u16 port_map) { int p; /* Set default VLAN_ID for port */ if (gvlnSetPortVid(qd_dev, switch_port, MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, switch_port)) != GT_OK) { printk(KERN_ERR "gvlnSetPortVid failed\n"); return -1; } /* Map port to VLAN DB */ if (gvlnSetPortVlanDBNum(qd_dev, switch_port, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id)) != GT_OK) { printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n"); return -1; } /* Add port to the VLAN (CPU port is not part of VLAN) */ if (mv_switch_port_based_vlan_set((port_map & ~(1 << qd_cpu_port)), 0) != 0) printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n"); /* Add port to vtu (used in tx) */ if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), (port_map | (1 << qd_cpu_port)))) { printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); } /* set vtu with each port private vlan id (used in rx) */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(port_map, p) && (p != qd_cpu_port)) { if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p), MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), port_map & ~(1 << qd_cpu_port)) != 0) { printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n"); } } } /* Enable port */ if (gstpSetPortState(qd_dev, switch_port, GT_PORT_FORWARDING) != GT_OK) printk(KERN_ERR "gstpSetPortState failed\n"); #ifdef CONFIG_MV_ETH_SWITCH_LINK if (!qsgmii_module) { /* Enable Phy Link Status Changed interrupt at Phy level for the port */ if (gprtPhyIntEnable(qd_dev, switch_port, (GT_LINK_STATUS_CHANGED)) != GT_OK) printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", switch_port); } #endif /* CONFIG_MV_ETH_SWITCH_LINK */ return 0; }
static int mv_gtw_set_vlan_in_vtu(unsigned short vlan_id,unsigned int ports_mask) { GT_VTU_ENTRY vtu_entry; unsigned int p; vtu_entry.vid = vlan_id; vtu_entry.DBNum = MV_GTW_VLAN_TO_GROUP(vlan_id); vtu_entry.vidPriOverride = GT_FALSE; vtu_entry.vidPriority = 0; vtu_entry.vidExInfo.useVIDFPri = GT_FALSE; vtu_entry.vidExInfo.vidFPri = 0; vtu_entry.vidExInfo.useVIDQPri = GT_FALSE; vtu_entry.vidExInfo.vidQPri = 0; vtu_entry.vidExInfo.vidNRateLimit = GT_FALSE; ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("vtu entry: vid=0x%x, port ", vtu_entry.vid)); for(p=0; p<qd_dev->numOfPorts; p++) { if(MV_BIT_CHECK(ports_mask, p)) { ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("%d ", p)); if(qd_dev->deviceId == GT_88E6061) { /* for 6061 device, no double/provider tag controlling on ingress. */ /* therefore, we need to strip the tag on egress on all ports except cpu port */ /* anyway, if we're using header mode no vlan-tag need to be added here */ vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED; } else { vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED; } } else { vtu_entry.vtuData.memberTagP[p] = NOT_A_MEMBER; } vtu_entry.vtuData.portStateP[p] = 0; } if(gvtuAddEntry(qd_dev, &vtu_entry) != GT_OK) { printk("gvtuAddEntry failed\n"); return -1; } ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("\n")); return 0; }
int mv_switch_port_del(int switch_port, u16 vlan_grp_id, u16 port_map) { int p; #ifdef CONFIG_MV_ETH_SWITCH_LINK if (!qsgmii_module) { /* Disable link change interrupts on unmapped port */ if (gprtPhyIntEnable(qd_dev, switch_port, 0) != GT_OK) printk(KERN_ERR "gprtPhyIntEnable failed on port #%d\n", switch_port); } #endif /* CONFIG_MV_ETH_SWITCH_LINK */ /* Disable unmapped port */ if (gstpSetPortState(qd_dev, switch_port, GT_PORT_DISABLE) != GT_OK) printk(KERN_ERR "gstpSetPortState failed on port #%d\n", switch_port); /* Remove port from the VLAN (CPU port is not part of VLAN) */ if (mv_switch_port_based_vlan_set((port_map & ~(1 << qd_cpu_port)), 0) != 0) printk(KERN_ERR "mv_gtw_set_port_based_vlan failed\n"); /* Remove port from vtu (used in tx) */ if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), (port_map | (1 << qd_cpu_port))) != 0) { printk(KERN_ERR "mv_gtw_set_vlan_in_vtu failed\n"); } /* Remove port from vtu of each port private vlan id (used in rx) */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(port_map, p) && (p != qd_cpu_port)) { if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p), MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), (port_map & ~(1 << qd_cpu_port))) != 0) printk(KERN_ERR "mv_gtw_set_vlan_in_vtu failed\n"); } } return 0; }
int mv_switch_vlan_in_vtu_set(unsigned short vlan_id, unsigned short db_num, unsigned int ports_mask) { GT_VTU_ENTRY vtu_entry; unsigned int p; memset(&vtu_entry, 0, sizeof(GT_VTU_ENTRY)); vtu_entry.sid = 1; vtu_entry.vid = vlan_id; vtu_entry.DBNum = db_num; vtu_entry.vidPriOverride = GT_FALSE; vtu_entry.vidPriority = 0; vtu_entry.vidExInfo.useVIDFPri = GT_FALSE; vtu_entry.vidExInfo.vidFPri = 0; vtu_entry.vidExInfo.useVIDQPri = GT_FALSE; vtu_entry.vidExInfo.vidQPri = 0; vtu_entry.vidExInfo.vidNRateLimit = GT_FALSE; SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("vtu entry: vid=0x%x, port ", vtu_entry.vid)); for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(ports_mask, p)) { SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("%d ", p)); vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED; } else { vtu_entry.vtuData.memberTagP[p] = NOT_A_MEMBER; } vtu_entry.vtuData.portStateP[p] = 0; } if (gvtuAddEntry(qd_dev, &vtu_entry) != GT_OK) { printk(KERN_ERR "gvtuAddEntry failed\n"); return -1; } SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("\n")); return 0; }
static int mv_gw_switch_init(int port) { unsigned int i, p; unsigned char cnt; GT_LPORT port_list[MAX_SWITCH_PORTS]; struct mv_vlan_cfg *nc; GT_JUMBO_MODE jumbo_mode; GT_DEV_EVENT gt_event; printk("init switch layer... "); if (!qd_dev) { printk("qd_dev is NULL in %s\n",__func__); return -1; } ETH_DBG( ETH_DBG_LOAD, ("Device ID : 0x%x\n",qd_dev->deviceId)); ETH_DBG( ETH_DBG_LOAD, ("Base Reg Addr : 0x%x\n",qd_dev->baseRegAddr)); ETH_DBG( ETH_DBG_LOAD, ("No. of Ports : %d\n",qd_dev->numOfPorts)); ETH_DBG( ETH_DBG_LOAD, ("CPU Ports : %ld\n",qd_dev->cpuPortNum)); /* disable all ports */ for(p=0; p<qd_dev->numOfPorts; p++) { gstpSetPortState(qd_dev, p, GT_PORT_DISABLE); } /* set all ports to not modify the vlan tag on egress */ for(i=0; i<qd_dev->numOfPorts; i++) { if(gprtSetEgressMode(qd_dev, i, GT_UNMODIFY_EGRESS) != GT_OK) { printk("gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n"); return -1; } } /* initialize Switch according to Switch ID */ switch (qd_dev->deviceId) { case GT_88E6065: /* set CPU port number */ if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) { printk("gsysSetCPUPort failed\n"); return -1; } /* flush all counters for all ports */ if(gstatsFlushAll(qd_dev) != GT_OK) printk("gstatsFlushAll failed\n"); /* use Marvell Header mode */ if(gprtSetHeaderMode(qd_dev, SWITCH_PORT_CPU, GT_TRUE) != GT_OK) { printk("gprtSetHeaderMode GT_TRUE failed\n"); return -1; } /* init counters */ if(gprtClearAllCtr(qd_dev) != GT_OK) printk("gprtClearAllCtr failed\n"); if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK) printk("gprtSetCtrMode failed\n"); break; case GT_88E6061: /* set CPU port number */ if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) { printk("gsysSetCPUPort failed\n"); return -1; } /* use Marvell Header mode */ if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) { printk("gprtSetHeaderMode GT_TRUE failed\n"); return -1; } /* init counters */ if(gprtClearAllCtr(qd_dev) != GT_OK) printk("gprtClearAllCtr failed\n"); if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK) printk("gprtSetCtrMode failed\n"); break; case GT_88E6161: case GT_88E6165: case GT_88E6171: /* flush all counters for all ports */ if(gstatsFlushAll(qd_dev) != GT_OK) { printk("gstatsFlushAll failed\n"); } /* use Marvell Header mode */ if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) { printk("gprtSetHeaderMode GT_TRUE failed\n"); return -1; } /* set all ports to work in Normal mode (non-DSA tag) */ for(i=0; i<qd_dev->numOfPorts; i++) { if (gprtSetFrameMode(qd_dev, i, GT_FRAME_MODE_NORMAL) != GT_OK) { printk("gprtSetFrameMode to GT_FRAME_MODE_NORMAL on port %d failed\n", i); return -1; } } /* Setup jumbo frames mode */ if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 1522) jumbo_mode = GT_JUMBO_MODE_1522; else if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 2048) jumbo_mode = GT_JUMBO_MODE_2048; else jumbo_mode = GT_JUMBO_MODE_10240; for(i=0; i<qd_dev->numOfPorts; i++) { if(gsysSetJumboMode(qd_dev, i, jumbo_mode) != GT_OK) { printk("gsysSetJumboMode %d failed\n",jumbo_mode); return -1; } } break; default: printk("Unsupported Switch. Switch ID is 0x%X.\n", qd_dev->deviceId); return -1; } /* set priorities rules */ for(i=0; i<qd_dev->numOfPorts; i++) { /* default port priority to queue zero */ if(gcosSetPortDefaultTc(qd_dev, i, 0) != GT_OK) printk("gcosSetPortDefaultTc failed (port %d)\n", i); /* enable IP TOS Prio */ if(gqosIpPrioMapEn(qd_dev, i, GT_TRUE) != GT_OK) printk("gqosIpPrioMapEn failed (port %d)\n",i); /* set IP QoS */ if(gqosSetPrioMapRule(qd_dev, i, GT_FALSE) != GT_OK) printk("gqosSetPrioMapRule failed (port %d)\n",i); /* disable Vlan QoS Prio */ if(gqosUserPrioMapEn(qd_dev, i, GT_FALSE) != GT_OK) printk("gqosUserPrioMapEn failed (port %d)\n",i); /* Set force flow control to FALSE for all ports */ if(gprtSetForceFc(qd_dev, i, GT_FALSE) != GT_OK) printk("gprtSetForceFc failed (port %d)\n",i); } /* The switch CPU port is not part of the VLAN, but rather connected by tunneling to each */ /* of the VLAN's ports. Our MAC addr will be added during start operation to the VLAN DB */ /* at switch level to forward packets with this DA to CPU port. */ ETH_DBG( ETH_DBG_LOAD, ("Enabling Tunneling on ports: ")); for(i=0; i<qd_dev->numOfPorts; i++) { if(i != SWITCH_PORT_CPU) { if(gprtSetVlanTunnel(qd_dev, i, GT_TRUE) != GT_OK) { printk("gprtSetVlanTunnel failed (port %d)\n",i); return -1; } else { ETH_DBG( ETH_DBG_LOAD, ("%d ",i)); } } } ETH_DBG( ETH_DBG_LOAD, ("\n")); /* configure ports (excluding CPU port) for each network interface (VLAN): */ for(i=0, nc=>w_config.vlan_cfg[i]; i<gtw_config.vlans_num; i++,nc++) { ETH_DBG( ETH_DBG_LOAD, ("vlan%d configuration (nc->ports_mask = 0x%08x) \n", i, nc->ports_mask)); /* set port's defaul private vlan id and database number (DB per group): */ for(p=0; p<qd_dev->numOfPorts; p++) { if( MV_BIT_CHECK(nc->ports_mask, p) && (p != SWITCH_PORT_CPU) ) { ETH_DBG(ETH_DBG_LOAD,("port %d default private vlan id: 0x%x\n", p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p))); if( gvlnSetPortVid(qd_dev, p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p)) != GT_OK ) { printk("gvlnSetPortVid failed"); return -1; } if( gvlnSetPortVlanDBNum(qd_dev, p, MV_GTW_VLAN_TO_GROUP(nc->vlan_grp_id)) != GT_OK) { printk("gvlnSetPortVlanDBNum failed\n"); return -1; } } } /* set port's port-based vlan (CPU port is not part of VLAN) */ if(mv_gtw_set_port_based_vlan(nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) { printk("mv_gtw_set_port_based_vlan failed\n"); } /* set vtu with group vlan id (used in tx) */ if(mv_gtw_set_vlan_in_vtu(nc->vlan_grp_id, nc->ports_mask | (1<<SWITCH_PORT_CPU)) != 0) { printk("mv_gtw_set_vlan_in_vtu failed\n"); } /* set vtu with each port private vlan id (used in rx) */ for(p=0; p<qd_dev->numOfPorts; p++) { if(MV_BIT_CHECK(nc->ports_mask, p) && (p!=SWITCH_PORT_CPU)) { if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p), nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) { printk("mv_gtw_set_vlan_in_vtu failed\n"); } } } } /* set cpu-port with port-based vlan to all other ports */ ETH_DBG( ETH_DBG_LOAD, ("cpu port-based vlan:")); for(p=0,cnt=0; p<qd_dev->numOfPorts; p++) { if(p != SWITCH_PORT_CPU) { ETH_DBG( ETH_DBG_LOAD, ("%d ",p)); port_list[cnt] = p; cnt++; } } ETH_DBG( ETH_DBG_LOAD, ("\n")); if(gvlnSetPortVlanPorts(qd_dev, SWITCH_PORT_CPU, port_list, cnt) != GT_OK) { printk("gvlnSetPortVlanPorts failed\n"); return -1; } if(gfdbFlush(qd_dev,GT_FLUSH_ALL) != GT_OK) { printk("gfdbFlush failed\n"); } /* done! enable all Switch ports according to the net config table */ ETH_DBG( ETH_DBG_LOAD, ("enabling: ports ")); for(p=0; p<qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_enabled_ports, p)) { ETH_DBG( ETH_DBG_LOAD, ("%d ",p)); if(gstpSetPortState(qd_dev, p, GT_PORT_FORWARDING) != GT_OK) { printk("gstpSetPortState failed\n"); } } } ETH_DBG( ETH_DBG_LOAD, ("\n")); #ifdef CONFIG_MV_GTW_LINK_STATUS /* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */ for(p=0; p<qd_dev->numOfPorts; p++) { if(MV_BIT_CHECK(switch_enabled_ports, p) && (p != SWITCH_PORT_CPU)) { if(gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK) { printk("gprtPhyIntEnable failed port %d\n", p); } } } if ((qd_dev->deviceId != GT_88E6161) && (qd_dev->deviceId != GT_88E6165) && (qd_dev->deviceId != GT_88E6171)) { if (switch_irq != -1) { if(eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK) { printk("eventSetActive failed\n"); } } } else { gt_event.event = GT_DEV_INT_PHY; gt_event.portList = 0; gt_event.phyList = 0x1F; /* 0x1F is a bit mask for ports 0-4 */ if (switch_irq != -1) { if(eventSetDevInt(qd_dev, >_event) != GT_OK) { printk("eventSetDevInt failed\n"); } if(eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK) { printk("eventSetActive failed\n"); } } } #endif /* CONFIG_MV_GTW_LINK_STATUS */ /* Configure Ethernet related LEDs, currently according to Switch ID */ switch (qd_dev->deviceId) { case GT_88E6161: case GT_88E6165: case GT_88E6171: break; /* do nothing */ default: for(p=0; p<qd_dev->numOfPorts; p++) { if( (p != SWITCH_PORT_CPU) && (SWITCH_IS_PORT_CONNECTED(p)) ) { if(gprtSetPhyReg(qd_dev,p,22,0x1FFA)) { /* Configure Register 22 LED0 to 0xA for Link/Act */ printk("gprtSetPhyReg failed (port=%d)\n", p); } } } break; } /* printk("done\n"); */ return 0; }
static irqreturn_t mv_gtw_link_interrupt_handler(int irq , void *dev_id) { unsigned short switch_cause = 0, phy_cause, phys_port = 0, p; OUT GT_DEV_INT_STATUS devIntStatus; if (switch_irq != -1 ) { if ((qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) || (qd_dev->deviceId == GT_88E6171)) { /* required to clear the interrupt, and updates phys_port */ if (geventGetDevIntStatus(qd_dev, &devIntStatus) != GT_OK) { printk("geventGetDevIntStatus failed, ignoring interrupt\n"); return IRQ_HANDLED; } if (devIntStatus.devIntCause != GT_DEV_INT_PHY) { printk("devIntCause != GT_DEV_INT_PHY, igonring interrupt\n"); return IRQ_HANDLED; } phys_port = devIntStatus.phyInt & 0xFF; if (phys_port) switch_cause = GT_PHY_INTERRUPT; } else { if(eventGetIntStatus(qd_dev, &switch_cause) != GT_OK) switch_cause = 0; } } else { switch_cause = GT_PHY_INTERRUPT; } if(switch_cause & GT_PHY_INTERRUPT) { /* If we're using a 6161/6165 Switch and using the Switch interrupt, we already have phys_port updated above */ /* If we're using any other Switch, or if we're using polling, we need to update phys_port now */ if ((qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) || (qd_dev->deviceId == GT_88E6171)) { if (switch_irq == -1) { geventGetDevIntStatus(qd_dev, &devIntStatus); phys_port = devIntStatus.phyInt & 0xFF; /* TODO: check if next line is needed */ phys_port |= 0x18; /* we cannot get indication for these ports in this method, so check them */ } } else { /* not 6161 or 6165 */ gprtGetPhyIntPortSummary(qd_dev,&phys_port); } for(p=0; p<qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(phys_port, p)) { if(gprtGetPhyIntStatus(qd_dev,p,&phy_cause) == GT_OK) { if(phy_cause & GT_LINK_STATUS_CHANGED) { char *link=NULL, *duplex=NULL, *speed=NULL; GT_BOOL flag; GT_PORT_SPEED_MODE speed_mode; if(gprtGetLinkState(qd_dev,p,&flag) != GT_OK) { printk("gprtGetLinkState failed (port %d)\n",p); link = "ERR"; } else link = (flag)?"up":"down"; if(flag) { if(gprtGetDuplex(qd_dev,p,&flag) != GT_OK) { printk("gprtGetDuplex failed (port %d)\n",p); duplex = "ERR"; } else duplex = (flag)?"Full":"Half"; if(gprtGetSpeedMode(qd_dev,p,&speed_mode) != GT_OK) { printk("gprtGetSpeedMode failed (port %d)\n",p); speed = "ERR"; } else { if (speed_mode == PORT_SPEED_1000_MBPS) speed = "1000Mbps"; else if (speed_mode == PORT_SPEED_100_MBPS) speed = "100Mbps"; else speed = "10Mbps"; } mv_gtw_update_link_status(p, 1); printk("Port %d: Link-%s, %s-duplex, Speed-%s.\n", mv_gtw_port2lport(p),link,duplex,speed); } else { mv_gtw_update_link_status(p, 0); printk("Port %d: Link-down\n",mv_gtw_port2lport(p)); } } } } } } if (switch_irq == -1 ) { switch_link_timer.expires = jiffies + (HZ); /* 1 second */ add_timer(&switch_link_timer); } return IRQ_HANDLED; }
unsigned int mv_switch_link_detection_init(void) { #ifdef CONFIG_MV_ETH_SWITCH_LINK unsigned int p; static int link_init_done = 0; unsigned int connected_phys_mask = 0; if (qd_dev == NULL) { printk(KERN_ERR "%s: qd_dev not initialized, call mv_switch_load() first\n", __func__); return 0; } switch_irq = mvBoardSwitchIrqGet(); if (!qsgmii_module) { /* liron, TODO: find a nicer solution or use BoardEnv */ #ifdef MV_INCLUDE_ETH_COMPLEX /* QSGMII module is not connected, Switch is working in 3xFE mode */ connected_phys_mask = 0x0E; /* KW2: Switch PHYs 1, 2, 3 */ #else connected_phys_mask = 0x1F; /* KW40: Switch PHYs 0, 1, 2, 3, 4 */ #endif if (!link_init_done) { /* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(connected_phys_mask, p) && (p != qd_cpu_port)) { if (gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK) printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", p); } } if (switch_irq != -1) { /* Interrupt supported */ if ((qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) || (qd_dev->deviceId == GT_88E6351) || (qd_dev->deviceId == GT_88E6171) || (qd_dev->deviceId == GT_88E6172) || (qd_dev->deviceId == GT_88E6176)) { GT_DEV_EVENT gt_event = { GT_DEV_INT_PHY, 0, connected_phys_mask }; if (eventSetDevInt(qd_dev, >_event) != GT_OK) printk(KERN_ERR "eventSetDevInt failed\n"); if (eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK) printk(KERN_ERR "eventSetActive failed\n"); } else { if (eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK) printk(KERN_ERR "eventSetActive failed\n"); } } } } if (!link_init_done) { if (gephy_on_port >= 0) { if (gprtPhyIntEnable(qd_dev, gephy_on_port, (GT_LINK_STATUS_CHANGED)) != GT_OK) printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", gephy_on_port); } } if (qsgmii_module) connected_phys_mask = 0x0F; /* Switch ports 0, 1, 2, 3 connected to QSGMII */ if (gephy_on_port >= 0) connected_phys_mask |= (1 << gephy_on_port); if (rgmiia_on_port >= 0) connected_phys_mask |= (1 << rgmiia_on_port); if (!link_init_done) { /* we want to use a timer for polling link status if no interrupt is available for all or some of the PHYs */ if ((switch_irq == -1)) { /* liron, TODO: || (rgmiia_on_port >= 0) */ /* Use timer for polling */ switch_link_poll = 1; init_timer(&switch_link_timer); switch_link_timer.function = mv_switch_link_timer_function; if (switch_irq == -1) switch_link_timer.data = connected_phys_mask; else /* timer only for RGMII-A connected port */ switch_link_timer.data = (1 << rgmiia_on_port); switch_link_timer.expires = jiffies + (HZ); /* 1 second */ add_timer(&switch_link_timer); } } if (!link_init_done) { if (switch_irq != -1) { /* Interrupt supported */ mv_eth_switch_interrupt_unmask(qsgmii_module, gephy_on_port); if (request_irq(switch_irq, mv_switch_isr, (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "switch", NULL)) printk(KERN_ERR "failed to assign irq%d\n", switch_irq); } } link_init_done = 1; return connected_phys_mask; #endif /* CONFIG_MV_ETH_SWITCH_LINK */ }
int mv_switch_init(int mtu, unsigned int switch_ports_mask) { unsigned int p; unsigned char cnt; GT_LPORT port_list[MAX_SWITCH_PORTS]; if (qd_dev == NULL) { printk(KERN_ERR "%s: qd_dev not initialized, call mv_switch_load() first\n", __func__); return -1; } /* general Switch initialization - relevant for all Switch devices */ /* disable all ports */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) if (gstpSetPortState(qd_dev, p, GT_PORT_DISABLE) != GT_OK) { printk(KERN_ERR "gstpSetPortState failed\n"); return -1; } } /* flush All counters for all ports */ if (gstatsFlushAll(qd_dev) != GT_OK) printk(KERN_ERR "gstatsFlushAll failed\n"); /* set all ports not to unmodify the vlan tag on egress */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) { if (gprtSetEgressMode(qd_dev, p, GT_UNMODIFY_EGRESS) != GT_OK) { printk(KERN_ERR "gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n"); return -1; } } } /* initializes the PVT Table (cross-chip port based VLAN) to all one's (initial state) */ if (gpvtInitialize(qd_dev) != GT_OK) { printk(KERN_ERR "gpvtInitialize failed\n"); return -1; } /* set all ports to work in Normal mode */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) { if (gprtSetFrameMode(qd_dev, p, GT_FRAME_MODE_NORMAL) != GT_OK) { printk(KERN_ERR "gprtSetFrameMode GT_FRAME_MODE_NORMAL failed\n"); return -1; } } } /* set priorities rules */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) { /* default port priority to queue zero */ if (gcosSetPortDefaultTc(qd_dev, p, 0) != GT_OK) printk(KERN_ERR "gcosSetPortDefaultTc failed (port %d)\n", p); /* enable IP TOS Prio */ if (gqosIpPrioMapEn(qd_dev, p, GT_TRUE) != GT_OK) printk(KERN_ERR "gqosIpPrioMapEn failed (port %d)\n", p); /* set IP QoS */ if (gqosSetPrioMapRule(qd_dev, p, GT_FALSE) != GT_OK) printk(KERN_ERR "gqosSetPrioMapRule failed (port %d)\n", p); /* disable Vlan QoS Prio */ if (gqosUserPrioMapEn(qd_dev, p, GT_FALSE) != GT_OK) printk(KERN_ERR "gqosUserPrioMapEn failed (port %d)\n", p); } } /* specific Switch initialization according to Switch ID */ switch (qd_dev->deviceId) { case GT_88E6161: case GT_88E6165: case GT_88E6171: case GT_88E6351: case GT_88E6172: case GT_88E6176: /* set Header Mode in all ports to False */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) { if (gprtSetHeaderMode(qd_dev, p, GT_FALSE) != GT_OK) { printk(KERN_ERR "gprtSetHeaderMode GT_FALSE failed\n"); return -1; } } } if (gprtSetHeaderMode(qd_dev, qd_cpu_port, GT_TRUE) != GT_OK) { printk(KERN_ERR "gprtSetHeaderMode GT_TRUE failed\n"); return -1; } mv_switch_jumbo_mode_set(mtu); break; default: printk(KERN_ERR "Unsupported Switch. Switch ID is 0x%X.\n", qd_dev->deviceId); return -1; } /* The switch CPU port is not part of the VLAN, but rather connected by tunneling to each */ /* of the VLAN's ports. Our MAC addr will be added during start operation to the VLAN DB */ /* at switch level to forward packets with this DA to CPU port. */ SWITCH_DBG(SWITCH_DBG_LOAD, ("Enabling Tunneling on ports: ")); for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p) && (p != qd_cpu_port)) { if (gprtSetVlanTunnel(qd_dev, p, GT_TRUE) != GT_OK) { printk(KERN_ERR "gprtSetVlanTunnel failed (port %d)\n", p); return -1; } else { SWITCH_DBG(SWITCH_DBG_LOAD, ("%d ", p)); } } } SWITCH_DBG(SWITCH_DBG_LOAD, ("\n")); /* set cpu-port with port-based vlan to all other ports */ SWITCH_DBG(SWITCH_DBG_LOAD, ("cpu port-based vlan:")); for (p = 0, cnt = 0; p < qd_dev->numOfPorts; p++) { if (p != qd_cpu_port) { SWITCH_DBG(SWITCH_DBG_LOAD, ("%d ", p)); port_list[cnt] = p; cnt++; } } SWITCH_DBG(SWITCH_DBG_LOAD, ("\n")); if (gvlnSetPortVlanPorts(qd_dev, qd_cpu_port, port_list, cnt) != GT_OK) { printk(KERN_ERR "gvlnSetPortVlanPorts failed\n"); return -1; } if (gfdbFlush(qd_dev, GT_FLUSH_ALL) != GT_OK) printk(KERN_ERR "gfdbFlush failed\n"); mv_switch_link_detection_init(); /* Configure Ethernet related LEDs, currently according to Switch ID */ switch (qd_dev->deviceId) { case GT_88E6161: case GT_88E6165: case GT_88E6171: case GT_88E6351: case GT_88E6172: case GT_88E6176: break; /* do nothing */ default: for (p = 0; p < qd_dev->numOfPorts; p++) { if ((p != qd_cpu_port) && ((p))) { if (gprtSetPhyReg(qd_dev, p, 22, 0x1FFA)) { /* Configure Register 22 LED0 to 0xA for Link/Act */ printk(KERN_ERR "gprtSetPhyReg failed (port=%d)\n", p); } } } break; } /* enable all relevant ports (ports connected to the MAC or external ports) */ for (p = 0; p < qd_dev->numOfPorts; p++) { if (MV_BIT_CHECK(switch_ports_mask, p)) { if ((mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p) != -1) || (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) == p) || (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) == p)) { if (gstpSetPortState(qd_dev, p, GT_PORT_FORWARDING) != GT_OK) { printk(KERN_ERR "gstpSetPortState failed\n"); return -1; } } } } #ifdef SWITCH_DEBUG /* for debug: */ mv_switch_status_print(); #endif return 0; }
int mv_switch_load(unsigned int switch_ports_mask) { int p; GT_STU_ENTRY stuEntry; printk(KERN_ERR " o Loading Switch QuarterDeck driver\n"); if (qd_dev) { printk(KERN_ERR " o %s: Already initialized\n", __func__); return 0; } memset((char *)&qd_cfg, 0, sizeof(GT_SYS_CONFIG)); spin_lock_init(&switch_lock); /* init config structure for qd package */ qd_cfg.BSPFunctions.readMii = mv_switch_mii_read; qd_cfg.BSPFunctions.writeMii = mv_switch_mii_write; qd_cfg.BSPFunctions.semCreate = NULL; qd_cfg.BSPFunctions.semDelete = NULL; qd_cfg.BSPFunctions.semTake = NULL; qd_cfg.BSPFunctions.semGive = NULL; qd_cfg.initPorts = GT_TRUE; qd_cfg.cpuPortNum = mvBoardSwitchCpuPortGet(MV_SWITCH_DEF_INDEX); if (mvBoardSmiScanModeGet(MV_SWITCH_DEF_INDEX) == 1) { qd_cfg.mode.baseAddr = 0; qd_cfg.mode.scanMode = SMI_MANUAL_MODE; } else if (mvBoardSmiScanModeGet(MV_SWITCH_DEF_INDEX) == 2) { qd_cfg.mode.scanMode = SMI_MULTI_ADDR_MODE; if (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) != -1) { qd_cfg.mode.baseAddr = mvBoardPhyAddrGet(MV_ETH_PORT_0); } else if (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) != -1) { qd_cfg.mode.baseAddr = mvBoardPhyAddrGet(MV_ETH_PORT_1); } else { printk(KERN_ERR "mv_switch_load failed: Wrong SCAN mode\n"); return -1; } } /* load switch sw package */ if (qdLoadDriver(&qd_cfg, &qddev) != GT_OK) { printk(KERN_ERR "qdLoadDriver failed\n"); return -1; } qd_dev = &qddev; qd_cpu_port = qd_cfg.cpuPortNum; /* Create entry in STU table */ memset(&stuEntry, 0, sizeof(GT_STU_ENTRY)); stuEntry.sid = 1; /* required: ((sid > 0) && (sid < 0x3F)) */ gstuAddEntry(qd_dev, &stuEntry); printk(KERN_ERR " o Device ID : 0x%x\n", qd_dev->deviceId); printk(KERN_ERR " o No. of Ports : %d\n", qd_dev->numOfPorts); printk(KERN_ERR " o CPU Port : %ld\n", qd_dev->cpuPortNum); qsgmii_module = mvBoardIsQsgmiiModuleConnected(); if (qsgmii_module) printk(KERN_ERR " o QSGMII Module Detected\n"); gephy_on_port = mvBoardGePhySwitchPortGet(); if (gephy_on_port >= 0) printk(KERN_ERR " o Internal GE PHY Connected to Switch Port %d Detected\n", gephy_on_port); rgmiia_on_port = mvBoardRgmiiASwitchPortGet(); if (rgmiia_on_port >= 0) printk(KERN_ERR " o RGMII-A Connected to Switch Port %d Detected\n", rgmiia_on_port); /* disable all disconnected ports */ for (p = 0; p < qd_dev->numOfPorts; p++) { /* Do nothing for ports that are not part of the given switch_port_mask */ if (!MV_BIT_CHECK(switch_ports_mask, p)) continue; if (mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p) != -1) { /* Switch port mapped to connector on the board */ if ((gpcsSetFCValue(qd_dev, p, GT_FALSE) != GT_OK) || (gpcsSetForcedFC(qd_dev, p, GT_FALSE) != GT_OK)) { printk(KERN_ERR "Force Flow Control - Failed\n"); return -1; } #if 0 /* TODO - decide if we want to enable auto-negotiation of Flow Control for external ports */ if (qsgmii_module) { /* TODO - configure ports via QSGMII registers */ } else { GT_STATUS status; status = gprtSetPause(qd_dev, p, GT_PHY_PAUSE); if (status != GT_OK) printk(KERN_ERR "Failed set pause for switch port #%d: status = %d\n", p, status); } #endif continue; } if ((mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) == p) || (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) == p)) { /* Switch port connected to GMAC - force link UP - 1000 Full with FC */ printk(KERN_ERR " o Setting Switch Port #%d connected to GMAC port for 1000 Full with FC\n", p); if (gpcsSetForceSpeed(qd_dev, p, PORT_FORCE_SPEED_1000_MBPS) != GT_OK) { printk(KERN_ERR "Force speed 1000mbps - Failed\n"); return -1; } if ((gpcsSetDpxValue(qd_dev, p, GT_TRUE) != GT_OK) || (gpcsSetForcedDpx(qd_dev, p, GT_TRUE) != GT_OK)) { printk(KERN_ERR "Force duplex FULL - Failed\n"); return -1; } if ((gpcsSetFCValue(qd_dev, p, GT_TRUE) != GT_OK) || (gpcsSetForcedFC(qd_dev, p, GT_TRUE) != GT_OK)) { printk(KERN_ERR "Force Flow Control - Failed\n"); return -1; } if ((gpcsSetLinkValue(qd_dev, p, GT_TRUE) != GT_OK) || (gpcsSetForcedLink(qd_dev, p, GT_TRUE) != GT_OK)) { printk(KERN_ERR "Force Link UP - Failed\n"); return -1; } continue; } printk(KERN_ERR " o Disable disconnected Switch Port #%d and force link down\n", p); if (gstpSetPortState(qd_dev, p, GT_PORT_DISABLE) != GT_OK) { printk(KERN_ERR "gstpSetPortState failed\n"); return -1; } if ((gpcsSetLinkValue(qd_dev, p, GT_FALSE) != GT_OK) || (gpcsSetForcedLink(qd_dev, p, GT_TRUE) != GT_OK)) { printk(KERN_ERR "Force Link DOWN - Failed\n"); return -1; } } return 0; }
void mv_gtw_set_multicast_list(struct net_device *dev) { struct dev_mc_list *curr_addr = dev->mc_list; struct mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev); int i; GT_ATU_ENTRY mac_entry; GT_BOOL found = GT_FALSE; GT_STATUS status; if((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) { /* promiscuous mode - connect the CPU port to the VLAN (port based + 802.1q) */ /* if(dev->flags & IFF_PROMISC) printk("mv_gateway: setting promiscuous mode\n"); if(dev->flags & IFF_ALLMULTI) printk("mv_gateway: setting multicast promiscuous mode\n"); */ mv_gtw_set_port_based_vlan(vlan_cfg->ports_mask|(1<<SWITCH_PORT_CPU)); for(i=0; i<qd_dev->numOfPorts; i++) { if(MV_BIT_CHECK(vlan_cfg->ports_mask, i) && (i!=SWITCH_PORT_CPU)) { if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(vlan_cfg->vlan_grp_id,i), vlan_cfg->ports_mask | (1<<SWITCH_PORT_CPU)) != 0) { printk("mv_gtw_set_vlan_in_vtu failed\n"); } } } } else { /* not in promiscuous or allmulti mode - disconnect the CPU port to the VLAN (port based + 802.1q) */ mv_gtw_set_port_based_vlan(vlan_cfg->ports_mask&(~(1<<SWITCH_PORT_CPU))); for(i=0; i<qd_dev->numOfPorts; i++) { if(MV_BIT_CHECK(vlan_cfg->ports_mask, i) && (i!=SWITCH_PORT_CPU)) { if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(vlan_cfg->vlan_grp_id,i),vlan_cfg->ports_mask&(~(1<<SWITCH_PORT_CPU))) != 0) { printk("mv_gtw_set_vlan_in_vtu failed\n"); } } } if(dev->mc_count) { /* accept specific multicasts */ for(i=0; i<dev->mc_count; i++, curr_addr = curr_addr->next) { if (!curr_addr) break; /* The Switch may already have information about this multicast address in */ /* its ATU. If this address is already in the ATU, use the existing port vector */ /* ORed with the CPU port. Otherwise, just use the CPU port. */ memset(&mac_entry,0,sizeof(GT_ATU_ENTRY)); mac_entry.DBNum = MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id); memcpy(mac_entry.macAddr.arEther, curr_addr->dmi_addr, 6); status = gfdbFindAtuMacEntry(qd_dev, &mac_entry, &found); if ( (status != GT_OK) || (found != GT_TRUE) ) { mv_gtw_set_mac_addr_to_switch(curr_addr->dmi_addr, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), (1<<SWITCH_PORT_CPU)|(vlan_cfg->ports_mask), 1); } else { mv_gtw_set_mac_addr_to_switch(curr_addr->dmi_addr, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), (mac_entry.portVec | (1<<SWITCH_PORT_CPU)), 1); } } } } }
int mv_switch_unload(unsigned int switch_ports_mask) { int i; printk(KERN_ERR " o Unloading Switch QuarterDeck driver\n"); if (qd_dev == NULL) { printk(KERN_ERR " o %s: Already un-initialized\n", __func__); return 0; } /* Flush all addresses from the MAC address table */ /* this also happens in mv_switch_init() but we call it here to clean-up nicely */ /* Note: per DB address flush (gfdbFlushInDB) happens when doing ifconfig down on a Switch interface */ if (gfdbFlush(qd_dev, GT_FLUSH_ALL) != GT_OK) printk(KERN_ERR "gfdbFlush failed\n"); /* Reset VLAN tunnel mode */ for (i = 0; i < qd_dev->numOfPorts; i++) { if (MV_BIT_CHECK(switch_ports_mask, i) && (i != qd_cpu_port)) if (gprtSetVlanTunnel(qd_dev, i, GT_FALSE) != GT_OK) printk(KERN_ERR "gprtSetVlanTunnel failed (port %d)\n", i); } /* restore port's default private vlan id and database number to their default values after reset: */ for (i = 0; i < qd_dev->numOfPorts; i++) { if (gvlnSetPortVid(qd_dev, i, 0x0001) != GT_OK) { /* that's the default according to the spec */ printk(KERN_ERR "gvlnSetPortVid failed\n"); return -1; } if (gvlnSetPortVlanDBNum(qd_dev, i, 0) != GT_OK) { printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n"); return -1; } } /* Port based VLAN */ if (mv_switch_port_based_vlan_set(switch_ports_mask, 1)) printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n"); /* Remove all entries from the VTU table */ if (gvtuFlush(qd_dev) != GT_OK) printk(KERN_ERR "gvtuFlush failed\n"); /* unload switch sw package */ if (qdUnloadDriver(qd_dev) != GT_OK) { printk(KERN_ERR "qdUnloadDriver failed\n"); return -1; } qd_dev = NULL; qd_cpu_port = -1; qsgmii_module = 0; gephy_on_port = -1; rgmiia_on_port = -1; #ifdef CONFIG_MV_ETH_SWITCH_LINK switch_irq = -1; switch_link_poll = 0; del_timer(&switch_link_timer); #endif /* CONFIG_MV_ETH_SWITCH_LINK */ return 0; }
/* time_mode: 0 - time stamp normalized to oldest message, 1 - difference from previous message */ void TRC_OUTPUT(int cpu_mask, int time_mode) { int i, last, next, cpu, active; struct trace *p; struct timeval *tv_base; active = trc_active; trc_active = 0; if (cpu_mask == 0) cpu = smp_processor_id(); else { for_each_possible_cpu(cpu) { if (MV_BIT_CHECK(cpu_mask, cpu)) break; } } next = trc_index[cpu]; last = mv_trace_prev_idx(next); p = &trc_arr[cpu][last]; if (p->valid == 0) { printk(KERN_INFO "\nTrace: cpu=%d - No valid entries\n", cpu); return; } /* Find first valid entry */ i = next; while (i != last) { p = &trc_arr[cpu][i]; if (p->valid) break; i = mv_trace_next_idx(i); } tv_base = &trc_arr[cpu][i].tv; printk(KERN_INFO "\nTrace: cpu=%d, first=%d, last=%d, base time: %lu sec, %lu usec\n", cpu, i, last, tv_base->tv_sec, tv_base->tv_usec); printk(KERN_INFO "\n No CPU [s : ms : us] message\n"); do { unsigned int sec, msec, usec; p = &trc_arr[cpu][i]; sec = p->tv.tv_sec - tv_base->tv_sec; if (p->tv.tv_usec >= tv_base->tv_usec) usec = (p->tv.tv_usec - tv_base->tv_usec); else { sec--; usec = 1000000 - (tv_base->tv_usec - p->tv.tv_usec); } msec = usec / 1000; usec = usec % 1000; printk(KERN_INFO "%03d: %d: [%02u:%03u:%03u]: ", i, cpu, sec, msec, usec); printk(KERN_INFO "%s", p->str); i = mv_trace_next_idx(i); if (time_mode == 1) tv_base = &p->tv; } while (i != next); memset(trc_arr[cpu], 0, TRACE_ARR_LEN * sizeof(struct trace)); trc_index[cpu] = 0; trc_active = active; }