Skip to content

Commit 6e8ab30

Browse files
santildavem330
authored andcommitted
ibmveth: Add scatter-gather support
ibmveth can scatter gather up to 6 segments. If we go over this then we have no option but to call skb_linearize, like other drivers with similar limitations do. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Santiago Leon <santil@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f89e49e commit 6e8ab30

File tree

1 file changed

+124
-60
lines changed

1 file changed

+124
-60
lines changed

drivers/net/ibmveth.c

Lines changed: 124 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
897897
.get_strings = ibmveth_get_strings,
898898
.get_sset_count = ibmveth_get_sset_count,
899899
.get_ethtool_stats = ibmveth_get_ethtool_stats,
900+
.set_sg = ethtool_op_set_sg,
900901
};
901902

902903
static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -906,96 +907,158 @@ static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
906907

907908
#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
908909

909-
static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
910-
struct net_device *netdev)
910+
static int ibmveth_send(struct ibmveth_adapter *adapter,
911+
union ibmveth_buf_desc *descs)
911912
{
912-
struct ibmveth_adapter *adapter = netdev_priv(netdev);
913-
union ibmveth_buf_desc desc;
914-
unsigned long lpar_rc;
915913
unsigned long correlator;
916914
unsigned int retry_count;
917-
unsigned int tx_dropped = 0;
918-
unsigned int tx_bytes = 0;
919-
unsigned int tx_packets = 0;
920-
unsigned int tx_send_failed = 0;
921-
unsigned int tx_map_failed = 0;
922-
int used_bounce = 0;
923-
unsigned long data_dma_addr;
915+
unsigned long ret;
916+
917+
/*
918+
* The retry count sets a maximum for the number of broadcast and
919+
* multicast destinations within the system.
920+
*/
921+
retry_count = 1024;
922+
correlator = 0;
923+
do {
924+
ret = h_send_logical_lan(adapter->vdev->unit_address,
925+
descs[0].desc, descs[1].desc,
926+
descs[2].desc, descs[3].desc,
927+
descs[4].desc, descs[5].desc,
928+
correlator, &correlator);
929+
} while ((ret == H_BUSY) && (retry_count--));
930+
931+
if (ret != H_SUCCESS && ret != H_DROPPED) {
932+
ibmveth_error_printk("tx: h_send_logical_lan failed with "
933+
"rc=%ld\n", ret);
934+
return 1;
935+
}
936+
937+
return 0;
938+
}
924939

925-
desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
940+
static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
941+
struct net_device *netdev)
942+
{
943+
struct ibmveth_adapter *adapter = netdev_priv(netdev);
944+
unsigned int desc_flags;
945+
union ibmveth_buf_desc descs[6];
946+
int last, i;
947+
int force_bounce = 0;
948+
949+
/*
950+
* veth handles a maximum of 6 segments including the header, so
951+
* we have to linearize the skb if there are more than this.
952+
*/
953+
if (skb_shinfo(skb)->nr_frags > 5 && __skb_linearize(skb)) {
954+
netdev->stats.tx_dropped++;
955+
goto out;
956+
}
926957

958+
/* veth can't checksum offload UDP */
927959
if (skb->ip_summed == CHECKSUM_PARTIAL &&
928960
ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
929961
ibmveth_error_printk("tx: failed to checksum packet\n");
930-
tx_dropped++;
962+
netdev->stats.tx_dropped++;
931963
goto out;
932964
}
933965

966+
desc_flags = IBMVETH_BUF_VALID;
967+
934968
if (skb->ip_summed == CHECKSUM_PARTIAL) {
935-
unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
969+
unsigned char *buf = skb_transport_header(skb) +
970+
skb->csum_offset;
936971

937-
desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
972+
desc_flags |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
938973

939974
/* Need to zero out the checksum */
940975
buf[0] = 0;
941976
buf[1] = 0;
942977
}
943978

944-
if (skb->len < tx_copybreak) {
945-
used_bounce = 1;
946-
} else {
947-
data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
948-
skb->len, DMA_TO_DEVICE);
949-
if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) {
950-
if (!firmware_has_feature(FW_FEATURE_CMO))
951-
ibmveth_error_printk("tx: unable to map "
952-
"xmit buffer\n");
953-
tx_map_failed++;
954-
used_bounce = 1;
955-
}
956-
}
979+
retry_bounce:
980+
memset(descs, 0, sizeof(descs));
957981

