public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.6] POWER5 Virtual Ethernet Checkum offload
@ 2004-08-27 19:04 Santiago Leon
  2004-08-27 19:28 ` Jeff Garzik
  0 siblings, 1 reply; 2+ messages in thread
From: Santiago Leon @ 2004-08-27 19:04 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Linux Kernel list

[-- Attachment #1: Type: text/plain, Size: 782 bytes --]

Andrew,

The following patch adds checksum offloading for the POWER5 Virtual 
Ethernet driver.  In the case where the OS in the partitions 
communicating support this feature (i.e. both partition have this patch 
applied), no checksum will be created because the link is reliable. 
However, in the case where one of the OS in a partition does support 
this feature and the other doesn't (i.e. linux with patch applied 
talking to AIX), then the hypervisor will generate the checksum.

Some levels of firmware will not support this feature but the code will 
figure it out and not enable it.

Applies against the latest mainline and -mm trees. Please apply.


Signed-off-by: Santiago Leon <santil@us.ibm.com>

-- 
Santiago A. Leon
Power Linux Development
IBM Linux Technology Center

[-- Attachment #2: ibmveth_chkoff.patch --]
[-- Type: text/plain, Size: 5466 bytes --]

===== drivers/net/ibmveth.c 1.17 vs edited =====
--- 1.17/drivers/net/ibmveth.c	Mon Aug 23 03:14:44 2004
+++ edited/drivers/net/ibmveth.c	Fri Aug 27 14:23:56 2004
@@ -49,6 +49,7 @@
 #include <linux/mm.h>
 #include <linux/ethtool.h>
 #include <linux/proc_fs.h>
+#include <linux/tcp.h>
 #include <asm/semaphore.h>
 #include <asm/hvcall.h>
 #include <asm/atomic.h>
@@ -104,7 +105,7 @@
 
 static const char ibmveth_driver_name[] = "ibmveth";
 static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
-#define ibmveth_driver_version "1.02"
+#define ibmveth_driver_version "1.03"
 
 MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
 MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
@@ -132,6 +133,11 @@
 	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
 }
 
+static inline int ibmveth_rxq_frame_checksum_good(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].checksum_good);
+}
+
 /* setup the initial settings for a buffer pool */
 static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size)
 {
@@ -403,6 +409,11 @@
 
 static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
 {
+	unsigned long chkoff_result, dummy;
+
+	h_illan_attributes(adapter->vdev->unit_address, CHECKSUM_OFFLOAD, 0, 
+		chkoff_result, dummy);
+
 	if(adapter->buffer_list_addr != NULL) {
 		if(!dma_mapping_error(adapter->buffer_list_dma)) {
 			vio_unmap_single(adapter->vdev, adapter->buffer_list_dma, 4096, DMA_BIDIRECTIONAL);
@@ -645,6 +656,12 @@
 					desc[0].fields.length, DMA_TO_DEVICE);
 	desc[0].fields.valid   = 1;
 
+	if (adapter->can_checksum_offload && skb->ip_summed == CHECKSUM_HW) {
+		desc[0].fields.no_checksum = 1;
+		desc[0].fields.checksum_good = 1;
+		skb->h.th->check = 0;
+	}
+
 	if(dma_mapping_error(desc[0].fields.address)) {
 		ibmveth_error_printk("tx: unable to map initial fragment\n");
 		adapter->tx_map_failed++;
@@ -743,6 +760,7 @@
 			} else {
 				int length = ibmveth_rxq_frame_length(adapter);
 				int offset = ibmveth_rxq_frame_offset(adapter);
+				int checksum_good = ibmveth_rxq_frame_checksum_good(adapter);
 				skb = ibmveth_rxq_get_buffer(adapter);
 
 				ibmveth_rxq_harvest_buffer(adapter);
@@ -751,6 +769,11 @@
 				skb_put(skb, length);
 				skb->dev = netdev;
 				skb->protocol = eth_type_trans(skb, netdev);
+				
+				if (checksum_good)
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+				else
+					skb->ip_summed = CHECKSUM_NONE;
 
 				netif_receive_skb(skb);	/* send it up */
 
@@ -878,7 +901,7 @@
 
 	unsigned char *mac_addr_p;
 	unsigned int *mcastFilterSize_p;
-
+	unsigned long chkoff_result, dummy;
 
 	ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", 
 					dev->unit_address);
@@ -926,6 +949,18 @@
 
 	adapter->liobn = dev->iommu_table->it_index;
 	
+	rc = h_illan_attributes(dev->unit_address, 0, CHECKSUM_OFFLOAD, 
+		chkoff_result, dummy);
+
+	if (rc == H_Success)
+		adapter->can_checksum_offload = 1;
+	else 
+		adapter->can_checksum_offload = 0;
+	
+	ibmveth_printk("Firmware %s checksum offload, result mask=%lu\n",
+			adapter->can_checksum_offload? "supports" : 
+			"does not support", chkoff_result);
+
 	netdev->irq = dev->irq;
 	netdev->open               = ibmveth_open;
 	netdev->poll               = ibmveth_poll;
@@ -937,6 +972,8 @@
 	netdev->do_ioctl           = ibmveth_ioctl;
 	netdev->ethtool_ops           = &netdev_ethtool_ops;
 	netdev->change_mtu         = ibmveth_change_mtu;
+	if (adapter->can_checksum_offload)
+		netdev->features           = NETIF_F_HW_CSUM; 
 	SET_NETDEV_DEV(netdev, &dev->dev);
 
 	memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
===== drivers/net/ibmveth.h 1.2 vs edited =====
--- 1.2/drivers/net/ibmveth.h	Mon Aug 23 03:14:44 2004
+++ edited/drivers/net/ibmveth.h	Fri Aug 27 14:21:15 2004
@@ -49,6 +49,7 @@
 #define H_SEND_LOGICAL_LAN       0x120
 #define H_MULTICAST_CTRL         0x130
 #define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+#define H_ILLAN_ATTRIBUTES       0x244
 
 /* hcall macros */
 #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
@@ -69,6 +70,9 @@
 #define h_change_logical_lan_mac(ua, mac) \
   plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
 
+#define h_illan_attributes(ua, reset_mask, set_mask, result, dummy) \
+  plpar_hcall(H_ILLAN_ATTRIBUTES, ua, reset_mask, set_mask, 0, &result, &dummy, &dummy)
+
 #define IbmVethNumBufferPools 3
 #define IbmVethPool0DftSize (1024 * 2)
 #define IbmVethPool1DftSize (1024 * 4)
@@ -79,6 +83,8 @@
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
 
+#define CHECKSUM_OFFLOAD 0x6
+
 struct ibmveth_buff_pool {
     u32 size;
     u32 index;
@@ -115,6 +121,7 @@
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
     atomic_t not_replenishing;
+    int can_checksum_offload;
 
     /* helper tasks */
     struct work_struct replenish_task;
@@ -136,7 +143,9 @@
 struct ibmveth_buf_desc_fields {	
     u32 valid : 1;
     u32 toggle : 1;
-    u32 reserved : 6;
+    u32 reserved : 4;
+    u32 no_checksum : 1;
+    u32 checksum_good :1;
     u32 length : 24;
     u32 address;
 };
@@ -149,7 +158,10 @@
 struct ibmveth_rx_q_entry {
     u16 toggle : 1;
     u16 valid : 1;
-    u16 reserved : 14;
+    u16 reserved : 4;
+    u16 no_checksum : 1;
+    u16 checksum_good : 1;
+    u16 reserved2 : 8;
     u16 offset;
     u32 length;
     u64 correlator;

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2.6] POWER5 Virtual Ethernet Checkum offload
  2004-08-27 19:04 [PATCH 2.6] POWER5 Virtual Ethernet Checkum offload Santiago Leon
@ 2004-08-27 19:28 ` Jeff Garzik
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2004-08-27 19:28 UTC (permalink / raw)
  To: Santiago Leon; +Cc: Andrew Morton, Linux Kernel list

