Skip to content

Commit f3b03c6

Browse files
Mengyuan Loukuba-moo
authored andcommitted
net: wangxun: Implement vlan add and kill functions
Implement vlan add/kill functions which add and remove vlan id in hardware. Signed-off-by: Mengyuan Lou <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ef4f3c1 commit f3b03c6

File tree

4 files changed

+316
-2
lines changed

4 files changed

+316
-2
lines changed

drivers/net/ethernet/wangxun/libwx/wx_hw.c

Lines changed: 271 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1182,12 +1182,28 @@ static void wx_enable_sec_rx_path(struct wx *wx)
11821182
WX_WRITE_FLUSH(wx);
11831183
}
11841184

1185+
static void wx_vlan_strip_control(struct wx *wx, bool enable)
1186+
{
1187+
int i, j;
1188+
1189+
for (i = 0; i < wx->num_rx_queues; i++) {
1190+
struct wx_ring *ring = wx->rx_ring[i];
1191+
1192+
j = ring->reg_idx;
1193+
wr32m(wx, WX_PX_RR_CFG(j), WX_PX_RR_CFG_VLAN,
1194+
enable ? WX_PX_RR_CFG_VLAN : 0);
1195+
}
1196+
}
1197+
11851198
void wx_set_rx_mode(struct net_device *netdev)
11861199
{
11871200
struct wx *wx = netdev_priv(netdev);
1201+
netdev_features_t features;
11881202
u32 fctrl, vmolr, vlnctrl;
11891203
int count;
11901204

1205+
features = netdev->features;
1206+
11911207
/* Check for Promiscuous and All Multicast modes */
11921208
fctrl = rd32(wx, WX_PSR_CTL);
11931209
fctrl &= ~(WX_PSR_CTL_UPE | WX_PSR_CTL_MPE);
@@ -1254,6 +1270,13 @@ void wx_set_rx_mode(struct net_device *netdev)
12541270
wr32(wx, WX_PSR_VLAN_CTL, vlnctrl);
12551271
wr32(wx, WX_PSR_CTL, fctrl);
12561272
wr32(wx, WX_PSR_VM_L2CTL(0), vmolr);
1273+
1274+
if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
1275+
(features & NETIF_F_HW_VLAN_STAG_RX))
1276+
wx_vlan_strip_control(wx, true);
1277+
else
1278+
wx_vlan_strip_control(wx, false);
1279+
12571280
}
12581281
EXPORT_SYMBOL(wx_set_rx_mode);
12591282

@@ -1462,6 +1485,16 @@ static void wx_configure_tx(struct wx *wx)
14621485
WX_MAC_TX_CFG_TE, WX_MAC_TX_CFG_TE);
14631486
}
14641487

