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 */
|
#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
|
* 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;
|
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 segment_count);
|
||||||
|
|
||||||
unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue