@@ -1747,72 +1747,186 @@ static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
1747
1747
}
1748
1748
1749
1749
static int
1750
- mlxsw_sp_setup_tc_cls_flower (struct mlxsw_sp_port * mlxsw_sp_port ,
1751
- struct tc_cls_flower_offload * f ,
1752
- bool ingress )
1750
+ mlxsw_sp_setup_tc_cls_flower (struct mlxsw_sp_acl_block * acl_block ,
1751
+ struct tc_cls_flower_offload * f )
1753
1752
{
1753
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_acl_block_mlxsw_sp (acl_block );
1754
+
1754
1755
switch (f -> command ) {
1755
1756
case TC_CLSFLOWER_REPLACE :
1756
- return mlxsw_sp_flower_replace (mlxsw_sp_port , ingress , f );
1757
+ return mlxsw_sp_flower_replace (mlxsw_sp , acl_block , f );
1757
1758
case TC_CLSFLOWER_DESTROY :
1758
- mlxsw_sp_flower_destroy (mlxsw_sp_port , ingress , f );
1759
+ mlxsw_sp_flower_destroy (mlxsw_sp , acl_block , f );
1759
1760
return 0 ;
1760
1761
case TC_CLSFLOWER_STATS :
1761
- return mlxsw_sp_flower_stats (mlxsw_sp_port , ingress , f );
1762
+ return mlxsw_sp_flower_stats (mlxsw_sp , acl_block , f );
1762
1763
default :
1763
1764
return - EOPNOTSUPP ;
1764
1765
}
1765
1766
}
1766
1767
1767
- static int mlxsw_sp_setup_tc_block_cb (enum tc_setup_type type , void * type_data ,
1768
- void * cb_priv , bool ingress )
1768
+ static int mlxsw_sp_setup_tc_block_cb_matchall (enum tc_setup_type type ,
1769
+ void * type_data ,
1770
+ void * cb_priv , bool ingress )
1769
1771
{
1770
1772
struct mlxsw_sp_port * mlxsw_sp_port = cb_priv ;
1771
1773
1772
- if (!tc_can_offload (mlxsw_sp_port -> dev ))
1773
- return - EOPNOTSUPP ;
1774
-
1775
1774
switch (type ) {
1776
1775
case TC_SETUP_CLSMATCHALL :
1776
+ if (!tc_can_offload (mlxsw_sp_port -> dev ))
1777
+ return - EOPNOTSUPP ;
1778
+
1777
1779
return mlxsw_sp_setup_tc_cls_matchall (mlxsw_sp_port , type_data ,
1778
1780
ingress );
1779
1781
case TC_SETUP_CLSFLOWER :
1780
- return mlxsw_sp_setup_tc_cls_flower (mlxsw_sp_port , type_data ,
1781
- ingress );
1782
+ return 0 ;
1782
1783
default :
1783
1784
return - EOPNOTSUPP ;
1784
1785
}
1785
1786
}
1786
1787
1787
- static int mlxsw_sp_setup_tc_block_cb_ig (enum tc_setup_type type ,
1788
- void * type_data , void * cb_priv )
1788
+ static int mlxsw_sp_setup_tc_block_cb_matchall_ig (enum tc_setup_type type ,
1789
+ void * type_data ,
1790
+ void * cb_priv )
1789
1791
{
1790
- return mlxsw_sp_setup_tc_block_cb (type , type_data , cb_priv , true);
1792
+ return mlxsw_sp_setup_tc_block_cb_matchall (type , type_data ,
1793
+ cb_priv , true);
1791
1794
}
1792
1795
1793
- static int mlxsw_sp_setup_tc_block_cb_eg (enum tc_setup_type type ,
1794
- void * type_data , void * cb_priv )
1796
+ static int mlxsw_sp_setup_tc_block_cb_matchall_eg (enum tc_setup_type type ,
1797
+ void * type_data ,
1798
+ void * cb_priv )
1795
1799
{
1796
- return mlxsw_sp_setup_tc_block_cb (type , type_data , cb_priv , false);
1800
+ return mlxsw_sp_setup_tc_block_cb_matchall (type , type_data ,
1801
+ cb_priv , false);
1802
+ }
1803
+
1804
+ static int mlxsw_sp_setup_tc_block_cb_flower (enum tc_setup_type type ,
1805
+ void * type_data , void * cb_priv )
1806
+ {
1807
+ struct mlxsw_sp_acl_block * acl_block = cb_priv ;
1808
+
1809
+ switch (type ) {
1810
+ case TC_SETUP_CLSMATCHALL :
1811
+ return 0 ;
1812
+ case TC_SETUP_CLSFLOWER :
1813
+ if (mlxsw_sp_acl_block_disabled (acl_block ))
1814
+ return - EOPNOTSUPP ;
1815
+
1816
+ return mlxsw_sp_setup_tc_cls_flower (acl_block , type_data );
1817
+ default :
1818
+ return - EOPNOTSUPP ;
1819
+ }
1820
+ }
1821
+
1822
+ static int
1823
+ mlxsw_sp_setup_tc_block_flower_bind (struct mlxsw_sp_port * mlxsw_sp_port ,
1824
+ struct tcf_block * block , bool ingress )
1825
+ {
1826
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
1827
+ struct mlxsw_sp_acl_block * acl_block ;
1828
+ struct tcf_block_cb * block_cb ;
1829
+ int err ;
1830
+
1831
+ block_cb = tcf_block_cb_lookup (block , mlxsw_sp_setup_tc_block_cb_flower ,
1832
+ mlxsw_sp );
1833
+ if (!block_cb ) {
1834
+ acl_block = mlxsw_sp_acl_block_create (mlxsw_sp , block -> net );
1835
+ if (!acl_block )
1836
+ return - ENOMEM ;
1837
+ block_cb = __tcf_block_cb_register (block ,
1838
+ mlxsw_sp_setup_tc_block_cb_flower ,
1839
+ mlxsw_sp , acl_block );
1840
+ if (IS_ERR (block_cb )) {
1841
+ err = PTR_ERR (block_cb );
1842
+ goto err_cb_register ;
1843
+ }
1844
+ } else {
1845
+ acl_block = tcf_block_cb_priv (block_cb );
1846
+ }
1847
+ tcf_block_cb_incref (block_cb );
1848
+ err = mlxsw_sp_acl_block_bind (mlxsw_sp , acl_block ,
1849
+ mlxsw_sp_port , ingress );
1850
+ if (err )
1851
+ goto err_block_bind ;
1852
+
1853
+ if (ingress )
1854
+ mlxsw_sp_port -> ing_acl_block = acl_block ;
1855
+ else
1856
+ mlxsw_sp_port -> eg_acl_block = acl_block ;
1857
+
1858
+ return 0 ;
1859
+
1860
+ err_block_bind :
1861
+ if (!tcf_block_cb_decref (block_cb )) {
1862
+ __tcf_block_cb_unregister (block_cb );
1863
+ err_cb_register :
1864
+ mlxsw_sp_acl_block_destroy (acl_block );
1865
+ }
1866
+ return err ;
1867
+ }
1868
+
1869
+ static void
1870
+ mlxsw_sp_setup_tc_block_flower_unbind (struct mlxsw_sp_port * mlxsw_sp_port ,
1871
+ struct tcf_block * block , bool ingress )
1872
+ {
1873
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
1874
+ struct mlxsw_sp_acl_block * acl_block ;
1875
+ struct tcf_block_cb * block_cb ;
1876
+ int err ;
1877
+
1878
+ block_cb = tcf_block_cb_lookup (block , mlxsw_sp_setup_tc_block_cb_flower ,
1879
+ mlxsw_sp );
1880
+ if (!block_cb )
1881
+ return ;
1882
+
1883
+ if (ingress )
1884
+ mlxsw_sp_port -> ing_acl_block = NULL ;
1885
+ else
1886
+ mlxsw_sp_port -> eg_acl_block = NULL ;
1887
+
1888
+ acl_block = tcf_block_cb_priv (block_cb );
1889
+ err = mlxsw_sp_acl_block_unbind (mlxsw_sp , acl_block ,
1890
+ mlxsw_sp_port , ingress );
1891
+ if (!err && !tcf_block_cb_decref (block_cb )) {
1892
+ __tcf_block_cb_unregister (block_cb );
1893
+ mlxsw_sp_acl_block_destroy (acl_block );
1894
+ }
1797
1895
}
1798
1896
1799
1897
static int mlxsw_sp_setup_tc_block (struct mlxsw_sp_port * mlxsw_sp_port ,
1800
1898
struct tc_block_offload * f )
1801
1899
{
1802
1900
tc_setup_cb_t * cb ;
1901
+ bool ingress ;
1902
+ int err ;
1803
1903
1804
- if (f -> binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS )
1805
- cb = mlxsw_sp_setup_tc_block_cb_ig ;
1806
- else if (f -> binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS )
1807
- cb = mlxsw_sp_setup_tc_block_cb_eg ;
1808
- else
1904
+ if (f -> binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS ) {
1905
+ cb = mlxsw_sp_setup_tc_block_cb_matchall_ig ;
1906
+ ingress = true;
1907
+ } else if (f -> binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS ) {
1908
+ cb = mlxsw_sp_setup_tc_block_cb_matchall_eg ;
1909
+ ingress = false;
1910
+ } else {
1809
1911
return - EOPNOTSUPP ;
1912
+ }
1810
1913
1811
1914
switch (f -> command ) {
1812
1915
case TC_BLOCK_BIND :
1813
- return tcf_block_cb_register (f -> block , cb , mlxsw_sp_port ,
1814
- mlxsw_sp_port );
1916
+ err = tcf_block_cb_register (f -> block , cb , mlxsw_sp_port ,
1917
+ mlxsw_sp_port );
1918
+ if (err )
1919
+ return err ;
1920
+ err = mlxsw_sp_setup_tc_block_flower_bind (mlxsw_sp_port ,
1921
+ f -> block , ingress );
1922
+ if (err ) {
1923
+ tcf_block_cb_unregister (f -> block , cb , mlxsw_sp_port );
1924
+ return err ;
1925
+ }
1926
+ return 0 ;
1815
1927
case TC_BLOCK_UNBIND :
1928
+ mlxsw_sp_setup_tc_block_flower_unbind (mlxsw_sp_port ,
1929
+ f -> block , ingress );
1816
1930
tcf_block_cb_unregister (f -> block , cb , mlxsw_sp_port );
1817
1931
return 0 ;
1818
1932
default :
@@ -1842,10 +1956,18 @@ static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable)
1842
1956
{
1843
1957
struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (dev );
1844
1958
1845
- if (!enable && (mlxsw_sp_port -> acl_rule_count ||
1846
- !list_empty (& mlxsw_sp_port -> mall_tc_list ))) {
1847
- netdev_err (dev , "Active offloaded tc filters, can't turn hw_tc_offload off\n" );
1848
- return - EINVAL ;
1959
+ if (!enable ) {
1960
+ if (mlxsw_sp_acl_block_rule_count (mlxsw_sp_port -> ing_acl_block ) ||
1961
+ mlxsw_sp_acl_block_rule_count (mlxsw_sp_port -> eg_acl_block ) ||
1962
+ !list_empty (& mlxsw_sp_port -> mall_tc_list )) {
1963
+ netdev_err (dev , "Active offloaded tc filters, can't turn hw_tc_offload off\n" );
1964
+ return - EINVAL ;
1965
+ }
1966
+ mlxsw_sp_acl_block_disable_inc (mlxsw_sp_port -> ing_acl_block );
1967
+ mlxsw_sp_acl_block_disable_inc (mlxsw_sp_port -> eg_acl_block );
1968
+ } else {
1969
+ mlxsw_sp_acl_block_disable_dec (mlxsw_sp_port -> ing_acl_block );
1970
+ mlxsw_sp_acl_block_disable_dec (mlxsw_sp_port -> eg_acl_block );
1849
1971
}
1850
1972
return 0 ;
1851
1973
}
0 commit comments