aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/renesas
diff options
context:
space:
mode:
authorYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>2012-02-15 12:55:06 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-16 17:08:09 -0500
commit71cc7c37af71b497698f7f8a68e46a458071fcef (patch)
tree5ac6cf763fd29fe93b02b2eed8404276064d1c87 /drivers/net/ethernet/renesas
parent6743fe6df43b4dc5950f605edfeee086d0a80f06 (diff)
net: sh_eth: add support for VLAN tag filtering
Some controllers have TSU. It can register one VLAN tag, and it can filter other VLAN tag by hardware. If vlan_rx_add_vid() is called twice or more, the driver will disable the filtering. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/renesas')
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c59
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h5
2 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 99d8ce8379c8..8615961c1287 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1888,6 +1888,62 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
1888 1888
1889 spin_unlock_irqrestore(&mdp->lock, flags); 1889 spin_unlock_irqrestore(&mdp->lock, flags);
1890} 1890}
1891
1892static int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
1893{
1894 if (!mdp->port)
1895 return TSU_VTAG0;
1896 else
1897 return TSU_VTAG1;
1898}
1899
1900static int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
1901{
1902 struct sh_eth_private *mdp = netdev_priv(ndev);
1903 int vtag_reg_index = sh_eth_get_vtag_index(mdp);
1904
1905 if (unlikely(!mdp->cd->tsu))
1906 return -EPERM;
1907
1908 /* No filtering if vid = 0 */
1909 if (!vid)
1910 return 0;
1911
1912 mdp->vlan_num_ids++;
1913
1914 /*
1915 * The controller has one VLAN tag HW filter. So, if the filter is
1916 * already enabled, the driver disables it and the filte
1917 */
1918 if (mdp->vlan_num_ids > 1) {
1919 /* disable VLAN filter */
1920 sh_eth_tsu_write(mdp, 0, vtag_reg_index);
1921 return 0;
1922 }
1923
1924 sh_eth_tsu_write(mdp, TSU_VTAG_ENABLE | (vid & TSU_VTAG_VID_MASK),
1925 vtag_reg_index);
1926
1927 return 0;
1928}
1929
1930static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
1931{
1932 struct sh_eth_private *mdp = netdev_priv(ndev);
1933 int vtag_reg_index = sh_eth_get_vtag_index(mdp);
1934
1935 if (unlikely(!mdp->cd->tsu))
1936 return -EPERM;
1937
1938 /* No filtering if vid = 0 */
1939 if (!vid)
1940 return 0;
1941
1942 mdp->vlan_num_ids--;
1943 sh_eth_tsu_write(mdp, 0, vtag_reg_index);
1944
1945 return 0;
1946}
1891#endif /* SH_ETH_HAS_TSU */ 1947#endif /* SH_ETH_HAS_TSU */
1892 1948
1893/* SuperH's TSU register init function */ 1949/* SuperH's TSU register init function */
@@ -2037,6 +2093,8 @@ static const struct net_device_ops sh_eth_netdev_ops = {
2037 .ndo_get_stats = sh_eth_get_stats, 2093 .ndo_get_stats = sh_eth_get_stats,
2038#if defined(SH_ETH_HAS_TSU) 2094#if defined(SH_ETH_HAS_TSU)
2039 .ndo_set_rx_mode = sh_eth_set_multicast_list, 2095 .ndo_set_rx_mode = sh_eth_set_multicast_list,
2096 .ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid,
2097 .ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid,
2040#endif 2098#endif
2041 .ndo_tx_timeout = sh_eth_tx_timeout, 2099 .ndo_tx_timeout = sh_eth_tx_timeout,
2042 .ndo_do_ioctl = sh_eth_do_ioctl, 2100 .ndo_do_ioctl = sh_eth_do_ioctl,
@@ -2141,6 +2199,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
2141 mdp->tsu_addr = ioremap(rtsu->start, 2199 mdp->tsu_addr = ioremap(rtsu->start,
2142 resource_size(rtsu)); 2200 resource_size(rtsu));
2143 mdp->port = devno % 2; 2201 mdp->port = devno % 2;
2202 ndev->features = NETIF_F_HW_VLAN_FILTER;
2144 } 2203 }
2145 2204
2146 /* initialize first or needed device */ 2205 /* initialize first or needed device */
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 86b392e22c01..57dc26261116 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -679,6 +679,10 @@ enum TSU_FWSLC_BIT {
679 TSU_FWSLC_CAMSEL11 = 0x0002, TSU_FWSLC_CAMSEL10 = 0x0001, 679 TSU_FWSLC_CAMSEL11 = 0x0002, TSU_FWSLC_CAMSEL10 = 0x0001,
680}; 680};
681 681
682/* TSU_VTAGn */
683#define TSU_VTAG_ENABLE 0x80000000
684#define TSU_VTAG_VID_MASK 0x00000fff
685
682/* 686/*
683 * The sh ether Tx buffer descriptors. 687 * The sh ether Tx buffer descriptors.
684 * This structure should be 20 bytes. 688 * This structure should be 20 bytes.
@@ -781,6 +785,7 @@ struct sh_eth_private {
781 char post_fw; /* POST forward */ 785 char post_fw; /* POST forward */
782 struct net_device_stats tsu_stats; /* TSU forward status */ 786 struct net_device_stats tsu_stats; /* TSU forward status */
783 int port; /* for TSU */ 787 int port; /* for TSU */
788 int vlan_num_ids; /* for VLAN tag filter */
784 789
785 unsigned no_ether_link:1; 790 unsigned no_ether_link:1;
786 unsigned ether_link_active_low:1; 791 unsigned ether_link_active_low:1;