1488+
static void wx_restore_vlan(struct wx *wx)
1489+
{
1490+
u16 vid = 1;
1491+
1492+
wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), 0);
1493+
1494+
for_each_set_bit_from(vid, wx->active_vlans, VLAN_N_VID)
1495+
wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
1496+
}
1497+
14651498
/**
14661499
* wx_configure_rx - Configure Receive Unit after Reset
14671500
* @wx: pointer to private structure
@@ -1527,7 +1560,7 @@ void wx_configure(struct wx *wx)
15271560
wx_configure_port(wx);
15281561

15291562
wx_set_rx_mode(wx->netdev);
1530-
1563+
wx_restore_vlan(wx);
15311564
wx_enable_sec_rx_path(wx);
15321565

15331566
wx_configure_tx(wx);
@@ -1727,4 +1760,241 @@ int wx_sw_init(struct wx *wx)
17271760
}
17281761
EXPORT_SYMBOL(wx_sw_init);
17291762

1763+
/**
1764+
* wx_find_vlvf_slot - find the vlanid or the first empty slot
1765+
* @wx: pointer to hardware structure
1766+
* @vlan: VLAN id to write to VLAN filter
1767+
*
1768+
* return the VLVF index where this VLAN id should be placed
1769+
*
1770+
**/
1771+
static int wx_find_vlvf_slot(struct wx *wx, u32 vlan)
1772+
{
1773+
u32 bits = 0, first_empty_slot = 0;
1774+
int regindex;
1775+
1776+
/* short cut the special case */
1777+
if (vlan == 0)
1778+
return 0;
1779+
1780+
/* Search for the vlan id in the VLVF entries. Save off the first empty
1781+
* slot found along the way
1782+
*/
1783+
for (regindex = 1; regindex < WX_PSR_VLAN_SWC_ENTRIES; regindex++) {
1784+
wr32(wx, WX_PSR_VLAN_SWC_IDX, regindex);
1785+
bits = rd32(wx, WX_PSR_VLAN_SWC);
1786+
if (!bits && !(first_empty_slot))
1787+
first_empty_slot = regindex;
1788+
else if ((bits & 0x0FFF) == vlan)
1789+
break;
1790+
}
1791+
1792+
if (regindex >= WX_PSR_VLAN_SWC_ENTRIES) {
1793+
if (first_empty_slot)
1794+
regindex = first_empty_slot;
1795+
else
1796+
regindex = -ENOMEM;
1797+
}
1798+
1799+
return regindex;
1800+
}
1801+
1802+
/**
1803+
* wx_set_vlvf - Set VLAN Pool Filter
1804+
* @wx: pointer to hardware structure
1805+
* @vlan: VLAN id to write to VLAN filter
1806+
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
1807+
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
1808+
* @vfta_changed: pointer to boolean flag which indicates whether VFTA
1809+
* should be changed
1810+
*
1811+
* Turn on/off specified bit in VLVF table.
1812+
**/
1813+
static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
1814+
bool *vfta_changed)
1815+
{
1816+
int vlvf_index;
1817+
u32 vt, bits;
1818+
1819+
/* If VT Mode is set
1820+
* Either vlan_on
1821+
* make sure the vlan is in VLVF
1822+
* set the vind bit in the matching VLVFB
1823+
* Or !vlan_on
1824+
* clear the pool bit and possibly the vind
1825+
*/
1826+
vt = rd32(wx, WX_CFG_PORT_CTL);
1827+
if (!(vt & WX_CFG_PORT_CTL_NUM_VT_MASK))
1828+
return 0;
1829+
1830+
vlvf_index = wx_find_vlvf_slot(wx, vlan);
1831+
if (vlvf_index < 0)
1832+
return vlvf_index;
1833+
1834+
wr32(wx, WX_PSR_VLAN_SWC_IDX, vlvf_index);
1835+
if (vlan_on) {
1836+
/* set the pool bit */
1837+
if (vind < 32) {
1838+
bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
1839+
bits |= (1 << vind);
1840+
wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
1841+
} else {
1842+
bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
1843+
bits |= (1 << (vind - 32));
1844+
wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
1845+
}
1846+
} else {
1847+
/* clear the pool bit */
1848+
if (vind < 32) {
1849+
bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
1850+
bits &= ~(1 << vind);
1851+
wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
1852+
bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_H);
1853+
} else {
1854+
bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
1855+
bits &= ~(1 << (vind - 32));
1856+
wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
1857+
bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_L);
1858+
}
1859+
}
1860+
1861+
if (bits) {
1862+
wr32(wx, WX_PSR_VLAN_SWC, (WX_PSR_VLAN_SWC_VIEN | vlan));
1863+
if (!vlan_on && vfta_changed)
1864+
*vfta_changed = false;
1865+
} else {
1866+
wr32(wx, WX_PSR_VLAN_SWC, 0);
1867+
}
1868+
1869+
return 0;
1870+
}
1871+
1872+
/**
1873+
* wx_set_vfta - Set VLAN filter table
1874+
* @wx: pointer to hardware structure
1875+
* @vlan: VLAN id to write to VLAN filter
1876+
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
1877+
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
1878+
*
1879+
* Turn on/off specified VLAN in the VLAN filter table.
1880+
**/
1881+
static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
1882+
{
1883+
u32 bitindex, vfta, targetbit;
1884+
bool vfta_changed = false;
1885+
int regindex, ret;
1886+
1887+
/* this is a 2 part operation - first the VFTA, then the
1888+
* VLVF and VLVFB if VT Mode is set
1889+
* We don't write the VFTA until we know the VLVF part succeeded.
1890+
*/
1891+
1892+
/* Part 1
1893+
* The VFTA is a bitstring made up of 128 32-bit registers
1894+
* that enable the particular VLAN id, much like the MTA:
1895+
* bits[11-5]: which register
1896+
* bits[4-0]: which bit in the register
1897+
*/
1898+
regindex = (vlan >> 5) & 0x7F;
1899+
bitindex = vlan & 0x1F;
1900+
targetbit = (1 << bitindex);
1901+
/* errata 5 */
1902+
vfta = wx->mac.vft_shadow[regindex];
1903+
if (vlan_on) {
1904+
if (!(vfta & targetbit)) {
1905+
vfta |= targetbit;
1906+
vfta_changed = true;
1907+
}
1908+
} else {
1909+
if ((vfta & targetbit)) {
1910+
vfta &= ~targetbit;
1911+
vfta_changed = true;
1912+
}
1913+
}
1914+
/* Part 2
1915+
* Call wx_set_vlvf to set VLVFB and VLVF
1916+
*/
1917+
ret = wx_set_vlvf(wx, vlan, vind, vlan_on, &vfta_changed);
1918+
if (ret != 0)
1919+
return ret;
1920+
1921+
if (vfta_changed)
1922+
wr32(wx, WX_PSR_VLAN_TBL(regindex), vfta);
1923+
wx->mac.vft_shadow[regindex] = vfta;
1924+
1925+
return 0;
1926+
}
1927+
1928+
/**
1929+
* wx_clear_vfta - Clear VLAN filter table
1930+
* @wx: pointer to hardware structure
1931+
*
1932+
* Clears the VLAN filer table, and the VMDq index associated with the filter
1933+
**/
1934+
static void wx_clear_vfta(struct wx *wx)
1935+
{
1936+
u32 offset;
1937+
1938+
for (offset = 0; offset < wx->mac.vft_size; offset++) {
1939+
wr32(wx, WX_PSR_VLAN_TBL(offset), 0);
1940+
wx->mac.vft_shadow[offset] = 0;
1941+
}
1942+
1943+
for (offset = 0; offset < WX_PSR_VLAN_SWC_ENTRIES; offset++) {
1944+
wr32(wx, WX_PSR_VLAN_SWC_IDX, offset);
1945+
wr32(wx, WX_PSR_VLAN_SWC, 0);
1946+
wr32(wx, WX_PSR_VLAN_SWC_VM_L, 0);
1947+
wr32(wx, WX_PSR_VLAN_SWC_VM_H, 0);
1948+
}
1949+
}
1950+
1951+
int wx_vlan_rx_add_vid(struct net_device *netdev,
1952+
__be16 proto, u16 vid)
1953+
{
1954+
struct wx *wx = netdev_priv(netdev);
1955+
1956+
/* add VID to filter table */
1957+
wx_set_vfta(wx, vid, VMDQ_P(0), true);
1958+
set_bit(vid, wx->active_vlans);
1959+
1960+
return 0;
1961+
}
1962+
EXPORT_SYMBOL(wx_vlan_rx_add_vid);
1963+
1964+
int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
1965+
{
1966+
struct wx *wx = netdev_priv(netdev);
1967+
1968+
/* remove VID from filter table */
1969+
if (vid)
1970+
wx_set_vfta(wx, vid, VMDQ_P(0), false);
1971+
clear_bit(vid, wx->active_vlans);
1972+
1973+
return 0;
1974+
}
1975+
EXPORT_SYMBOL(wx_vlan_rx_kill_vid);
1976+
1977+
/**
1978+
* wx_start_hw - Prepare hardware for Tx/Rx
1979+
* @wx: pointer to hardware structure
1980+
*
1981+
* Starts the hardware using the generic start_hw function
1982+
* and the generation start_hw function.
1983+
* Then performs revision-specific operations, if any.
1984+
**/
1985+
void wx_start_hw(struct wx *wx)
1986+
{
1987+
int i;
1988+
1989+
/* Clear the VLAN filter table */
1990+
wx_clear_vfta(wx);
1991+
WX_WRITE_FLUSH(wx);
1992+
/* Clear the rate limiters */
1993+
for (i = 0; i < wx->mac.max_tx_queues; i++) {
1994+
wr32(wx, WX_TDM_RP_IDX, i);
1995+
wr32(wx, WX_TDM_RP_RATE, 0);
1996+
}
1997+
}
1998+
EXPORT_SYMBOL(wx_start_hw);
1999+
17302000
MODULE_LICENSE("GPL");

drivers/net/ethernet/wangxun/libwx/wx_hw.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ void wx_set_rx_mode(struct net_device *netdev);
2626
int wx_change_mtu(struct net_device *netdev, int new_mtu);
2727
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
2828
void wx_configure(struct wx *wx);
29+
void wx_start_hw(struct wx *wx);
2930
int wx_disable_pcie_master(struct wx *wx);
3031
int wx_stop_adapter(struct wx *wx);
3132
void wx_reset_misc(struct wx *wx);
3233
int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
3334
int wx_sw_init(struct wx *wx);
35+
int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
36+
int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
3437

3538
#endif /* _WX_HW_H_ */

drivers/net/ethernet/wangxun/libwx/wx_lib.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,23 @@ static void wx_rx_checksum(struct wx_ring *ring,
634634
ring->rx_stats.csum_good_cnt++;
635635
}
636636

637+
static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc,
638+
struct sk_buff *skb)
639+
{
640+
u16 ethertype;
641+
u8 idx = 0;
642+
643+
if ((ring->netdev->features &
644+
(NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) &&
645+
wx_test_staterr(rx_desc, WX_RXD_STAT_VP)) {
646+
idx = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
647+
0x1c0) >> 6;
648+
ethertype = ring->q_vector->wx->tpid[idx];
649+
__vlan_hwaccel_put_tag(skb, htons(ethertype),
650+
le16_to_cpu(rx_desc->wb.upper.vlan));
651+
}
652+
}
653+
637654
/**
638655
* wx_process_skb_fields - Populate skb header fields from Rx descriptor
639656
* @rx_ring: rx descriptor ring packet is being transacted on
@@ -650,6 +667,7 @@ static void wx_process_skb_fields(struct wx_ring *rx_ring,
650667
{
651668
wx_rx_hash(rx_ring, rx_desc, skb);
652669
wx_rx_checksum(rx_ring, rx_desc, skb);
670+
wx_rx_vlan(rx_ring, rx_desc, skb);
653671
skb_record_rx_queue(skb, rx_ring->queue_index);
654672
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
655673
}

0 commit comments

Comments
 (0)