Santiago Leon wrote:
> Andrew,
> 
> The following patch adds checksum offloading for the POWER5 Virtual 
> Ethernet driver.  In the case where the OS in the partitions 
> communicating support this feature (i.e. both partition have this patch 
> applied), no checksum will be created because the link is reliable. 
> However, in the case where one of the OS in a partition does support 
> this feature and the other doesn't (i.e. linux with patch applied 
> talking to AIX), then the hypervisor will generate the checksum.
> 
> Some levels of firmware will not support this feature but the code will 
> figure it out and not enable it.
> 
> Applies against the latest mainline and -mm trees. Please apply.

First, please always CC net driver patches to me and netdev@oss.sgi.com.

Second, this patch is incorrect.  Read the top of include/linux/skbuff.h 
for the various levels of checksum offloading, and how to use them.

Specifically,

a) you should not be using CHECKSUM_HW unless your hardware provides a 
valid csum (ipv4 or ipv6) that you store in skb->csum.

b) you should not be using NETIF_F_HW_CSUM for reasons similar to (a): 
your hardware must be able to csum the packet whether its ipv4 or ipv6 
or whatever, given the information in the skb.

c) use of NETIF_F_xxx_CSUM is pointless without NETIF_F_SG and code in 
the transmit path to handle page-based fragments (a scatter-gather list).

	Jeff






^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-08-27 19:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-27 19:04 [PATCH 2.6] POWER5 Virtual Ethernet Checkum offload Santiago Leon
2004-08-27 19:28 ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox