Skip to content
Permalink
Browse files
net: dsa: rtl8367: add rtk_vlan_portPvid_set
  • Loading branch information
frank-w committed Nov 14, 2021
1 parent 5c74980 commit e011078a3905661586c48399e06ab99ab4be40c2
Show file tree
Hide file tree
Showing 2 changed files with 280 additions and 1 deletion.
@@ -966,6 +966,18 @@ static void _rtl8367c_Vlan4kStUser2Smi(rtl8367c_user_vlan4kentry *pUserVlan4kEnt
pSmiVlan4kEntry[2] |= ((pUserVlan4kEntry->meteridx & 0x0020) >> 5) << 6;
}

static void _rtl8367c_Vlan4kStSmi2User(rtk_uint16 *pSmiVlan4kEntry, rtl8367c_user_vlan4kentry *pUserVlan4kEntry)
{
pUserVlan4kEntry->mbr = (pSmiVlan4kEntry[0] & 0x00FF) | ((pSmiVlan4kEntry[2] & 0x0007) << 8);
pUserVlan4kEntry->untag = ((pSmiVlan4kEntry[0] & 0xFF00) >> 8) | (((pSmiVlan4kEntry[2] & 0x0038) >> 3) << 8);
pUserVlan4kEntry->fid_msti = pSmiVlan4kEntry[1] & 0x000F;
pUserVlan4kEntry->vbpen = (pSmiVlan4kEntry[1] & 0x0010) >> 4;
pUserVlan4kEntry->vbpri = (pSmiVlan4kEntry[1] & 0x00E0) >> 5;
pUserVlan4kEntry->envlanpol = (pSmiVlan4kEntry[1] & 0x0100) >> 8;
pUserVlan4kEntry->meteridx = ((pSmiVlan4kEntry[1] & 0x3E00) >> 9) | (((pSmiVlan4kEntry[2] & 0x0040) >> 6) << 5);
pUserVlan4kEntry->ivl_svl = (pSmiVlan4kEntry[1] & 0x4000) >> 14;
}

static void _rtl8367c_VlanMCStUser2Smi(rtl8367c_vlanconfiguser *pVlanCg, rtk_uint16 *pSmiVlanCfg)
{
pSmiVlanCfg[0] |= pVlanCg->mbr & 0x07FF;
@@ -980,6 +992,89 @@ static void _rtl8367c_VlanMCStUser2Smi(rtl8367c_vlanconfiguser *pVlanCg, rtk_uin
pSmiVlanCfg[3] |= pVlanCg->evid & 0x1FFF;
}

static void _rtl8367c_VlanMCStSmi2User(rtk_uint16 *pSmiVlanCfg, rtl8367c_vlanconfiguser *pVlanCg)
{
pVlanCg->mbr = pSmiVlanCfg[0] & 0x07FF;
pVlanCg->fid_msti = pSmiVlanCfg[1] & 0x000F;
pVlanCg->meteridx = (pSmiVlanCfg[2] >> 5) & 0x003F;
pVlanCg->envlanpol = (pSmiVlanCfg[2] >> 4) & 0x0001;
pVlanCg->vbpri = (pSmiVlanCfg[2] >> 1) & 0x0007;
pVlanCg->vbpen = pSmiVlanCfg[2] & 0x0001;
pVlanCg->evid = pSmiVlanCfg[3] & 0x1FFF;
}

ret_t rtl8367c_getAsicVlan4kEntry(rtl8367c_user_vlan4kentry *pVlan4kEntry )
{
rtk_uint16 vlan_4k_entry[RTL8367C_VLAN_4KTABLE_LEN];
rtk_uint32 page_idx;
rtk_uint16 *tableAddr;
ret_t retVal;
rtk_uint32 regData;
rtk_uint32 busyCounter;

if(pVlan4kEntry->vid > RTL8367C_VIDMAX)
return RT_ERR_VLAN_VID;

/* Polling status */
busyCounter = RTL8367C_VLAN_BUSY_CHECK_NO;
while(busyCounter)
{
retVal = rtl8367c_getAsicRegBit(RTL8367C_TABLE_ACCESS_STATUS_REG, RTL8367C_TABLE_LUT_ADDR_BUSY_FLAG_OFFSET,&regData);
if(retVal != RT_ERR_OK)
return retVal;

if(regData == 0)
break;

busyCounter --;
if(busyCounter == 0)
return RT_ERR_BUSYWAIT_TIMEOUT;
}

/* Write Address (VLAN_ID) */
regData = pVlan4kEntry->vid;
retVal = rtl8367c_setAsicReg(RTL8367C_TABLE_ACCESS_ADDR_REG, regData);
if(retVal != RT_ERR_OK)
return retVal;

/* Read Command */
retVal = rtl8367c_setAsicRegBits(RTL8367C_TABLE_ACCESS_CTRL_REG, RTL8367C_TABLE_TYPE_MASK | RTL8367C_COMMAND_TYPE_MASK, RTL8367C_TABLE_ACCESS_REG_DATA(TB_OP_READ,TB_TARGET_CVLAN));
if(retVal != RT_ERR_OK)
return retVal;

/* Polling status */
busyCounter = RTL8367C_VLAN_BUSY_CHECK_NO;
while(busyCounter)
{
retVal = rtl8367c_getAsicRegBit(RTL8367C_TABLE_ACCESS_STATUS_REG, RTL8367C_TABLE_LUT_ADDR_BUSY_FLAG_OFFSET,&regData);
if(retVal != RT_ERR_OK)
return retVal;

if(regData == 0)
break;

busyCounter --;
if(busyCounter == 0)
return RT_ERR_BUSYWAIT_TIMEOUT;
}

/* Read VLAN data from register */
tableAddr = vlan_4k_entry;
for(page_idx = 0; page_idx < RTL8367C_VLAN_4KTABLE_LEN; page_idx++)
{
retVal = rtl8367c_getAsicReg(RTL8367C_TABLE_ACCESS_RDDATA_BASE + page_idx, &regData);
if(retVal != RT_ERR_OK)
return retVal;

*tableAddr = regData;
tableAddr++;
}

_rtl8367c_Vlan4kStSmi2User(vlan_4k_entry, pVlan4kEntry);

return RT_ERR_OK;
}

ret_t rtl8367c_setAsicVlan4kEntry(rtl8367c_user_vlan4kentry *pVlan4kEntry )
{
rtk_uint16 vlan_4k_entry[RTL8367C_VLAN_4KTABLE_LEN];
@@ -1035,6 +1130,37 @@ ret_t rtl8367c_setAsicVlan4kEntry(rtl8367c_user_vlan4kentry *pVlan4kEntry )
return RT_ERR_OK;
}

ret_t rtl8367c_getAsicVlanMemberConfig(rtk_uint32 index, rtl8367c_vlanconfiguser *pVlanCg)
{
ret_t retVal;
rtk_uint32 page_idx;
rtk_uint32 regAddr;
rtk_uint32 regData;
rtk_uint16 *tableAddr;
rtk_uint16 smi_vlancfg[RTL8367C_VLAN_MBRCFG_LEN];

if(index > RTL8367C_CVIDXMAX)
return RT_ERR_VLAN_ENTRY_NOT_FOUND;

memset(smi_vlancfg, 0x00, sizeof(rtk_uint16) * RTL8367C_VLAN_MBRCFG_LEN);
tableAddr = smi_vlancfg;

for(page_idx = 0; page_idx < 4; page_idx++) /* 4 pages per VLAN Member Config */
{
regAddr = RTL8367C_VLAN_MEMBER_CONFIGURATION_BASE + (index * 4) + page_idx;

retVal = rtl8367c_getAsicReg(regAddr, &regData);
if(retVal != RT_ERR_OK)
return retVal;

*tableAddr = (rtk_uint16)regData;
tableAddr++;
}

_rtl8367c_VlanMCStSmi2User(smi_vlancfg, pVlanCg);
return RT_ERR_OK;
}

ret_t rtl8367c_setAsicVlanMemberConfig(rtk_uint32 index, rtl8367c_vlanconfiguser *pVlanCg)
{
ret_t retVal;
@@ -1514,7 +1640,153 @@ rtk_api_ret_t rtk_vlan_init(void)
return RT_ERR_OK;
}

rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority) {return 0;}
rtk_api_ret_t rtk_vlan_checkAndCreateMbr(rtk_vlan_t vid, rtk_uint32 *pIndex)
{
rtk_api_ret_t retVal;
rtl8367c_user_vlan4kentry vlan4K;
rtl8367c_vlanconfiguser vlanMC;
rtk_uint32 idx;
rtk_uint32 empty_idx = 0xFFFF;

/* Check initialization state */
RTK_CHK_INIT_STATE();

/* vid must be 0~8191 */
if (vid > RTL8367C_EVIDMAX)
return RT_ERR_VLAN_VID;

/* Null pointer check */
if(NULL == pIndex)
return RT_ERR_NULL_POINTER;

/* Get 4K VLAN */
if (vid <= RTL8367C_VIDMAX)
{
memset(&vlan4K, 0x00, sizeof(rtl8367c_user_vlan4kentry));
vlan4K.vid = vid;
if ((retVal = rtl8367c_getAsicVlan4kEntry(&vlan4K)) != RT_ERR_OK)
return retVal;
}

/* Search exist entry */
for (idx = 0; idx <= RTL8367C_CVIDXMAX; idx++)
{
if(vlan_mbrCfgUsage[idx] == MBRCFG_USED_BY_VLAN)
{
if(vlan_mbrCfgVid[idx] == vid)
{
/* Found! return index */
*pIndex = idx;
return RT_ERR_OK;
}
}
}

/* Not found, Read H/W Member Configuration table to update database */
for (idx = 0; idx <= RTL8367C_CVIDXMAX; idx++)
{
if ((retVal = rtl8367c_getAsicVlanMemberConfig(idx, &vlanMC)) != RT_ERR_OK)
return retVal;

if( (vlanMC.evid == 0) && (vlanMC.mbr == 0x00))
{
vlan_mbrCfgUsage[idx] = MBRCFG_UNUSED;
vlan_mbrCfgVid[idx] = 0;
}
else
{
vlan_mbrCfgUsage[idx] = MBRCFG_USED_BY_VLAN;
vlan_mbrCfgVid[idx] = vlanMC.evid;
}
}

/* Search exist entry again */
for (idx = 0; idx <= RTL8367C_CVIDXMAX; idx++)
{
if(vlan_mbrCfgUsage[idx] == MBRCFG_USED_BY_VLAN)
{
if(vlan_mbrCfgVid[idx] == vid)
{
/* Found! return index */
*pIndex = idx;
return RT_ERR_OK;
}
}
}

/* try to look up an empty index */
for (idx = 0; idx <= RTL8367C_CVIDXMAX; idx++)
{
if(vlan_mbrCfgUsage[idx] == MBRCFG_UNUSED)
{
empty_idx = idx;
break;
}
}

if(empty_idx == 0xFFFF)
{
/* No empty index */
return RT_ERR_TBL_FULL;
}

if (vid > RTL8367C_VIDMAX)
{
/* > 4K, there is no 4K entry, create on member configuration directly */
memset(&vlanMC, 0x00, sizeof(rtl8367c_vlanconfiguser));
vlanMC.evid = vid;
if ((retVal = rtl8367c_setAsicVlanMemberConfig(empty_idx, &vlanMC)) != RT_ERR_OK)
return retVal;
}
else
{
/* Copy from 4K table */
vlanMC.evid = vid;
vlanMC.mbr = vlan4K.mbr;
vlanMC.fid_msti = vlan4K.fid_msti;
vlanMC.meteridx= vlan4K.meteridx;
vlanMC.envlanpol= vlan4K.envlanpol;
vlanMC.vbpen = vlan4K.vbpen;
vlanMC.vbpri = vlan4K.vbpri;
if ((retVal = rtl8367c_setAsicVlanMemberConfig(empty_idx, &vlanMC)) != RT_ERR_OK)
return retVal;
}

/* Update Database */
vlan_mbrCfgUsage[empty_idx] = MBRCFG_USED_BY_VLAN;
vlan_mbrCfgVid[empty_idx] = vid;

*pIndex = empty_idx;
return RT_ERR_OK;
}

rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority)
{
rtk_api_ret_t retVal;
rtk_uint32 index;

/* Check initialization state */
RTK_CHK_INIT_STATE();

/* Check Port Valid */
RTK_CHK_PORT_VALID(port);

/* vid must be 0~8191 */
if (pvid > RTL8367C_EVIDMAX)
return RT_ERR_VLAN_VID;

/* priority must be 0~7 */
if (priority > RTL8367C_PRIMAX)
return RT_ERR_VLAN_PRIORITY;

if((retVal = rtk_vlan_checkAndCreateMbr(pvid, &index)) != RT_ERR_OK)
return retVal;

if ((retVal = rtl8367c_setAsicVlanPortBasedVID(rtk_switch_port_L2P_get(port), index, priority)) != RT_ERR_OK)
return retVal;

return RT_ERR_OK;
}

rtk_api_ret_t rtk_vlan_set(rtk_vlan_t vid, rtk_vlan_cfg_t *pVlanCfg)
{
@@ -143,6 +143,13 @@ typedef unsigned int rtk_uint32;
#define RTL8367C_REG_VLAN_EXT_CTRL2 0x07b6
#define RTL8367C_VLAN_EXT_CTRL2_OFFSET 0

#define RTL8367C_VLAN_BUSY_CHECK_NO (10)
#define RTL8367C_REG_TABLE_LUT_ADDR 0x0502
#define RTL8367C_TABLE_ACCESS_STATUS_REG RTL8367C_REG_TABLE_LUT_ADDR
#define RTL8367C_TABLE_LUT_ADDR_BUSY_FLAG_OFFSET 13
#define RTL8367C_REG_TABLE_READ_DATA0 0x0520
#define RTL8367C_TABLE_ACCESS_RDDATA_BASE RTL8367C_REG_TABLE_READ_DATA0

enum RTL8367C_TABLE_ACCESS_OP
{
TB_OP_READ = 0,

0 comments on commit e011078

Please sign in to comment.