mac80211: allow segmentation offloads
Implement the necessary software segmentation on the normal TX path so that fast-xmit can use segmentation offload if the hardware (or driver) supports it. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
680a0daba7
commit
80616c0db8
2 changed files with 48 additions and 25 deletions
|
@ -840,7 +840,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
|
|
||||||
/* Only HW csum features are currently compatible with mac80211 */
|
/* Only HW csum features are currently compatible with mac80211 */
|
||||||
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||||
NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA;
|
NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA |
|
||||||
|
NETIF_F_GSO_SOFTWARE;
|
||||||
if (WARN_ON(hw->netdev_features & ~feature_whitelist))
|
if (WARN_ON(hw->netdev_features & ~feature_whitelist))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -2843,6 +2843,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
struct sk_buff *next;
|
||||||
|
|
||||||
if (unlikely(skb->len < ETH_HLEN)) {
|
if (unlikely(skb->len < ETH_HLEN)) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
@ -2864,36 +2865,57 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we cannot process non-linear frames on this path */
|
if (skb_is_gso(skb)) {
|
||||||
if (skb_linearize(skb)) {
|
struct sk_buff *segs;
|
||||||
kfree_skb(skb);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the frame could be fragmented, software-encrypted, and other things
|
segs = skb_gso_segment(skb, 0);
|
||||||
* so we cannot really handle checksum offload with it - fix it up in
|
if (IS_ERR(segs)) {
|
||||||
* software before we handle anything else.
|
|
||||||
*/
|
|
||||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
||||||
if (skb->encapsulation)
|
|
||||||
skb_set_inner_transport_header(skb,
|
|
||||||
skb_checksum_start_offset(skb));
|
|
||||||
else
|
|
||||||
skb_set_transport_header(skb,
|
|
||||||
skb_checksum_start_offset(skb));
|
|
||||||
if (skb_checksum_help(skb))
|
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
} else if (segs) {
|
||||||
|
consume_skb(skb);
|
||||||
|
skb = segs;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* we cannot process non-linear frames on this path */
|
||||||
|
if (skb_linearize(skb)) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the frame could be fragmented, software-encrypted, and other
|
||||||
|
* things so we cannot really handle checksum offload with it -
|
||||||
|
* fix it up in software before we handle anything else.
|
||||||
|
*/
|
||||||
|
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
|
if (skb->encapsulation)
|
||||||
|
skb_set_inner_transport_header(skb,
|
||||||
|
skb_checksum_start_offset(skb));
|
||||||
|
else
|
||||||
|
skb_set_transport_header(skb,
|
||||||
|
skb_checksum_start_offset(skb));
|
||||||
|
if (skb_checksum_help(skb))
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
|
next = skb;
|
||||||
if (IS_ERR(skb))
|
while (next) {
|
||||||
goto out;
|
skb = next;
|
||||||
|
next = skb->next;
|
||||||
|
|
||||||
dev->stats.tx_packets++;
|
skb->prev = NULL;
|
||||||
dev->stats.tx_bytes += skb->len;
|
skb->next = NULL;
|
||||||
dev->trans_start = jiffies;
|
|
||||||
|
|
||||||
ieee80211_xmit(sdata, sta, skb);
|
skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
|
||||||
|
if (IS_ERR(skb))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dev->stats.tx_packets++;
|
||||||
|
dev->stats.tx_bytes += skb->len;
|
||||||
|
dev->trans_start = jiffies;
|
||||||
|
|
||||||
|
ieee80211_xmit(sdata, sta, skb);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
out_free:
|
out_free:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
|
Loading…
Add table
Reference in a new issue