Skip to content

Commit

Permalink
sfc: receive packets from EF100 VFs into representors
Browse files Browse the repository at this point in the history
If the source m-port of a packet in __ef100_rx_packet() is a VF,
 hand off the packet to the corresponding representor with
 efx_ef100_rep_rx_packet().

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Edward Cree authored and Jakub Kicinski committed Jul 30, 2022
1 parent 08d0b16 commit f50e8fc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
19 changes: 19 additions & 0 deletions drivers/net/ethernet/sfc/ef100_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)
list_del(&efv->list);
spin_unlock_bh(&efx->vf_reps_lock);
rtnl_unlock();
synchronize_rcu();
free_netdev(efv->net_dev);
}

Expand Down Expand Up @@ -375,3 +376,21 @@ void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf)
if (primed)
napi_schedule(&efv->napi);
}

struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport)
{
struct efx_rep *efv, *out = NULL;

/* spinlock guards against list mutation while we're walking it;
* but caller must also hold rcu_read_lock() to ensure the netdev
* isn't freed after we drop the spinlock.
*/
spin_lock_bh(&efx->vf_reps_lock);
list_for_each_entry(efv, &efx->vf_reps, list)
if (efv->mport == mport) {
out = efv;
break;
}
spin_unlock_bh(&efx->vf_reps_lock);
return out;
}
5 changes: 5 additions & 0 deletions drivers/net/ethernet/sfc/ef100_rep.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,9 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv);
void efx_ef100_fini_vfreps(struct efx_nic *efx);

void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf);
/* Returns the representor corresponding to a VF m-port, or NULL
* @mport is an m-port label, *not* an m-port ID!
* Caller must hold rcu_read_lock().
*/
struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
#endif /* EF100_REP_H */
18 changes: 18 additions & 0 deletions drivers/net/ethernet/sfc/ef100_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ void __ef100_rx_packet(struct efx_channel *channel)
nic_data = efx->nic_data;

if (nic_data->have_mport && ing_port != nic_data->base_mport) {
#ifdef CONFIG_SFC_SRIOV
struct efx_rep *efv;

rcu_read_lock();
efv = efx_ef100_find_rep_by_mport(efx, ing_port);
if (efv) {
if (efv->net_dev->flags & IFF_UP)
efx_ef100_rep_rx_packet(efv, rx_buf);
rcu_read_unlock();
/* Representor Rx doesn't care about PF Rx buffer
* ownership, it just makes a copy. So, we are done
* with the Rx buffer from PF point of view and should
* free it.
*/
goto free_rx_buffer;
}
rcu_read_unlock();
#endif
if (net_ratelimit())
netif_warn(efx, drv, efx->net_dev,
"Unrecognised ing_port %04x (base %04x), dropping\n",
Expand Down

0 comments on commit f50e8fc

Please sign in to comment.