@@ -132,6 +132,7 @@ static int efx_ef10_filter_add_vlan(struct efx_nic *efx, u16 vid);
132
132
static void efx_ef10_filter_del_vlan_internal (struct efx_nic * efx ,
133
133
struct efx_ef10_filter_vlan * vlan );
134
134
static void efx_ef10_filter_del_vlan (struct efx_nic * efx , u16 vid );
135
+ static int efx_ef10_set_udp_tnl_ports (struct efx_nic * efx , bool unloading );
135
136
136
137
static int efx_ef10_get_warm_boot_count (struct efx_nic * efx )
137
138
{
@@ -624,6 +625,8 @@ static int efx_ef10_probe(struct efx_nic *efx)
624
625
if (rc )
625
626
goto fail2 ;
626
627
628
+ mutex_init (& nic_data -> udp_tunnels_lock );
629
+
627
630
/* Reset (most) configuration for this function */
628
631
rc = efx_mcdi_reset (efx , RESET_TYPE_ALL );
629
632
if (rc )
@@ -712,6 +715,14 @@ static int efx_ef10_probe(struct efx_nic *efx)
712
715
fail4 :
713
716
device_remove_file (& efx -> pci_dev -> dev , & dev_attr_link_control_flag );
714
717
fail3 :
718
+ efx_mcdi_detach (efx );
719
+
720
+ mutex_lock (& nic_data -> udp_tunnels_lock );
721
+ memset (nic_data -> udp_tunnels , 0 , sizeof (nic_data -> udp_tunnels ));
722
+ (void )efx_ef10_set_udp_tnl_ports (efx , true);
723
+ mutex_unlock (& nic_data -> udp_tunnels_lock );
724
+ mutex_destroy (& nic_data -> udp_tunnels_lock );
725
+
715
726
efx_mcdi_fini (efx );
716
727
fail2 :
717
728
efx_nic_free_buffer (efx , & nic_data -> mcdi_buf );
@@ -981,6 +992,15 @@ static void efx_ef10_remove(struct efx_nic *efx)
981
992
device_remove_file (& efx -> pci_dev -> dev , & dev_attr_primary_flag );
982
993
device_remove_file (& efx -> pci_dev -> dev , & dev_attr_link_control_flag );
983
994
995
+ efx_mcdi_detach (efx );
996
+
997
+ memset (nic_data -> udp_tunnels , 0 , sizeof (nic_data -> udp_tunnels ));
998
+ mutex_lock (& nic_data -> udp_tunnels_lock );
999
+ (void )efx_ef10_set_udp_tnl_ports (efx , true);
1000
+ mutex_unlock (& nic_data -> udp_tunnels_lock );
1001
+
1002
+ mutex_destroy (& nic_data -> udp_tunnels_lock );
1003
+
984
1004
efx_mcdi_fini (efx );
985
1005
efx_nic_free_buffer (efx , & nic_data -> mcdi_buf );
986
1006
kfree (nic_data );
@@ -6066,6 +6086,271 @@ static int efx_ef10_vlan_rx_kill_vid(struct efx_nic *efx, __be16 proto, u16 vid)
6066
6086
return efx_ef10_del_vlan (efx , vid );
6067
6087
}
6068
6088
6089
+ /* We rely on the MCDI wiping out our TX rings if it made any changes to the
6090
+ * ports table, ensuring that any TSO descriptors that were made on a now-
6091
+ * removed tunnel port will be blown away and won't break things when we try
6092
+ * to transmit them using the new ports table.
6093
+ */
6094
+ static int efx_ef10_set_udp_tnl_ports (struct efx_nic * efx , bool unloading )
6095
+ {
6096
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6097
+ MCDI_DECLARE_BUF (inbuf , MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX );
6098
+ MCDI_DECLARE_BUF (outbuf , MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN );
6099
+ bool will_reset = false;
6100
+ size_t num_entries = 0 ;
6101
+ size_t inlen , outlen ;
6102
+ size_t i ;
6103
+ int rc ;
6104
+ efx_dword_t flags_and_num_entries ;
6105
+
6106
+ WARN_ON (!mutex_is_locked (& nic_data -> udp_tunnels_lock ));
6107
+
6108
+ nic_data -> udp_tunnels_dirty = false;
6109
+
6110
+ if (!(nic_data -> datapath_caps &
6111
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN ))) {
6112
+ netif_device_attach (efx -> net_dev );
6113
+ return 0 ;
6114
+ }
6115
+
6116
+ BUILD_BUG_ON (ARRAY_SIZE (nic_data -> udp_tunnels ) >
6117
+ MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM );
6118
+
6119
+ for (i = 0 ; i < ARRAY_SIZE (nic_data -> udp_tunnels ); ++ i ) {
6120
+ if (nic_data -> udp_tunnels [i ].count &&
6121
+ nic_data -> udp_tunnels [i ].port ) {
6122
+ efx_dword_t entry ;
6123
+
6124
+ EFX_POPULATE_DWORD_2 (entry ,
6125
+ TUNNEL_ENCAP_UDP_PORT_ENTRY_UDP_PORT ,
6126
+ ntohs (nic_data -> udp_tunnels [i ].port ),
6127
+ TUNNEL_ENCAP_UDP_PORT_ENTRY_PROTOCOL ,
6128
+ nic_data -> udp_tunnels [i ].type );
6129
+ * _MCDI_ARRAY_DWORD (inbuf ,
6130
+ SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES ,
6131
+ num_entries ++ ) = entry ;
6132
+ }
6133
+ }
6134
+
6135
+ BUILD_BUG_ON ((MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES_OFST -
6136
+ MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS_OFST ) * 8 !=
6137
+ EFX_WORD_1_LBN );
6138
+ BUILD_BUG_ON (MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES_LEN * 8 !=
6139
+ EFX_WORD_1_WIDTH );
6140
+ EFX_POPULATE_DWORD_2 (flags_and_num_entries ,
6141
+ MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING ,
6142
+ !!unloading ,
6143
+ EFX_WORD_1 , num_entries );
6144
+ * _MCDI_DWORD (inbuf , SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS ) =
6145
+ flags_and_num_entries ;
6146
+
6147
+ inlen = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LEN (num_entries );
6148
+
6149
+ rc = efx_mcdi_rpc_quiet (efx , MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS ,
6150
+ inbuf , inlen , outbuf , sizeof (outbuf ), & outlen );
6151
+ if (rc == - EIO ) {
6152
+ /* Most likely the MC rebooted due to another function also
6153
+ * setting its tunnel port list. Mark the tunnel port list as
6154
+ * dirty, so it will be pushed upon coming up from the reboot.
6155
+ */
6156
+ nic_data -> udp_tunnels_dirty = true;
6157
+ return 0 ;
6158
+ }
6159
+
6160
+ if (rc ) {
6161
+ /* expected not available on unprivileged functions */
6162
+ if (rc != - EPERM )
6163
+ netif_warn (efx , drv , efx -> net_dev ,
6164
+ "Unable to set UDP tunnel ports; rc=%d.\n" , rc );
6165
+ } else if (MCDI_DWORD (outbuf , SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS ) &
6166
+ (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING_LBN )) {
6167
+ netif_info (efx , drv , efx -> net_dev ,
6168
+ "Rebooting MC due to UDP tunnel port list change\n" );
6169
+ will_reset = true;
6170
+ if (unloading )
6171
+ /* Delay for the MC reset to complete. This will make
6172
+ * unloading other functions a bit smoother. This is a
6173
+ * race, but the other unload will work whichever way
6174
+ * it goes, this just avoids an unnecessary error
6175
+ * message.
6176
+ */
6177
+ msleep (100 );
6178
+ }
6179
+ if (!will_reset && !unloading ) {
6180
+ /* The caller will have detached, relying on the MC reset to
6181
+ * trigger a re-attach. Since there won't be an MC reset, we
6182
+ * have to do the attach ourselves.
6183
+ */
6184
+ netif_device_attach (efx -> net_dev );
6185
+ }
6186
+
6187
+ return rc ;
6188
+ }
6189
+
6190
+ static int efx_ef10_udp_tnl_push_ports (struct efx_nic * efx )
6191
+ {
6192
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6193
+ int rc = 0 ;
6194
+
6195
+ mutex_lock (& nic_data -> udp_tunnels_lock );
6196
+ if (nic_data -> udp_tunnels_dirty ) {
6197
+ /* Make sure all TX are stopped while we modify the table, else
6198
+ * we might race against an efx_features_check().
6199
+ */
6200
+ efx_device_detach_sync (efx );
6201
+ rc = efx_ef10_set_udp_tnl_ports (efx , false);
6202
+ }
6203
+ mutex_unlock (& nic_data -> udp_tunnels_lock );
6204
+ return rc ;
6205
+ }
6206
+
6207
+ static struct efx_udp_tunnel * __efx_ef10_udp_tnl_lookup_port (struct efx_nic * efx ,
6208
+ __be16 port )
6209
+ {
6210
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6211
+ size_t i ;
6212
+
6213
+ for (i = 0 ; i < ARRAY_SIZE (nic_data -> udp_tunnels ); ++ i ) {
6214
+ if (!nic_data -> udp_tunnels [i ].count )
6215
+ continue ;
6216
+ if (nic_data -> udp_tunnels [i ].port == port )
6217
+ return & nic_data -> udp_tunnels [i ];
6218
+ }
6219
+ return NULL ;
6220
+ }
6221
+
6222
+ static int efx_ef10_udp_tnl_add_port (struct efx_nic * efx ,
6223
+ struct efx_udp_tunnel tnl )
6224
+ {
6225
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6226
+ struct efx_udp_tunnel * match ;
6227
+ char typebuf [8 ];
6228
+ size_t i ;
6229
+ int rc ;
6230
+
6231
+ if (!(nic_data -> datapath_caps &
6232
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN )))
6233
+ return 0 ;
6234
+
6235
+ efx_get_udp_tunnel_type_name (tnl .type , typebuf , sizeof (typebuf ));
6236
+ netif_dbg (efx , drv , efx -> net_dev , "Adding UDP tunnel (%s) port %d\n" ,
6237
+ typebuf , ntohs (tnl .port ));
6238
+
6239
+ mutex_lock (& nic_data -> udp_tunnels_lock );
6240
+ /* Make sure all TX are stopped while we add to the table, else we
6241
+ * might race against an efx_features_check().
6242
+ */
6243
+ efx_device_detach_sync (efx );
6244
+
6245
+ match = __efx_ef10_udp_tnl_lookup_port (efx , tnl .port );
6246
+ if (match != NULL ) {
6247
+ if (match -> type == tnl .type ) {
6248
+ netif_dbg (efx , drv , efx -> net_dev ,
6249
+ "Referencing existing tunnel entry\n" );
6250
+ match -> count ++ ;
6251
+ /* No need to cause an MCDI update */
6252
+ rc = 0 ;
6253
+ goto unlock_out ;
6254
+ }
6255
+ efx_get_udp_tunnel_type_name (match -> type ,
6256
+ typebuf , sizeof (typebuf ));
6257
+ netif_dbg (efx , drv , efx -> net_dev ,
6258
+ "UDP port %d is already in use by %s\n" ,
6259
+ ntohs (tnl .port ), typebuf );
6260
+ rc = - EEXIST ;
6261
+ goto unlock_out ;
6262
+ }
6263
+
6264
+ for (i = 0 ; i < ARRAY_SIZE (nic_data -> udp_tunnels ); ++ i )
6265
+ if (!nic_data -> udp_tunnels [i ].count ) {
6266
+ nic_data -> udp_tunnels [i ] = tnl ;
6267
+ nic_data -> udp_tunnels [i ].count = 1 ;
6268
+ rc = efx_ef10_set_udp_tnl_ports (efx , false);
6269
+ goto unlock_out ;
6270
+ }
6271
+
6272
+ netif_dbg (efx , drv , efx -> net_dev ,
6273
+ "Unable to add UDP tunnel (%s) port %d; insufficient resources.\n" ,
6274
+ typebuf , ntohs (tnl .port ));
6275
+
6276
+ rc = - ENOMEM ;
6277
+
6278
+ unlock_out :
6279
+ mutex_unlock (& nic_data -> udp_tunnels_lock );
6280
+ return rc ;
6281
+ }
6282
+
6283
+ /* Called under the TX lock with the TX queue running, hence no-one can be
6284
+ * in the middle of updating the UDP tunnels table. However, they could
6285
+ * have tried and failed the MCDI, in which case they'll have set the dirty
6286
+ * flag before dropping their locks.
6287
+ */
6288
+ static bool efx_ef10_udp_tnl_has_port (struct efx_nic * efx , __be16 port )
6289
+ {
6290
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6291
+
6292
+ if (!(nic_data -> datapath_caps &
6293
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN )))
6294
+ return false;
6295
+
6296
+ if (nic_data -> udp_tunnels_dirty )
6297
+ /* SW table may not match HW state, so just assume we can't
6298
+ * use any UDP tunnel offloads.
6299
+ */
6300
+ return false;
6301
+
6302
+ return __efx_ef10_udp_tnl_lookup_port (efx , port ) != NULL ;
6303
+ }
6304
+
6305
+ static int efx_ef10_udp_tnl_del_port (struct efx_nic * efx ,
6306
+ struct efx_udp_tunnel tnl )
6307
+ {
6308
+ struct efx_ef10_nic_data * nic_data = efx -> nic_data ;
6309
+ struct efx_udp_tunnel * match ;
6310
+ char typebuf [8 ];
6311
+ int rc ;
6312
+
6313
+ if (!(nic_data -> datapath_caps &
6314
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN )))
6315
+ return 0 ;
6316
+
6317
+ efx_get_udp_tunnel_type_name (tnl .type , typebuf , sizeof (typebuf ));
6318
+ netif_dbg (efx , drv , efx -> net_dev , "Removing UDP tunnel (%s) port %d\n" ,
6319
+ typebuf , ntohs (tnl .port ));
6320
+
6321
+ mutex_lock (& nic_data -> udp_tunnels_lock );
6322
+ /* Make sure all TX are stopped while we remove from the table, else we
6323
+ * might race against an efx_features_check().
6324
+ */
6325
+ efx_device_detach_sync (efx );
6326
+
6327
+ match = __efx_ef10_udp_tnl_lookup_port (efx , tnl .port );
6328
+ if (match != NULL ) {
6329
+ if (match -> type == tnl .type ) {
6330
+ if (-- match -> count ) {
6331
+ /* Port is still in use, so nothing to do */
6332
+ netif_dbg (efx , drv , efx -> net_dev ,
6333
+ "UDP tunnel port %d remains active\n" ,
6334
+ ntohs (tnl .port ));
6335
+ rc = 0 ;
6336
+ goto out_unlock ;
6337
+ }
6338
+ rc = efx_ef10_set_udp_tnl_ports (efx , false);
6339
+ goto out_unlock ;
6340
+ }
6341
+ efx_get_udp_tunnel_type_name (match -> type ,
6342
+ typebuf , sizeof (typebuf ));
6343
+ netif_warn (efx , drv , efx -> net_dev ,
6344
+ "UDP port %d is actually in use by %s, not removing\n" ,
6345
+ ntohs (tnl .port ), typebuf );
6346
+ }
6347
+ rc = - ENOENT ;
6348
+
6349
+ out_unlock :
6350
+ mutex_unlock (& nic_data -> udp_tunnels_lock );
6351
+ return rc ;
6352
+ }
6353
+
6069
6354
#define EF10_OFFLOAD_FEATURES \
6070
6355
(NETIF_F_IP_CSUM | \
6071
6356
NETIF_F_HW_VLAN_CTAG_FILTER | \
@@ -6269,6 +6554,10 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
6269
6554
.ptp_set_ts_config = efx_ef10_ptp_set_ts_config ,
6270
6555
.vlan_rx_add_vid = efx_ef10_vlan_rx_add_vid ,
6271
6556
.vlan_rx_kill_vid = efx_ef10_vlan_rx_kill_vid ,
6557
+ .udp_tnl_push_ports = efx_ef10_udp_tnl_push_ports ,
6558
+ .udp_tnl_add_port = efx_ef10_udp_tnl_add_port ,
6559
+ .udp_tnl_has_port = efx_ef10_udp_tnl_has_port ,
6560
+ .udp_tnl_del_port = efx_ef10_udp_tnl_del_port ,
6272
6561
#ifdef CONFIG_SFC_SRIOV
6273
6562
.sriov_configure = efx_ef10_sriov_configure ,
6274
6563
.sriov_init = efx_ef10_sriov_init ,
0 commit comments