958-
if (used_bounce) {
982+
/*
983+
* If a linear packet is below the rx threshold then
984+
* copy it into the static bounce buffer. This avoids the
985+
* cost of a TCE insert and remove.
986+
*/
987+
if (force_bounce || (!skb_is_nonlinear(skb) &&
988+
(skb->len < tx_copybreak))) {
959989
skb_copy_from_linear_data(skb, adapter->bounce_buffer,
960990
skb->len);
961-
desc.fields.address = adapter->bounce_buffer_dma;
962-
} else
963-
desc.fields.address = data_dma_addr;
964991

965-
/* send the frame. Arbitrarily set retrycount to 1024 */
966-
correlator = 0;
967-
retry_count = 1024;
968-
do {
969-
lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
970-
desc.desc, 0, 0, 0, 0, 0,
971-
correlator, &correlator);
972-
} while ((lpar_rc == H_BUSY) && (retry_count--));
973-
974-
if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
975-
ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
976-
ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
977-
(desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
978-
skb->len, desc.fields.address);
979-
tx_send_failed++;
980-
tx_dropped++;
992+
descs[0].fields.flags_len = desc_flags | skb->len;
993+
descs[0].fields.address = adapter->bounce_buffer_dma;
994+
995+
if (ibmveth_send(adapter, descs)) {
996+
adapter->tx_send_failed++;
997+
netdev->stats.tx_dropped++;
998+
} else {
999+
netdev->stats.tx_packets++;
1000+
netdev->stats.tx_bytes += skb->len;
1001+
}
1002+
1003+
goto out;
1004+
}
1005+
1006+
/* Map the header */
1007+
descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
1008+
skb_headlen(skb),
1009+
DMA_TO_DEVICE);
1010+
if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address))
1011+
goto map_failed;
1012+
1013+
descs[0].fields.flags_len = desc_flags | skb_headlen(skb);
1014+
1015+
/* Map the frags */
1016+
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1017+
unsigned long dma_addr;
1018+
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1019+
1020+
dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,
1021+
frag->page_offset, frag->size,
1022+
DMA_TO_DEVICE);
1023+
1024+
if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
1025+
goto map_failed_frags;
1026+
1027+
descs[i+1].fields.flags_len = desc_flags | frag->size;
1028+
descs[i+1].fields.address = dma_addr;
1029+
}
1030+
1031+
if (ibmveth_send(adapter, descs)) {
1032+
adapter->tx_send_failed++;
1033+
netdev->stats.tx_dropped++;
9811034
} else {
982-
tx_packets++;
983-
tx_bytes += skb->len;
1035+
netdev->stats.tx_packets++;
1036+
netdev->stats.tx_bytes += skb->len;
9841037
}
9851038

986-
if (!used_bounce)
987-
dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
988-
skb->len, DMA_TO_DEVICE);
1039+
for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++)
1040+
dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
1041+
descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
1042+
DMA_TO_DEVICE);
9891043

9901044
out:
991-
netdev->stats.tx_dropped += tx_dropped;
992-
netdev->stats.tx_bytes += tx_bytes;
993-
netdev->stats.tx_packets += tx_packets;
994-
adapter->tx_send_failed += tx_send_failed;
995-
adapter->tx_map_failed += tx_map_failed;
996-
9971045
dev_kfree_skb(skb);
9981046
return NETDEV_TX_OK;
1047+
1048+
map_failed_frags:
1049+
last = i+1;
1050+
for (i = 0; i < last; i++)
1051+
dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
1052+
descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
1053+
DMA_TO_DEVICE);
1054+
1055+
map_failed:
1056+
if (!firmware_has_feature(FW_FEATURE_CMO))
1057+
ibmveth_error_printk("tx: unable to map xmit buffer\n");
1058+
adapter->tx_map_failed++;
1059+
skb_linearize(skb);
1060+
force_bounce = 1;
1061+
goto retry_bounce;
9991062
}
10001063

10011064
static int ibmveth_poll(struct napi_struct *napi, int budget)
@@ -1316,6 +1379,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
13161379
netdev->netdev_ops = &ibmveth_netdev_ops;
13171380
netdev->ethtool_ops = &netdev_ethtool_ops;
13181381
SET_NETDEV_DEV(netdev, &dev->dev);
1382+
netdev->features |= NETIF_F_SG;
13191383

13201384
memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
13211385

0 commit comments

Comments
 (0)