Skip to content

Commit 8ae74ab

Browse files
committed
Merge branch 'ibmvnic-Fix-VLAN-and-other-device-errata'
Thomas Falcon says: ==================== ibmvnic: Fix VLAN and other device errata This patch series contains fixes for VLAN and other backing hardware errata. The VLAN fixes are mostly to account for the additional four bytes VLAN header in TX descriptors and buffers, when applicable. The other fixes for device errata are to pad small packets to avoid a possible connection error that can occur when some devices attempt to transmit small packets. The other fixes are GSO related. Some devices cannot handle a smaller MSS or a packet with a single segment, so disable GSO in those cases. v2: Fix style mistake (unneeded brackets) in patch 3/4 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 9ba3204 + f10b09e commit 8ae74ab

File tree

1 file changed

+45
-4
lines changed

1 file changed

+45
-4
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ static int init_tx_pools(struct net_device *netdev)
659659

660660
if (alloc_long_term_buff(adapter, &tx_pool->long_term_buff,
661661
adapter->req_tx_entries_per_subcrq *
662-
adapter->req_mtu)) {
662+
(adapter->req_mtu + VLAN_HLEN))) {
663663
release_tx_pools(adapter);
664664
return -1;
665665
}
@@ -1221,7 +1221,10 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
12211221
int len = 0;
12221222
u8 *hdr;
12231223

1224-
hdr_len[0] = sizeof(struct ethhdr);
1224+
if (skb_vlan_tagged(skb) && !skb_vlan_tag_present(skb))
1225+
hdr_len[0] = sizeof(struct vlan_ethhdr);
1226+
else
1227+
hdr_len[0] = sizeof(struct ethhdr);
12251228

12261229
if (skb->protocol == htons(ETH_P_IP)) {
12271230
hdr_len[1] = ip_hdr(skb)->ihl * 4;
@@ -1337,6 +1340,19 @@ static void build_hdr_descs_arr(struct ibmvnic_tx_buff *txbuff,
13371340
txbuff->indir_arr + 1);
13381341
}
13391342

1343+
static int ibmvnic_xmit_workarounds(struct sk_buff *skb,
1344+
struct net_device *netdev)
1345+
{
1346+
/* For some backing devices, mishandling of small packets
1347+
* can result in a loss of connection or TX stall. Device
1348+
* architects recommend that no packet should be smaller
1349+
* than the minimum MTU value provided to the driver, so
1350+
* pad any packets to that length
1351+
*/
1352+
if (skb->len < netdev->min_mtu)
1353+
return skb_put_padto(skb, netdev->min_mtu);
1354+
}
1355+
13401356
static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
13411357
{
13421358
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
@@ -1374,6 +1390,13 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
13741390
goto out;
13751391
}
13761392

1393+
if (ibmvnic_xmit_workarounds(skb, adapter)) {
1394+
tx_dropped++;
1395+
tx_send_failed++;
1396+
ret = NETDEV_TX_OK;
1397+
goto out;
1398+
}
1399+
13771400
tx_pool = &adapter->tx_pool[queue_num];
13781401
tx_scrq = adapter->tx_scrq[queue_num];
13791402
txq = netdev_get_tx_queue(netdev, skb_get_queue_mapping(skb));
@@ -1391,9 +1414,9 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
13911414
if (tx_pool->tso_index == IBMVNIC_TSO_BUFS)
13921415
tx_pool->tso_index = 0;
13931416
} else {
1394-
offset = index * adapter->req_mtu;
1417+
offset = index * (adapter->req_mtu + VLAN_HLEN);
13951418
dst = tx_pool->long_term_buff.buff + offset;
1396-
memset(dst, 0, adapter->req_mtu);
1419+
memset(dst, 0, adapter->req_mtu + VLAN_HLEN);
13971420
data_dma_addr = tx_pool->long_term_buff.addr + offset;
13981421
}
13991422

@@ -2026,6 +2049,23 @@ static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
20262049
return wait_for_reset(adapter);
20272050
}
20282051

2052+
static netdev_features_t ibmvnic_features_check(struct sk_buff *skb,
2053+
struct net_device *dev,
2054+
netdev_features_t features)
2055+
{
2056+
/* Some backing hardware adapters can not
2057+
* handle packets with a MSS less than 224
2058+
* or with only one segment.
2059+
*/
2060+
if (skb_is_gso(skb)) {
2061+
if (skb_shinfo(skb)->gso_size < 224 ||
2062+
skb_shinfo(skb)->gso_segs == 1)
2063+
features &= ~NETIF_F_GSO_MASK;
2064+
}
2065+
2066+
return features;
2067+
}
2068+
20292069
static const struct net_device_ops ibmvnic_netdev_ops = {
20302070
.ndo_open = ibmvnic_open,
20312071
.ndo_stop = ibmvnic_close,
@@ -2038,6 +2078,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
20382078
.ndo_poll_controller = ibmvnic_netpoll_controller,
20392079
#endif
20402080
.ndo_change_mtu = ibmvnic_change_mtu,
2081+
.ndo_features_check = ibmvnic_features_check,
20412082
};
20422083

20432084
/* ethtool functions */

0 commit comments

Comments
 (0)