22
22
23
23
#define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
24
24
25
+ #define NFP_MIN_INT_PORT_ID 1
26
+ #define NFP_MAX_INT_PORT_ID 256
27
+
25
28
static const char * nfp_flower_extra_cap (struct nfp_app * app , struct nfp_net * nn )
26
29
{
27
30
return "FLOWER" ;
@@ -32,6 +35,113 @@ static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
32
35
return DEVLINK_ESWITCH_MODE_SWITCHDEV ;
33
36
}
34
37
38
+ static int
39
+ nfp_flower_lookup_internal_port_id (struct nfp_flower_priv * priv ,
40
+ struct net_device * netdev )
41
+ {
42
+ struct net_device * entry ;
43
+ int i , id = 0 ;
44
+
45
+ rcu_read_lock ();
46
+ idr_for_each_entry (& priv -> internal_ports .port_ids , entry , i )
47
+ if (entry == netdev ) {
48
+ id = i ;
49
+ break ;
50
+ }
51
+ rcu_read_unlock ();
52
+
53
+ return id ;
54
+ }
55
+
56
+ static int
57
+ nfp_flower_get_internal_port_id (struct nfp_app * app , struct net_device * netdev )
58
+ {
59
+ struct nfp_flower_priv * priv = app -> priv ;
60
+ int id ;
61
+
62
+ id = nfp_flower_lookup_internal_port_id (priv , netdev );
63
+ if (id > 0 )
64
+ return id ;
65
+
66
+ idr_preload (GFP_ATOMIC );
67
+ spin_lock_bh (& priv -> internal_ports .lock );
68
+ id = idr_alloc (& priv -> internal_ports .port_ids , netdev ,
69
+ NFP_MIN_INT_PORT_ID , NFP_MAX_INT_PORT_ID , GFP_ATOMIC );
70
+ spin_unlock_bh (& priv -> internal_ports .lock );
71
+ idr_preload_end ();
72
+
73
+ return id ;
74
+ }
75
+
76
+ u32 nfp_flower_get_port_id_from_netdev (struct nfp_app * app ,
77
+ struct net_device * netdev )
78
+ {
79
+ int ext_port ;
80
+
81
+ if (nfp_netdev_is_nfp_repr (netdev )) {
82
+ return nfp_repr_get_port_id (netdev );
83
+ } else if (nfp_flower_internal_port_can_offload (app , netdev )) {
84
+ ext_port = nfp_flower_get_internal_port_id (app , netdev );
85
+ if (ext_port < 0 )
86
+ return 0 ;
87
+
88
+ return nfp_flower_internal_port_get_port_id (ext_port );
89
+ }
90
+
91
+ return 0 ;
92
+ }
93
+
94
+ static struct net_device *
95
+ nfp_flower_get_netdev_from_internal_port_id (struct nfp_app * app , int port_id )
96
+ {
97
+ struct nfp_flower_priv * priv = app -> priv ;
98
+ struct net_device * netdev ;
99
+
100
+ rcu_read_lock ();
101
+ netdev = idr_find (& priv -> internal_ports .port_ids , port_id );
102
+ rcu_read_unlock ();
103
+
104
+ return netdev ;
105
+ }
106
+
107
+ static void
108
+ nfp_flower_free_internal_port_id (struct nfp_app * app , struct net_device * netdev )
109
+ {
110
+ struct nfp_flower_priv * priv = app -> priv ;
111
+ int id ;
112
+
113
+ id = nfp_flower_lookup_internal_port_id (priv , netdev );
114
+ if (!id )
115
+ return ;
116
+
117
+ spin_lock_bh (& priv -> internal_ports .lock );
118
+ idr_remove (& priv -> internal_ports .port_ids , id );
119
+ spin_unlock_bh (& priv -> internal_ports .lock );
120
+ }
121
+
122
+ static int
123
+ nfp_flower_internal_port_event_handler (struct nfp_app * app ,
124
+ struct net_device * netdev ,
125
+ unsigned long event )
126
+ {
127
+ if (event == NETDEV_UNREGISTER &&
128
+ nfp_flower_internal_port_can_offload (app , netdev ))
129
+ nfp_flower_free_internal_port_id (app , netdev );
130
+
131
+ return NOTIFY_OK ;
132
+ }
133
+
134
+ static void nfp_flower_internal_port_init (struct nfp_flower_priv * priv )
135
+ {
136
+ spin_lock_init (& priv -> internal_ports .lock );
137
+ idr_init (& priv -> internal_ports .port_ids );
138
+ }
139
+
140
+ static void nfp_flower_internal_port_cleanup (struct nfp_flower_priv * priv )
141
+ {
142
+ idr_destroy (& priv -> internal_ports .port_ids );
143
+ }
144
+
35
145
static struct nfp_flower_non_repr_priv *
36
146
nfp_flower_non_repr_priv_lookup (struct nfp_app * app , struct net_device * netdev )
37
147
{
@@ -119,12 +229,21 @@ nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
119
229
}
120
230
121
231
static struct net_device *
122
- nfp_flower_repr_get (struct nfp_app * app , u32 port_id )
232
+ nfp_flower_dev_get (struct nfp_app * app , u32 port_id , bool * redir_egress )
123
233
{
124
234
enum nfp_repr_type repr_type ;
125
235
struct nfp_reprs * reprs ;
126
236
u8 port = 0 ;
127
237
238
+ /* Check if the port is internal. */
239
+ if (FIELD_GET (NFP_FLOWER_CMSG_PORT_TYPE , port_id ) ==
240
+ NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT ) {
241
+ if (redir_egress )
242
+ * redir_egress = true;
243
+ port = FIELD_GET (NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM , port_id );
244
+ return nfp_flower_get_netdev_from_internal_port_id (app , port );
245
+ }
246
+
128
247
repr_type = nfp_flower_repr_get_type_and_port (app , port_id , & port );
129
248
if (repr_type > NFP_REPR_TYPE_MAX )
130
249
return NULL ;
@@ -641,11 +760,30 @@ static int nfp_flower_init(struct nfp_app *app)
641
760
goto err_cleanup_metadata ;
642
761
}
643
762
763
+ if (app_priv -> flower_ext_feats & NFP_FL_FEATS_FLOW_MOD ) {
764
+ /* Tell the firmware that the driver supports flow merging. */
765
+ err = nfp_rtsym_write_le (app -> pf -> rtbl ,
766
+ "_abi_flower_merge_hint_enable" , 1 );
767
+ if (!err ) {
768
+ app_priv -> flower_ext_feats |= NFP_FL_FEATS_FLOW_MERGE ;
769
+ nfp_flower_internal_port_init (app_priv );
770
+ } else if (err == - ENOENT ) {
771
+ nfp_warn (app -> cpp , "Flow merge not supported by FW.\n" );
772
+ } else {
773
+ goto err_lag_clean ;
774
+ }
775
+ } else {
776
+ nfp_warn (app -> cpp , "Flow mod/merge not supported by FW.\n" );
777
+ }
778
+
644
779
INIT_LIST_HEAD (& app_priv -> indr_block_cb_priv );
645
780
INIT_LIST_HEAD (& app_priv -> non_repr_priv );
646
781
647
782
return 0 ;
648
783
784
+ err_lag_clean :
785
+ if (app_priv -> flower_ext_feats & NFP_FL_FEATS_LAG )
786
+ nfp_flower_lag_cleanup (& app_priv -> nfp_lag );
649
787
err_cleanup_metadata :
650
788
nfp_flower_metadata_cleanup (app );
651
789
err_free_app_priv :
@@ -664,6 +802,9 @@ static void nfp_flower_clean(struct nfp_app *app)
664
802
if (app_priv -> flower_ext_feats & NFP_FL_FEATS_LAG )
665
803
nfp_flower_lag_cleanup (& app_priv -> nfp_lag );
666
804
805
+ if (app_priv -> flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE )
806
+ nfp_flower_internal_port_cleanup (app_priv );
807
+
667
808
nfp_flower_metadata_cleanup (app );
668
809
vfree (app -> priv );
669
810
app -> priv = NULL ;
@@ -762,6 +903,10 @@ nfp_flower_netdev_event(struct nfp_app *app, struct net_device *netdev,
762
903
if (ret & NOTIFY_STOP_MASK )
763
904
return ret ;
764
905
906
+ ret = nfp_flower_internal_port_event_handler (app , netdev , event );
907
+ if (ret & NOTIFY_STOP_MASK )
908
+ return ret ;
909
+
765
910
return nfp_tunnel_mac_event_handler (app , netdev , event , ptr );
766
911
}
767
912
@@ -800,7 +945,7 @@ const struct nfp_app_type app_flower = {
800
945
.sriov_disable = nfp_flower_sriov_disable ,
801
946
802
947
.eswitch_mode_get = eswitch_mode_get ,
803
- .repr_get = nfp_flower_repr_get ,
948
+ .dev_get = nfp_flower_dev_get ,
804
949
805
950
.setup_tc = nfp_flower_setup_tc ,
806
951
};
0 commit comments