diff options
Diffstat (limited to 'drivers/net/ibmveth.c')
-rw-r--r-- | drivers/net/ibmveth.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 0c35d72f5f8d..9353890dcda0 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
48 | #include <linux/ethtool.h> | 48 | #include <linux/ethtool.h> |
49 | #include <linux/proc_fs.h> | 49 | #include <linux/proc_fs.h> |
50 | #include <linux/in.h> | ||
51 | #include <linux/ip.h> | ||
50 | #include <net/net_namespace.h> | 52 | #include <net/net_namespace.h> |
51 | #include <asm/semaphore.h> | 53 | #include <asm/semaphore.h> |
52 | #include <asm/hvcall.h> | 54 | #include <asm/hvcall.h> |
@@ -132,6 +134,11 @@ static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) | |||
132 | return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); | 134 | return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); |
133 | } | 135 | } |
134 | 136 | ||
137 | static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter) | ||
138 | { | ||
139 | return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].csum_good); | ||
140 | } | ||
141 | |||
135 | /* setup the initial settings for a buffer pool */ | 142 | /* setup the initial settings for a buffer pool */ |
136 | static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active) | 143 | static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active) |
137 | { | 144 | { |
@@ -695,6 +702,24 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
695 | desc[0].fields.length, DMA_TO_DEVICE); | 702 | desc[0].fields.length, DMA_TO_DEVICE); |
696 | desc[0].fields.valid = 1; | 703 | desc[0].fields.valid = 1; |
697 | 704 | ||
705 | if (skb->ip_summed == CHECKSUM_PARTIAL && | ||
706 | ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { | ||
707 | ibmveth_error_printk("tx: failed to checksum packet\n"); | ||
708 | tx_dropped++; | ||
709 | goto out; | ||
710 | } | ||
711 | |||
712 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | ||
713 | unsigned char *buf = skb_transport_header(skb) + skb->csum_offset; | ||
714 | |||
715 | desc[0].fields.no_csum = 1; | ||
716 | desc[0].fields.csum_good = 1; | ||
717 | |||
718 | /* Need to zero out the checksum */ | ||
719 | buf[0] = 0; | ||
720 | buf[1] = 0; | ||
721 | } | ||
722 | |||
698 | if(dma_mapping_error(desc[0].fields.address)) { | 723 | if(dma_mapping_error(desc[0].fields.address)) { |
699 | ibmveth_error_printk("tx: unable to map initial fragment\n"); | 724 | ibmveth_error_printk("tx: unable to map initial fragment\n"); |
700 | tx_map_failed++; | 725 | tx_map_failed++; |
@@ -713,6 +738,10 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
713 | frag->size, DMA_TO_DEVICE); | 738 | frag->size, DMA_TO_DEVICE); |
714 | desc[curfrag+1].fields.length = frag->size; | 739 | desc[curfrag+1].fields.length = frag->size; |
715 | desc[curfrag+1].fields.valid = 1; | 740 | desc[curfrag+1].fields.valid = 1; |
741 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | ||
742 | desc[curfrag+1].fields.no_csum = 1; | ||
743 | desc[curfrag+1].fields.csum_good = 1; | ||
744 | } | ||
716 | 745 | ||
717 | if(dma_mapping_error(desc[curfrag+1].fields.address)) { | 746 | if(dma_mapping_error(desc[curfrag+1].fields.address)) { |
718 | ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag); | 747 | ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag); |
@@ -801,7 +830,11 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) | |||
801 | } else { | 830 | } else { |
802 | int length = ibmveth_rxq_frame_length(adapter); | 831 | int length = ibmveth_rxq_frame_length(adapter); |
803 | int offset = ibmveth_rxq_frame_offset(adapter); | 832 | int offset = ibmveth_rxq_frame_offset(adapter); |
833 | int csum_good = ibmveth_rxq_csum_good(adapter); | ||
834 | |||
804 | skb = ibmveth_rxq_get_buffer(adapter); | 835 | skb = ibmveth_rxq_get_buffer(adapter); |
836 | if (csum_good) | ||
837 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
805 | 838 | ||
806 | ibmveth_rxq_harvest_buffer(adapter); | 839 | ibmveth_rxq_harvest_buffer(adapter); |
807 | 840 | ||
@@ -962,8 +995,10 @@ static void ibmveth_poll_controller(struct net_device *dev) | |||
962 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) | 995 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) |
963 | { | 996 | { |
964 | int rc, i; | 997 | int rc, i; |
998 | long ret; | ||
965 | struct net_device *netdev; | 999 | struct net_device *netdev; |
966 | struct ibmveth_adapter *adapter; | 1000 | struct ibmveth_adapter *adapter; |
1001 | union ibmveth_illan_attributes set_attr, ret_attr; | ||
967 | 1002 | ||
968 | unsigned char *mac_addr_p; | 1003 | unsigned char *mac_addr_p; |
969 | unsigned int *mcastFilterSize_p; | 1004 | unsigned int *mcastFilterSize_p; |
@@ -1057,6 +1092,24 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ | |||
1057 | 1092 | ||
1058 | ibmveth_debug_printk("registering netdev...\n"); | 1093 | ibmveth_debug_printk("registering netdev...\n"); |
1059 | 1094 | ||
1095 | ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr.desc); | ||
1096 | |||
1097 | if (ret == H_SUCCESS && !ret_attr.fields.active_trunk && | ||
1098 | !ret_attr.fields.trunk_priority && | ||
1099 | ret_attr.fields.csum_offload_padded_pkt_support) { | ||
1100 | set_attr.desc = 0; | ||
1101 | set_attr.fields.tcp_csum_offload_ipv4 = 1; | ||
1102 | |||
1103 | ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc, | ||
1104 | &ret_attr.desc); | ||
1105 | |||
1106 | if (ret == H_SUCCESS) | ||
1107 | netdev->features |= NETIF_F_IP_CSUM; | ||
1108 | else | ||
1109 | ret = h_illan_attributes(dev->unit_address, set_attr.desc, | ||
1110 | 0, &ret_attr.desc); | ||
1111 | } | ||
1112 | |||
1060 | rc = register_netdev(netdev); | 1113 | rc = register_netdev(netdev); |
1061 | 1114 | ||
1062 | if(rc) { | 1115 | if(rc) { |