sfc: commonise TSO fallback code
ef100 will need this if it gets GSO skbs it can't handle (e.g. too long header length). Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
80a0074e6a
commit
740acc15c8
|
@ -268,34 +268,6 @@ static int efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue,
|
|||
}
|
||||
#endif /* EFX_USE_PIO */
|
||||
|
||||
/*
|
||||
* Fallback to software TSO.
|
||||
*
|
||||
* This is used if we are unable to send a GSO packet through hardware TSO.
|
||||
* This should only ever happen due to per-queue restrictions - unsupported
|
||||
* packets should first be filtered by the feature flags.
|
||||
*
|
||||
* Returns 0 on success, error code otherwise.
|
||||
*/
|
||||
static int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *segments, *next;
|
||||
|
||||
segments = skb_gso_segment(skb, 0);
|
||||
if (IS_ERR(segments))
|
||||
return PTR_ERR(segments);
|
||||
|
||||
dev_consume_skb_any(skb);
|
||||
|
||||
skb_list_walk_safe(segments, skb, next) {
|
||||
skb_mark_not_on_list(skb);
|
||||
efx_enqueue_skb(tx_queue, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a socket buffer to a TX queue
|
||||
*
|
||||
|
|
|
@ -405,3 +405,30 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
|
|||
|
||||
return max_descs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fallback to software TSO.
|
||||
*
|
||||
* This is used if we are unable to send a GSO packet through hardware TSO.
|
||||
* This should only ever happen due to per-queue restrictions - unsupported
|
||||
* packets should first be filtered by the feature flags.
|
||||
*
|
||||
* Returns 0 on success, error code otherwise.
|
||||
*/
|
||||
int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *segments, *next;
|
||||
|
||||
segments = skb_gso_segment(skb, 0);
|
||||
if (IS_ERR(segments))
|
||||
return PTR_ERR(segments);
|
||||
|
||||
dev_consume_skb_any(skb);
|
||||
|
||||
skb_list_walk_safe(segments, skb, next) {
|
||||
skb_mark_not_on_list(skb);
|
||||
efx_enqueue_skb(tx_queue, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,5 +38,5 @@ int efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
|
|||
unsigned int segment_count);
|
||||
|
||||
unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
|
||||
|
||||
int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue