Example #1
0
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;
}
Example #2
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");
}
Example #4
0
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));
				}
			}
		}
	}
}
Example #5
0
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;
}
Example #6
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;
}
Example #7
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;
}
Example #8
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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
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=&gtw_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, &gt_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;
}
Example #12
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;
}
Example #13
0
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, &gt_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 */
}
Example #14
0
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;
}
Example #15
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;
}
Example #16
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);
		        }
	        }
	    }
    }
}
Example #17
0
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;
}
Example #18
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;

}