aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantiago Leon <santil@linux.vnet.ibm.com>2010-09-03 14:28:36 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-06 21:21:48 -0400
commit6e8ab30ec677925e8999a9f5bdb028736d22d48c (patch)
tree23738f9382f6d0f1b1cd6dba62394ac53aeeb12e
parentf89e49e79f839dbe79364ec6cd7e2274ad11b120 (diff)
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>
-rw-r--r--drivers/net/ibmveth.c184
1 files changed, 124 insertions, 60 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index aedcb1802182..d8a89846c6a8 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -897,6 +897,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
897 .get_strings = ibmveth_get_strings, 897 .get_strings = ibmveth_get_strings,
898 .get_sset_count = ibmveth_get_sset_count, 898 .get_sset_count = ibmveth_get_sset_count,
899 .get_ethtool_stats = ibmveth_get_ethtool_stats, 899 .get_ethtool_stats = ibmveth_get_ethtool_stats,
900 .set_sg = ethtool_op_set_sg,
900}; 901};
901 902
902static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 903static 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)
906 907
907#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) 908#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
908 909
909static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, 910static int ibmveth_send(struct ibmveth_adapter *adapter,
910 struct net_device *netdev) 911 union ibmveth_buf_desc *descs)
911{ 912{
912 struct ibmveth_adapter *adapter = netdev_priv(netdev);
913 union ibmveth_buf_desc desc;
914 unsigned long lpar_rc;
915 unsigned long correlator; 913 unsigned long correlator;
916 unsigned int retry_count; 914 unsigned int retry_count;
917 unsigned int tx_dropped = 0; 915 unsigned long ret;
918 unsigned int tx_bytes = 0; 916
919 unsigned int tx_packets = 0; 917 /*
920 unsigned int tx_send_failed = 0; 918 * The retry count sets a maximum for the number of broadcast and
921 unsigned int tx_map_failed = 0; 919 * multicast destinations within the system.
922 int used_bounce = 0; 920 */
923 unsigned long data_dma_addr; 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}
924 939
925 desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len; 940static 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 }
926 957
958 /* veth can't checksum offload UDP */
927 if (skb->ip_summed == CHECKSUM_PARTIAL && 959 if (skb->ip_summed == CHECKSUM_PARTIAL &&
928 ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { 960 ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
929 ibmveth_error_printk("tx: failed to checksum packet\n"); 961 ibmveth_error_printk("tx: failed to checksum packet\n");
930 tx_dropped++; 962 netdev->stats.tx_dropped++;
931 goto out; 963 goto out;
932 } 964 }
933 965
966 desc_flags = IBMVETH_BUF_VALID;
967
934 if (skb->ip_summed == CHECKSUM_PARTIAL) { 968 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;
936 971
937 desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD); 972 desc_flags |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
938 973
939 /* Need to zero out the checksum */ 974 /* Need to zero out the checksum */
940 buf[0] = 0; 975 buf[0] = 0;
941 buf[1] = 0; 976 buf[1] = 0;
942 } 977 }
943 978
944 if (skb->len < tx_copybreak) { 979retry_bounce:
945 used_bounce = 1; 980 memset(descs, 0, sizeof(descs));
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 }
957 981
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))) {
959 skb_copy_from_linear_data(skb, adapter->bounce_buffer, 989 skb_copy_from_linear_data(skb, adapter->bounce_buffer,
960 skb->len); 990 skb->len);
961 desc.fields.address = adapter->bounce_buffer_dma;
962 } else
963 desc.fields.address = data_dma_addr;
964 991
965 /* send the frame. Arbitrarily set retrycount to 1024 */ 992 descs[0].fields.flags_len = desc_flags | skb->len;
966 correlator = 0; 993 descs[0].fields.address = adapter->bounce_buffer_dma;
967 retry_count = 1024; 994
968 do { 995 if (ibmveth_send(adapter, descs)) {
969 lpar_rc = h_send_logical_lan(adapter->vdev->unit_address, 996 adapter->tx_send_failed++;
970 desc.desc, 0, 0, 0, 0, 0, 997 netdev->stats.tx_dropped++;
971 correlator, &correlator); 998 } else {
972 } while ((lpar_rc == H_BUSY) && (retry_count--)); 999 netdev->stats.tx_packets++;
973 1000 netdev->stats.tx_bytes += skb->len;
974 if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) { 1001 }
975 ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); 1002
976 ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n", 1003 goto out;
977 (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0, 1004 }
978 skb->len, desc.fields.address); 1005
979 tx_send_failed++; 1006 /* Map the header */
980 tx_dropped++; 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++;
981 } else { 1034 } else {
982 tx_packets++; 1035 netdev->stats.tx_packets++;
983 tx_bytes += skb->len; 1036 netdev->stats.tx_bytes += skb->len;
984 } 1037 }
985 1038
986 if (!used_bounce) 1039 for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++)
987 dma_unmap_single(&adapter->vdev->dev, data_dma_addr, 1040 dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
988 skb->len, DMA_TO_DEVICE); 1041 descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
1042 DMA_TO_DEVICE);
989 1043
990out: 1044out:
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
997 dev_kfree_skb(skb); 1045 dev_kfree_skb(skb);
998 return NETDEV_TX_OK; 1046 return NETDEV_TX_OK;
1047
1048map_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
1055map_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;
999} 1062}
1000 1063
1001static int ibmveth_poll(struct napi_struct *napi, int budget) 1064static 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_
1316 netdev->netdev_ops = &ibmveth_netdev_ops; 1379 netdev->netdev_ops = &ibmveth_netdev_ops;
1317 netdev->ethtool_ops = &netdev_ethtool_ops; 1380 netdev->ethtool_ops = &netdev_ethtool_ops;
1318 SET_NETDEV_DEV(netdev, &dev->dev); 1381 SET_NETDEV_DEV(netdev, &dev->dev);
1382 netdev->features |= NETIF_F_SG;
1319 1383
1320 memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); 1384 memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
1321 1385